views:

1134

answers:

4

I am working on a project with multiple JDBC data sources and JTA. I use Maven as a build tool, and I'd like to use the Jetty plugin (6.1.20) to run the application during development.

I am trying to configure Jetty to use Atomikos as the transaction manager. I'm following the Atomikos documentation from Jetty, but the Jetty startup fails with what looks like a class loader issue.

Here are the relevant bits of my configuration.

runtime scope dependencies in my pom.xml:

<dependency>
 <groupId>com.atomikos</groupId>
 <artifactId>transactions-jta</artifactId>
 <version>3.5.7</version>
 <scope>runtime</scope>
</dependency>
<dependency>
 <groupId>com.atomikos</groupId>
 <artifactId>transactions-jdbc</artifactId>
 <version>3.5.7</version>
 <scope>runtime</scope>
</dependency>
<dependency>
 <groupId>javax.transaction</groupId>
 <artifactId>jta</artifactId>
 <version>1.1</version>
 <scope>runtime</scope>
</dependency>

My jetty-env.xml located in /WEB-INF (autodiscovered by Jetty):

<New id="userTxImpl" class="com.atomikos.icatch.jta.UserTransactionImp" />

<New id="tx" class="org.mortbay.jetty.plus.naming.Transaction">
 <Arg>
  <Ref id="userTxImpl" />
 </Arg>
</New>

The instantiation of tx at the end is the bit that fails, if I leave it out, Jetty starts up fine (but does not expose UserTransaction via JNDI, of course).

The Stacktrace:

    2009-09-02 18:42:18.910::WARN:  Config error at <New id="tx" class="org.mortbay.jetty.plus.naming.Transaction"><Arg>
      <Ref id="userTxImpl"/>
     </Arg></New>
2009-09-02 18:42:18.910::WARN:  Failed startup of context org.mortbay.jetty.plugin.Jetty6PluginWebAppContext@12515db{/administrator,C:\workspace\administrator\src\main\webapp}
java.lang.IllegalStateException: No Constructor: <New id="tx" class="org.mortbay.jetty.plus.naming.Transaction"><Arg>
      <Ref id="userTxImpl"/>
     </Arg></New> on org.mortbay.jetty.plugin.Jetty6PluginWebAppContext@12515db{/administrator,C:\workspace\administrator\src\main\webapp}
    at org.mortbay.xml.XmlConfiguration.newObj(XmlConfiguration.java:631)
    at org.mortbay.xml.XmlConfiguration.configure(XmlConfiguration.java:256)
    at org.mortbay.xml.XmlConfiguration.configure(XmlConfiguration.java:190)
    at org.mortbay.jetty.plus.webapp.EnvConfiguration.configureWebApp(EnvConfiguration.java:130)
    at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1247)
    at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
    at org.mortbay.jetty.plugin.Jetty6PluginWebAppContext.doStart(Jetty6PluginWebAppContext.java:124)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152)
    at org.mortbay.jetty.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:156)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
    at org.mortbay.jetty.Server.doStart(Server.java:224)
    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
    at org.mortbay.jetty.plugin.Jetty6PluginServer.start(Jetty6PluginServer.java:132)
    at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:441)
    at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:383)
    at org.mortbay.jetty.plugin.AbstractJettyRunMojo.execute(AbstractJettyRunMojo.java:210)
    at org.mortbay.jetty.plugin.Jetty6RunMojo.execute(Jetty6RunMojo.java:184)
    at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:579)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:498)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegmentForProject(DefaultLifecycleExecutor.java:265)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:191)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:149)
    at org.apache.maven.DefaultMaven.execute_aroundBody0(DefaultMaven.java:223)
    at org.apache.maven.DefaultMaven.execute_aroundBody1$advice(DefaultMaven.java:304)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:1)
    at org.apache.maven.embedder.MavenEmbedder.execute_aroundBody2(MavenEmbedder.java:904)
    at org.apache.maven.embedder.MavenEmbedder.execute_aroundBody3$advice(MavenEmbedder.java:304)
    at org.apache.maven.embedder.MavenEmbedder.execute(MavenEmbedder.java:1)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:176)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:63)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:408)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:351)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:31)

This looks like a classloader issue, as org.mortbay.jetty.plus.naming.Transaction has got a Constructor taking a javax.transaction.UserTransaction, and com.atomikos.icatch.jta.UserTransactionImp implements javax.transaction.UserTransaction, yet Jetty complains it does not have a proper constructor to use.

I'm obviously missing something here, but what is it?

Thanks!

+5  A: 

You may have multiple copies of the UserTransaction class kicking around in your deployment. If these are loaded from different classloaders, then you can end up with this sort of error.

Check Jetty's libraries for UserTransaction, and then check your application's libraries. You should only have one copy.

skaffman
An indirect dependency on jboss-j2ee, which comes with its own UserTransaction, was the problem. Thanks so much! I thought I was going mad.
Henning
+4  A: 

I believe that you should not be specifying the JTA jar as a 'runtime' requirement, but rather as a 'provided' requirement. Similar to servlet-api and JMS, the individual implementers provide their own copies of the API and providing the Sun jar can muck them up.

Jherico
+2  A: 

I realize this is already answered, but I wanna put up my experience to save others the grief I just went through.

I had a similar problem, but it was caused by a conflict in versions of geronimo-jta spec. Specifically the one depended on by atomikos wasn't getting along with the one used by jetty. I had to exclude the one from atomikos, e.g.:

com.atomikos transactions-essentials-all 3.5.9 org.apache.geronimo.specs geronimo-jta_1.0.1B_spec

Taylor
A: 

Like Taylor, I just blew a couple hours on this exact same issue. I use Hibernate as a JPA provider and it had a Maven depdency on its own JTA User Tranaction. Once I excluded this dependency I got past the issue.

HDave