How to access lazy hibernate collections from jsp foreach in spring? - spring

I need to do forEach over lazy collection in jsp from spring controller. But this invocation crashes because session was closed in controller. I solve this by loding collection via:
Hibernate.initialize(obj.getCollection())
Is it possible to tune mvc to have hibernate session inside jsp?
Thanx

But this invocation crashes because session was closed in controller
I assume by crash you mean that you caused a LazyInitializationException by accessing a mapped collection after the session was closed.
Tuning mvc to have Hibernate session inside you JSP essentially means that you want to hold the session open for the duration of your HTTP request. This means that at render time you can still load the data you require.
You can achieve this using the open session in view pattern. In Spring this is implemented using the OpenSessionInViewFilter. See this answer for more detail on setting it up.
The alternative as you have already demonstrated it to load the data that you require within the transaction which loaded the parent. This is why Hibernate supports lazy loading. Sometimes you will need to load child entities and collections but sometimes you don't. By mapping it as lazy you can choose depending on the specific interaction.

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.

Hibernate.Initialize(x.getXX) with Spring and Junit

I use to hibernate before and I require an opensession to use Hibernate.Initialize()
but apparently for Spring, if OpenSessionInViewInterceptor is set up properly, it can use Hibernate.Initialize() anywhere.
My question is, what must I setup to use Hibernate.Initialize() in JUnit?
The whole point of OpenSessionInViewInterceptor is precisely to leave the Hibernate session open until the view has been rendered. This is why you can call Hibernate.initialize() "anywhere": Spring doesn't close the session until the request has been completely handled by the view.
So the answer is always the same: to be able to call this method, the session must be opened.

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.

Spring MVC Load page automatically

I have a quick question about how to use the Spring MVC.
I just started with it and i was used to have pages that always had their data loaded calling some controller that you setted ON THE PAGE.. calling some methods on controllers to load objects at the page at load time.
Is it the same in Spring MVC? Cuz what im seeing so far is that if you want to load a page with data, you always have to use a modelandview object which is loaded by a method that you must call before... and them you return the modelandview object with its destination to the view that you want.
What im trying to know is if there is a way that the page requests some data from the controller before it gets loaded... automatically...
Dont know if im making my self clear... thanks anyway for the help!
in spring mvc, using Controllers, it is always Request->Controller(populates model and chooses view)->Response.
you could use ajax to load data from any resource (even Controllers) or jsp:useBean to explicitly call some business logic or jsp:include to include a certain fragment or a custom jsp tag.
I also face the same situation.
check the below link for getting the data from the controller before view(JSP) load.
how to load the data into index page

Use cases of Request and Session scoped beans

Can someone list the practical use cases of Request , Session and Global-Session scoped beans ? In most of the projects I have been using singleton and prototype . I understand that request scope beans are instantiated per request and in session scoped beans , the beans are instantiated when a session gets started .
Please enlighten me on the practical aspects .
So far we're using request scoped beans for information that should only be valid on one page like the result of a search or the confirmation of an order. The bean will be valid until the page is reloaded.
A session scoped bean is useful to hold authentication information getting invalidated when the session is closed (by timeout or logout). You can store other user information that you don't want to reload with every request here as well. Or another use case for us is to store a conversation scope in the session scope which we use to persist information between requests but to that we can assign a custom timeout and invalidation condition.
Pretty much any information that needs to be available after the request needs to be stored in the session scope. The only exception we use is with a view scope that stores information in the page's view map to be available after ajax requests for example in wizzards.
Singleton scope however means, that the information exists only once per application so if two users request your page they will access the same information. This is usefull for controllers, as they shouldn't store data anyway.
A prototype scope is the same as initialitzing an object with new, as it is created every time you inject it. We don't use this at all at the moment.

Resources