#Async Spring gets recalled for every request of different sessions - java

I have a spring #Async annotated method in a bean, then in the controller I call that bean's method on a user request, and I do it this way so I can get a progress back from that bean, and it works fine for that.
But when I open it from another session the controller appears to restart the method and the progress is back again to the start point.
How to do this correctly, I have a progress count number as a field in the bean. and I increment it in the #Async method then get back via AJAX request to in a controller that retrieves it from the bean.
but its like the controller have only one bean injected to it. or there is only one controller for the whole app, whats is wrong here ?
EDIT
I tested in with opening two different browsers and running the task but it gets reloaded in both.

Apparently Spring Controllers are singletons per web app (and when you think about it they should be), so they are not thread safe if you have a component wired to it.
Meaning that suppose you have bean A wired to controller AC if two users send requests to an AC method that uses bean A at the same time, you'll have wrong values for both or you'll have bean reconstructing at each call, so if user1 starts the task and after a while before the task is finished user2 comes into play and wants to start it too, then user1' values will reset and so on.
To avoid this I found that you should make beans that are wired to controllers annotated with Session Scoped using annotations or xml.
in my case I used
#Scope("session")
You should never annotate the controller, as it won't work and if it does it will give weird behavior.
you should also (if using annotations like me) add scoped-proxy="targetClass" in your <context:component-scan /> element

Related

AspectJ with Spring : intercepted methods lose their parameters annotations

I recently added AOP with aspectJ and spring-aop to my existent spring project. The goal was to actually intercept controller calls to modify the response they send back, in order to bind some values to this response I didn't want to add manually to each and everyone of my controllers, for example the expiration date of the actual token used by the end-user (which I wasn't even able to showcase within my controller in any case). I actually managed to get it working until I started my unit tests :
In my unit tests I call directly my controller methods using Reflection feature from java, then replicate usual process (calling the filter chain, pre handler and post handlers, and the controller method itself which is first manually validated using spring validator when annotation #Valid is present on one of my parameters. All this process works fine and gets executed properly). The problem is that now that the controller method is intercepted by spring-aop, it's mentionned as coming from the proxy controller created, and all of my parameters annotations disapear. Here is a controller example :
#Override
public ResponseEntity<Object> editPassword(#Valid #RequestBody PasswordEditForm passwordEditForm, HttpServletRequest request) {
return factorizedUserBaseController.editPassword(passwordEditForm, request, User.class);
}
the parameter PasswordEditForm has the annotation #Valid so in my test cases it was first validated before any other step, but now as I double checked it, the #Valid annotation is not present on the proxy method, and therefore the parameter doesn't get validated, any clue for how to fix this and make my parameters annotation still understandable from my test point of view?
Note : when running the spring through mvn spring-boot:run, parameters with #Valid annotation gets correctly validated and then goes to my error handler method properly.
Problem Solved : from several other stackoverflow posts I understand that CGLIB (aop proxy lib used by Spring) doesn't support annotations. ( see Retain annotations on CGLIB proxies?). But my problem wasn't here, I was literally sure I was finding the method using the controller class itself (the one I coded) but what I was wrong about is that I was giving the controller instance as a parameter to some other parts of my code which in turn would use this controller class to find the method which of course wasn't working because thanks to Spring proxies, it wasn't anymore my controller itself but a proxy class extending my own controller class. Instead, I just had to replace :
Class<?> controllerClass = controllerInstanciationContainer
.getController()
.getClass();
with
Class<?> controllerClass = controllerInstanciationContainer
.getController()
.getClass()
.getSuperclass();

How does spring come to know about the new request or session?

I know in a web application, for every request it gets, spring creates a new instance of the bean in ints container.
I want to know how does spring differentiate between the requests and create new instances of bean accordingly?
This work is done by Request context listener where it takes the decision of instantiating beans based on incoming http request and discarding them once their life cycle is over. Session , Request scope beans are only relevant if the application context web aware, if otherwise IllegalStateException will be thrown.
And also refer -
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-scopes-other

Does Spring generate code for validaiton?

lately I was trying to understand how spring processes #Valid annotation. For example look at the following controller's method:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public ModelAndView createEmployee(#Valid EmployeeForm form, Errors errors) {
if(errors.hasErrors()) {
//validation errors
}
//method code
}
I am struggling to understand how errors instance is getting populated with validation errors in real-time. Does Spring, during compilation of the controller, inject code responsible for validation at the beginning of the createEmployee method? If so how this code would look?
I really tried to find an example of how this validation is performed in real life but it's just impossible. Help me please.
Everything happens at runtime. See the reference for more details on doing validation or this post for extra explanations.
Basically this is part of how Spring works internally. When you start your application Spring registers some beans, bean processors, can scan your classpath for annotated classes, registers those found annotated classes, builds proxies for some of them etc and uses all of them to build a context.
When handling a request, the request is handled on some predetermined execution path that starts with the DispatcherServlet, picking up other beans from the context as needed to handle the request (like validation for example) then forwarding to you controller in the createEmployee (which was registered as startup because Spring found your #RequestMapping annotations on your controller). When you return from the method the flow continues by building a model, selecting a view to display and then generating the response to the client.
For your example, Spring basically finds the #Valid annotation, looks for an already configured validator (configured by you or by a provided implementation for e.g. JSR-303), runs the validator and stores the validation result inside the Errors object. It does this when the request is processed, as mentioned above, it does not generate code.
If your question is to know exactly how Spring does this, in all it's details, you could take the Spring source code and have a look/debug it.

Returning a Stateful Java Bean from a Stateless Bean?

I want to handle a login scenario as follows:
Client connects to a Stateless Java Bean (SLJB) and tries to login;
If login succeeds, the SLJB returns to the user a Stateful Java Bean (SFJB), so that the client can continue using the application.
I am currently doing the second step as:
return new StatefulBean(some params);
Is this the right way to do it? It does not seem to me as I get the exception:
Class org.eclipse.persistence.internal.jpa.EntityManagerImpl is not Serializable
when running my application, and I think it is related to the described method.
What would be the correct way to return a reference to the SFJB from the SLJB to the client?
First of all, this is completely wrong:
new StatefulBean(some params)
EJB container is responsible for creating and destroying instances of beans, you should never create them manually.
In your scenario I would reverse the flow: the client connects to the stateful bean which might stateless session bean as a helper. No need to pass beans around, client always uses the same bean.
As Tomasz mentions, you probably need to rethink your flow.
That said, you can get a hold of a new stateful instance by doing a JNDI lookup, using the portable JNDI name that us assigned to each bean at startup.

How to ensure the user is logged into the system at the controller level?

I'm using spring MVC, and I have a custom authentication/security system that I had to build.
NOTE: I know of spring security, but my requirements were to do this in a custom way so please not looking for suggestions about using spring's security modules.
When the user logs into the system, it creates a session cookie. When the user visits a page, a interceptor looks for the existance of that cookie, and looks up the session guid in mysql and if it is present that it loads some data and stores it in the request's attributes.
Now for pages where the user has to be logged in, how can I restrict access at the controller level?
I could do this in an interceptor:
if url.contains("projects/") ...
If I want to restrict access to only logged in users in the ProjectController, but this isn't really something I want to do.
But I am looking for maybe a annotation I could add at the controller level, or maybe somehow create a BaseController that all controllers that require a loggedin user will inherit from.
What are my options for something like this?
In ASP.NET, I created a baseController, and the controller has an event cycle, and in the before-action fired event I checked to see if the user was logged in.
So looking for suggestions for spring mvc?
Update
For example, in ASP.NET you have 2 methods, 1 that fires just before the controller's action method and one that fires after:
Controller.OnActionExecuting
Controller.OnActionExecuted
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onactionexecuting.aspx
So in the OnActionExecuting, I can actually see exactly which controller I am in, and which action is about to get called in a programatic way, not by looking at the request URL and then doing string compares to see if it is a particular controller etc.
So in this event, I can simply check for things in cookies or in my request attributes etc.
This is a much more stable way to do it, does spring have anything similiar?
If you need this at the controller level, you could:
1) declare a java.security.Principal parameter in the controller method signature, which Spring will fill in with a Principal object, or
2) implement a PermissionEvaluator, which can be called on a controller method using the #PreAuthorize annotation, and which would have access to a Authentication object.
Similar to what you did in ASP.NET, you can take advantage of OncePerRequestFilter and chain it to the chain of filters you have in web.xml or Spring application context. The good point about this filter is that it's independent of the MVC approach that you take and no need for a "base controller".
On the other hand, if you're also using Spring security module, you can use a custom filter configuration and place it in the correct place that it should be.
If the check fails, then you'd probably want to raise exceptions or redirect user to the correct navigation.
Based on the last comment, you can also use mapped interceptors:
<mvc:interceptors>
<mvc:interceptor>
<mapping path="/myFirstPath/*"/>
<mapping path="/mySecondPath/*"/>
<bean class="org.example.SomeInteceptor" />
</mvc:interceptor>
<mvc:interceptor>another one</mvc:interceptor>
</mvc:interceptors>

Categories