Strange Spring Transaction Behavior - java

I'm having a difficult time understanding Spring Transactions. First off, I am trying to use as little of Spring as possible. Basically, I want to use #Transactional and some of its injection capabilities with JPA/Hibernate. My transactional usage is in my service layer. I try to keep them out of test cases. I use CTW and am spring-configured. I have component scan on the root of my packages right now. I also am using Java configuration for my datasource, JpaTransactionManager, and EntityManagerFactory. My configuration for the JpaTransactionFactory uses:
AnnotationTransactionAspect.aspectOf().setTransactionManager( txnMgr );
I do not use #EnableTransactionManagement.
Unfortunately, I'm having a hard time understanding the rules for #Transactional and can't find an easy page that describes them simply. Especially with regards to Session usage. For example, what if I want to use #Transactional on a class that does not have a default no-arg constructor?
The weirdest problem I'm having is that in some of the POJO service classes Transacitonal works great while in others I can see the transactions being created but operations ultimately fall saying that there is "no session or the session has been closed". I apologize for not having code to reproduce this, I can't get it down to a small set. This is why I am looking for the best resources so I can figure it out myself.
For example, I can have a method that gets a lazily fetched collection of children, iterates through it and puts it into a Set and returns that set. In one class it will work fine while in another class also marked with #Transactional it will fail while trying to iterate through the PersistentSet saying that there is no session (even though there IS a transaction).
Maybe this is because I create both of these service objects in a test case and the first one is somehow hijacking the session?
By the way, I have read through the spring source transaction documents. I'm looking for a clear set of rules and tips for debugging issues like this. Thanks.

Are you sure you loaded your parent entity in the scope of the very transaction where you try to load the lazy children? If it was passed in as parameter for example (that is, loaded from outside your #Transactional method) then it might not be bound to a persistence context anymore...
Note that when no #Transactional context is given, any database-related action may have a short tx to be created, then immediately closed - disabling subsequent lazy-loading calls. It depends on your persistence context and auto-commit configurations.
To put it simply, the behaviour with no transactional context being sometimes unexpected, the ground rule is to always have one. If you access your database, then you give yourself a well-defined tx - period. With spring-tx, it means all your #Repository's and #Services are #Transactional. This way you should avoid most of tx-related issues.

Related

Hibernate - Centralized entity instantiation

I have some old code that basically uses singleton services inside entities to perform some tasks, and to start cleaning up thinks, I want to inject those services on entities, so at least I can break that hard dependencies for now.
I'm trying to find some place in Hibernate where I can control entities instantiation, by now I've found some possible hooks, like:
- org.hibernate.tuple.Instantiator
- org.hibernate.Interceptor
I need to control that instantiation when an object is first loaded from database, as well as when it's loaded from cache... Also, maybe a global PreLoadEvent may help, I just need to make sure that when an object is returned from Hibernate, it has all it's (service) dependencies injected (spring is already here).
Can someone please point me to where to continue the search?
You could use #Configurable annotation,
see this blog post for more info.
Well, after some testing, an instance of org.hibernate.event.PreLoadEventListener does the trick.
It gets called always, no matter where the instance came from. This way I'm not controlling instantiation, but at least I have a place to inject dependencies befor the instance is returned to client code.
Thanks all for your time!

JTA & MySQL - How to Retrieve records from database

I am new to JTA and I need a method to retrieve some some elements from the database. I can do this through EntityManager but that works only for ResourceLocal.
I want to know how can I do this:
Query q = em.createNamedQuery("AnyQuery");
q.getResultList();
without the use of EntityManager.
Any ideas?
The question itself shows that you don't understand any of the technologies you try to work with. You probably need to study some more general stuff before you do any actual development.
you are probably confusing JTA and JPA,
your statement about RESOURCE_LOCAL is not true (and irrelevant) - there are JTA and RESOURCE_LOCAL transactions and in Java EE you usually use the former,
your thought of using Named JPA queries without EntityManager is plain absurd and probably stems from misunderstanding of some kind (what would be the point of using named queries without an entity manager?),
saying "some elements from database" shows that you can't really tell the difference between records and mapped objects, in which case you probably should not use JPA at all.
I am not really expecting that you accept this answer. That's just my frustration taking over.
EDIT
OK, now that you mentioned JSF I understand more of your problem.
I assume you want to use JPA. In such case you have a choice of:
creating your own EntityManager (in such case you cannot have it injected; instead you have yo use an EntityManagerFactory and build your own). This is an "application managed EntityManager". You don't really want to do this.
using an injected EntityManaged ("conatiner managed EntityManager"). This is the standard choice.
Now you need a transaction. Since you should be using a JTA EntityManager, you will need a transaction object that is responsible for coordinating the whole thing. Again, you have two choices:
in a JSF bean, inject a UserTransaction (using #Resource annotation). This is messy, error-prone and takes a lot of boilerplate, but you will find all the necessary methods. You can create your own (application managed) EntityManager, call its joinTransaction method and then call begin-commit on UserTransaction. This is would be an "application managed transaction"
move your EntityManager code to EJB. It only takes a couple of lines of code and a single annotation (#Statless). All the code inside an EJB is - magically - wrapped inside a transaction that the container manages for you. This is the "container managed transaction" - the default and common choice.
Each of the things above could (and should) be expanded with some additional information. But the short path for you is:
create an EJB (a simple class with #Stateless annotation),
move the method that uses EntityManager to the EJB,
inject the EJB into your managed bean (using #EJB annotation) and call the relevant method.
The JTA transaction will happen around each call to any EJB method. This should get you started :-)

Using and controlling Spring transactions within Struts 2 actions

I have been working for a while on a project with the following components:
Struts2.1.8.1,
Spring 3.0.3
JPA 2.0,
Hibernate 3
I am using Spring's EntityManager magic... But I'm having problems dealing with transactions inside my actions. For instance, I am setting values on my persisted object in several methods within my class, and I want to be able to rollback if the validate method finds a validation error, or commit these changes otherwise. I have already spent quite a long time reading half of the internet for a comprehensive explanation. Unfortunately, no complete examples exist (at least similar to my stack).
I have stumbled with this thread on a mailing list: #Transactional Spring Annotation in a Struts2 Action does not work. The message I'm linking at seems to have a pretty simple and straightforward solution, using a TransactionInterceptor will do the trick it seems... The problem is that I'm not finding useful information regarding this interceptor.
Anyone here has experience with this technology and can spare a tip and a link or two on how to use Spring transactions inside Struts2 actions?
Thanks!
- Edit 1 -
I have set up a test project if you are interested, just download the file and try it out (or inspect it). Thanks!
Generally, controllers/actions/backing beans/etc don't handle transactions. Actions are the web-part of your back-end code - they should only be concerned with gathering request data, and sending response data. The logic itself (including database access) should be done in another layer. E.g. a service layer. So you create another bean, inject it in the action, and make it do the work - userService.register(user). Then configuring transactions on a service layer should be trivial since it is both in the spring documentation and in countless examples:
<tx:annotation-driven /> and #Transactional (btw, make sure you have the <tx:..> now, it might be causing the issue. Even if it works, this does not invalidate my suggestion about the service layer)
I don't like answering my own question, but since I solved this ages ago... I thought I should share the knowledge (or lack of... in this case).
The book I was using to learn about Struts 2 and Spring-JPA-Hibernate, adds the #Transactional annotation right before the declaration of the service class. This is terribly wrong, for all methods (including those that only retrieve stuff from the database) are inside a committable transaction. Long story short everything got committed event if exceptions occurred.
The solution, as Bozho so wisely pointed out, was to look at examples. That is, set your transtactional methods carefully, in my case I set up transactions for the methods that had to write back to the database and everything started to work just fine.
Thanks to Steven and Quaternion too for taking the time to answer my question.
Based on your question, here's what I understand about your problem.
You want to wrap your action invocation in a transaction. If the validate method records validation errors, you want to roll the transaction back. Presumably, you also want to rollback in case of an error.
Solution
Create an interceptor that will:
Start a transaction
Invoke the action inside of a try/catch block
Rollback the transaction if there is an exception or if there are any validation errors on the action (this can be detected using action.hasErrors)
Commit the transaction
You will probably want this interceptor defined pretty early in the stack. I don't know of any pre-built interceptors for this (although there may be some), but it should be fairly easy to assemble.
Update
I don't use Spring, so I can't say how the JPA transaction support works there, but you can handle transactions for your EntityManager like:
try {
entityManager.getTransaction().begin();
// do your thing
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
throw new PersistenceException(e);
}
This is just a crude example, but it should illustrate the point.

Sharing a Spring transaction between hibernate & JdbcTemplate within a AbstractTransactionalTestNGSpringContextTests

I'm running a test within a subclass of AbstractTransactionalTestNGSpringContextTests, where I execute tests over a partial Spring context. Each test runs within a transaction, which is rolled back at the end to leave the database unchanged.
One test writes to the database through Hibernate, while another reads from the same database using the JdbcTemplate, with both share the same datasource.
I'm finding that I can't see the hibernate updates when querying through the JdbcTemplate. This does make some sense, as each is presumably getting its own connection from the connection pool and so is operating within its own transaction.
I've seen indications that it's possible to get the two to share a connection & transaction, but am not clear of the best way to set this up, especially with the involvement of the connection factory. All these components are declared as Spring beans. Can anyone give me any pointers?
Edit:
Well I've gone to the trouble of actually reading some documentation and the HibernateTransactionManager class states that this is definitely possible: "This transaction manager is appropriate for applications that use a single Hibernate SessionFactory for transactional data access, but it also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource)...".
The only requirement appears to be setting the datasource property, which isn't otherwise required. Having done that, though, I'm still not seeing my changes shared before the transaction has been committed. I will update if I get it working.
The Spring bean that writes has to flush its changes in order for the bean that reads to see them.

how does spring allow for lazy-loading?

If you have a call in a Dao method like (pseudo code):
return ..getHibernateTemplate( get by id );
Now say that entity has a lazy-loaded collection. Once you return from your Dao using the hibernateTemplate helper method, how come the session stays in scope and allows you to lazy-load a collection?
Is the session initialized and committed at a global level on a per request basis?
Update
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
It is handling the Unit of work also, where/how?
Once you return from your Dao using the hibernateTemplate helper method, how come the session stays in scope and allows you to lazy-load a collection?
Because the Session hasn't been closed yet and your entity is thus still Persistent (as opposed to the Detached object state). As long as your entity has not been detached, you can lazy load collections and proxies. See chapter 10.1. Hibernate object states for more details on these states (it's very important to understand them and the terminology used).
Is the session initialized and committed at a global level on a per request basis?
With web applications, it's typically per request. As mentioned in the javadoc of HibernateTemplate:
Lazy loading will also just work with an open Hibernate Session, either within a transaction or within OpenSessionInViewFilter/Interceptor.
And if you look at the javadoc of OpenSessionInViewFilter or OpenSessionInViewInterceptor, you'll read that they are slightly different but both binds a Hibernate Session to the thread for the entire processing of the request and provide an implementation of the "Open Session in View" pattern.
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
You could look at the sources and use a debugger for this you know :) Look at HibernateTemplate, more precisely the doExecute() method, this is where the session is obtained. For the close/commit, look at the previously mentioned OpenSessionInViewFilter/Interceptor, both have methods for this purpose.
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
I think I covered that part: the session is created at the start of a request and closed at the end.
It is handling the Unit of work also, where/how?
I'm not sure to get this one. To me, Hibernate's Session is an implementation of the unit of work pattern. So this question is actually the same as the previous one.
PS: I provided some links that show that everything is actually clearly documented. Spring and Hibernate have extremely nice documentation and javadoc. Take advantage of that, look at them by yourself, look at the code by yourself, use your debugger, you'll learn a lot more.
Hibernate returns a custom implementation of the collection which does the loading only whenever any of the collection methods is been invoked. This collection has been constructed with the session as argument.
Do a sysout of getSomeCollection().getClass() to see which Hibernate custom class it is and check the appropriate javadocs/sourcecode to see how exactly they did it.
If you ever questioned the sense/use/value of interfaces and declaring against interfaces, now, this is a good example. You didn't see anything from it, did you? ;)
Is the session initialized and committed at a global level on a per request basis?
It's typically initialized on a per-request basis using ... (wait for it)
Please explain where exactly the call to 'getcurrentsession' is made, and when is it actually closed/committed?
It: org.springframework.orm.hibernate3.HibernateTemplate
... is the heart of Spring's integration with Hibernate. HibernateTemplate will initialize the session as necessary (or pull an already existing one from a ThreadLocal store) and provide it to any callbacks you give to the HibernateTemplate#execute* methods.
From what I understand, the spring framework has to handle the session lifecycle, where does it do this? at what point the in the requests lifecycle?
Also done by HibernateTemplate, and ...
It is handling the Unit of work also, where/how?
Done by HibernateTransactionManager, if you have one configured in your applicationContext.
If this was a web application I would use the OpenSessionInViewFilter

Categories