openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Will Hoover" <java.whoo...@gmail.com>
Subject OpenJPA 2.2.0 + Atomikos + Embedded Jetty
Date Wed, 02 May 2012 18:12:36 GMT
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>


Mime
View raw message