Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

How do I assign an Interceptor after a SessionFactory has been created?

 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,

We have a code base that uses the Hibernate implementation of JPA but that has to date only utilized the basic facilities of JPA. In particular that means we have used EntityManager instead of SessionBuilder. This approach was taken because (until now) we only needed the base JPA facilities and saw no benefit to using Hibernate constructs. However, we now need the facilities that a Hibernate Interceptor can provide and are looking for some way to implement this.

We see how to obtain the Session and SessionFactory from an existing EntityManager but cannot see how to "add" an Interceptor to an existing Session(Builder). We can find numerous examples showing how to configure a SessionFactory so that upon construction of the SessionFactory it will start up with an Interceptor but how can an Interceptor be added if (through the creation of an EntiryManager) the SessionFactor already exists?

Thank you.
 
H Paul
Ranch Hand
Posts: 471
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is this what you're looking for?

http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#events

Chapter 14. Interceptors and events

There are two kinds of inteceptors: Session-scoped and SessionFactory-scoped.
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi H Paul,

Thanks but (I think) we understand the basic creation and use of an Interceptor. My problem is that we have a large code base that has used the JPA API (EntityManager) not the Hibernate API (SessionFactory) so we can't just "hook in"/register the Interceptor at the time the Hibernate Session is created. We can obtain the Hibernate Session from the EntityManager on the em is created so my question is how to we "hook in"/register the Interceptor with Hibernate AFTER the Hibernate Session has been created.

Any ideas?

Thanks.
 
H Paul
Ranch Hand
Posts: 471
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Instead of getting session from entityManager




You can get session and set interceptor as below:

 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It looks like we may be getting close. The immediate problem with using your suggested code "as is" is that our code uses injection to get the EM instantiated. We have a class (JPAFacade) that handles all of the interface issues with JPA - here are the (I think relevant) bits of code:


@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class JPAFacade {
..
@PersistenceContext(unitName=UtilitiesModel.JPA_PERSISTENCE_UNIT)
private EntityManager em;
...
}

then we use em within this class to handle all the CRUD.

I don't know how to make the leap from what you propose to the injection approach currently used (I inherited this code and am scrambling to get up to speed on Hibernate!). Can you adapt your approach to work with injection?

Thanks again for your help!
 
H Paul
Ranch Hand
Posts: 471
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
http://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceUnit.html
Expresses a dependency on an EntityManagerFactory and its associated persistence unit.


Try this:




Read Detail explanation between Container-Managed Entity Managers and Application-Managed Entity Managers
http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

Container-Managed Entity Managers
@PersistenceContext
EntityManager em;

Application-Managed Entity Managers
@PersistenceUnit
EntityManagerFactory emf;
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi H Paul,

Thanks for the help with the EntityManagerFactory annotation. After adding the annotation I tried your code :

// Don't use the following since the entityManagerFactory is injected!
//EntityManagerFactory entityManagerFactory= Persistence.createEntityManagerFactory( "YOUR PU" );
SessionFactory sessionFactory= entityManagerFactory.unwrap(SessionFactory.class);
org.hibernate.Session session = sessionFactory.withOptions().interceptor(new MyInterceptor()).openSession();

This generated an error on unwrap (it's not defined for EntityManagerFactory ). I changed this to be called off of EntityManager as follows:
SessionFactory sessionFactory= entityManager.unwrap(SessionFactory.class);
but upon execution this yields:

Hibernate cannot unwrap interface org.hibernate.SessionFactory.

In case it is helpful, here is the persistence.xml:


(Note above that the Interceptor Property is triggering a Class Not Found. This is an "upcoming" problem but I don't think that not including that <property> is affecting the current problem.

Can you help me determine what's wrong here?

Again, thanks for your ongoing help.

 
H Paul
Ranch Hand
Posts: 471
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. This is what I have in mind:



2. If I read you correctly, the code in point 1 generate an error. What exception? check log.

3. What hibernate version do you use? I used the latest 4.3.5 Final (hibernate-entitymanager-4.3.5)
 
H Paul
Ranch Hand
Posts: 471
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you experiment with this?

 
H Paul
Ranch Hand
Posts: 471
4
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. Taking from (EE6 compliant)

https://docs.jboss.org/author/display/AS7/JPA+Reference+Guide

section Native Hibernate use

section Injection of Hibernate Session and SessionFactoryInjection of Hibernate Session and SessionFactory
You can inject a org.hibernate.Session and org.hibernate.SessionFactory directly, just as you can do with EntityManagers and EntityManagerFactorys.




2. Taking from

http://docs.jboss.org/ejb3/docs/tutorial/1.0.7/html/Hibernate_Session_In_EJB3.html

Injecting Hibernate Session and SessionFactory :
You can inject a org.hibernate.Session and org.hibernate.SessionFactory directly into your EJBs just as you can do with EntityManagers and EntityManagerFactorys. The behavior of a Session is just the same as the behavior of an injected EntityManager. The application server controls the lifecycle of the Session so that you do not have to open, flush, or close the session. Extended persistence contexts also work with injected Hibernate Sessions.



3. For your JBoss EJB container, check its version and its documentation to see its feasibility.
And try for point 1 and 2.
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi H Paul,

I appreciate the post you made (sorry about the slowness of my responses - I am having to work several unrelated issues in our code and have to cycle between them).

I implemented you suggestion of:

and I no longer have any errors for that code.

It is my understanding that I also need to "register" the Interceptor in persistence.xml and here is that is done (the full xml is in an earlier post)


Finally, here is HibernateInterceptor:


Unfortunately, I now get the following error when I deploy (out of Eclipse - Kepler) to JBoss 7:


Do I need to annotate HibernateInterceptor in some fashion? Can you see what is wrong here? (It feels like we are almost there!)

As always, thanks for the continued help.
 
H Paul
Ranch Hand
Posts: 471
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Read Key Differences between below Point 1 and 2. Point 3 is what you need.

1.

Look at the posted September 6, 2014 1:15:10 PM PDT


That's for Native Hibernate Api, you extend





2.

For JPA Interceptor, you need to implement org.hibernate.Interceptor. <<<<<<<<< THIS IS WHAT YOU NEED TO IMPLEMENT. See below doc note.




Read this doc http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/configuration.html

There are two kinds of inteceptors: Session-scoped and SessionFactory-scoped.

hibernate.ejb.interceptor

An optional Hibernate interceptor. The interceptor instance is shared by all Session instances. T
his interceptor has to implement org.hibernate.Interceptor and have a no-arg constructor. T
his property can not be combined with hibernate.ejb.interceptor.session_scoped.

hibernate.ejb.interceptor.session_scoped

An optional Hibernate interceptor.
The interceptor instance is specific to a given Session instance (and hence can be non thread-safe).
This interceptor has to implement org.hibernate.Interceptor and have a no-arg constructor.
This property can not be combined with hibernate.ejb.interceptor.



3. After reading again, this is what you need:



with Yours: <property name="hibernate.ejb.interceptor" value="example.interceptor.JPAInterceptor"/> // for example

use em to work and you don't need to go thru an intermediate Session

for example: entityManager.persist( anyObject );

The interceptor configured on Point 2 will be called.
 
H Paul
Ranch Hand
Posts: 471
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In addition to above thread:

1. I just did 1 quick experiment and found that you can extends EmptyInterceptor




2. If you test with the JPAInterceptor implements Interceptor
you will get an exception



Googled:
http://forum.spring.io/forum/spring-projects/data/13059-hibernate-spring-transaction-flushing-issue
It turns out this was due to a change in the default behaviour of the Entity Interceptor in 3.x. Prior to 3.x, the on prepared statement could return null in the implementation.
However, in 3.x+ there is an assertion check which is what I was experiencing.
This was easily solved by extending one of the new helper base classes rather than implementing the interface directly.



3. If you test with NativeHibernateApiInterceptor extends EmptyInterceptor

it will be OK.
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi H Paul,

Thanks for all of the info in your posts. Unfortunately I am missing what you feel I am doing wrong because I think I am doing what you suggest.

1) I am implementing from EmptyHibernator as:

2) I am annotating as you suggest:

3) I am using the <property> in persistence.xml that you suggest:


The problem is that upon deployment to JBoss 7 I get:


Can you see why this class is not being found? (Is there an annotation on HibernateInterceptor I am missing?)

Thank you!

 
H Paul
Ranch Hand
Posts: 471
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. Already read what you wrote.
2. Can you post the full exception if you have it?
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here it is. (I included a little bit of console output prior to the error to provide a little context:



The error I have telling you about is at line 30.

If I remove <property name="hibernate.ejb.interceptor" value="com.MyCom.model.HibernateInterceptor"/> from persistence.xml all of my JPA/Hiberbate actions are working. I can fetch and insert so I think that my Persistence Unit is being managed correctly by JBoss and it seems that Hibernate is working properly. It's just when I include the <property> that we have a problem.

Thank you.
 
H Paul
Ranch Hand
Posts: 471
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
See below point 1,2,3:



1.
I repeat There is NO issue with <property name="hibernate.ejb.interceptor"

Look at the source: Your Version is 4.1.0.Final




I tested with and WORKED fine because I have the java class concepts.interceptor.NativeHibernateApiInterceptor

<property name="hibernate.ejb.interceptor" value="concepts.interceptor.NativeHibernateApiInterceptor"/>



2.
I also did 1 experiment to see. I just put a NON EXISTING class concepts.interceptor.DoesNotExistInterceptor.java


<property name="hibernate.ejb.interceptor" value="concepts.interceptor.DoesNotExistInterceptor"/>

I also got the same exception like Yours.



3. Check to see if your Interceptor java class exist.
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi H Paul,

GOT IT!!! The problem with the <property> was that there was a trailing "." on the value! That is, I had <property name="hibernate.ejb.interceptor" value="com.MyCom.model.HibernateInterceptor."/> My keystrokes for copying this from the file somehow missed that last dot and that is why it wasn't shown in my posting!

I apologize for that mistake. The interceptor is now running just fine.

Let me take a moment to say that I REALLY appreciate all of the time you took and for staying with this problem till it was solved. I've been in a lot of support forums over many years and you are one of the very few people who have shown such commitment to helping someone out. (Why can't I "award" you points of some type on this site?)

May I ask you a final question? I have been scrambling to get up to speed on Hibernate and have been reading a lot of blog posts and forum posts but it has all been rather haphazard. You have obviously mastered Hibernate so is there a book or other resource (in addition to the formal docs) you would recommend for me to read?

Again, thank you very much for all of your time and help!

 
H Paul
Ranch Hand
Posts: 471
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Many people from JPA Certification forum often mentioned:

1. Pro JPA 2: Mastering the Java™ Persistence API

2. Java Persistence with Hibernate

But you can use as a hint/pointer below:

3. Official document of Hibernate and Hibernate Entity Manager of your version

4. Official document of your EJB container which is specific: JBOSS AS 7

tried {} finally { GOOD LUCK !}
 
Al Koch
Ranch Hand
Posts: 48
Eclipse IDE Firefox Browser Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'll go check these out.

Again, many, many thanks!

 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic