0

Could someone explain to me why Web Sphere Application Server 8.5.5 does not commit (or even begin?) transactions in JTA mode.

I have a dao class annotated with @Stateless @TransactionManagement(value = TransactionManagementType.CONTAINER)

And I have a method annotated with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW). The method simply inserts some entities into the database (if they do not exist yet).

for (MyEntity entity : entities) {
  if (validate(entity) { // Programmatic bean validation, returns true when ok
    getEntityManager().persist(entity);
  }
}

Tests run with Arquillian in Embedded GlassFish, this works perfectly. I can breakpoint stop the code in Eclipse (Luna & Kepler) after this method completes and check the db that there is data. The data used in the test is identical to the data used when deployed on WAS. (Validation errors are shown correctly when tested separately)

According to instructions (http://docs.oracle.com/javaee/6/tutorial/doc/bncij.html)

The code does not include statements that begin and end the transaction...

I probably can't understand this correctly as I have to explicitly wrap the method contents with these:

getEntityManager().getTransaction().begin();
... The persist loop ...
getEntityManager().getTransaction().commit();

...to make the the persisting work. If I do not do this, there is nothing put in to the database.

I also injected an extra resource for checking the transaction status

@Resource
private TransactionSynchronizationRegistry tsr;

and put this at the end of the method

System.out.println("Transaction status: " + tsr.getTransactionStatus());
getEntityManager().flush();

The output was this:

Transaction status: 0

where 0 = Status.STATUS_ACTIVE

However at the 'flush', an excpetion was thrown:

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

I spent days trying to figure this out on WAS, while I had it all the time working with the embedded GlassFish (v3) tests. Both using JavaEE6 (and java 6), though for the debug in Eclipse I have to switch to JavaEE7 + Java7.

Prior to this in another project I have done similar code on GlasFish v4 without any kind of problems.

So could someone clarify me if there are some WAS specific requirements to make this work, or do I just need to do the exact opposite with WAS than the instructions say and how I understand things should work?

I have already the following configuration on WAS: (admin console)

server > server types > WebSphere application servers > server1 > Container Services > Default Java Persistence API settings > Default JTA data source JNDI name = 'jdbc/kr' (the same as configured in my persistence.xml)

resources > JDBC > JDBC providers > Oracle JDBC Driver (pings ok) (When this was created) the 'Implementation type' was set to 'connection Pool Datasource', but I also tried this using the 'XA'.

// UPDATE

The getEntityManager-method simply returns the injected entity manager from the super class.

public abstract GenericDAO<T extends GenericEntity> {

  @PersistenceContext
  private EntityManager em;

  ...
  public EntityManager getEntityManager() {
    return this.em;
  }
}

// GenericEntity is an interface to force the entities to have the "get all" named query.

The class uses generic dao -pattern (you get the idea from this Single DAO & generic CRUD methods (JPA/Hibernate + Spring), though I have my own modifications as it's an abstract class with default CRUD methods). When the metdhod getEntityManager is used instead of directly accessing the resource, it's possible to override the entity manager used in the super class if the real dao-class decides to use it's own. => Also the super class has getEntityManager calls and if you override this in implementing class, it will get the same em in the abstract what the actual implementing class uses. Also this method is usable in tests when you can get the em and evict data when needed. Also this way you can easily add logging when em is accessed (logging interceptor).

// UPDATE 2

Occurred to my mind that there is a separate resource manager used to get remote resources (ejb's). This is so that the location of the ejb is configurable from a property file. However the inner-injection still works within the ejb of this service of mine. I started thinking that could this cause somehow that the container losses it's transaction handling ability? Also I noted that there is a @Singleton scoped bean along the path using the actual transactional resources. I could not find a clear explanation on what scopes the beans should be (probably there is not any kind of requirement), but I ended up with understanding that the dao should be @Stateless. In JavaEE7 this is much more clearer as there is the @Transactional annotation for pointing this.

Community
  • 1
  • 1
Ville Myrskyneva
  • 1,560
  • 3
  • 20
  • 35
  • And when I have those begin and commit statements, I get these in tests: Exception Description: Cannot use an EntityTransaction while using JTA. – Ville Myrskyneva Nov 27 '15 at 12:51
  • What does getEntityManager() do? How do you lookup/invoke the REQUIRES_NEW method? In any case, it's unclear to me why this works in Glassfish but not WebSphere, but perhaps printing the EntityManager.toString and a stack trace in that REQUIRES_NEW method would give enough hints for someone to figure out what's wrong. – Brett Kail Nov 28 '15 at 01:31
  • As @bkail says what happens in the getEntityManager is important for answering this question. If it is calling the Persistence class to get an EntityManagerFactory then it wont be container managed and therefore wont be enlisted in the transaction. – Alasdair Nov 28 '15 at 02:08
  • @bkail Updated my question. – Ville Myrskyneva Nov 30 '15 at 05:17
  • Add your `presistence.xml` as it looks like you might be using `transaction=RESOURCE_LOCAL` instead of `JTA` in the xml. – Gas Nov 30 '15 at 11:44
  • @Gas Nope. As I said it works for GlassFish and the persistence.xmls are identical. I do have to change it for resource local if I want to generate the tables manually by Eclipse, but this is not the case that I had forgotten to change it back. Anyway, here it is. http://pastebin.com/qJ34hUux ... A note though. I use EclipseLink when the WAS provides OpenJPA (and some IBM version), but they say in the documentation that you can use what your wish. I tried OpenJPA, but had some problems with it, so I switched to EclipseLink which has worked fine (except for this?) and haven't switched back. – Ville Myrskyneva Dec 01 '15 at 10:19

0 Answers0