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

3

9

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

Miscarry answered 21/4, 2010 at 22:56 Comment(1)
See also #2414411Guiltless
M
7

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.

Miscarry answered 24/4, 2010 at 22:3 Comment(0)
S
7

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.

Smuggle answered 21/4, 2010 at 23:14 Comment(2)
Thank you, I will post it asap but in the meantinme, is there a way to specify XADataSource in persistence.xml? I couln't find it anywhere and every time i deploy via netbeans the glassfish setting in connection pool is reverted to plain DataSource.Miscarry
That was useful for me at the end of 2021 :) Thanks a lot @Pascal. Thanks a lot stack overflowOrthopedist
M
7

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.

Miscarry answered 24/4, 2010 at 22:3 Comment(0)
A
2

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.

Asserted answered 21/12, 2011 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.