I have the following session scoped bean:
#ManagedBean
#Component
#Scope(proxyMode= ScopedProxyMode.TARGET_CLASS, value="session")
public class SessionData implements Serializable {}
and I store tomcat sessions in a database. The problem is that, when the application tries to deserialize a stored session, I receive the following error:
org.apache.catalina.session.PersistentManagerBase.swapIn Error deserializing Session EE913D2ACAD49EB55EDA657A54DFA2CB: {1}
java.lang.ClassNotFoundException: de.myproject.SessionData$$EnhancerBySpringCGLIB$$768b59b9
It seems that it serialized actually the whole Spring context, and obviously there is no such class de.myproject.SessionData$$EnhancerBySpringCGLIB$$768b59b9 after server restarts, so I receive the aforementioned exception.
Is there a way to avoid this, so that the session-scoped bean is serialized properly?
UPDATE: There is an issue regards this which marked as resolved without comments, however I still face it.
Please have a try:
using: import org.springframework.test.util.AopTestUtils;
Serializable readyToSerialize = AopTestUtils.getUltimateTargetObject(yourInstance);
before serialize it.
Note: this code is usefull to understund the problem, if this work, you have to analyze the project architecture and dependecies, to better accomplish for production code. First of all, why you need to serialize a ScopedProxyMode.TARGET_CLASS
Having a bean with a scope session doesn't mean that the bean is serializable and that it can be stored in a session.
As you can guess from the name of the class, a proxy class is generated at runtime with a different name at each startup. This explains why a problem occurs at deserialization.
I guess you try to add this SessionData as an attribute of the web session. You should not. Store your POJO data in the web session without using beans.
If you use the bean to inject database connections or similar objects, forget it. You can just use session scope beans for particular contexts which don't feet your requirements I guess.
i don't know well the your task, but in my opinion a data object like this should not be a spring bean because spring bean should be business logic bean, controller bean and so on and not session dto.
for this reason i consider thag you should try to think why you want store the data of your spring bean, and try to decopled the data that you want in http session, #sessionattribute of springmvc,from the business logic bean that shoud nor be session aware.
i hooe that this can help you to change your implementation stategy in order to find the solution of your problem
Related
We have a distributed web application implemented in Spring using Method Name Resolver. We are now migrating from Method Name Resolver to Spring Annotation (#Controller). Once we did that change, the big issue that we are facing is all the LAZY Initialization is not working. We started getting the below error:
2020-11-10 13:12:53,678 DEBUG o.s.web.servlet.DispatcherServlet:1182 Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'XXXXXXXX'; model is {XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-4.2.17.Final.jar:4.2.17.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286) ~[hibernate-core-4.2.17.Final.jar:4.2.17.Final]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) ~[hibernate-core-4.2.17.Final.jar:4.2.17.Final]
On Analysis, we are able to find that, with the Method Name Resolver, System was able to Lazy Initialize the object. While in the #Controller annotation, System throws the LazyInitializationError, since the Session object is getting closed and not able to lazily initialize.
What could be the solution to overcome this? how to maintain the session through with the #Controller similar to Method name resolver.
Any insights will be highly apprecitated. Thanks.
Sounds like you are using the "Open Session In View" (anti-)pattern. Look at Spring's OpenSessionInViewFilter.
Sounds like your controller method is asynchronous. If that's the case there would be no session as the call is done in a different thread and the session doesn't come along with it. This similar question explains that and has a solution.
Check if your controller method have an #Async annotation or something similar. If that's the case, it would definitely throw that error.
All.
I looked through web but didn't find applicable solution for me.
I need to access information, from globalsession scoped beans in HttpSessionListener , before the session is destroyed.
I found one solution, after inspecting session attributes, but it doesn't seems smooth:
MyBean myBean = httpSessionEvent.getSession().getAttribute("scopedTarget."+"myBeanImlp");
I also have singleton beans, containing session beans via target+proxy, but getting them in sessionDestroyed via ctx.getBean("mySingletonBean"), the reference to session bean is invalid inside them (session bean was already destroyed before sessionDestroyed call)
Does anybody know good and proper solution for such problem?
I'm thinking we need something like DestructionAwareBeanPostProcessor, but for session beans, where I could look through beans, ready for destroy and take an action I need.
You can try to define your session listener as a component and inject ApplicationContext (or required bean) and then access it. You can take a look at How to inject dependencies into HttpSessionListener, using Spring?
I was creating my first application using Apache wicket and am stuck on a problem. After the user logs in through the authentication method I have a new session which is created for that user. Now if I wanted to have data stored for just that user how would I use bean to implement that?
At the moment i created an interface and a class with get and set methods for the variables i wanted stored and created a bean such as <bean id="springApplicationContext" class="com..util.SpringApplicationContext"/> but what happens is the data gets overwritten but when i change the scope to "session" everyone has the same data in the bean still.
Thanks
The correct way is to use Session scoped Spring bean. There must be some error in your config if the data is visible to all users.
Using Spring has nothing to do with Wicket though!
Alternative approach is to store your data in Wicket's Session class.
Override MyApplication#newSession() method and return MySession class. The instance of MySession will be stored as an attribute in the HTTP session by Wicket. You can put any member fields inside MySession, e.g.;
public class MySession extends WebSession {
...
private MyBean myBean;
// setter and getter
...
}
Then in your Wicket code use it with: MySession.get().getMyBean().setSome(thing);
I've a doubt about Spring session bean. Let me try to explain what I need and what I did. I need to store on a session variable (in that case a Bean) the user_id so, when I need to create some record on db I can keep track of who did what.
To do that, for first, I created a bean and, second, I modified my application context in that way:
<bean id="UserInfo" class="net.agdev.session.UserInfo" scope="session">
<aop:scoped-proxy/>
</bean>
I read that using this :
ContextLoader.getCurrentWebApplicationContext().getBean("UserInfo");
is ppossible to access to the bean, but it's not yet clear how to fill that bean..
I tryed to read on Spring documentation how to initalize the bean and how to recall on my Class controller but I didn't find anything.
Could you suggest where to find an example or a tutorial to do that?
many thanks!
Andrea
You mean how to get the user_id into the session bean? Depending on your application this should probably happen right after the user "logged in". Meaning, if you for instance have a login webflow or controller, set the user_id in your session bean within that webflow or controller.
So if I understood your context correctly this has only very little to do with Spring itself and mostly with your application :-)
If you want other aspects of your bean initialized for instance from operations on other services you could set an init-method on the bean definition as detailed here.
By aspect programming like AspectJ. You have to set some trigger, for example after an user does something you have to read your bean and fill it the operation info that have been performed by the user.
You can use #annotation to define trigger or you can do it by spring xml file. I think you have to use an application context bean and not a session bean.
How can I inject dependencies into a deserialized bean?
Some of my Spring beans should be serialized during the render-response phase of our JSF application, and then deserialized at the beginning of the next request. Some of those beans have dependencies which are scoped to the request. If I configure the dependencies with the scoped proxy ("<aop:scoped-proxy>"), I can't serialize my dependent beans - the proxy isn't serializable.
So right now we do it by declaring the appropriate member variables of the serialized bean classes as transient, and then calling context.getAutowireCapableBeanFactory().configureBean(bean, name) just after deserializing the beans - but this sucks, because the bean's initializer is called again. (As for other dependencies that are in the same scope, are not transient, and are deserialized, I'm not even sure why they don't get overwritten by configureBean, but I don't think they are.)
What's better? Should I just get the bean definition, loop through it, find the dependencies that are scoped to the request, and then call getBean(name) on the context?
(BTW, I'm not sure it makes a difference, but we are using Spring kind of weirdly. We instantiate a new ClassPathXmlApplicationContext for each non-posted-back HTTP request, rather than a single WebApplicationContext. Upon postback, we deserialize the beans. So when I say "scoped to the request", I'm lying; these beans are actually singleton-scoped. I'd like to use the WebApplicationContext and the more sane scoping with it, but as far as I can tell, that's orthogonal to our problem at the moment.)
It makes all the difference - I've been using spring with JSF for quite a long time and hadn't had any serialization problems. The way to go is simply define the following in your faces-config.xml:
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
This integrates spring with JSF by providing spring beans (using the request and session spring scopes) to JSF pages.
So, I'd advice for changing your approach drastically so that you aren't bug with such problems in the future.