views:

1248

answers:

3

Hi all,

I've been wrestling with this problem for a while, and don't see a solution. Hope anyone can help me.

I have a HibernateTransactionManager configured. However, I see the following message in the log file:

DEBUG [http-8080-1] AnnotationTransactionAttributeSource.getTransactionAttribute(107) | Adding transactional method [cashIn] with attribute [PROPAGATION_REQUIRED, ISOLATION_DEFAULT, -nl.forestfields.picnic.domain.model.exception.IllegalCostException]

DEBUG [http-8080-1] AnnotationTransactionAspect.createTransactionIfNecessary(267) | Skipping transactional joinpoint [nl.forestfields.picnic.view.controller.ShoppingListController.cashIn] because no transaction manager has been configured

Also, in case of an exception, the transaction isn't rolled back.

Here's my configuration:

picnic-servlet.xml:

  <beans>

    <context:component-scan base-package="picnic" />
    <context:annotation-config />

    <tx:annotation-driven />
    .
    .
    .

picnic-context-db.xml:

<bean class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" id="sessionFactory">

    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="sessionFactory" />
 </bean>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
        <value>${hibernate.connection.driver_class}</value>
    </property>
    <property name="url">
        <value>${hibernate.connection.url}</value>
    </property>
    <property name="username">
        <value>${hibernate.connection.username}</value>
    </property>
    <property name="password">
        <value>${hibernate.connection.password}</value>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

The code that should be executed inside a transaction:

@Transactional(rollbackFor=IllegalCostException.class)
public ModelAndView cashIn(@RequestParam final Long id) throws IllegalCostException, llegalOrderStateException, IllegalShoppingListStateException {

  final ShoppingList shoppingList = shoppingListRepository.getById(id);
  shoppingList.cashIn();
  shoppingListRepository.add(shoppingList);

  return new ModelAndView(...);
}

Can anyone see the problem?

Cheers, Jippe

+1  A: 

Try changing

<tx:annotation-driven />
       to
<tx:annotation-driven transaction-manager="transactionManager" />

Couldn't find any other problem here.

Jerrish Varghese
+1  A: 

Also, rollback only occurs for Unchecked Exceptions. If you want to rollback for Checked Exceptions, you'll have to declare it in the @Transactional annotation:

@Transactional(rollbackFor = { IllegalCostException.class, llegalOrderStateException.class })
public ModelAndView cashIn(@RequestParam final Long id) throws IllegalCostException, llegalOrderStateException, IllegalShoppingListStateException {

  final ShoppingList shoppingList = shoppingListRepository.getById(id);
  shoppingList.cashIn();
  shoppingListRepository.add(shoppingList);

  return new ModelAndView(...);
}
Miguel Ping
A: 

You say you have two different bean definition files. Do these represent two different application contexts, or does one import the other?

The spring docs aren't clear on this, but it may be that will only auto-locate the "transactionManager" bean if it's in the same context as itself. If the transactionManager is in the parent context, it may not find it.

As jerrish said, just explicitly specify the transaction-manager attribute of the element.

skaffman