0

I am trying to learn the transactions. So I have developed a small application in ejb 3.1 and hibernate 5.2 .Now I have a scenario like below

 @Stateles
    @TransactionManagement(TransactionManagementType.CONTAINER)
    public class MyEJb implements ejbxyz {

    @Resource
    SessionContext sessionContext;

    @Override
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void method(){
          Dao dao=new Dao() //Dao class is simple java class
          try{
          dao.fooMethod(); 
          }catch(DaoException e){
               sessionContext.setRollbackOnly();
          }
          try{
          dao.barMethod();  // this method updates some other record
           }catch(DaoException e){
               sessionContext.setRollbackOnly();
          }
         }
    } 




public class Dao{
             void fooMethod(){
             try{
             Session session=sessFactory.getCurrentSession();
             ....
             session.save(x);
             }catch(Exception e){
                 throw new DaoException();
             }
          }
         void barMethod(){
                   try{
                           Session session=sessFactory.getCurrentSession();
                            session.getNamedQuery("xyz").executeUpdate();
                      }catch(HibernateException ex){
                            throw new DaoException();
                    } 
               }
       }
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.datasource">java:/XYZDB</property>
<property name="show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hbm2ddl.auto">update</property>
</session-factory>
</hibernate-configuration>

Below is the stacktrace of exception that I get when I try to run the application.

 org.hibernate.HibernateException: save is not valid without active transaction

-   at com.ebs.service.implementation.OnlineBankingServiceImpl.fundTransfer(OnlineBankingServiceImpl.java:27)

-   at com.ebs.presentation.action.TransferFundAction.create(TransferFundAction.java:127)

-   at com.ebs.presentation.action.TransferFundAction$$FastClassBySpringCGLIB$$bd64a4af.invoke(<generated>)

-   at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

-   at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)

-   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)

-   at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)

-   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)

-   at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)

-   at com.ebs.presentation.action.TransferFundAction$$EnhancerBySpringCGLIB$$7fb221bd.create(<generated>)

-   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

-   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

-   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

-   at java.lang.reflect.Method.invoke(Method.java:498)

Exception says clearly that there is no active transaction during save operation. But then why ? since I expect EJB to start a transaction by itself. Is there anything that I missed.

Mayank Vaid
  • 330
  • 1
  • 7
  • 18

2 Answers2

0

try bellow code :-

 Session session=getSessionFactory().getCurrentSession();
 Transaction trans=session.beginTransaction();
 session.save(entity);
 trans.commit();

also use @Transactional(propagation = Propagation.REQUIRED) annotation

Anshul Sharma
  • 3,432
  • 1
  • 12
  • 17
  • My concern is If I am using @TransactionAttribute(TransactionAttributeType.REQUIRED) then ejb should automatically generate the transaction which will continue to persist throught the child methods execution. If something goes wrong then it should rollback.. That is what oracle docs says about CMT docs.oracle.com/javaee/6/tutorial/doc/bncij.html – Mayank Vaid Jul 10 '17 at 17:57
0

Blockquote

Why don't you use JPA? define persistence.xml, inject an EntityManager using @PersistenceContext ... that should give you something which works inside the Container Transaction. A simple war with different testcases could help see: war examplebean the bean is used to compare an ejb-like environment, to a wildfly running with arquillian. So therefore there are different transactional situation together with one primitive Entity simulated.

if you need to use the hibernate API because of legacy code to be ported in a stable way and with minimal effort: using unwrap you can access the session underlying the entityManager. Db-Operation done using this Object should be handled in context of the current transaction. You should probably not use the hibernates session in different thread and transaction contextes but fetch it always immediately before the legacy code is running. But that is to be checked.

aschoerk
  • 3,333
  • 2
  • 15
  • 29
  • Okay I can use EntityManager. Since I can now understand (from ejb specs) that since my Dao is a plain old java class therefore It doesn't comes under the container managed transaction. But however I have seen the projects where they have used same setup and its working as expected. I believe they are using JTA... But I have no idea about this.. – Mayank Vaid Jul 19 '17 at 16:54
  • [geht hibernate Session from entitymanager](https://stackoverflow.com/questions/4335570/accessing-hibernate-session-from-ejb-using-entitymanager) could help to stick with the hibernate API. – aschoerk Jul 19 '17 at 18:56
  • Please look at the last paragraph of my answer, I elaborated a bit more about the idea of getting the hibernate session from the entity manager. – aschoerk Jul 19 '17 at 19:35
  • is using hibernate api to get sessions and create queries discouraged? What I use to believe is hibernate api is more flexible and it is a good way to implement the Dao layer. However from your answer and also with some googling I understand that JPA2 is more powerful and should be used over hibernate. – Mayank Vaid Jul 21 '17 at 03:24
  • jpa is part of the j2ee spec, Together with toplink it influenced the JPA spec. Therefore, how it is integrated into the transactionmanagement depends heavily on technical details of the server and might not be very well documented and could change. So I recommend using JPA. – aschoerk Jul 21 '17 at 04:02