Will - I'm betting that the em.persist(..) call isn't happening inside a transaction. Can you enable openjpa trace[1] and rerun your scenario?
[1] <property name="openjpa.Log" value="DefaultLevel=trace" /> Thanks, Rick On Wed, May 2, 2012 at 1:12 PM, Will Hoover <java.whoo...@gmail.com> wrote: > 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> > > -- *Rick Curtis*