First off, in your pom.xml you need to add the configuration for maven-jetty-plugin... we need to dance around the various activemq/activeio versions and ensure that we get the correct version of ant...
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.openejb.examples</groupId>
<artifactId>jetty-openejb</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>jetty-openejb Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.22</version>
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>4.1.1</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-ra</artifactId>
<version>4.1.1</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
<version>3.1.2</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>3.1.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-ra</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- in order to use the latest version of openejb, we need to exclude
the dependencies provided in jsp-2.1-jetty -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-jetty</artifactId>
<version>6.1.22</version>
<exclusions>
<exclusion>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<configuration>
<jettyConfig>${basedir}/src/main/jetty/jetty.xml</jettyConfig>
</configuration>
</plugin>
</plugins>
</build>
</project>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.openejb.examples</groupId>
<artifactId>jetty-openejb</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>jetty-openejb Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.22</version>
<dependencies>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>4.1.1</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-ra</artifactId>
<version>4.1.1</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
<version>3.1.2</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>3.1.2</version>
<exclusions>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-ra</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activeio-core</artifactId>
</exclusion>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- in order to use the latest version of openejb, we need to exclude
the dependencies provided in jsp-2.1-jetty -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-jetty</artifactId>
<version>6.1.22</version>
<exclusions>
<exclusion>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<configuration>
<jettyConfig>${basedir}/src/main/jetty/jetty.xml</jettyConfig>
</configuration>
</plugin>
</plugins>
</build>
</project>
Next we need to configure a src/main/jetty/jetty.xml to bind the UserTransaction instance into jetty...
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="srv" class="org.mortbay.jetty.Server">
<New class="javax.naming.InitialContext">
<Arg>
<New class="java.util.Properties">
<Call name="setProperty">
<Arg>java.naming.factory.initial</Arg>
<Arg>org.apache.openejb.client.LocalInitialContextFactory</Arg>
</Call>
</New>
</Arg>
<Call name="lookup" id="tm">
<Arg>openejb:TransactionManager</Arg>
</Call>
</New>
<New class="org.mortbay.jetty.plus.naming.Transaction">
<Arg>
<New class="org.apache.openejb.core.CoreUserTransaction">
<Arg>
<Ref id="tm"/>
</Arg>
</New>
</Arg>
</New>
</Configure>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="srv" class="org.mortbay.jetty.Server">
<New class="javax.naming.InitialContext">
<Arg>
<New class="java.util.Properties">
<Call name="setProperty">
<Arg>java.naming.factory.initial</Arg>
<Arg>org.apache.openejb.client.LocalInitialContextFactory</Arg>
</Call>
</New>
</Arg>
<Call name="lookup" id="tm">
<Arg>openejb:TransactionManager</Arg>
</Call>
</New>
<New class="org.mortbay.jetty.plus.naming.Transaction">
<Arg>
<New class="org.apache.openejb.core.CoreUserTransaction">
<Arg>
<Ref id="tm"/>
</Arg>
</New>
</Arg>
</New>
</Configure>
And presto-chango, now jetty has a transaction manager provided by openejb. (Note: if we don't mind storing that in a jetty-env in /WEB-INF, you can put the same config in WEB-INF/jetty-env.xml)
OK, so here are the issues:
- Reloading does not work (because org.apache.openejb.core.ivm.naming.IvmContext does not support the destroySubcontext(Context) method
- We are using jetty's JNDI provider in the web-app and openejb's JNDI provider for the EJBs... this is because
When jetty binds names to JNDI (using org.mortbay.jetty.plus.naming.Resource or org.mortbay.jetty.plus.naming.Transaction) it binds the object to JNDIName and it also binds a NamingEnrtry for the object to __/JNDIName
Unfortunately, openejb's JNDI implementation seems to be somewhat strange in this regard... if we add the SystemProperties to jetty to have it use openejb's JNDI implementation, e.g. add the following to /project/build/plugins/plugin[maven-jetty-plugin]/configuration/systemProperties
<systemProperty>
<name>java.naming.factory.initial</name>
<value>org.apache.openejb.client.LocalInitialContextFactory</value>
</systemProperty>
Then when we bind __/UserTransaction it gets bound to openejb:__/UserTransaction but when we lookup __/UserTransaction openejb looks up openejb:local/__/UserTransaction
And that is just for starters... there seems to be a whole host of other JNDI strangeness between jetty's side and openejb's side
The side effect of all this is that if you want resource refs to work correctly, you need to fish them out of openejb's JNDI context and push them into jetty's JNDI context
Very cool. I've been trying to figure out this setup for a few weeks; you've really saved me some time.
ReplyDeleteNice work Stephen. Do you have a similar POM for the OpenEJB Tomcat integration?
ReplyDeleteI haven't tried the Tomcat integration, but I believe it's easier. I'm currently looking into forking jetty-plus to avaoid the requirement for jetty to have its own jndi implementation at all
ReplyDeleteHi
ReplyDeleteThanks for this article, i have succeeded to run openejb and jetty using you pom.xml configuration.
But where do we put ejb descriptors, i have added a EJB jar file in the classpath but cannot see it loaded, any idea ?
@cordenier
ReplyDeleteIt all depends!
The way I do this is I add the ejb dependencies as dependencies to the jetty plugin, so that they are available on the openejb classpath... you are treating the jetty-maven-plugin like it is the EAR in which your application is deployed. You'll then need to fish out the ejb refs from openejb's context and push them into the jetty context using jetty.xml
@Stephen Thanks for quick reply !
ReplyDeleteok now i got you, my EJB is now deployed but i cannot access to it but i guess i have enough informations now to find out why.
Thanks, you saved me some time
@cordenier
ReplyDeleteWhat you need to do is add additional Call entries to the end of the New section where we create the openejb initial context, each one looking up your EJBs
Then you add additional Resource entries to your jetty.xml to bind these back into jetty's jndi tree
@Stephen
ReplyDeleteActually, i have a resource locator layer that implements openejb DeploymentListener, and EJB ids are located via their class name.
There is a weird thing, the locator map is well populated but when i ask for an EJB ref with a class as parameter it does not return the value associated to the class. I guess i have to solve a classloading issue first.
Btw, Thank you for your help.
This comment has been removed by the author.
ReplyDeleteNow it works but i had to set ejb lib to provided scope in my web project to avoid classloading issues.
ReplyDeleteBy the way, everything looks to magic now :) Do you know Which class is responsible for auto launching OpenEJB, because i don't see any other configuration than the JNDI one...