Domanda

Hi I have a Java web application using spring and hibernate.

I have a model class called Role. For all model classes there is common 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);
}

And has its implementation 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);
    }
}

I have a controller which calls this findbyid methid and passing a value - 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");
    }
}

Finally my spring applicationContext.xml is

<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>

I run this application in tomcat. It gives the following error.

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)

It happens when I call the roleService.findById(1);

Why its happening? And how can I resolve?

I am using spring 3.2.1.RELEASE, Hibernate 4.2.0.Final, btm 2.1.3

È stato utile?

Soluzione

The sessionFactory is configured to use JtaTransactionManager. When you do that, hibernate is smart enough to look into current transactionnal resources to find the session.

Your spring configuration allows you to use annotations to do transaction demarcation.

Your transaction manager seems correctly configured.

So, everything looks fine. The only missing part are the transactional annotations !

Just add @Transactional in your service layer:

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

(you can also put this annotation on the service class)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top