[ 
https://issues.apache.org/jira/browse/OLINGO-976?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15407609#comment-15407609
 ] 

Enrique Rodriguez commented on OLINGO-976:
------------------------------------------

Hi Michael, Alex,

I agree with Alex, and i'm working with olingo using JTA with Bean Managed 
Transaction on a javaee 6 application server (Websphere 8.5)

First of all, I use CDI to inject dependecies (EntityManager, 
EntityManagerFactory ans UserTransaction). To do it we need to give the control 
to the container from the servlet, so I extend ODataServlet to inject the 
ODataJPAServiceFactory overriding getServiceFactory method

@WebServlet("/OData.svc/*")
public class JtaODataServlet extends ODataServlet{
        
        public JtaODataServlet() {
                super();
        }
        
        /**
         * 
         */
        private static final long serialVersionUID = 7405803151288216396L;
        
        @javax.inject.Inject
        private JpaInjectedServiceFactory serviceFactory;
        
         /**
           * Get the service factory instance which is used for creation of the
           * <code>ODataService</code> which handles the processing of the 
request.
           * 
           *
           * @param request the http request which is processed as an OData 
request
           * @return an instance of an ODataServiceFactory
           */
          protected ODataServiceFactory getServiceFactory(HttpServletRequest 
request) {
                  return (ODataJPAServiceFactory)serviceFactory;
          }

}

The JpaInjectedServiceFactory load all resources it need from container. In 
also need to modify oDataJpaContext and oDataJpaContextImpl to store 
userTransaction and TransactionSynchronizationRegistry 

public class JpaInjectedServiceFactory extends ODataJPAServiceFactory {
        public static final String DEFAULT_ENTITY_UNIT_NAME = "Model";

        @PersistenceContext//(unitName = "Model")
        private EntityManager entityManager;
        
        @PersistenceUnit
        private EntityManagerFactory emf;
        
        @Resource 
        UserTransaction userTran;
        
        @Resource
        TransactionSynchronizationRegistry tsr;
        
    public JpaInjectedServiceFactory() {}

        @Override
        public ODataJPAContext initializeODataJPAContext() throws 
ODataJPARuntimeException {
                ODataJPAContext oDataJPAContext = getODataJPAContext();
                
                //Context ctx;
                try {
                //      ctx = new InitialContext();
                
                        
                // Now get the EntityManager from JNDI
                        oDataJPAContext.setEntityManagerFactory(emf);
                        oDataJPAContext.setEntityManager(entityManager);
                        
oDataJPAContext.setPersistenceUnitName(DEFAULT_ENTITY_UNIT_NAME);
                        oDataJPAContext.setContainerManaged(true);
                        oDataJPAContext.setUserTransaction(userTran, tsr);
                        
                        return oDataJPAContext;
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

                return null;
        }
}


OdataJPAContextImpl now manage to create the transaction it needs, ( i think 
that using callback for this configuration is very complex for most of people.)


  @Override
  public ODataJPATransaction getODataJPATransaction() {
          if (transaction == null) {
              transaction = 
odataContext.getServiceFactory().getCallback(ODataJPATransaction.class);
              if (transaction == null) {
                      if (containerManaged){
                                  transaction = new 
ODataJPATransactionBeanManaged(userTran, tsr);
                          }else{
                        transaction = new 
ODataJPATransactionLocalDefault(getEntityManager());
                      }
              }
          }
    return transaction;
  }

Finallly ODataJPATransactionBeanManaged control the JTA transaction similar as 
Local transaction.


public class ODataJPATransactionBeanManaged implements ODataJPATransaction {
          
  private UserTransaction userTran;
  private TransactionSynchronizationRegistry tsr;
  public ODataJPATransactionBeanManaged(UserTransaction 
userTran,TransactionSynchronizationRegistry tsr) {
          this.userTran = userTran;
          this.tsr = tsr;
          
  }

    @Override
    public void begin() {
                try {
                        userTran.begin();
                } catch (Exception e) {
                        throw new RuntimeException("error begin transaction", 
e);
            }
    }

    @Override
    public void commit() {
                try {
                        userTran.commit();
                } catch (Exception e) {
                        throw new RuntimeException("error begin transaction", 
e);
            }
    }

    @Override
    public void rollback() {
        try{            
                userTran.rollback();
            } catch (Exception e) {
                        throw new RuntimeException("error rollback 
transaction", e);
            }
      /** do nothing for CMP */
    }

    @Override
    public boolean isActive() {
        if (tsr.getTransactionStatus()==Status.STATUS_ACTIVE ){
                return true;
        }else {
                return false;
        }
    }
}

I made more changes to code to make olingo run with websphere 8.5 using Apache 
OpenJPA.... but this is for other post.

I hope this comments help, i spend a lot of time making it work.

Enrique.

> Problem with JTA transactions
> -----------------------------
>
>                 Key: OLINGO-976
>                 URL: https://issues.apache.org/jira/browse/OLINGO-976
>             Project: Olingo
>          Issue Type: Bug
>          Components: odata2-jpa
>    Affects Versions: V2 2.0.7
>         Environment: neo-javaee6-wp-sdk (SAP HANA cloud)
>            Reporter: Alex Key
>            Assignee: Michael Bolz
>             Fix For: V2 2.0.7
>
>
> There are still problems with JTA transaction after fixing OLINGO-882.
> At the moment IllegalStateException is thrown by 
> ODataJPATransactionLocalDefault constructor, which has em.getTransaction() 
> call.
> Here's stacktrace:
> {code}
> java.lang.IllegalStateException: A JTA EntityManager can not use the 
> EntityTransaction API.  See JPA 1.0 section 5.5
>       at 
> org.apache.openejb.persistence.JtaEntityManager.getTransaction(JtaEntityManager.java:349)
>       at 
> org.apache.olingo.odata2.jpa.processor.core.ODataJPATransactionLocalDefault.<init>(ODataJPATransactionLocalDefault.java:31)
>       at 
> org.apache.olingo.odata2.jpa.processor.core.ODataJPAContextImpl.getODataJPATransaction(ODataJPAContextImpl.java:178)
>       at 
> org.apache.olingo.odata2.jpa.processor.core.access.data.JPAProcessorImpl.setTransaction(JPAProcessorImpl.java:451)
>       at 
> org.apache.olingo.odata2.jpa.processor.core.access.data.JPAProcessorImpl.processCreate(JPAProcessorImpl.java:335)
>       at 
> org.apache.olingo.odata2.jpa.processor.core.access.data.JPAProcessorImpl.process(JPAProcessorImpl.java:223)
>       at 
> org.apache.olingo.odata2.jpa.processor.core.ODataJPAProcessorDefault.createEntity(ODataJPAProcessorDefault.java:122)
>       at org.apache.olingo.odata2.core.Dispatcher.dispatch(Dispatcher.java:79)
>       at 
> org.apache.olingo.odata2.core.ODataRequestHandler.handle(ODataRequestHandler.java:130)
>       at 
> org.apache.olingo.odata2.core.rest.ODataSubLocator.handle(ODataSubLocator.java:164)
>       at 
> org.apache.olingo.odata2.core.rest.ODataSubLocator.handlePost(ODataSubLocator.java:86)
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to