I have a GenericService class that encapsulates crud methods for subclasses:
public abstract class GenericService<D extends GenericDao<T, I>, T extends DomainObject<I>, I> { public I save(T t) { return getDao().save(t); } ........................... }
The AnswerService class extends the GenericService . It automatically executes AnswerDao and declares itself as a component of @Service and @Transactional spring.
@Service @Transactional(propagation = Propagation.REQUIRED) public class AnswerService extends GenericService<AnswerDao, Answer, Long> { @Autowired private AnswerDao answerDao; @Override public void setDao(AnswerDao d) { this.answerDao = d; } @Override public AnswerDao getDao() { return answerDao; } ................................ }
AnswerDao extends GenericDao , which implements the save method.
public abstract class GenericDaoHibernate<T extends DomainObject<I>, I extends Serializable> implements GenericDao<T, I> { private Class<? extends T> entityClass; private SessionFactory sessionFactory; public GenericDaoHibernate(Class<? extends T> entityClass) { this.entityClass = entityClass; } public GenericDaoHibernate() { } @Autowired private void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; Assertor.assertNotNull(sessionFactory); } public Session currentSession() { return getSessionFactory().getCurrentSession(); } @SuppressWarnings("unchecked") @Override public I save(T entity) {
When I call the save method on the GenericService , I expect spring to create a transaction for the hibernation session, but the transaction will not be created, and I get this error directly in the GenericDaoHibernate.save method:
org.hibernate.HibernateException: save is not valid without active transaction
My spring configuration file for the service level:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" p:dataSource-ref="dataSource" p:packagesToScan="com.javahelp.domain.impl"> <property name="configLocations"> <array> <value>classpath:META-INF/hibernate/hibernate.cfg.xml</value> </array> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <context:component-scan base-package="com.javahelp.service" />
Therefore, when I do not rely on spring @Transactional support and start / commit transaction org.hibernate.Session , then everything is fine and I have no error.
Why doesn't spring provide a transaction for methods called GenericSerice?
BTW, GenericService and AnswerService do not have interfaces.
EDIT . This is the transaction returned by the HibernateTransactionManager.doGetTransaction method:
txObject HibernateTransactionManager$HibernateTransactionObject (id=190) connectionHolder null newSession false newSessionHolder false previousIsolationLevel null savepointAllowed false sessionHolder null
I also changed my services to use interfaces, but that didn't help.