Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent "Local transaction already has 1 non-XA Resource" exception?

I'm using 2 PU in stateless EJB and each of them is invoked on one method:

@PersistenceContext(unitName="PU")
private EntityManager em;
@PersistenceContext(unitName="PU2")
private EntityManager em2;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW )
public void getCandidates(final Integer eventId) throws ControllerException {
    ElectionEvent electionEvent = em.find(ElectionEvent.class, eventId);
    ...
    Person person = getPerson(candidate.getLogin());
    ...
}

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW )
private Person getPerson(String login) throws ControllerException {
    Person person = em2.find(Person.class, login);
    return person;
}

Those methods are annotated with REQUIRES_NEW transcaction to avoid this exception. When I was calling these method from javaFX applet, all worked as expected. Now I'm trying to call them from JAX-RS webservice (I don't see any logical difference as in both cases ejb was looked up in initial context) and I keep getting this exception. When I set up XADatasource in glassfish 2.1 connection pools, I got nullpointer exception on em2.

Any ideas what to try next?

Regards

like image 620
zeratul021 Avatar asked Apr 21 '10 22:04

zeratul021


3 Answers

I'm using 2 PU in stateless EJB and each of them is invoked on one method

Indeed. But you're calling the second method from the first one so you're doing a distributed transaction and you need to use XA for this (at least for one of the resource since GlassFish supports the last agent optimization allowing to involve one non-XA resource). In other words, setting one of your datasource as a XADataSource is the way to go.

If you get an error when doing this, please add details about what you did exactly and the stacktrace.

like image 78
Pascal Thivent Avatar answered Nov 08 '22 23:11

Pascal Thivent


Ok,

it's solved now. I'll share just in case somebody got tackled by similar thing. Whole problem was with netbeans deploying. They overwrite the settings in glassfish connection pool and when you set them proper at runtime, you got npe's or missing password silly stuff. The place to edit this is sun-resources.xml. XML element has attributes datasource-classname and rs-type. What needs to be done in case of Derby database is:

<jdbc-connection-pool ... 
        datasource-classname="org.apache.derby.jdbc.ClientXADataSource" 
        res-type="javax.sql.XADataSource">
   ...
</jdbc-connection-pool>

Works like a charm now.

like image 7
zeratul021 Avatar answered Nov 08 '22 23:11

zeratul021


When calling the second method from the first, it is not an EJB method call. It treats it as just a regular method call and does not look at @TransactionAttribute. If you want a call to the same EJB, you can inject the SessionContext and call getBusinessObject. Then call the method on the returned EJB.

like image 2
amda88 Avatar answered Nov 08 '22 22:11

amda88