You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@olingo.apache.org by "Enrique Rodriguez (JIRA)" <ji...@apache.org> on 2016/08/04 11:49:20 UTC
[jira] [Commented] (OLINGO-976) Problem with JTA transactions
[ 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)