views:

82

answers:

3

I am working on a J2EE server application which is deployed on Tomcat. I use Spring source as MVC framework and Hibernate as ORM provider. My object model has lot of Lazy relationships (dependent objects are fetched on request). The high level design is like Service level methods call a few DAO methods to perform database operation. The service method is called either from the Flex UI or as a scheduled job. When it is called from Flex UI, the service method works fine i.e. it fetches some objects using DAO methods and even Lazy loading works. This is possible by the use of OpenSessionInViewFilter configured with the UI servlet.

But when the same service method is called as scheduled Job, it gives LazyInitializationException. I can not configure OpenSessionInViewFilter because there is no servlet or UI request associated with that.

I tried configuring Transaction around the scheduled job method so that service method starts a transaction and all the DAO methods participate in that same transaction, hoping that the transaction will remain active and hibernate session will be available. But it does not work.

Please suggest if anyone has ever been able to get such a configuration working. If needed, I can post the Hibernate configuration and log messages.

Thanks a lot for help!

Shreerang

A: 

OpenSessionInViewFilter is a bit of a hack anyway, it's not good to rely on it too much.

A better general solution is to write your hibernate queries so that the data is fetched eagerly, not lazily. That means using fetch joins.

If that's not possible or practical, then your scheduled task can perform the whole job inside a transaction. This should keep the session open until it's finished.

skaffman
Yeah, I was trying to execute the job inside a transaction but was not able to get it working through point-cut expression. The Transaction did not start. Hence I posted this question. But thanks for confirming that I am heading in right direction.
Shreerang
Persevere with transactions, that's the right way to go.
skaffman
A: 

The code inside OpenSessionInViewFilter is not complex, I have had success in modifying the source to fit my own needs, all it really needs is the thread in which the lazy loading will occur.

I've also used Quartz for lots of scheduled jobs, it works very nicely with container managed transactions. A trick I've resorted to a few times to ensure lazy collections get loaded before the code exits the transactional boundary is to create a dedicated method where I call the necessary methods:

@Transactional
private SomeOobj getSomeObj(Long id) {
  SomeObj o = someObjDao.find(id);
  o.getLazyCollection().size(); // <- load the collection
  return o;
}

In these cases, it would be better to have the needed data loaded eagerly when the object is fetched the first time, but I know it's not always an option. Good luck.

Lauri Lehtinen
A: 

Finally I was able to fix my problem after some reading on Spring Transaction reference material. Earlier I was trying to write a point-cut expression to run my scheduled jon inside a Transaction. But the point-cut was using an OR (||) and somehow it did not pick up my method when it started execution. Hence the Transaction was never open. (I already have a working point-cut expression for my DAO methods and I was trying to add my scheduled method in that point-cut.)

Then I found a way to programatically open the Transaction which fixed my problem. For the benefit of others, here is the code snippet to do it:

       transactionTemplate.execute(new TransactionCallbackWithoutResult() {
          protected void doInTransactionWithoutResult(TransactionStatus status) {
                // Invoke the real method inside transaction context
                doWork();
          }
        });

For details on the TransactionTemplate please refer Spring Source documentation here : http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-programmatic

Shreerang