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.
Related
I have a problem with spring request scope. It works fine in 99.9% of my calls, because there is almost always a web request available. Unfortunately a few things are done via #Async and here things get tricky.
My desired solution is to replace the bean using #Scope(value = "request" proxyMode = ScopedProxyMode.TARGET_CLASS) with basically the same implementation but using a prototype scope.
I could have both beans inheriting from the same parent and then add the different scopes.
However I have no idea how to make this work. As we have the same Bean, I will get an error that the bean is not unique.
The logic would be to try to create the primary request scope bean and on failure catch the BeanCreationException and replace it with the prototype implementation.
I cannot find a solution with #Primary or named beans here, because in principle, the context of the calling method (somewhere higher in the callstack, i.e. Async or not) decides, whether the bean will be of type request or prototype.
Unfortunately I have not found any real solution for this so far.
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
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 have an annotation driven spring mvc project templated after the JBoss web mvc sample. (Spring, Hibernate, JPA 2.0)
I have a utility package where I want to put reusable classes for obviously utility functions.
Specifically I have a LogonUtilities class where I want to query a database to get information.
I autowire my DAO there but when I debug the DAO is always null and fails with that exception.
I have read and tried many things - I know I've probably come across the solution already - but missed something and moved on and tried something else. I probably am not googling the correct terms since annotations are new to me. (I've worked with spring & hibernate for years - but with xml)
I've added this to my applicationContext.xml
<context:component-scan base-package="util"/>
which I thought was all I needed to do.
This is what I currently have in my LogonUtility class - but it doesn't work, keywordDao is always null. I think I could probably get it to work if I wired the DAO to a LogonUtility bean in the applicationContext (the old way) but I would think there's a better way to do it with annotations.
#Service
public class LogonUtilities {
#Autowired private KeywordDao keywordDao;
My application isn't brand new, I probably have ten working controllers and over a dozen working DAOs at this point, including a Keyword Controller and DAO that already does CRUD operations, so I don't think my setups with that stuff is incorrect.
I just have some code I want to reuse that pulls from a database.
Thanks in advance.
*in my code it's actually called "TrainingKeyword" not "Keyword"
This is the nullPointer error because the DAO is null
10:52:07,673 ERROR [io.undertow.request] (default task-1) UT005023: Exception handling request to /Training/Home: java.lang.NullPointerException
at util.LogonUtilities.trainingOffices(LogonUtilities.java:59) [classes:]
at filter.LogonFilter.doFilter(LogonFilter.java:100) [classes:]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]
This is the code where the error happens
//Set TrainingOffices
List<TrainingKeyword> kList1 = keywordDao.getAllTrainingKeywordsByName("Level 200 Training Offices");
I solved my problem by listening to your ideas and with help from this question.
JPA is not Autowiring
Basically I had already tried everything that worked - but never all together. I was constantly making edits to my code trying to get it to work and always had either something missing or something bad. For anyone with a similar question here are the steps
In my LogonFilter I added
#Autowired private LogonUtilities lu
In my LogonUtilites class I added
#Autowired private TrainingKeywordDao keywordDao;
There was no need to add the LogonUtility bean to my applicationContext - I took it out and it still works.
Thank you to all that helped - your ideas kept making me rethink what I was doing.
You are trying to do a #Autowired private KeywordDao keywordDao; but you not getting any autowiring error. but #Autowired is by default #Autowired(required=true) meaning that these dependencies are by default mandatory, and throw an error if not met.
No autowiring error is received, so the conclusion is that it seems that this class is not being scanned for autowiring at all.
If it would then an error would be thrown. Try to see why the class is not being autowired, here are some common causes:
the package where the class is placed is not being scanned, is the name of the classes package util or a subpackage?
The scanning is being done in the wrong spring context. Most Spring applications have two contexts, one root context and one servlet dispatcher context. Try to move the component scan <context:component-scan base-package="util"/> from one context to the other, by copying this configuration line from one XML file to the other.
Make sure that base-package is the fully qualified path of the service from the root on, and make sure that KeywordDao is annotated with #Repository.
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.