Struts 2 tomcat request/session contamination - spring

I am using Struts 2 v 2.3.16.3 with tomcat 6.
A user will click on an action which finds an object by id and the page displays it. I have encountered a sporadic bug where the user will all of a sudden get the id of another lookup from another user on another machine. So effectively they are both calling the same action but passing different id to the request, but both end up viewing the same id.
This is obviously disastrous, and the data is totally corrupted as both users think they are editing a different record. Any ideas how make sure session/request activity is kept secure to each session?
I am also using spring and am using the #Transactional annotation in my Service layer, which returns the objects from the DAO. Is there something I need to do with this annotation to make it secure for each session ?
I am using org.springframework.orm.hibernate3.HibernateTransactionManager

Classic Thread-UnSafe problem.
Since you nominated Spring, my first guess is that you have not specified the right scope for your action beans in Spring xml configuration.
Be sure you are using scope="prototype" because otherwise the default scope of Spring is Singleton, and you don't want a single(ton) instance of an Action, that would not be ThreadLocal (and hence ThreadSafe) anymore.
If it is not that, it could be something on an Interceptor (that, differently from an action, is not Thread Safe), or you are using something static (in your Business / DAO layer, or in the Action itself) that should be not.

Related

What can cause a LazyInitatializationException whereas Spring Open In View is enabled?

I am analysing a "classic" Hibernate error :
org.hibernate.LazyInitializationException : could not initialize proxy – no Session.
I am wondering how it could happen whereas the Spring Open In View mode is enabled?
If you have any documentation or knowledge on a possible reason, please share.
Thanks
Here are some feebacks on my context, and an example of what could cause LazyInitializationException event if Spring Open In View is enabled.
Context
My application is a REST API server developed with Spring Boot 2.5.3.
Spring Open In View is kept enabled by default.
A lot of Services are annotated with #Transactional methods.
Spring-data is used, and Entitymanager too, to create some native queries.
The error
One REST API request, that generates a lot requests to the database (both selections and insertions), fails with LazyInitializationException.
Debugging
By setting a breakpoint when LazyInitializationException is thrown, I discovered that the exception is thrown in org.hibernate.proxy.AbstractLazyInitializer#initialize, because the session is null. Then I discovered that the session is set to null, when the method EntityManager.clear is called. For any reason I don't know, this method was explicitely called in the code.
Fixing
So I just removed the call to EntityManager.clear, and the request works. I'm still wondering why previous developers wanted to clear the EntityManager, probably because they were confused with the transaction management.
Conclusion
Even in Spring Open In View is enabled, and as a result, event if a Hibernate Session is opened, calling EntityManager.clear unset the session to the entities loaded before. Then trying to access a Lazy Loaded field on those entities throws LazyInitializationException.
I hope this will help someone.
Here is the documentation from the latest hibernate version.
As you can see
Indicates an attempt to access not-yet-fetched data outside of a
session context. For example, when an uninitialized proxy or
collection is accessed after the session was closed.
Most probably somewhere you read some entity and then outside of a transaction you try to read some collection which was by default lazy loaded. So then another request needs to be done to database, but since you are out of transaction you receive this exception.
This usually occurs in case you load an entity without the annotation #Transactional or some other configuration to load it inside a transaction and then you give this to your controller to be returned to the user. Then the controller will use jackson or some other library to convert the entity object into a json and will try to read any field. At this point trying to read any lazy loaded collections from the entity, will result in this exception since the read will be outside of a transaction.

How Struts 2 will behave with Spring integration

Usually Struts 2 action instances will get create on the request. I mean per every request new action instance will get create. But if I integrate with Spring then there will be only one action instance will get create (I am not sure correct me if I am wrong).
So in this case what is if I have instance variables in the action class?
First user here will set that instance with some instance variables and second user may set there something. How it will behave at this time?
More clarification: Instance variable means, in Struts 2, action forms won't be there so, your action itself work as a form to get the request parameters. First user enters something and second user enters something and both are setting to one instance action.
If your actions are managed by Struts container, then Struts is creating them in the default scope.
If your actions are managed by Spring container, then you need to define the scope of the action beans, because Spring by default uses singleton scope.
If you don't want to share your action beans between user's requests you should define the corresponding scope.
You can use prototype scope, which means a new instance is returned by the Spring each time Struts is being built an action instance.

If we integrate struts2 with spring then who will maintain the action instances, spring container or struts 2 container

I am asking this question because of the following reasons:
Usually struts 2 action instances will get create on the request. I mean per every request new action instance will get create. But if I integrate with spring then there will be only one action instance will get create (I am not sure correct me if i am wrong). So in this case what is if I have instance variables in the action class. First user he will set that instance with some instance variables and second user may set the something.
How it will behave at this time.
More clarification: Instance variable means, in struts 2, action forms wont be there so, your action itself work as a form to get the request parameters. First user enters something and second user enters something and both are setting to one instance action.
By default Spring will create a singleton instance of your action class. In that case, depending on how your action classes are written there might be such a danger.
But you can also specify that a bean be created prototypically (scope="prototype") so that a new instance of the class is created with each request.
First, If you integrated struts2 with spring, normally, the action instances are managed by spring container! this is supported by struts2 spring plugin: https://struts.apache.org/release/2.3.x/docs/spring-plugin.html
Second, as the plugin doc mentioned, by default, the action bean's scope is request, this is up to the struts2, but you can change yuor action scope to other type,i.e. session,application,etc.

Stateless session bean maintaining state

I deployed a web application on the localhost GlassFish server. This application takes order information from user and stores it in a List type variable in a Stateless Session Bean.The list object is created in the constructor.
I open the order page and add multiple orders in it. When I open the show orders page in different tabs and different browsers, it displays all the order information bean correctly, as though the state is maintained in a Stateless Bean!
I think this behavior is wrong as each browser/tab should create different session with the server and new order information should be shown for each browser/tab. How can this behavior be explained?
Your use case is precisely what a stateful session bean is for, if you want your List object to be maintained across method invocations, and if you want each session to be assigned its own bean.
Stateless session beans are pooled and made available to any session. But your instance fields are not guaranteed to be cleared, so you can't depend on them being cleared. The behavior that you are seeing is not unexpected. Even if you were successful in creating separate sessions in multiple tabs, those sessions could very well have been (and apparently were) assigned the same session bean. That's because the associated method invocations occurred at different points in time. Now if the associated method invocations occurred simultaneously instead, then the platform would have assigned a different stateless bean to each invocation (session). In that case, you'd see different behavior.
See also;
conversational state of session beans
and
Stateless and Stateful Enterprise Java Beans
Never let what you can't do get in the way of what you can do.
Problem: Stateful Session Bean was not maintaining separate state per client. In the example I tried, I input orders from the JSP page, which were stored in a List in a Stateful Session Bean. When I called the same URL from a different browser (i.e. a different session), the list of orders input in the previous session were visible. The same EJB was getting referenced in both sessions. (Verified by sysouts)
It's like saying, the shopping cart of some other user was directly visible to me as if they were my orders!!
Solution: Used an HttpSessionListener and got the dependency of the Stateful EJB through JNDI, in sessionCreated(HttpSessionEvent se) method. Next, added the stateful EJB in an HttpSession and accessed the EJB through session in servlet.
Suggestions for using JNDI, instead of DI, for Stateful Session Bean and Adding EJB to HttpSession are given in the answer above. Don't know if it is the proper way to go, but it works!!

Spring annotation based configuration change

I have a spring MVC (3.1) web app using Hibernate that is all working correctly - today, I have tried to move the configuration completely over to annotation based config (only using xml for the security stuff that isnt yet supported by Spring in code config).
After some tuning I got the app starting with no errors and the home page loads correctly - however I am seeing some different behaviour with the Hibernate sessions - namely, I am getting the following error when loading a page that actually touches Hibernate entities:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.tmm.web.domain.Profile.connections, no session or session was closed
This is happening in the following scenario:
a request hits my #Controller and it loads the user Profile object
In the same method call (so we are not talking detached entities etc here) it tries to call profile.getConnections()
Profile.connections do not actually explicitly state a fetchtype, so should default to eager load (is my understanding?), but either way, the getConnections() call is directly after the loading of the profile - so would have thought even if it was being loaded lazily, it could easily just go back to the DB and load connections on demand.
//#Controller Code
Account viewedUser = accountService.loadAccountByUserName(userName);
model.put("viewedUserConnections", viewedUser.getUserProfile().getConnections());
//Profile Entity
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List connections = new ArrayList();
Now, I know about lazy loading etc, so it's not a question about that - like i mentioned all the Hibernate stuff was working correctly - so really my question is, what Spring configuration might affect this behaviour?
I can post my before and after xml vs annotation config, but am hoping that someone can point me in the direction of some config that I might have missed in switching.
Your assumptions are mainly wrong:
In the same method call (so we are not talking detached entities etc here)
The method is a method of the controller. In typical Spring applications, controllers are not transactional, but services are. So, unless you configured an "open session in view" filter or interceptor, the session is closed when the transactional service method returns, and the controller thus always uses detached entities
Profile.connections do not actually explicitly state a fetchtype, so should default to eager load
No. XxxToMany associations are lazy by default.
If the same code worked before the transition, my guess is that you had an open session in view filter or interceptor, and that you forgot it when migrating to annotations.

Resources