title: Getting started with embeddable JBoss EAP 6 / AS 7
body: <p>I'm trying out embeddable JBoss with the EJBContainer.createEJBContainer API described in the spec (JSR 318: Enterprise JavaBeans, Version 3.1, ch. 22: Embeddable Usage), <strong>not</strong> any of the <a href="http://shrubbery.mynetgear.net/c/display/W/Embedded+JBoss+and+Embedded+EJB3" rel="nofollow">various predecessors</a> using JBoss specific APIs.</p>
  
  <h1>Overview</h1>
  
  <ul>
  <li>When i invoke my main method normally, a session bean invocation succeeds. But there seem to be some classloading issues, because the JNDI object at <code>"java:jboss/UserTransaction"</code> cannot be cast to javax.transaction.UserTransaction.</li>
  <li>So i guess the classloading magic of <a href="https://docs.jboss.org/author/display/MODULES/Home" rel="nofollow">JBoss Modules</a> is required here. With my attempts at that, createEJBContainer does not find any EJBContainerProviders and throws an EJBException.</li>
  </ul>
  
  <p>Note that not all my questions require reading all subsequent details. So if this is too much to read, please have a look at the questions section nevertheless. Thanks!</p>
  
  <h1>Environment</h1>
  
  <p>JBoss AS 7.1.1.Final (jboss-as-7.1.1.Final.zip with only logging conf changed in standalone.xml)<br>
  (Initially JBoss EAP 6.0.1 GA which is the actual target environment - same problem)<br>
  Oracle JDK 1.7.0_11<br>
  Windows 7 Prof 64 bit  </p>
  
  <h1>Details</h1>
  
  <h3>The stateless session bean</h3>
  
  <pre><code>package test.helloworld.impl;
  
  import javax.ejb.Remote;
  import javax.ejb.Stateless;
  import test.helloworld.api.HelloWorld;
  
  @Stateless
  @Remote(HelloWorld.class)
  public class HelloWorldBean implements HelloWorld
  {
      @Override
      public String salute()
      {
          return "Hello, world";
      }
  }
  </code></pre>
  
  <p>... and its business interface:</p>
  
  <pre><code>package test.helloworld.api;
  
  public interface HelloWorld
  {
      String salute();
  }
  </code></pre>
  
  <h3>The client program</h3>
  
  <pre><code>package test.helloworld.client;
  
  import static java.lang.System.out;
  import java.io.File;
  import java.util.HashMap;
  import java.util.Map;
  import javax.ejb.embeddable.EJBContainer;
  import javax.naming.Context;
  import javax.transaction.UserTransaction;
  import test.helloworld.api.HelloWorld;
  
  
  public class HelloWorldEmbeddedEjbTestClient
  {
      public static void main(String[] args)
      {
          int status = 1;
  
          try
          {
              main();
              status = 0;
          }
          catch (Throwable e)
          {
              e.printStackTrace(System.err);
              System.err.flush();
          }
          finally
          {
              // Simply returning from main leaves some thread (and
              // hence the JVM) running for another 60s, so force exit
              System.exit(status);
          }
      }
  
  
      private static void main() throws Exception
      {
          Map&lt;String, Object&gt; properties = new HashMap&lt;String, Object&gt;();
          properties.put(EJBContainer.MODULES, new File[]{new File("./HelloWorld-EJB.jar")});
          EJBContainer container = EJBContainer.createEJBContainer(properties);
  
          try
          {
              Context jndiContext = container.getContext();
              Object serviceObj = jndiContext.lookup("java:global/HelloWorld-EJB/HelloWorldBean");
              out.println("service:\t" + serviceObj);
              HelloWorld service = (HelloWorld) serviceObj;
              out.println("result:\t" + service.salute());
  
              callInTx(service, jndiContext);
          }
          finally
          {
              out.println("closing EJBContainer...");
              container.close();
              out.println("EJBContainer closed.");
          }
      }
  
  
      private static void callInTx(HelloWorld service, Context jndiContext) throws Exception
      {
          UserTransaction tx = (UserTransaction) jndiContext.lookup("java:jboss/UserTransaction");
          tx.begin();
          out.println("result in tx:\t" + service.salute());
          tx.commit();
      }
  }
  </code></pre>
  
  <h3>Packaging</h3>
  
  <p>C:\eclipse\projects\HelloWorldSlSB-Client\rt\HelloWorld-API.jar:</p>
  
  <pre><code>META-INF/MANIFEST.MF
  test/helloworld/api/HelloWorld.class
  </code></pre>
  
  <p>C:\eclipse\projects\HelloWorldSlSB-Client\rt\HelloWorld-EJB.jar:</p>
  
  <pre><code>META-INF/MANIFEST.MF
  META-INF/jboss-deployment-structure.xml
  test/helloworld/impl/HelloWorldBean.class
  test/helloworld/api/HelloWorld.class
  </code></pre>
  
  <p>HelloWorld-EJB.jar:META-INF/jboss-deployment-structure.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;
  &lt;jboss-deployment-structure&gt;
      &lt;deployment&gt;
          &lt;dependencies&gt;&lt;/dependencies&gt;
          &lt;exclusions&gt;
              &lt;module name="Classpath"/&gt;
          &lt;/exclusions&gt;
      &lt;/deployment&gt;
  &lt;/jboss-deployment-structure&gt;
  </code></pre>
  
  <p>C:\eclipse\projects\HelloWorldSlSB-Client\rt\modules\test\helloworld\client\main\HelloWorldSlSB-Client.jar:</p>
  
  <pre><code>META-INF/MANIFEST.MF
  test/helloworld/client/HelloWorldEmbeddedEjbTestClient.class
  </code></pre>
  
  <p>C:\eclipse\projects\HelloWorldSlSB-Client\rt\modules\test\helloworld\client\main\module.xml:
      
      </p>
  
  <pre><code>    &lt;main-class name="test.helloworld.client.HelloWorldEmbeddedEjbTestClient"/&gt;
  
      &lt;resources&gt;
          &lt;resource-root path="HelloWorldSlSB-Client.jar"/&gt;
      &lt;/resources&gt;
  
      &lt;dependencies&gt;
          &lt;module name="javax.api"/&gt;
          &lt;module name="javax.ejb.api"/&gt;
          &lt;module name="org.jboss.as.embedded" export="true"/&gt;
  &lt;!--
          &lt;module name="org.jboss.as.server" export="true"/&gt;
  --&gt;
      &lt;/dependencies&gt;
  &lt;/module&gt;
  </code></pre>
  
  <p>All META-INF/MANIFEST.MF files contain nothing but "Manifest-Version: 1.0".  </p>
  
  <h1>Results</h1>
  
  <h2>Direct invocation</h2>
  
  <p>With a direct invocation of HelloWorldEmbeddedEjbTestClient.main with <code>-Xmx512m -XX:MaxPermSize=256m</code>, classpath  </p>
  
  <pre><code>C:\eclipse\output\HelloWorldSlSB-Client
  C:\java\jboss-as-7\jboss-modules.jar
  C:\java\jboss-as-7\modules\org\jboss\as\embedded\main\jboss-as-embedded-7.1.1.Final.jar
  C:\java\jboss-as-7\modules\javax\ejb\api\main\jboss-ejb-api_3.1_spec-1.0.1.Final.jar
  C:\java\jboss-as-7\modules\javax\transaction\api\main\jboss-transaction-api_1.1_spec-1.0.0.Final.jar
  C:\java\jboss-as-7\modules\org\jboss\logging\main\jboss-logging-3.1.0.GA.jar
  C:\java\jboss-as-7\modules\org\jboss\as\controller-client\main\jboss-as-controller-client-7.1.1.Final.jar
  C:\java\jboss-as-7\modules\org\jboss\logmanager\main\jboss-logmanager-1.2.2.GA.jar
  C:\java\jboss-as-7\modules\org\jboss\dmr\main\jboss-dmr-1.1.1.Final.jar
  C:\eclipse\projects\HelloWorldSlSB-Client\rt\HelloWorld-API.jar
  </code></pre>
  
  <p>and system properties</p>
  
  <pre><code>-Duser.language=en
  -Djboss.home=c:/java/jboss-as-7
  -Djboss.home.dir=c:/java/jboss-as-7
  -Dorg.jboss.as.embedded.ejb3.BARREN=true
  -Dfile.encoding=ISO-8859-1
  </code></pre>
  
  <p>the EJB invocation succeeds, but JNDI object "java:jboss/UserTransaction" cannot be cast to javax.transaction.UserTransaction:  </p>
  
  <pre><code>...
  19:21:01,875 INFO  [org.jboss.ejb.client] (main) JBoss EJB Client version 1.0.5.Final
  service:    Proxy for remote EJB StatelessEJBLocator{appName='', moduleName='HelloWorld-EJB', distinctName='', beanName='HelloWorldBean', view='interface test.helloworld.api.HelloWorld'}
  result: Hello, world
  closing EJBContainer...
  19:21:06,362 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015877: Stopped deployment HelloWorld-EJB.jar in 90ms
  19:21:06,370 INFO  [org.jboss.as.repository] (pool-9-thread-1) JBAS014901: Content removed from location c:\java\jboss-as-7\standalone\data\content\35\424415b9a67d64fe8a6dc7ee0700480282f34b\content
  19:21:06,370 INFO  [org.jboss.as.server] (pool-9-thread-1) JBAS018558: Undeployed "HelloWorld-EJB.jar"
  19:21:06,390 INFO  [org.jboss.as.osgi] (MSC service thread 1-1) JBAS011942: Stopping OSGi Framework
  EJBContainer closed.
  java.lang.ClassCastException: org.jboss.tm.usertx.client.ServerVMClientUserTransaction cannot be cast to javax.transaction.UserTransaction
      at test.helloworld.client.HelloWorldEmbeddedEjbTestClient.callInTx(HelloWorldEmbeddedEjbTestClient.java:65)
      at test.helloworld.client.HelloWorldEmbeddedEjbTestClient.main(HelloWorldEmbeddedEjbTestClient.java:52)
      at test.helloworld.client.HelloWorldEmbeddedEjbTestClient.main(HelloWorldEmbeddedEjbTestClient.java:21)
  </code></pre>
  
  <p>(Looks a little strange, because the exception is caught and printed at the end of main. But of course, it happens before the container is closed.)</p>
  
  <p>The debugger shows that the JNDI object's getClass().getClassLoader() is org.jboss.modules.ModuleClassLoader<br>
  <code>ModuleClassLoader for Module "org.jboss.jboss-transaction-spi:main" from local module loader @4b436982 (roots: c:\java\jboss-as-7\modules)</code><br>
  and its getClass().getInterfaces()[0] /* == interface javax.transaction.UserTransaction */.getClassLoader() is<br>
  <code>ModuleClassLoader for Module "javax.transaction.api:main" from local module loader @4b436982 (roots: c:\java\jboss-as-7\modules)</code><br>
  However, UserTransaction.class.getClassLoader() is of type sun.misc.Launcher$AppClassLoader.</p>
  
  <h2>jboss-modules.jar invocation</h2>
  
  <p>Invoked via org.jboss.modules.Main.main (i.e. what <code>java -jar jboss-modules.jar</code> also does) with classpath</p>
  
  <pre><code>C:\java\jboss-as-7\jboss-modules.jar
  </code></pre>
  
  <p>system properties as above, and arguments</p>
  
  <pre><code>-mp "C:\java\jboss-as-7\modules;C:\eclipse\projects\HelloWorldSlSB-Client\rt\modules"
  test.helloworld.client
  </code></pre>
  
  <p>it fails already in createEJBContainer:</p>
  
  <pre><code>javax.ejb.EJBException: Unable to instantiate container with factories []
      at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:97)
      at test.helloworld.client.HelloWorldEmbeddedEjbTestClient.main(HelloWorldEmbeddedEjbTestClient.java:42)
      at test.helloworld.client.HelloWorldEmbeddedEjbTestClient.main(HelloWorldEmbeddedEjbTestClient.java:21)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at org.jboss.modules.Module.run(Module.java:260)
      at org.jboss.modules.Main.main(Main.java:291)
  </code></pre>
  
  <p>Debugging shows that this happens because in method EJBContainer.findAllFactories(), no resources "META-INF/services/javax.ejb.spi.EJBContainerProvider" are found in the thread context classloader, which is<br>
  <code>ModuleClassLoader for Module "test.helloworld.client:main" from local module loader @1afec586 (roots: C:\java\jboss-as-7\modules,C:\eclipse\projects\HelloWorldSlSB-Client\rt\modules)</code></p>
  
  <h1>Questions</h1>
  
  <ul>
  <li>Does anyone know how to fix this or has gotten anything similar to work?</li>
  <li>Is a normal JBoss installation the right starting point, or do i need a specific embeddable variant?</li>
  <li>Is UserTransaction even supposed to be usable in the embeddable scenario?
  <ul>
  <li>If it is, does that mean i could also use one XA datasource for both JPA 2 CMT entities and legacy JDBC code? And both could participate in the same transaction (e.g. JDBC code starts tx with java.sql.Connection.setAutoCommit(false), then calls EJB with TransactionAttributeType.REQUIRED)?</li>
  </ul></li>
  <li>Can someone point me to some documentation? All i find is about the older stuff with JBoss specific API, not the standard EJB 3.1 way.
  <ul>
  <li>Preferably, documentation how to use without any test frameworks, since i'm evaluating this for production use.</li>
  </ul></li>
  </ul>
  
  <p>Thanks for reading all (or part of :-) this!</p>