0

I am working on spring4 mvc to introduce in our new web application and currently we are using struts1.x and wanted to use new framework for support html5/ajax request as simple as possible and wanted to use the power of DI and spring webflow support.

Currently in our struts1.x application db transaction management is done at our custom GenericAction which is subclass of Action, In GenericAction we are getting the connection from data source and handover to the subclasses then any exception raised then caught and rollback, otherwise commit such that database atomicity (transaction management )is done at one place. All the module action classes should extends GenericAction such that database connection will be available and performs the module related stuff and after completing connection will be either rollback or commit in GenericAction as said above.

In spring, scope of the Transaction is started with @Transactional annotation and then ends with a method in Service Class since the service class marked as @Transactional. This is not feasible solution for me. I have read several documents related to the spring transaction before starting and below are my questions. I am using HibernateTransactionManager as transaction manager

  1. Transaction should start from interceptors in case web request or any class (in case of unit testing).

  2. Transaction should ends with the after interceptor is executed in case of web request or any class in case of unit testing.

  3. In case of any exception raised then our HandlerExceptionResolverImpl handler will execute then connection should be rollback.

Any workaround or best practices would be greatly appreciate.

Thanks Dhorrairaajj

Dhorrairaajj
  • 55
  • 11
  • For q3, the following question might be related: http://stackoverflow.com/questions/29955159/ – Gábor Bakos May 06 '15 at 13:23
  • Why is the @Transactional on service methods unacceptable? That is not clear in the question ... Is unit testing the only concern for Transactionality to be in the interceptors? – Shiraaz.M May 06 '15 at 13:42
  • For how you described the problem, it seems to me that @transactional paradigm is a good solution; it allows to you to specify the Exception class that needs roll-back (point 3) and points 1 and 2 are satisfied for default – Angelo Immediata May 06 '15 at 17:21
  • @Gabor Bakos -Thanks for reply, that is what exactly i did – Dhorrairaajj May 07 '15 at 04:07
  • @Shiraaz. M -- As for unit testing is concerned, there is no need for interceptors, when it is web/ajax request then need for interceptors. I am design application with spring by replicating the existing practices in struts which would eventually easy for all developers to develop – Dhorrairaajj May 07 '15 at 04:09

2 Answers2

0

In my opinion, you can achieve this with minimal change on the current application by following what Spring does in its org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(Object, TransactionDefinition). In detail, I think something like following should work:

  1. On the GenericAction, get connection from data source (as you've already done)
  2. Bind the connection via its holder with the current data source: TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
  3. Eventually, commit the transaction as org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DefaultTransactionStatus).

In any case, Spring's http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/support/TransactionTemplate.html can help to achieve any programmatic transactional scenario that you want. Just need to ensure that the right transactional resource is bound to the opening transaction.

Hope this helps.

Phoenix VN
  • 201
  • 2
  • 4
  • @Dhorrairaajj: Glad it helps. I think the last missing piece in your code is to gracefully close the session and the underlying resources. – Phoenix VN May 07 '15 at 09:09
0

Thanks for you reply. Your post/suggestion drives to do the following

I written an interceptor called TxtManager and below are methods to perform the transaction management.

public boolean preHandle(HttpServletRequest request,
    HttpServletResponse response, Object handler) throws Exception
{
    Session session = sessionFactory.openSession();
    SessionHolder hold = new SessionHolder(
        session);
    TransactionSynchronizationManager.bindResource(sessionFactory, hold);
    // passing null would accept the default transaction definition.
    status = transactionManager.getTransaction(null);

    return true;
}


public void afterCompletion(HttpServletRequest request,
    HttpServletResponse response, Object handler, Exception ex)
    throws Exception
{
    Exception hanlderEx = (Exception) request
        .getAttribute(HandlerExceptionResolverImpl.EXCEPTION_KEY);

    if (hanlderEx != null)
    {
        transactionManager.rollback(status);
    }
    else
    {
        transactionManager.commit(status);
    }
}

In HandlerExceptionResolverImpl class which responsible for handling things upon exception, put an exception object in request and read the same exception to rollback or commit in afterCompletion method of the interceptor.

In between(preHandler and afterCompletion) we will going to use the standard practices to perform the module related stuff including any other interceptos. Unit testing may not be supported, i will check other alternative for unit testing.

Finally we were able to simulate the existing frame work with your suggestion Thanks

Any suggestion to improves this would be much appreciate !!..

Thanks Dhorrairaajj

Dhorrairaajj
  • 55
  • 11