I have successfully setup an OpenJPA (2.2.0) + Atomikos (3.7.1) + Embedded
Jetty (8.1.2) stack (example code below). Everything seems to works without
any errors, but OpenJPA doesn't seem to recognize dirty entities after a
call to EntityManager#persist and a new EntityManager is created (see
DefaultAppServlet.java below). Any idea why this would be happening?

ServiceManager.java

public class ServiceManager {
        
        private static final Logger log =
LoggerFactory.getLogger(ServiceManager.class);
        public static final String DEFAULT_PERSISTENT_UNIT = "test-pu";
        private static EntityManagerFactory factory;
        private static WebServer webServer;

        public static void startServices(final String persistentUnit) {
                stopServices();
                setEmFactory(null);
                webServer = WebServer.start(9080);
        }
        public static void stopServices() {
                if (webServer != null) {
                        webServer.stop();
                }
                try {
                        if (factory != null && factory.isOpen()) {
                                factory.close();
                        }
                        factory = null;
                } catch (final Exception e) {
                        log.error("Unable to close " +
EntityManagerFactory.class.getSimpleName(), e);
                }
        }
        public static final EntityManagerFactory getEmFactory() {
                return factory;
        }
        protected static final void setEmFactory(final EntityManagerFactory
factory) {
                if (ServiceManager.factory != null &&
ServiceManager.factory.isOpen()) {
                        ServiceManager.factory.close();
                }
                if (factory == null || !factory.isOpen()) {
                        ServiceManager.factory = Persistence.
        
createEntityManagerFactory(DEFAULT_PERSISTENT_UNIT, 
                                        System.getProperties());
                }
                ServiceManager.factory = factory;
        }
}

WebServer.java

public class WebServer {

        private static final Logger log =
LoggerFactory.getLogger(WebServer.class);
        private final int portNumber;
        private Server server;
        
        private WebServer(final int portNumber) {
                this.portNumber = portNumber <=0 ? 80 : portNumber;
        }
        public static final WebServer start() {
                final WebServer webServer = new WebServer();
                final Thread webServerAgent = new
Thread(Thread.currentThread().getThreadGroup(), new Runnable() {
                        @Override
                        public void run() {
                                webServer.startServer();
                        }
                }, WebServer.class.getSimpleName() + '-' +
System.currentTimeMillis());
                webServerAgent.setDaemon(true);
                webServerAgent.start();
                return webServer;
        }
        protected final void startServer() {
                try {
                        final Resource serverXml =
Resource.newSystemResource("META-INF/jetty.xml");
                        final XmlConfiguration configuration = new
XmlConfiguration(serverXml.getInputStream());
                        server = (Server) configuration.configure();
                        // set the connector based upon user settings
                        final SelectChannelConnector defaultConnnector = new
SelectChannelConnector();
                        defaultConnnector.setPort(getPortNumber());
                        server.setConnectors(new Connector[] {
defaultConnnector });
                        
                        final EnumSet<DispatcherType> dispatchers =
EnumSet.range(DispatcherType.FORWARD, DispatcherType.ERROR);
                        ServletContextHandler context = new
ServletContextHandler(ServletContextHandler.SESSIONS);
                        context.setContextPath("/");
                        context.addFilter(TransactionFilter.class, "/*",
dispatchers);
                        context.addServlet(DefaultAppServlet.class, "/");
                        server.setHandler(context);
                        
                        server.setDumpAfterStart(true);
                        server.start();
                        server.join();
                } catch (final Throwable e) {
                        log.error("Unable to start web server", e);
                }
        }
        public final void stop() {
                try {
                        if (server != null && !server.isStopped() &&
!server.isStopping()) {
                                server.stop();
                        }
                        server.destroy();
                } catch (final Exception e) {
                        log.error("Unable to shutdown", e);
                }
        }
        public int getPortNumber() {
                return portNumber;
        }
}

DefaultAppServlet.java

public class DefaultAppServlet extends DefaultServlet {

        private static final Logger log =
LoggerFactory.getLogger(DefaultAppServlet.class);
        public DefaultAppServlet() {
                super();
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
                response.setContentType("text/html;charset=utf-8");
                response.setStatus(HttpServletResponse.SC_OK);
                response.getWriter().println("<h1>Hello Message
World</h1>");
                try {
                EntityManager em =
ServiceManager.getEmFactory().createEntityManager();
                        final Message msg = new Message("Hello Persistence!
" + System.currentTimeMillis());
                em.persist(msg);
                em.close();

                // DOES NOT RECOGNIZE THE ENTITY JUST PERSISTED
                EntityManager em2 =
ServiceManager.getEmFactory().createEntityManager();
                Query q = em2.createQuery("select m from Message m");
                for (Message m : (List<Message>) q.getResultList()) {
                    System.out.println(m.getMessage() + " (created on: " +
m.getCreated() + ')');
                    response.getWriter().println("<h3>" + m.getMessage() + "
(created on: " + m.getCreated() + ')' + "</h3>");
                }
                em2.close();
                } catch (Throwable t) {
                        log.error("Error: ", t);
                }
        }
}

TransactionFilter.java

public class TransactionFilter implements Filter {

        public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain) {
                try {

                        // start a new transaction for this request
                        getTransaction().setTransactionTimeout(10000);
                        getTransaction().begin();

                        // delegate the request to the next filter, and
eventually to the
                        // target servlet or JSP
                        chain.doFilter(request, response);

                        // if no exception happened: commit the transaction
                        getTransaction().commit();
                } catch (final Throwable t) {
                        // analyze exception to dermine of rollback is
required or not
                        // and then call rollback or commit on utx as
appropriate
                        t.printStackTrace();
                        try {
                                getTransaction().rollback();
                        } catch (final Throwable t2) {
                                t2.printStackTrace();
                        }
                }
        }
        @Override
        public void destroy() {
        }
        @Override
        public void init(FilterConfig filterConfig) throws ServletException
{
        }
        protected TransactionManager getTransaction() {
                try {
                        // from Jetty JNDI configuration
                        return (TransactionManager) new
InitialContext().lookup("UserTransaction");
                } catch (final NamingException e) {
                        e.printStackTrace();
                }
                return null;
        }
        
}

META-INF/persistence.xml

<?xml version="1.0"?>
<persistence 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";
        version="2.0">
        <persistence-unit name="test-pu" transaction-type="JTA">
        
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
                <jta-data-source>jdbc/testDS</jta-data-source>
                <class>com.example.jpa.entity.Message</class>
                <properties>
                        <property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>
<!--                    <property name="openjpa.jdbc.JDBCListeners" value="
com.example.jpa.UGateJdbcListener"/> -->
<!--                    <property name="openjpa.DynamicEnhancementAgent"
value="false"/> -->
                        <property name="openjpa.ConnectionFactoryProperties"
value="PrettyPrint=true, PrettyPrintLineLength=72" />
                        <property name="openjpa.Log"
value="DefaultLevel=WARN, Tool=INFO, SQL=WARN"/>

                        <property name="openjpa.ConnectionFactoryMode"
value="managed" />
                        <property name="openjpa.TransactionMode"
value="managed" />
                        <property name="openjpa.ManagedRuntime"
        
value="jndi(TransactionManagerName=UserTransaction)" />
<!--                    <property name="openjpa.ManagedRuntime" -->
<!--
value="invocation(TransactionManagerMethod=com.atomikos.icatch.jta.Transacti
onManagerImp.getTransactionManager)" /> -->
                </properties>
        </persistence-unit>
</persistence>

Jetty (plus: jetty-all version 8.1.2) configuration

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://www.eclipse.org/jetty/configure.dtd";>
<Configure id="Server" class="org.eclipse.jetty.server.Server">
        <!-- =========================================================== -->
        <!-- Define a server aware DB XA connection data source -->
        <!-- =========================================================== -->
        <New id="xaDataSource" class="org.eclipse.jetty.plus.jndi.Resource">
                <Arg></Arg>
                <Arg>jdbc/testDS</Arg>
                <Arg>
                        <New id="atomikosDS"
class="com.atomikos.jdbc.AtomikosDataSourceBean">
                                <Set name="minPoolSize">2</Set>
                                <Set name="maxPoolSize">50</Set>
                                <Set
name="xaDataSourceClassName">org.h2.jdbcx.JdbcDataSource</Set>
                                <Set
name="UniqueResourceName">jdbc/testDS</Set>
                                <Set name="testQuery">SELECT 1 and SELECT 1
FROM DUAL</Set>
                                <Get name="xaProperties">
                                        <Call name="setProperty">
                                                <!-- Must be upper case -->
                                                <Arg>URL</Arg>
        
<Arg>jdbc:h2:~/test;AUTO_SERVER=TRUE;FILE_LOCK=SOCKET;TRACE_LEVEL_FILE=0;TRA
CE_LEVEL_SYSTEM_OUT=1</Arg>
                                        </Call>
                                        <Call name="setProperty">
                                                <Arg>user</Arg>
                                                <Arg>sa</Arg>
                                        </Call>
                                        <Call name="setProperty">
                                                <Arg>password</Arg>
                                                <Arg>sa</Arg>
                                        </Call>
                                </Get>
                        </New>
                </Arg>
        </New>
        <!-- =========================================================== -->
        <!-- Add a closer bean that will dispose of the DB DS -->
        <!-- =========================================================== -->
        <Ref id='Server'>
                <Call name="addBean">
                        <Arg>
                                <New
class="org.eclipse.jetty.jndi.DataSourceCloser">
                                        <Arg>
                                                <Ref id="atomikosDS" />
                                        </Arg>
                                </New>
                        </Arg>
                </Call>
        </Ref>
        <!-- =========================================================== -->
        <!-- Define server transaction aware JTA implementation -->
        <!-- =========================================================== -->
        <New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
                <Arg>
                        <New
class="com.atomikos.icatch.jta.UserTransactionManager" />
                </Arg>
        </New>

        ...

</Configure>

Reply via email to