I am using Turbine 2.3.2 with Hibernate 3. My problem is that the Hibernate session is not active when my (Velocity 1.6.4) template is executed, and I am accessing data from the database for which Hibernate needs lazy initialization. Therefore I get a LazyInitializationException - no Session error.
Since I want my Hibernate session to be alive when a velocity template executes I would like to have a class to execute after and before the Velocity template. This way I could open and close my Hibernate session at one place. (Disabling lazy initialization in Hibernate is not an option for me). Are there any possibilities related or not to Turbine to write a kind of listener or a filter (I am not sure how to call it) that would execute right before and after a Velocity template has been executed? Or maybe the servlet container could filter requests .... What option would you recommend?
Try looking at the Spring OpenSessionInViewFilter. It opens the Hibernate Session and assigns it to a threadlocal. That way, you can pick it up in your data access layer and use it.
Open Session in View is not a clean solution. You can configure in your criteria (if you use it) which association paths Hibernate has to eagerly fetch.
If you use HQL, just "touch" the association while the session is still open.
Your question seems to be about the (in)famous Open Session In View (OSIV) pattern.
Have a look at the Open Session in View page on the JBoss wiki, you'll find a filter based implementation (non Spring based).
Related
We have a web application that is using Spring Boot (1.5) with Vaadin (7.7), and is using Apache Shiro (1.4.0) for security.
The application is configured to use DefaultWebSessionManager to let Shiro handle the session management instead of the servlet container.
We are using the official Vaadin Spring integration (1.2.0), and after some configuration it all works as intended. The VaadinSession contains a wrapped ShiroHttpSession internally.
We want to achieve session replication, by configuring Shiro to use a SessionDAO that is backed by an external Cache, which means the sessions get (de)serialized.
As soon as we start using this SessionDAO, Vaadin will crash and stop working. When replace the external cache by an in memory Map for the sake of debugging, it works again.
It seems this is caused by the SpringVaadinServlet, as it stores the VaadinSession as a session attribute. VaadinSession is Serializable and the Javadoc shows:
Everything inside a VaadinSession should be serializable to ensure
compatibility with schemes using serialization for persisting the
session data.
Inside the VaadinSession are some fields that are not Serializable, for example a Lock and the wrapped http session inside is also marked as transient.
Because of this, the session that Vaadin uses will be broken as soon as it is distributed, resulting in a lot of crashes.
So it turns out the VaadinSession is not actually usable in session replication? Why is this and how can we work around this?
Note: we also have a version of the application that is using Vaadin 8, and here the same thing happens. It seems that the issue is caused by the Vaadin Spring integration.
Inside the VaadinSession are some fields that are not Serializable, for example a Lock and the wrapped http session inside is also marked as transient.
The wrapped http session is not part of Vaadin session, it is the the http session. Thus it is transient. The same can be said about Lock, whose instance is stored in the http session.
In order to implement session serialization correctly, you need to hook into serialization events and update the transients when session is being deserialized. VaadinSession should be loaded with VaadinService#loadSession, which calls VaadinSession#refreshTransients.
Everything inside a VaadinSession should be serializable to ensure compatibility with schemes using serialization for persisting the session data.
This statement does not imply that you can serialize your application out of the box. It just means, that in case your application is serializable as well, with careful engineering you can serialize the whole thing.
For example Vaadin is not updating the session attribute in each possible occasion for performance reasons. There is method VaadinService#storeSession for that. So you need to either override right method or setup request filter. E.g. you could do this at VaadinService#endRequest.
Note, you need to use sticky sessions in order to get this to work with moderate amount of effort. If your session is de-serialized in different machine, the re-entrant lock instances wont be valid. If you would like to be able to de-serialize the session in different machine, it would require that your infrastructure can offer distributed lock that you can use instead of re-entrant Lock of Java and override Vaadin's getSessionLock and setSessionLock methods to use that.
Valuable sources of further info:
Generic notes from Vaadin's CTO
https://vaadin.com/blog/session-replication-in-the-world-of-vaadin
Testimonial from developer who did it with one stack
https://vaadin.com/learn/tutorials/hazelcast
Thoughts from another senior developer
https://mvysny.github.io/vaadin-14-session-replication/
I see with the Spring Boot you don't need to open and close the hibernate session.
But for the understanding purpose how it is working internally, On which layer it is opening the hibernate session and when it is closing.
I created one POC.
I have one Spring boot application it has two Entity One is Customer and other is Address and there is one to Many relation between Customer and Address.
And I have one two Apis one is adding record and other is fetching all the records.
These APis are there in the CustomerEndpoint and it is annotated with
#RestController
#RequestMapping(value="/customer").
And also created CustomerRepository which extends CrudRepository for saving and fetching the Customer records.
So as per my understanding while fetching the Customer using CustomerRepository inside CustomerEndpointclass should throw LazyInitialization error when we will say customer.getAddress(as its fetchtype is LAZY).
But it is not throwing any error, it is working properly.
I was thinking the hibernate session not be there in the CustomerEndpoint class.
Can anyone help me how this Hibernate session is maintained by Spring boot?
As everybody is thinking it as a duplicate of another question but my question is not top of their explanation as according to them session is valid till the Repository so according to that i should get LazyInitialization exception while saying customer.getAddress inside CustomerEndpoint as it is not a Repository but i am not getting any Exception
First of all it is not a good practice to use Repository layer in your Presentation layer.
OSIV (Open Session in View) is enabled by default in Spring Boot, and OSIV is really a bad idea from a performance and scalability perspective.
Because of this you are not getting the exception and able to work in your presentation layer.
Check by putting the follwoings in your application.properties file
spring.jpa.open-in-view=false
You can refer OSIV AntiPattern for more details
I think, It still works If your customer.getAddress is inside the transaction
I'm working on a system where things can and will change outside of JPA, so I need a new session for every request, but my JavaEE app deployed into TomEE persists sessions between requests, resulting in entities that are cached when they've since been updated somewhere outside of the app.
I attempted to create a cfg.xml and get the session factory that way, but was just met with exceptions. I also attempted to unwrap the entity manager class to get the factory that way, but got an exception saying the class couldn't be unwrapped. I feel like this may be something to do with how TomEE and Hibernate interact. Are there issues with my current setup. Or am I trying to implement session-per-request wrong,
The problem that you have is not with the session, it is related with the session cache, so what you can do is invalidate your session cache:
session.refresh(entity)
then hibernate will compare database data and entity object data if there are differences then it will execute again an sql query.
session.clear()
will remove everything from the session cache, so you will not get old data.
In Spring applications (that use Spring's declarative transaction management) when using JPA/Hibernate, when a transaction is first started within a request, Hibernate session is created and a database connection will be obtained from a datasource in order to execute this first transaction. Any subsequent transaction within the request will reuse the session and the connection. Is there a way to force Hibernate (or Spring's transaction management system) to obtain a new connection from the datasource for the subsequent transaction?
Background info and what I am trying to achieve
I'm using a custom implementation of AbstractRoutingDatasource to route database requests between a master and a replicated slave (read-only) database. I've created custom annotation with datasource routing information and AOP Aspect that intercepts the methods annotated with my custom annotation in order create a framework where one could add additional datasource routing annotation in addition to #Transactional in order to select a datasource (master or slave) on which the transaction should be executed. Aspect informs the routing datasource that next connection requested within current thread should go to a specific datasource (as defined in the annotation) before transaction starts. The problem is this only works on the first transaction because Hibernate caches connection and does not request new one for next transaction.
You will need to implement a custom ConnectionProvider. Hibernate will by default come with DriverManagerConnectionProviderImpl. However, most people end up using c3p0 (many without even knowing it), proxool, Hikari, or some other implementation.
All of these (including Hibernate's default) will cache connections (it is their primary purpose). You will probably need to create a connection provider which has a reference to two other connection providers (one per data source). The inner connection providers can be c3p0 or whatever other implementation you want to use.
This article gives a good basic overview of the concept (as well as describing what property to set to supply your own).
Open at the begin of the http request and close at the end and each http request is treated in a separated thread?
Maybe saving all session in a HashMap and access it statically?
Any information which explains how hibernate sessions work (or what they really are) are helpful.
If at the beginning of request/end of request means the http Request, then this is usually done by a servlet filter which opens/closes session for you. This design pattern is called OpenSessionInView (Filter). You can get details here.
This pattern is useful only if you application is rendered in same JVM where Hibernate Session exists. If Your data access tier resides on different JVM than your view rendering tier, you will have to (eagerly) fetch all the required model beans before dispatching the request for rendering of the view .
If you are using spring (or EJB3), you can get the Session (EntityManager) injected in your Data Access classes so you wont need to manually work on Opening and closing the session.
Ideally, you should not need to manually open/close session/transaction (because it leaves chances of missing out a session.close() or tx.commit() and the likes). Instead use the container provided JPA entitymanager or use spring to manage it for you.
There are multiple patterns of using the session, but the most common and usually the proper one is to open and close it on each request (=thread=unit of work)
In a JavaEE environment you would normally make use of JPA. So use hibernate through the EntityManager, which can be injected in components (like EJBs or cdi managed beans) with #PersistenceContext
usually a session is open when accessing data store is needed (e.g. transaction begins). When to close it has different patterns and approaches. you could keep the session open in views (jsps). but you don't have to do that.
e.g. one of our project doesn't allow to use opensessionInView filter. So the session was closed after transaction ended. All data (Value objects basically) need to send to view were loaded before dispatching.