Question

I created a "Java EE Web Module" project in IntelliJ. I then wrote a JaxRS annotated class that accepts JSON input. I then populate an annotated entity with the data, and try to persist it using a managed persistence context.


@Stateless
@Path("/states")
public class StateController {
    @PersistenceContext(unitName = "testunit")
    private EntityManager em;

    @POST
    @Path("/session_new")
    @Produces({ MediaType.APPLICATION_JSON })
    @Consumes({ MediaType.APPLICATION_JSON })
    public Response session_new(final CustomerSessionRequest req) {
        CustomerSessions cs = new CustomerSessions(req.session_data);
        em.persist(cs);
        em.flush();
        System.out.println("New CustomerSession saved: " + cs.getCustomerSessionId());

        return Response.ok(cs).build();
    }
}

I have a data source configured within IntelliJ called "testdb", and a persistence unit named "testunit" that maps to that data source in the persistence tool window.

My persistence XML looks like this:

    <persistence-unit name="testunit">
        <jta-data-source>testdb</jta-data-source>
        <class>datamodels.testdb.CustomerSessions</class>
        <properties>
            <property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/testdb"/>
            <property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
            <property name="openjpa.ConnectionUserName" value="testuser"/>
            <property name="openjpa.ConnectionPassword" value="testpassword"/>
            <property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
            <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema" />
        </properties>
    </persistence-unit>
</persistence>

Everything builds and deploys just fine, with no warnings. The request also runs just fine, and returns the expected response, with a new customer session ID generated.

However, nothing appears in the database.

So, my question: where is the data going, and how can I make the persist and flush calls work against my database?

EDIT: I've tried several more things.

1) It looks like TomEE is using some kind of in-memory HSQL database with a data source name of "Default JDBC Data Source". 2) When I manually create the entity manager factory, and then the entity manager, everything works correctly:

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("testunit");
    EntityManager em = emf.createEntityManager();

    try {
        em.getTransaction().begin();

        CustomerSessions cs = new CustomerSessions(req.session_data);
        em.persist(cs);
        em.flush();
        em.getTransaction().commit();
        System.out.println("New CustomerSession saved: " + cs.getCustomerSessionId());
        return Response.ok(cs).build();
    } catch (Exception ex) {
        em.getTransaction().rollback();
        return Response.serverError().entity("An exception occurred").build();
    }

2) If I try to create the EntityManagerFactory using the @PersistenceUnit annotation, the same initial problem occurs.

Was it helpful?

Solution

There were two things I was missing:

  1. I didn't specify <Resource> objects in tomee.xml (which I didn't want to, since I wanted it to deploy with the app). I discovered that this can be done in a resources.xml file in the WEB-INF or META-INF directories.
  2. I didn't have the MySQL driver jar in the TomEE lib directory. Unfortunately TomEE was transparently loading the Default JDBC driver instead, causing entities to persist in its own magical database.

I still don't have an explanation for why application-managed (manually created) persistence contexts worked in the first place, but at least now I have it working consistently.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top