bitronix - Не удалось найти текущую транзакцию JTA

Привет, у меня есть веб-приложение Java, использующее Spring и Hibernate.

У меня есть класс модели под названием Role. Для всех классов моделей есть общий GenericDao.java

public interface GenericDao<T>{
    public void insert(T transientInstance);      
    public T findById(Class<?> clazz, Serializable id); 
}

GenericHibernateDao.java

@Repository
public class GenericHibernateDao<T extends Serializable>
implements GenericDao<T>{

    @Resource
    protected SessionFactory sessionFactory;

    @Override
    public void insert(T transientInstance) {
        sessionFactory.getCurrentSession().persist(transientInstance);
    }
        @SuppressWarnings("unchecked")
    @Override
    public T findById(Class<?> clazz, Serializable id) {
        return (T) sessionFactory.getCurrentSession().get(clazz, id);
        }
}

RoleService.java

public interface RoleService {
    public void insert(Role role);
    public Role findById(Integer id);
}

И имеет свою реализацию RoleServiceImpl.java

@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private GenericDao<Role> roleDao;

    @Override
    public void insert(Role role) {
        roleDao.insert(role);
    }

    @Override
    public Role findById(Integer id) {
        return roleDao.findById(Role.class, id);
    }
}

У меня есть контроллер, который вызывает этот метод findbyid и передает значение — RegisterController.java

@Controller
public class UserRegisterController {

    @Autowired
    public RoleService roleService;

    @RequestMapping(value = "/register", method = RequestMethod.POST, consumes= MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public void registerUser(@RequestBody User user)
    {
        Role role=new Role();
        role=roleService.findById(1);
        System.out.println("Saved");
    }
}

Наконец, мой весенний applicationContext.xml

<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
        init-method="init" destroy-method="close">
        <property name="className"
            value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
        <property name="uniqueName" value="ocr/DocumentDatabase" />
        <property name="minPoolSize" value="1" />
        <property name="maxPoolSize" value="5" />
        <property name="automaticEnlistingEnabled" value="true" />
        <property name="allowLocalTransactions" value="true" />
        <property name="useTmJoin" value="true" />
        <property name="shareTransactionConnections" value="true" />
        <property name="driverProperties">
            <props>
                <prop key="url">${jdbc.url}</prop>
                <prop key="user">${jdbc.username}</prop>
                <prop key="password">${jdbc.password}</prop>
            </props>
        </property>
    </bean>
    <bean id="bitronixTransactionManager" factory-method="getTransactionManager"
        class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig, dataSource"
        destroy-method="shutdown" />

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="bitronixTransactionManager" />
        <property name="userTransaction" ref="bitronixTransactionManager" />
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
        destroy-method="destroy">
        <property name="dataSource" ref="dataSource" />
        <property name="jtaTransactionManager" ref="transactionManager"/>
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
            </props>
        </property>
    </bean>

Я запускаю это приложение в tomcat. Выдает следующую ошибку.

SEVERE: Servlet.service() for servlet [myappdemo] in context with path [/myappdemo] threw exception [Request processing failed; nested exception is org.hibernate.HibernateException: Unable to locate current JTA transaction] with root cause
org.hibernate.HibernateException: Unable to locate current JTA transaction
    at org.hibernate.context.internal.JTASessionContext.currentSession(JTASessionContext.java:88)
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:90)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:980)
    at com.myapp.myappdemo.dao.hibernate.GenericHibernateDao.findById(GenericHibernateDao.java:46)
    at com.myapp.myappdemo.dao.hibernate.GenericHibernateDao.findById(GenericHibernateDao.java:15)
    at com.myapp.myappdemo.service.impl.RoleServiceImpl.findById(RoleServiceImpl.java:38)
    at com.myapp.myappdemo.web.UserRegisterController.registerUser(UserRegisterController.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

Это происходит, когда я звоню в roleService.findById(1);

Почему это происходит? И как я могу решить?

Я использую spring 3.2.1.RELEASE, Hibernate 4.2.0.Final, btm 2.1.3.


person Shiju K Babu    schedule 07.01.2014    source источник


Ответы (1)


SessionFactory настроен на использование JtaTransactionManager. Когда вы это сделаете, спящий режим достаточно умен, чтобы просмотреть текущие транзакционные ресурсы, чтобы найти сеанс.

Ваша конфигурация spring позволяет использовать аннотации для разграничения транзакций.

Your transaction manager seems correctly configured.

Итак, все выглядит нормально. Единственной недостающей частью являются транзакционные аннотации!

Просто добавьте @Transactional в свой сервисный слой:

@Override
@Transactional
public Role findById(Integer id) {
    return roleDao.findById(Role.class, id);
}

(вы также можете поместить эту аннотацию в класс обслуживания)

person ben75    schedule 07.01.2014
comment
В классе обслуживания ставлю. В этот раз я получаю transaction timedout exception - person Shiju K Babu; 07.01.2014
comment
Итак, кажется, что Unable to locate current JTA transaction исправлено. Пожалуйста, примите ответ и задайте другой вопрос о тайм-ауте транзакции (если вы еще не решили ее). Не забудьте опубликовать свою конфигурацию spring (например, в этом посте + bean-компонент btmConfig) и трассировку стека. - person ben75; 07.01.2014