Jump to: navigation, search

Difference between revisions of "EclipseLink/Bugs/305331"

m (Option 3: Global Shared Library - Server level scope - verifying)
m (Specifying @Remote @Stateless Session Bean using Defaults)
 
(28 intermediate revisions by the same user not shown)
Line 14: Line 14:
 
| Michael O'Brien
 
| Michael O'Brien
 
| 1.0 Initial investigation of solution scenarios
 
| 1.0 Initial investigation of solution scenarios
 +
|-
 +
| 20100318
 +
| Michael O'Brien
 +
| 1.1 Issue #2 - the EJB ProxyFailure issue is resolved by using a 3 part JNDI lookup that includes a prefixed application name
 +
|-
 +
| 20100319
 +
| Michael O'Brien
 +
| 1.2 With Yiping Zhao and Peter Krogh - Solution for Issue #1 - the signing issue
 
|}
 
|}
  
 
== Status ==
 
== Status ==
*In progress 20100311 for options 3,4 and 5.
+
*Issue 1: Signing: Override signed '''%SERVER/common/lib/ejb3-persistence.jar''' with the lower unsigned  '''%SERVER/jboss-as/server/default/lib/'''' ''ejb3-persistence.jar (CE edition)'', ''trunk/plugins/javax.persistence_unsigned_for_testing_1.0.0.jar'' or ''trunk/jpa/plugins/javax.persistence_2.0.0.v201002051058.jar''
*<font color="red">Currently recommending '''[[EclipseLink/Bugs/305331#Option_1:_Replace_signed_ejb3-persistence.jar_with_an_unsigned_version_from_JBoss_5.1.0_community_edition_-_valid|Option 1]]'''</font> - until options 3,4 and 5 are validated
+
*<font color="green">Currently recommending '''[[EclipseLink/Bugs/305331#Option_7:_Override_common.2Flib_with_default.2Flib_for_both_eclipselink_and_javax.persistence_jars|Option 7]]'''</font>
 +
*Issue 2: EJB ProxyFactory Exception: Use 3-part '''(app_name/bean_name/remote)''' or '''(app_name/remote-bean_name/qualified_bean_name)'''.
  
 
== Overview ==
 
== Overview ==
*The EAP 5.0.0 GA version of the JBoss Application Server ships with signed library jars.  This presents a problem for users of EclipseLink that place our unsigned implementation jar '''eclipselink.jar''' beside the JPA 1.0 ''javax specification'' jar - '''ejb3-persistence.jar''' in the '''common/lib''' library folder off the server.  On deploymehnt in EAP 5.0.0 GA we receive a '''Security Exception''' because of the difference in security levels.
+
===Issue 1: Signed JAR===
 +
*The EAP 5.0.0 GA version of the JBoss Application Server ships with signed library jars.  This presents a problem for users of EclipseLink that place our unsigned implementation jar '''eclipselink.jar''' beside the JPA 1.0 ''javax specification'' jar - '''ejb3-persistence.jar''' in the '''common/lib''' library folder off the server.  On deployment in EAP 5.0.0 GA we receive a '''Security Exception''' because of the difference in security levels.
 
*The Community Edition of JBoss 5.1.0 and 6.0.0 M1 do not have these issues because their library jars are unsigned.
 
*The Community Edition of JBoss 5.1.0 and 6.0.0 M1 do not have these issues because their library jars are unsigned.
 
*This document details several possible solutions to this ''signed jar'' issue and recommends the best approach.
 
*This document details several possible solutions to this ''signed jar'' issue and recommends the best approach.
 
*JBoss '''[https://jira.jboss.org/jira/browse/JBPAPP-2971 JIRA JBPAPP-2971]''' is encountering the same issue with cglib.jar - one of the alternatives for this JIRA are the same as [[EclipseLink/Bugs/305331#Option_1:_Replace_signed_ejb3-persistence.jar_with_an_unsigned_version_from_JBoss_5.1.0_community_edition_-_valid|Option 1]]
 
*JBoss '''[https://jira.jboss.org/jira/browse/JBPAPP-2971 JIRA JBPAPP-2971]''' is encountering the same issue with cglib.jar - one of the alternatives for this JIRA are the same as [[EclipseLink/Bugs/305331#Option_1:_Replace_signed_ejb3-persistence.jar_with_an_unsigned_version_from_JBoss_5.1.0_community_edition_-_valid|Option 1]]
 +
 +
===Issue 2: EJB ProxyFactory Exception===
 +
*Outside of Eclipse we are not resolving an EJB Stateless Session bean Proxy properly - specifically in 5.0 EAP version of the JBoss server (The 5.1 and 6.0 version of the Community edition are working fine
 +
*The solution is to use a more strict JBoss specific JNDI format that is required of JBoss EAP but is optional in JBoss CE
 +
**Prepend the application(EAR) name in front of the bean_name/remote-qualified_bean_name JNDI lookup.
 +
**Both the JNDI lookup and narrow work fine and return a session bean proxy.
 +
**https://bugs.eclipse.org/bugs/show_bug.cgi?id=305330#c9
 +
====Exception====
 +
<pre>
 +
javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Exception while trying to locate proxy factory in JNDI,
 +
at key ProxyFactory/eclipselink-advanced-field-access-model/TestRunner/TestRunner]
 +
at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1504)
 +
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:822)
 +
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686)
 +
at javax.naming.InitialContext.lookup(InitialContext.java:392)
 +
at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBareClient(JUnitTestCase.java:480)
 +
at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBare(JUnitTestCase.java:455) Caused by: java.lang.RuntimeException: Exception while trying to locate proxy factory in JNDI,
 +
at key ProxyFactory/eclipselink-advanced-field-access-model/TestRunner/TestRunner
 +
at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getProxyFactoryFromJNDI(ProxyObjectFactory.java:235)
 +
at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getObjectInstance(ProxyObjectFactory.java:153)
 +
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
 +
at org.jnp.interfaces.NamingContext.getObjectInstance(NamingContext.java:1479)
 +
at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1496) Caused by: javax.naming.NameNotFoundException: ProxyFactory not bound at org.jnp.server.NamingServer.getBinding(NamingServer.java:771)
 +
at org.jnp.server.NamingServer.getBinding(NamingServer.java:779)
 +
at org.jnp.server.NamingServer.getObject(NamingServer.java:785)
 +
at org.jnp.server.NamingServer.lookup(NamingServer.java:396)
 +
at org.jnp.server.NamingServer.lookup(NamingServer.java:399)
 +
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
 +
at sun.rmi.transport.Transport$1.run(Transport.java:159)
 +
at java.security.AccessController.doPrivileged(Native Method)
 +
at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
 +
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
 +
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
 +
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
 +
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 +
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 +
at java.lang.Thread.run(Thread.java:619)
 +
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
 +
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
 +
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
 +
at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
 +
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:726)
 +
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686)
 +
at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getProxyFactoryFromJNDI(ProxyObjectFactory.java:226)
 +
</pre>
 +
 +
====Code Details of the fix====
 +
<source lang="java">
 +
        properties.put("java.naming.provider.url", "jnp://localhost:1099/");
 +
        //properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
 +
        Context context = new InitialContext(properties);
 +
        TestRunner runner;
 +
        testrunner = "eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner";
 +
        System.out.println("_lookup: " + testrunner);
 +
        Object reference = context.lookup(testrunner);
 +
        System.out.println("_reference:" + reference);
 +
        runner = (TestRunner) PortableRemoteObject.narrow(reference, TestRunner.class);
 +
        System.out.println("_narrowed:" + runner);
 +
</source>
 +
 +
====JNDI Output Logs====
 +
=====Previously not working with truncated JNDI lookup that is missing the EAR name=====
 +
<source lang="java">
 +
//testrunner = "eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner";
 +
[junit] _lookup: TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner
 +
</source>
 +
 +
=====Working=====
 +
<source lang="java">
 +
testrunner = "eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner";
 +
[junit] _lookup: eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner
 +
[junit] _reference:Proxy to jboss.j2ee:ear=eclipselink-advanced-field-access-model.ear,jar=eclipselink-advanced-field-access-model_ejb.jar,name=TestRunner,service=EJB3 implementing [interface org.eclipse.persistence.testing.framework.server.TestRunner]
 +
[junit] _narrowed:Proxy to jboss.j2ee:ear=eclipselink-advanced-field-access-model.ear,jar=eclipselink-advanced-field-access-model_ejb.jar,name=TestRunner,service=EJB3 implementing [interface org.eclipse.persistence.testing.framework.server.TestRunner]
 +
</source>
 +
 +
====Summary:====
 +
*The fix is to follow the more strict JBoss specific JNDI format of ''EAR_name/EJB_name/remote-qualified''_EJB_name instead of ''EJB_name/remote-qualified_EJB_name''
 +
 +
====EJB 3.0 Specification details on JNDI lookup of EJB reference====
 +
*The specification only mentions the standard 2 part format
 +
**3.6.1 p51
 +
<source lang="java">CartHome cartHome = (CartHome)ctx.lookup(“com.acme.example.MySessionBean/cartHome”);</source>
  
 
== Concepts ==
 
== Concepts ==
Line 62: Line 154:
 
===Prerequisites===
 
===Prerequisites===
 
===Data Model===
 
===Data Model===
*The testing models for reproduction are based off of the [http://wiki.eclipse.org/EclipseLink/Examples/JPA/JBoss_Web_Tutorial JBoss server example] in the SVN trunk.
+
*The standalone testing models for reproduction are based off of the [http://wiki.eclipse.org/EclipseLink/Examples/JPA/JBoss_Web_Tutorial JBoss server example] in the SVN trunk.
 +
*The formal testing model is the '''TestRunnerBean''' in the JPA test suite
 +
====EJB JNDI Specification Defaults====
 +
*There are 2 primary ways of defining a stateless session bean and it's remote interface, one involves using defaults, the other has annotation overrides.
 +
*The way that you define these classes will determine what the JNDI name is when looking up the Proxy from the ProxyFactory on JBoss.
 +
=====Specifying @Remote @Stateless Session Bean using Defaults=====
 +
*The following scenario specifies @Remote on the remote interface and @Stateless on the stateless session bean.
 +
**This results in the following JNDI name emitted by the server on EAR deploy
 +
<source lang="java">
 +
 
 +
 
 +
@Stateless(name="ApplicationService", mappedName="ApplicationService")
 +
@Remote(ApplicationServiceRemote.class)
 +
public class ApplicationService implements ApplicationServiceRemote  {
 +
@PersistenceContext(unitName="example", type=PersistenceContextType.TRANSACTION)
 +
private EntityManager entityManager;
 +
...
 +
}
 +
 
 +
public class FrontController extends HttpServlet implements Servlet {
 +
    public static final String APPLICATION_SERVICE_JNDI_NAME = "org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR/ApplicationService/remote-org.eclipse.persistence.example.jpa.server.business.ApplicationServiceRemote";   
 +
 
 +
    /**
 +
    * Get the SSB ApplicationService bean - using a JNDI context lookup (no EJB injection was used on this servlet)
 +
    * @param viaJNDILookup
 +
    * @return
 +
    */
 +
    public ApplicationServiceRemote getApplicationService(boolean viaJNDILookup) {
 +
        if(null == applicationService && viaJNDILookup) {
 +
            try {
 +
                Hashtable<String, String> env = new Hashtable<String, String>();     
 +
                env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");   
 +
                env.put(Context.PROVIDER_URL, "localhost");     
 +
                env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces" );   
 +
                InitialContext ctx = new InitialContext(env);
 +
                System.out.println("FrontController.getApplicationService() JNDI lookup of " + APPLICATION_SERVICE_JNDI_NAME);
 +
                return (ApplicationServiceRemote) ctx.lookup(APPLICATION_SERVICE_JNDI_NAME);           
 +
            } catch (Exception e) {
 +
                e.printStackTrace();
 +
                throw new RuntimeException("Exception looking up session bean: ", e);            }
 +
        } else {
 +
            return applicationService;
 +
        }
 +
    }
 +
...
 +
}
 +
</source>
 +
 
 +
=====Specifying @Remote @Stateless Session Bean using Overrides=====
 +
<source lang="java">
 +
public interface TestRunner { ... }
 +
 
 +
@Stateless(name="TestRunner", mappedName="TestRunner")
 +
@Remote(TestRunner.class)
 +
@TransactionManagement(TransactionManagementType.BEAN)
 +
public class TestRunnerBean implements TestRunner {
 +
    @PersistenceContext
 +
    private EntityManager entityManager;
 +
...
 +
}
 +
</source>
 +
 
 +
===Servlet Client for Local Stateless Session Bean===
 +
*The following JNDI context lookup is used to get a reference to the local interface of the stateless session bean deployed in the ejb.jar of the EAR.
 +
===SE Client for Remote Stateless Session Bean===
 +
*The following JNDI context lookup will get a standalone SE client a reference to the stateless session bean running in the example EAR.
 +
<source lang="java">
 +
</source>
 +
 
 
===Use Case 1: Container managed Persistence Unit injected on a Stateless Session Bean invoked via a Servlet client===
 
===Use Case 1: Container managed Persistence Unit injected on a Stateless Session Bean invoked via a Servlet client===
 
*This use case is valid for options 1, 2, 5
 
*This use case is valid for options 1, 2, 5
Line 78: Line 238:
 
* Remove the JPA 2.0 API in the stateless session bean and revert persistence.xml from a JPA 2.0 to JPA 1.0 level before running the example project in trunk
 
* Remove the JPA 2.0 API in the stateless session bean and revert persistence.xml from a JPA 2.0 to JPA 1.0 level before running the example project in trunk
 
* Client EAR runs out of the box using default HSQL TX datasource - https://bugs.eclipse.org/bugs/attachment.cgi?id=161810
 
* Client EAR runs out of the box using default HSQL TX datasource - https://bugs.eclipse.org/bugs/attachment.cgi?id=161810
 +
* Client is a Servlet with JNDI injection via
 +
<source lang="java">
 +
public static final String APPLICATION_SERVICE_JNDI_NAME = "org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR/ApplicationService/local";
 +
...
 +
        Hashtable<String, String> env = new Hashtable<String, String>();     
 +
        env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");   
 +
        env.put(Context.PROVIDER_URL, "localhost");     
 +
        env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces" );   
 +
        InitialContext ctx = new InitialContext(env);
 +
        return (ApplicationServiceLocal) ctx.lookup(APPLICATION_SERVICE_JNDI_NAME);           
 +
</source>
 +
* Need to test SE client
 +
 
====Results 1:====
 
====Results 1:====
 
*JPA 1.0 application runs fine
 
*JPA 1.0 application runs fine
Line 120: Line 293:
 
====Client Configuration 5:====
 
====Client Configuration 5:====
 
====Results 5:====
 
====Results 5:====
 +
===<font color="red">''Option 6: ship eclipselink and javax.persistence jar only in EAR - infeasible''</font>===
 +
====Server Configuration 6:====
 +
*Remove '''ejb3-persistence.jar''' from ''common/lib'' on the server.
 +
====Client Configuration 6:====
 +
*add '''javax.persistence''' and '''eclipselink.jar''' to the ''EAR/lib'' directory.
 +
====Results 6:====
 +
*The JBoss server will not start because the web apps internal to the server require the presence of '''ejb3-persistence''' at the global server classpath level.
 +
===<font color="green">''Option 7: Override common/lib with default/lib for both eclipselink and javax.persistence jars''</font>===
 +
====Server Configuration 7:====
 +
*keep the signed '''ejb3-persistence.jar''' from ''common/lib'' on the server in place.
 +
*copy eclipselink.jar to ''server/default/lib''
 +
*copy javax.persistence spec jar to ''server/default/lib''
 +
====Client Configuration 7:====
 +
*no changes
 +
====Results 7:====
 +
*EntityManager and EntityManagerFactory injection on the remote stateless session bean is working fine.
 +
*The JPA war applications that start with the JBoss server deploy fine
 +
*Weaving is unaffected as currently only static weaving is avaible on JBoss
  
 
== Open Issues ==
 
== Open Issues ==
Line 149: Line 340:
 
== References ==
 
== References ==
 
*[http://wiki.eclipse.org/EclipseLink/Examples/JPA/JBoss_Web_Tutorial EclipseLink JPA Tutorial EAR for JBoss 5.1.0 and 6.0.0 M1]
 
*[http://wiki.eclipse.org/EclipseLink/Examples/JPA/JBoss_Web_Tutorial EclipseLink JPA Tutorial EAR for JBoss 5.1.0 and 6.0.0 M1]
**EclipseLink JBoss Tutorial [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR/ EAR], [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEJB/ EJB] and [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseWeb/ WAR] projects in SVN.
+
*EclipseLink JBoss Tutorial [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR/ EAR], [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEJB/ EJB] and [http://dev.eclipse.org/svnroot/rt/org.eclipse.persistence/trunk/examples/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseWeb/ WAR] projects in SVN.
 +
*[https://community.jboss.org/message/533316 JBoss Community Post 531496]

Latest revision as of 10:05, 24 June 2010

Contents

Bug Analysis Document: 305331: EclipseLink deployment on JBoss EAP 5.0.0 GA using signed JPA 1.0 ejb3-persistence.jar

Document History

Date Author Version Description & Notes
20100312 Michael O'Brien 1.0 Initial investigation of solution scenarios
20100318 Michael O'Brien 1.1 Issue #2 - the EJB ProxyFailure issue is resolved by using a 3 part JNDI lookup that includes a prefixed application name
20100319 Michael O'Brien 1.2 With Yiping Zhao and Peter Krogh - Solution for Issue #1 - the signing issue

Status

  • Issue 1: Signing: Override signed %SERVER/common/lib/ejb3-persistence.jar with the lower unsigned %SERVER/jboss-as/server/default/lib/' ejb3-persistence.jar (CE edition), trunk/plugins/javax.persistence_unsigned_for_testing_1.0.0.jar or trunk/jpa/plugins/javax.persistence_2.0.0.v201002051058.jar
  • Currently recommending Option 7
  • Issue 2: EJB ProxyFactory Exception: Use 3-part (app_name/bean_name/remote) or (app_name/remote-bean_name/qualified_bean_name).

Overview

Issue 1: Signed JAR

  • The EAP 5.0.0 GA version of the JBoss Application Server ships with signed library jars. This presents a problem for users of EclipseLink that place our unsigned implementation jar eclipselink.jar beside the JPA 1.0 javax specification jar - ejb3-persistence.jar in the common/lib library folder off the server. On deployment in EAP 5.0.0 GA we receive a Security Exception because of the difference in security levels.
  • The Community Edition of JBoss 5.1.0 and 6.0.0 M1 do not have these issues because their library jars are unsigned.
  • This document details several possible solutions to this signed jar issue and recommends the best approach.
  • JBoss JIRA JBPAPP-2971 is encountering the same issue with cglib.jar - one of the alternatives for this JIRA are the same as Option 1

Issue 2: EJB ProxyFactory Exception

  • Outside of Eclipse we are not resolving an EJB Stateless Session bean Proxy properly - specifically in 5.0 EAP version of the JBoss server (The 5.1 and 6.0 version of the Community edition are working fine
  • The solution is to use a more strict JBoss specific JNDI format that is required of JBoss EAP but is optional in JBoss CE

Exception

javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Exception while trying to locate proxy factory in JNDI, 
at key ProxyFactory/eclipselink-advanced-field-access-model/TestRunner/TestRunner] 
at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1504) 
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:822) 
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686) 
at javax.naming.InitialContext.lookup(InitialContext.java:392) 
at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBareClient(JUnitTestCase.java:480) 
at org.eclipse.persistence.testing.framework.junit.JUnitTestCase.runBare(JUnitTestCase.java:455) Caused by: java.lang.RuntimeException: Exception while trying to locate proxy factory in JNDI, 
at key ProxyFactory/eclipselink-advanced-field-access-model/TestRunner/TestRunner 
at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getProxyFactoryFromJNDI(ProxyObjectFactory.java:235) 
at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getObjectInstance(ProxyObjectFactory.java:153) 
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304) 
at org.jnp.interfaces.NamingContext.getObjectInstance(NamingContext.java:1479) 
at org.jnp.interfaces.NamingContext.getObjectInstanceWrapFailure(NamingContext.java:1496) Caused by: javax.naming.NameNotFoundException: ProxyFactory not bound at org.jnp.server.NamingServer.getBinding(NamingServer.java:771) 
at org.jnp.server.NamingServer.getBinding(NamingServer.java:779) 
at org.jnp.server.NamingServer.getObject(NamingServer.java:785) 
at org.jnp.server.NamingServer.lookup(NamingServer.java:396) 
at org.jnp.server.NamingServer.lookup(NamingServer.java:399) 
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305) 
at sun.rmi.transport.Transport$1.run(Transport.java:159) 
at java.security.AccessController.doPrivileged(Native Method) 
at sun.rmi.transport.Transport.serviceCall(Transport.java:155) 
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535) 
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790) 
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649) 
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
at java.lang.Thread.run(Thread.java:619) 
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255) 
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233) 
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142) 
at org.jnp.server.NamingServer_Stub.lookup(Unknown Source) 
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:726) 
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686) 
at org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory.getProxyFactoryFromJNDI(ProxyObjectFactory.java:226)

Code Details of the fix

        properties.put("java.naming.provider.url", "jnp://localhost:1099/");
        //properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
        Context context = new InitialContext(properties);
        TestRunner runner;
        testrunner = "eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner";
        System.out.println("_lookup: " + testrunner);
        Object reference = context.lookup(testrunner);
        System.out.println("_reference:" + reference);
        runner = (TestRunner) PortableRemoteObject.narrow(reference, TestRunner.class);
        System.out.println("_narrowed:" + runner);

JNDI Output Logs

Previously not working with truncated JNDI lookup that is missing the EAR name
//testrunner = "eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner";
 [junit] _lookup: TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner
Working
testrunner = "eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner";
 [junit] _lookup: eclipselink-advanced-field-access-model/TestRunner/remote-org.eclipse.persistence.testing.framework.server.TestRunner
 [junit] _reference:Proxy to jboss.j2ee:ear=eclipselink-advanced-field-access-model.ear,jar=eclipselink-advanced-field-access-model_ejb.jar,name=TestRunner,service=EJB3 implementing [interface org.eclipse.persistence.testing.framework.server.TestRunner]
 [junit] _narrowed:Proxy to jboss.j2ee:ear=eclipselink-advanced-field-access-model.ear,jar=eclipselink-advanced-field-access-model_ejb.jar,name=TestRunner,service=EJB3 implementing [interface org.eclipse.persistence.testing.framework.server.TestRunner]

Summary:

  • The fix is to follow the more strict JBoss specific JNDI format of EAR_name/EJB_name/remote-qualified_EJB_name instead of EJB_name/remote-qualified_EJB_name

EJB 3.0 Specification details on JNDI lookup of EJB reference

  • The specification only mentions the standard 2 part format
    • 3.6.1 p51
CartHome cartHome = (CartHome)ctx.lookup(“com.acme.example.MySessionBean/cartHome”);

Concepts

JPA Specification Notes

JPA 1.0 Specification

JPA 2.0 Specification

Reproduction

Results: unsigned/signed conflict SecurityException - expected

Logs:

2010-03-11 11:10:08,988 INFO  [org.jboss.bootstrap.microcontainer.ServerImpl] (main) JBoss (Microcontainer) [5.0.0.GA (build: SVNTag=JBPAPP_5_0_0_GA
date=200910202128)] Started in 1m:3s:180ms
2010-03-11 11:10:47,698 INFO [org.jboss.ejb3.deployers.Ejb3DependenciesDeployer] (HDScanner) Encountered deployment
AbstractVFSDeploymentContext@26267218{vfszip:/C:/opt/jboss-eap-5.0/jboss-as/server/default/deploy/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR.ear/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEJB.jar/}
2010-03-11 11:10:48,059 INFO [org.jboss.jpa.deployment.PersistenceUnitDeployment] (HDScanner) Starting persistence unit
persistence.unit:unitName=org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR.ear/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEJB.jar#example
2010-03-11 11:10:48,069 WARN [org.jboss.detailed.classloader.ClassLoaderManager] (HDScanner) Unexpected error during load of:javax.persistence.spi.ProviderUtil java.lang.SecurityException:  lass "javax.persistence.spi.ProviderUtil"'s signer information does not match signer information of other classes in the
same package
    at java.lang.ClassLoader.checkCerts(ClassLoader.java:769)
...
    at
org.jboss.jpa.deployment.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:285)
>and resultant secondary exception CNFE because the signed JPA 1.0 specification class was not loaded 2010-03-11 11:10:48,069 ERROR
[org.jboss.kernel.plugins.dependency.AbstractKernelController] (HDScanner) Error installing to Start:
name=persistence.unit:unitName=org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR.ear/org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEJB.jar#example
state=Create
java.lang.NoClassDefFoundError: javax/persistence/spi/ProviderUtil
Caused by: java.lang.ClassNotFoundException: Unexpected error during load of: javax.persistence.spi.ProviderUtil, msg=class
"javax.persistence.spi.ProviderUtil"'s signer information does not match signer information of other classes in the same package

Prerequisites

Data Model

  • The standalone testing models for reproduction are based off of the JBoss server example in the SVN trunk.
  • The formal testing model is the TestRunnerBean in the JPA test suite

EJB JNDI Specification Defaults

  • There are 2 primary ways of defining a stateless session bean and it's remote interface, one involves using defaults, the other has annotation overrides.
  • The way that you define these classes will determine what the JNDI name is when looking up the Proxy from the ProxyFactory on JBoss.
Specifying @Remote @Stateless Session Bean using Defaults
  • The following scenario specifies @Remote on the remote interface and @Stateless on the stateless session bean.
    • This results in the following JNDI name emitted by the server on EAR deploy
@Stateless(name="ApplicationService", mappedName="ApplicationService")
@Remote(ApplicationServiceRemote.class)
public class ApplicationService implements ApplicationServiceRemote  {
	@PersistenceContext(unitName="example", type=PersistenceContextType.TRANSACTION)	
	private EntityManager entityManager;
...
}
 
public class FrontController extends HttpServlet implements Servlet {
    public static final String APPLICATION_SERVICE_JNDI_NAME = "org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR/ApplicationService/remote-org.eclipse.persistence.example.jpa.server.business.ApplicationServiceRemote";    
 
    /**
     * Get the SSB ApplicationService bean - using a JNDI context lookup (no EJB injection was used on this servlet)
     * @param viaJNDILookup
     * @return
     */
    public ApplicationServiceRemote getApplicationService(boolean viaJNDILookup) {
        if(null == applicationService && viaJNDILookup) {
            try {
                Hashtable<String, String> env = new Hashtable<String, String>();      
                env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");     
                env.put(Context.PROVIDER_URL, "localhost");      
                env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces" );     
                InitialContext ctx = new InitialContext(env);
                System.out.println("FrontController.getApplicationService() JNDI lookup of " + APPLICATION_SERVICE_JNDI_NAME);
                return (ApplicationServiceRemote) ctx.lookup(APPLICATION_SERVICE_JNDI_NAME);            
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("Exception looking up session bean: ", e);            }
        } else {
            return applicationService;
        }
    }
...
}
Specifying @Remote @Stateless Session Bean using Overrides
public interface TestRunner { ... }
 
@Stateless(name="TestRunner", mappedName="TestRunner")
@Remote(TestRunner.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class TestRunnerBean implements TestRunner {
    @PersistenceContext
    private EntityManager entityManager;
...
}

Servlet Client for Local Stateless Session Bean

  • The following JNDI context lookup is used to get a reference to the local interface of the stateless session bean deployed in the ejb.jar of the EAR.

SE Client for Remote Stateless Session Bean

  • The following JNDI context lookup will get a standalone SE client a reference to the stateless session bean running in the example EAR.
 

Use Case 1: Container managed Persistence Unit injected on a Stateless Session Bean invoked via a Servlet client

  • This use case is valid for options 1, 2, 5

Use Case 2: Application managed Persistence Unit injected on Servlet client

  • This use case is valid for options 1, 2, 3, 4, 5

StackTrace

Logs

Analysis

Option 1: Replace signed ejb3-persistence.jar with an unsigned version from JBoss 5.1.0 community edition - valid

Server Configuration 1:

  • place eclipselink.jar into common/lib.
  • replace the signed JBoss EAP 5.0.0 (ejb3-persistence.jar) with the unsigned version from JBoss 5.1.0 (community edition) - both JPA 1.0 versions in common/lib
  • restart server, deploy EAR

Client Configuration 1:

  • Remove the JPA 2.0 API in the stateless session bean and revert persistence.xml from a JPA 2.0 to JPA 1.0 level before running the example project in trunk
  • Client EAR runs out of the box using default HSQL TX datasource - https://bugs.eclipse.org/bugs/attachment.cgi?id=161810
  • Client is a Servlet with JNDI injection via
public static final String APPLICATION_SERVICE_JNDI_NAME = "org.eclipse.persistence.example.jpa.server.jboss.EnterpriseEAR/ApplicationService/local";
...
        Hashtable<String, String> env = new Hashtable<String, String>();      
        env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");     
        env.put(Context.PROVIDER_URL, "localhost");      
        env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces" );     
        InitialContext ctx = new InitialContext(env);
        return (ApplicationServiceLocal) ctx.lookup(APPLICATION_SERVICE_JNDI_NAME);
  • Need to test SE client

Results 1:

  • JPA 1.0 application runs fine
12:01:41,308 INFO  [STDOUT] [EL Finest]: 2010-03-11 12:01:41.308--UnitOfWork(11747982)--Thread(Thread[http-127.0.0.1-8080-1,5,jboss])--Register the existing object org.eclipse.persistence.example.jpa.server.business.Cell@3324876( id: 2 state: null left: null right: null parent: HashSet@34627602 references: HashSet@34627602)

Option 2: Ship signed eclipselink.jar - invalid

  • This option has us sign our eclipselink.jar with jarsigner - however we do not have access to the private keys used to sign the JBoss libraries so this is currently not feasible.
  • If the user's application is signed (IE: they are running a signed applet persistence client) - they will need to resign the jar.

Option 3: Global Shared Library - Server level scope - verifying

  • In this option we create a global shared library on the server or in a jar-only EAR that is accessible to all server applications.
  • This shared library must override the common/lib/ejb3-persistence.jar.

Server Configuration 3:

  • no eclipselink.jar into common/lib.
Shared Library on EAR/lib
  • Add EAR/lib/eclipselink.jar and EAR/lib/javax.persistence_2.0.0.v201002051058.jar
  • Reference these two jars in the war/src/META-INF/manifest.MF
    • Class-Path: javax.persistence_2.0.0.v201002051058.jar eclipselink.jar
  • Getting CCE because the ejb3.persistence.jar on the server is taking precedence by default over the specification jar shipped with the EAR - IE: you cannot have two javax.persistence jars.
    • java.lang.ClassCastException: org.eclipse.persistence.jpa.PersistenceProvider cannot be cast to javax.persistence.spi.PersistenceProvider
  • Solution would be a similar override as for WebLogic via
    <wls:prefer-application-packages>

Client Configuration 3:

  • place eclipselink.jar and the jpa 1.0/2.0 specification jar into EAR/lib.
  • One of
    • jboss-app.xml
    • EAR/lib
    • application.xml

Results 3:

Option 4: Application Shared Library - Local EAR level scope - verifying

Server Configuration 4:

Client Configuration 4:

Results 4:

Option 5: Generate an eclipselink jar with the JPA 2.0 dependencies removed

Server Configuration 5:

Client Configuration 5:

Results 5:

Option 6: ship eclipselink and javax.persistence jar only in EAR - infeasible

Server Configuration 6:

  • Remove ejb3-persistence.jar from common/lib on the server.

Client Configuration 6:

  • add javax.persistence and eclipselink.jar to the EAR/lib directory.

Results 6:

  • The JBoss server will not start because the web apps internal to the server require the presence of ejb3-persistence at the global server classpath level.

Option 7: Override common/lib with default/lib for both eclipselink and javax.persistence jars

Server Configuration 7:

  • keep the signed ejb3-persistence.jar from common/lib on the server in place.
  • copy eclipselink.jar to server/default/lib
  • copy javax.persistence spec jar to server/default/lib

Client Configuration 7:

  • no changes

Results 7:

  • EntityManager and EntityManagerFactory injection on the remote stateless session bean is working fine.
  • The JPA war applications that start with the JBoss server deploy fine
  • Weaving is unaffected as currently only static weaving is avaible on JBoss

Open Issues

Issue # Owner Description / Notes
I1 mobrien -

Decisions

Issue # Description / Notes Decision

Future Considerations

References