mkuff mkuff - 29 days ago 14
Java Question

WebSphere 8.5 - Rest - No active Transaction

I am struggling with WAS8.5 to use a simple Rest Service + an EJB to insert an entity into my DB2 database. Selecting works fine, because no transaction is needed.
The Entity is correctly annotated. (successful select proves at least that)

I always get the following exception:

javax.persistence.TransactionRequiredException: No active transaction for PuId=project.ear#included.war#persistence-unit-name
[29.08.13 15:14:59:714 CEST] 00000071 SystemErr R at com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:221)
[29.08.13 15:14:59:714 CEST] 00000071 SystemErr R at com.ibm.ws.jpa.management.JPATxEntityManager.getEMInvocationInfo(JPATxEntityManager.java:179)
[29.08.13 15:14:59:714 CEST] 00000071 SystemErr R at com.ibm.ws.jpa.management.JPAEntityManager.persist(JPAEntityManager.java:143)
[29.08.13 15:14:59:714 CEST] 00000071 SystemErr R at com.TestFacade.testEMInsert(TestFacade.java:72)


My persistence.xml (placed in META-INF):

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit
name="persistence-unit-name"
transaction-type="JTA">

<!-- <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> -->
<!-- <provider>com.ibm.websphere.persistence.PersistenceProviderImpl</provider> -->
<jta-data-source>jdbc/test-services-ds</jta-data-source>

<class>com.EntityTest</class>

<properties>
<!--<property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>-->
<property name="openjpa.Log" value="SQL=TRACE"/>
<!-- PrintParameters will show query parameters, remove when development has been finished -->
<!-- <property name="openjpa.ConnectionFactoryProperties" value="PrettyPrint=true, PrettyPrintLineLength=72, PrintParameters=true"/> -->
<property name="openjpa.jdbc.Schema" value="LKWSQL"/>
<property name="openjpa.TransactionMode" value="managed"/>
<property name="openjpa.ConnectionFactoryMode" value="managed"/>
<property name="openjpa.jdbc.DBDictionary" value="db2"/>
</properties>
</persistence-unit>
</persistence>


The persistence.xml will be read so i think the packaging of the ear seems to be ok. I know in JavaEE6 a war would be sufficent, but it was already an existing project setup.
The Team before us switched to user managed transactions, but i hope somebody can help me to point out the mistake.

@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED) // default, but was worth a try
@Path("servicepath")
public class TestFacade implements ITestFacade {

@Inject
private SearchService searchService;
@PersistenceContext(unitName="persistence-unit-name")
private EntityManager em;


The search service caused the first troubles. With @EJB it always was null. @Inject from CDI worked. Maybe that's a clue?

@GET
@Path("testInsert/")
@Produces({ MediaType.TEXT_PLAIN })
public String testEMInsert() {
try{
System.out.println("testing Insert: " + em.isOpen()); // open is true
EntityTest e = new EntityTest("name");
em.persist(e);

} catch (Exception e){
e.printStackTrace();
return e.getMessage();
}

return "OK";
}


I hope anyone has an idea what i could check. Had to change the facade+service names. :-/
greetings
m

Answer

@mkuff - I develop an ear project that targets WAS v8.0.0.7.

All I need to get an EJB properly configured is this:

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;
@Stateless
public class StateInfo {
    @Inject
    @SomeDatabase
    private EntityManager em;

To load the WAS 8.x.x libraries, my Maven pom uses the dependency:

    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>6.0</version>
        <scope>provided</scope>
    </dependency>

As for the @SomeDatabase annotation...that's present because I leverage WAS's CDI (OpenWebBeans). Here's my Qualifier:

import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;

/**
 * @author Chris Harris
 *
 */
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({FIELD, TYPE, METHOD})
public @interface SomeDatabase {}

Then, I use a Producer:

import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * @author Chris Harris
 *
 */
public class JPAResourceProducer {
@SuppressWarnings("unused")
@Produces
@PersistenceContext(unitName = "somePuName")
@SomeDatabase
private EntityManager em;
}

Here's my persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
         xmlns="http://java.sun.com/xml/ns/persistence" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
                             http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="somePuName" transaction-type="JTA">
    <jta-data-source>java:comp/env/someDb</jta-data-source>

Here's the relevant part of web.xml:

<resource-ref id="someDb">
    <res-ref-name>someDb</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

And finally, ibm-web-bnd.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-bnd 
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_1.xsd"
version="1.1">

<virtual-host name="default_host" />

<resource-ref name="someDb" binding-name="jdbc/someDb" />

I have a DataSource defined in WAS that uses the name jdbc/someDb.