How to access `ServletContext` from within a Vaadin 7 app? - servlets

How do I access the current ServletContext from within my Vaadin 7 app?
I want to use the ServletContext object’s setAttribute, getAttribute, removeAttribute, and getAttributeNames methods to manage some global state for my Vaadin app.
Also, if using those methods for that purpose is inappropriate for Vaadin apps, please explain.

tl;dr
For Vaadin 7 & 8, as well as Vaadin Flow (versions 10+):
VaadinServlet.getCurrent().getServletContext()
VaadinServlet
The VaadinServlet class inherits a getServletContext method.
To get the VaadinServlet object, call the static class method getCurrent.
From most anywhere within your Vaadin app, do something like this:
ServletContext servletContext = VaadinServlet.getCurrent().getServletContext();
CAVEATDoes not work in background threads. In threads you launch, this command returns NULL. As documented:
In other cases, (e.g. from background threads started in some other way), the current servlet is not automatically defined.
#WebListener (ServletContextListener)
By the way, you are likely to want to handle such global state when the web app deploys (launches) in the container.
You can hook into your Vaadin web app’s deployment with the #WebListener annotation on your class implementing the ServletContextListener interface. Both methods of that interface, contextInitialized and contextDestroyed, are passed a ServletContextEvent from which you can access the ServletContext object by calling getServletContext.
#WebListener ( "Context listener for doing something or other." )
public class MyContextListener implements ServletContextListener
{
// Vaadin app deploying/launching.
#Override
public void contextInitialized ( ServletContextEvent contextEvent )
{
ServletContext context = contextEvent.getServletContext();
context.setAttribute( … ) ;
// …
}
// Vaadin app un-deploying/shutting down.
#Override
public void contextDestroyed ( ServletContextEvent contextEvent )
{
ServletContext context = contextEvent.getServletContext();
// …
}
}
This hook is called as part of your Vaadin app being initialized, before executing the Vaadin servlet (or any other servlet/filter in your web app). To quote the doc on the contextInitialized method:
Receives notification that the web application initialization process is starting.
All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized.

Related

App Insights not using RequestTelemetryFilter for health check Controller in Spring Boot app

I have a Spring Boot app with a few Controllers I want to track their dependencies (including outbound Http requests). That all works as expected. However, I have one controller for a health check (returning 204) that I do not want telemetry for. All other responses mention custom code components, but according to the documentation, this should be doable within the AI-Agent.xml config.
<BuiltInProcessors>
<Processor type="RequestTelemetryFilter">
<Add name="NotNeededResponseCodes" value="204" />
</Processor>
</BuiltInProcessors>
I notice on the classpath that there are two RequestTelemtryFilter instances (one from ai-core and one from ai-web, neither of which get hit when i debug).
Configuring the Agent (via AI-Agent.xml) is different than configuring custom telemetry (via Applicationinsights.xml). Spring boot + the agent requires the use of a custom Telemetry Processor and pulling into your configuration via #Bean. No additional XML in the AI-Agent is necessary.
public class HealthCheckTelemetryFilter implements TelemetryProcessor
{
public HealthCheckTelemetryFilter()
{
// TODO Auto-generated constructor stub
}
#Override
public boolean process(Telemetry telemetry)
{
RequestTelemetry reqTel = (RequestTelemetry) telemetry;
if(reqTel.getResponseCode().equals(HttpStatus.NO_CONTENT.toString()))
return false;
else
return true;
}
}
NOTE: dont forget appropriate type check

How to add multiple Bindable services to a grpc server builder?

I have the gRPC server code as below:
public void buildServer() {
List<BindableService> theServiceList = new ArrayList<BindableService>();
theServiceList.add(new CreateModuleContentService());
theServiceList.add(new RemoveModuleContentService());
ServerBuilder<?> sb = ServerBuilder.forPort(m_port);
for (BindableService aService : theServiceList) {
sb.addService(aService);
}
m_server = sb.build();
}
and client code as below:
public class JavaMainClass {
public static void main(String[] args) {
CreateModuleService createModuleService = new CreateModuleService();
ESDStandardResponse esdReponse = createModuleService.createAtomicBlock("8601934885970354030", "atm1");
RemoveModuleService moduleService = new RemoveModuleService();
moduleService.removeAtomicBlock("8601934885970354030", esdReponse.getId());
}
}
While I am running the client I am getting an exception as below:
Exception in thread "main" io.grpc.StatusRuntimeException: UNIMPLEMENTED: Method grpc.blocks.operations.ModuleContentServices/createAtomicBlock is unimplemented
at io.grpc.stub.ClientCalls.toStatusRuntimeException(ClientCalls.java:233)
at io.grpc.stub.ClientCalls.getUnchecked(ClientCalls.java:214)
at io.grpc.stub.ClientCalls.blockingUnaryCall(ClientCalls.java:139)
In the above server class, if I am commenting the line theServiceList.add(new RemoveModuleContentService()); then the CreateModuleContentService service is working fine, also without commenting all the services of RemoveModuleContentService class are working as expected, which means the problem is with the first service when another gets added.
Can someone please suggest how can I add two services to Server Builder.
A particular gRPC service can only be implemented once per server. Since the name of the gRPC service in the error message is ModuleContentServices, I'm assuming CreateModuleContentService and RemoveModuleContentService both extend ModuleContentServicesImplBase.
When you add the same service multiple times, the last one wins. The way the generated code works, every method of a service is registered even if you don't implement that particular method. Every service method defaults to a handler that simply returns "UNIMPLEMENTED: Method X is unimplemented". createAtomicBlock isn't implemented in RemoveModuleContentService, so it returns that error.
If you interact with the ServerServiceDefinition returned by bindService(), you can mix-and-match methods a bit more, but this is a more advanced API and is intended more for frameworks to use because it can become verbose to compose every application service individually.

Spring Security: Why is my custom AccessDecisionVoter not invoked

I'm trying to do URL authorization using a custom AccessDecisionVoter. I don't get any errors and debugging shows that my voter is picked up at start up. However, at runtime, the vote method is not called, thus allowing every authenticated user full access.
Note that, I don't need method security. I'm also not using XML config. That rules out every example ever posted on the internet regarding this topic.
#Configuration
#EnableWebSecurity
#EnableWebMvc
#ComponentScan
#Order(-10)
public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${trusted_ports}")
private List<Integer> trustedPorts;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private ServiceIdAwareVoter serviceIdAwareVoter;
RequestMatcher requestMatcher = new OrRequestMatcher(
// #formatter:off
new AntPathRequestMatcher("/**", GET.name()),
new AntPathRequestMatcher("/**", POST.name()),
new AntPathRequestMatcher("/**", DELETE.name()),
new AntPathRequestMatcher("/**", PATCH.name()),
new AntPathRequestMatcher("/**", PUT.name())
// #formatter:on
);
#Override
protected UserDetailsService userDetailsService() {
return userDetailsService;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(preAuthProvider());
auth.authenticationProvider(authProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.
httpBasic().and().
authorizeRequests().anyRequest().fullyAuthenticated().
accessDecisionManager(accessDecisionManager()).and().
csrf().disable().
logout().disable().
exceptionHandling().and().
sessionManagement().sessionCreationPolicy(STATELESS).and().
anonymous().disable().
addFilterAfter(preAuthFilter(), X509AuthenticationFilter.class).
addFilter(authFilter());
// #formatter:on
}
AccessDecisionManager accessDecisionManager() {
return new UnanimousBased(ImmutableList.of(serviceIdAwareVoter));
}
Filter preAuthFilter() throws Exception {
PreAuthenticationFilter preAuthFilter = new PreAuthenticationFilter(trustedPorts);
preAuthFilter.setAuthenticationManager(super.authenticationManager());
return preAuthFilter;
}
PreAuthenticatedAuthenticationProvider preAuthProvider() {
PreAuthenticatedAuthenticationProvider preAuthProvider = new PreAuthenticatedAuthenticationProvider();
UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> userDetailsServiceWrapper = new UserDetailsByNameServiceWrapper<>();
userDetailsServiceWrapper.setUserDetailsService(userDetailsService());
preAuthProvider.setPreAuthenticatedUserDetailsService(userDetailsServiceWrapper);
return preAuthProvider;
}
Filter authFilter() throws Exception {
AppIdAppKeyAuthenticationFilter authFilter = new AppIdAppKeyAuthenticationFilter(requestMatcher);
authFilter.setAuthenticationFailureHandler(new ExceptionStoringAuthenticationFailureHandler());
authFilter.setAuthenticationSuccessHandler(new UrlForwardingAuthenticationSuccessHandler());
authFilter.setAuthenticationManager(authenticationManagerBean());
return authFilter;
}
AuthenticationProvider authProvider() {
AppIdAppKeyAuthenticationProvider authProvider = new AppIdAppKeyAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
return authProvider;
}
Background:
After hours of debugging, I found out the root cause of the problem, which is really deep. Part of it is due to the fact that the Spring Security Java config is very poorly documented (for which I've opened a JIRA ticket). Theirs, as well as most online, examples are copy-pasted from XML config whereas the world has stopped using Spring XML config since probably 2010. Another part is due to the fact that REST service security is an afterthought in the Spring Security design and they don't have first-class support for protecting applications that don't have a login page, error page and the usual view layer. Last but not the least is that there were several (mis)configurations in my app which all came together and created a perfect storm of mind-boggling complexity.
Technical Context:
Using the authorizeRequests() configures a ExpressionUrlAuthorizationConfigurer which ultimately sets up a UnanimousBased AccessDecisionManager with a WebExpressionVoter. This AccessDecisionManager is called from the FilterSecurityInterceptor if the authentication succeeds (obviously there's no point in authorization if the user fails authentication in the first place).
Issues:
In my AbstractAnnotationConfigDispatcherServletInitializer subclass, which is basically the Java version of the web.xml, I'd configured filters not to intercept forward requests. I'm not going to go into the why here. For the interested, here's an example of how it's done:
private Dynamic registerCorsFilter(ServletContext ctx) {
Dynamic registration = ctx.addFilter("CorsFilter", CorsFilter.class);
registration.addMappingForUrlPatterns(getDispatcherTypes(), false, "/*");
return registration;
}
private EnumSet<DispatcherType> getDispatcherTypes() {
return (isAsyncSupported() ? EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.ASYNC)
: EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE));
}
If you take the DispatcherType.FORWARD out of the dispatcher types set, the registered filter doesn't kick in for that kind of request.
The authFilter shown in my question extended from UsernamePasswordAuthenticationFilter and had an AuthenticationSuccessHandler which forwarded the request to the destination URL after successful authentication. The default Spring implementation uses a SavedRequestAwareAuthenticationSuccessHandler which does a redirect to a webpage, which is unwanted in the context of a REST app.
Due to the above 2 reasons, the FilterSecurityInterceptor was not invoked after successful authentication which in turn, skipped the authorization chain causing the issue in my original post.
Fix:
Get rid of custom dispatcher configuration from web app initializer.
Don't do forward, or redirect, from AuthenticationSuccessHandler. Just let the request take it's natural course.
The custom voter has a vote method that looks as follows:
public int vote(Authentication authentication, FilterInvocation fi,
Collection<ConfigAttribute> attributes) {
}
The attributes in my case, as shown in my original post, is the string expression fullyAuthenticated. I didn't use it for authorization as I already knew the user to have been authenticated through the various filters in the authentication flow.
I hope this serves as documentation for all those souls who're suffering from the lack of documentation in Spring Security Java config.
Your config is saying that you are allowing access to fully authenticated users right here:
authorizeRequests().anyRequest().fullyAuthenticated().
You are telling Spring Security to grant access to any request as long as they are fully authenticated. What's you're goal? How are you trying to restrict access, by a role/permission? I'm guessing it's something that you are dictating inside your custom voter bean?
Usually the voter bean comes into play when you have conflicting security levels, for example, here you say that that all requests have full access but if your code hits a method with method level security like this (not a very real-world example):
#PreAuthrorize("permitNone")
public void someMethod{
...
}
You're going to have voters come into play because your java security config is saying "grant access to everyone" (voting yes to access) but this method annotation is "grant access to no one" (voting no to access).
In your case, there's nothing to vote on, you are granting everyone access.

How to programmatically add actions to application events?

In global.asax we have the possibility to implement methods that corresponds to an application event, for example Application_EndRequest, and add whatever code we want to these.
I'm developing an plugin that have the need to attach to some of these events, is there any way to programmatically push actions for these into the application flow somehow?
The goal is obviously to avoid the need for manually adding code in global.asax when using the plugin.
How to hook an HTTP Module into an MVC application
If I understand you correctly, you want to create an external library and "hook" it up to an MVC application's events.
1. Create a simple class library.
The first thing is to create a simple class library. We'll call it TestLib.
2. Create a new class called TestLibHttpModule.
The class implements IHttpModule. This grants it the Init() method. This method will be called when the module is initialised and it passes us the HttpApplication object that is initialising the module.
In our Init method, we'll attach a new EventHandler to the EndRequest event.
For now, our event handler method will simply throw an exception with a cheeky message.
namespace TestLib
{
public class TestLibHttpModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.EndRequest += new EventHandler(context_EndRequest);
}
private void context_EndRequest(object sender, EventArgs e)
{
// get the HttpApplication context
HttpApplication context = (HttpApplication)sender;
throw new NotImplementedException("At least it works.");
}
}
}
3. Point the library's build path to our MVC project.
Assuming you have an MVC project already set up nearby, perhaps called TestApp, point the build path of your library to be the bin folder of your MVC project. Now, every time we build the module, it'll be thrown into the MVC project.
4. Update MVC project to use the HttpModule.
The Web.config of an MVC application has a spot for specifying Http Modules. Under the system.Web element, add a new httpModules section (if it doesn't already exist).
<system.web>
[ ... ]
<httpModules>
<add name="TestLibModule" type="TestLib.TestLibHttpModule, TestLib" />
</httpModules>
</system.web>
5. Run the MVC application.

ASP .NET Application Life Cycle + Singleton Instance Life Time

Please considerer the following scenario :
I have created a full-web application by using the ASP .NET MVC 3 framework. Now my application is managed by a web server.
An HTTP request is received on the server-side of my application.
A class implementing the singleton design pattern is instanciated on server-side.
A response is sent to the browser.
Another HTTP request is received on the server-side of my application. Is the singleton instance used at step 2 still available on server-side ?
I read some information about the life cycle of an ASP .NET application on this page : http://msdn.microsoft.com/en-us/library/ms178473.aspx
But I am still not able to answer my question.
Thanks in advance for your future help
I have just made some tests under VS2010.
Here is the list of the main components of my project :
The Home controller containing an Index HttpGet action method.
The view resulting from the Index action method.
The SingletonTest class which implements the singleton design pattern.
Here is the code of the SingletonTest class :
public class SingletonTest
{
private int counter;
private static SingletonTest instance = null;
public int Counter
{
get
{
return counter;
}
}
public static SingletonTest Instance
{
get
{
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
private SingletonTest()
{
counter = 0;
}
public void IncrementCounter()
{
counter++;
}
}
Here is the code of the Index action method :
public ActionResult Index()
{
SingletonTest st = SingletonTest.Instance;
st.IncrementCounter();
return View();
}
Here is the code of the view :
#SingletonTest.Instance.Counter
Here the test scenario I have followed :
The IIS server has been automatically launched by VS2010.
I have requested the /Home/Index/ URL then the value 1 has been displayed.
I have requested the /Home/Index/ URL then the value 2 has been displayed.
...
This test shows that the SingletonTest instance made at Step 1 is available when processing the next requests.
I guess that a memory space is allocated to my web application on the server.
Then I have stopped the IIS server and I have followed my test scenario again.
I have got the same results as before : 1, 2, ....
Even though the singleton may persist across multiple requests you need to be careful for exactly the reasons of your second test - when IIS is restarted or the app pool is recycled everything will be lost.
Are you sure that you need a singleton instance?
If you're looking to persist some state across all requests it would be better to use an external storage such as a database.
What about multi-instances of the same application that IIS Will Create to process the concurrent requests?
I thinks singleton Object will not be the same if IIS Create multiple instances of the same application in high traffic situation

Resources