1 2 Previous Next 21 Replies Latest reply on May 17, 2018 3:01 PM by ftg314159

    Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB

    ftg314159

      Background:

       

      I'm trying to port an EJB 2.1 application that was running happily under JBoss 6.0.0.Final to WildFly 12.0.  This does not use EJB 3 annotations, but has a full deployment descriptor.

       

      The EAR deploys without error, but when I try to look up the Remote EJB from a client, the lookup() returns an org.wildfly.naming.client.store.RelativeContext object that causes a ClassCastException when I try to cast it to the Remote EJB class, either with PortableRemoteObject.narrow() or with the EJB 3 direct cast.

       

      I've googled this, and all of the hits seem to deal with clashes between Classloaders for WARs and EJBs, but that's not the case here.  This is a vanilla WildFly install running standalone-full with no changes and nothing but the EAR containing the EJB deployed.

       

      Following the docs, I changed jndi.properties to use:

         java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory

         java.naming.provider.url=http-remoting://ftgme2.griffin.treehouse.com:8080

         jboss.naming.client.ejb.context=true

      where previously it had used port 1099 and a JBoss InitialContextFactory.

       

      The original lookup string was <ear-name>/<bean name>/remote.  That complained about no provider for URI: null, so following the quickstart I switched this to ear:<ear-name>/<bean name>/remote, and that got me to the ClassCastException.  The quickstart examples added !<full class name>, so I tried that with the same result.

       

      The examples also inserted the EJB jar name, but when I tried that the lookup itself failed saying the name couldn't be found.

       

      The deployment issues the messages:

       

      [0m [0m13:37:20,809 INFO  [org.jboss.as.ejb3.deployment] (MSC service thread 1-6) WFLYEJB0473: JNDI bindings for session bean named 'DBUtDVDSessionBean' in deployment unit 'subdeployment "dvd-ejb-1.0-SNAPSHOT.jar" of deployment "dvd-ear.ear"' are as follows:

       

          java:global/dvd-ear/dvd-ejb-1.0-SNAPSHOT/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanLocal

          java:app/dvd-ejb-1.0-SNAPSHOT/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanLocal

          java:module/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanLocal

          java:global/dvd-ear/dvd-ejb-1.0-SNAPSHOT/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanRemote

          java:app/dvd-ejb-1.0-SNAPSHOT/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanRemote

          java:module/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanRemote

          java:jboss/exported/dvd-ear/dvd-ejb-1.0-SNAPSHOT/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanRemote

       

       

      Looking through the docs, it seems that there are now two ways to do lookups, one that does the classic JNDI lookup on the server and one that builds a local proxy from extra information in the lookup string and only binds to the EJB when the proxy is used, but it's not clear to me which is which.  The other one uses port 4447 and "remote." properties, but nmap shows port 4447 to be closed, so I assumed port 8080 was now the default.

       

      So I have two questions.

       

      The first is why and under what circumstances a JNDI lookup would return a RelativeContext which can't possibly work.  I looked at the RelativeContext source, but it only has a few public methods that don't seem to have anything to do with proxying an EJB.

       

      The second is can someone point me to the correct jndi.properties and lookup string format for WildFly if mine aren't correct ?  When I originally wrote this application, I took great care to use as few JBoss-specific features as possible so as to ensure portability from one AS to another, so while I understand that the new delayed binding is more efficient from a network standpoint, if it involves WildFly-specific features I'd rather stay with the classic JNDI model.

       

      Thanks,

      Frank Griffin

        • 1. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
          jaikiran

          Can you post the complete exception stacktrace and the exact JNDI lookup string that you use to trigger that exception?

           

          When I originally wrote this application, I took great care to use as few JBoss-specific features as possible so as to ensure portability from one AS to another, so while I understand that the new delayed binding is more efficient from a network standpoint, if it involves WildFly-specific features I'd rather stay with the classic JNDI model.

          JNDI services are backed by context factories. In order to interact with a remote JNDI server, you will have to configure these context factories. Each server provides its own context factories and there's no standardization for this on the remote client side. However, all this info is/can be externalized in a properties file (like you have done). So the approach you follow is the right one and you aren't locking yourself to some server specific APIs. As long as you don't use any server specific code within your lookup code, you should be fine.

          • 2. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
            ftg314159

            The exception is pretty simple, just a ClassCastException when I try to cast the lookup() returned object to my session bean interface:

             

            Exception caught:

            org.wildfly.naming.client.store.RelativeContext cannot be cast to org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanIntf

                 java.lang.ClassCastException: org.wildfly.naming.client.store.RelativeContext cannot be cast to org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanIntf

                     at org.profsoftsvcs.dbutils.DVD.DBUtDVDDisks.init(DBUtDVDDisks.java:369)

                     at org.profsoftsvcs.dbutils.DVD.DBUtDVDDisks.main(DBUtDVDDisks.java:210)

             

            No exception occurs during the lookup or in WildFly code.

             

            The lookup string is "ejb:dvd-ear/DBUtDVDSessionBean/remote".  I've also tried "ejb:dvd-ear/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanIntf" with the same result.  The EAR is dvd-ear.ear.

             

            The jndi.properties is:

             

            java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory

            #java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

            #java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

            #java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory

            java.naming.provider.url=http-remoting://ftgme2.griffin.treehouse.com:8080

            #java.naming.provider.url=jnp://ftgme2.griffin.treehouse.com:1099

            #java.naming.provider.url=http-remoting://127.0.0.1:8080

            jboss.naming.client.ejb.context=true

            #jnp.disableDiscovery=true

            java.naming.security.principal=userA

            java.naming.security.credentials=*********

             

             

            Both DBUtDVDSessionBeanLocal and DBUtDVDSessionBeanRemote implement DBUtSessionBeanIntf, the intention being that except for the actual lookup the same client code can be used for both the Local and Remote Bean objects.

            • 3. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
              jaikiran

              ftg314159  wrote:

               

               

               

              The lookup string is "ejb:dvd-ear/DBUtDVDSessionBean/remote".  I've also tried "ejb:dvd-ear/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanIntf" with the same result.  The EAR is dvd-ear.ear.

               

              Looking at the log you posted in the first post, the lookup string should be:

               

              ejb:dvd-ear/dvd-ejb-1.0-SNAPSHOT//DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanRemote

              Can you use this exact lookup string and see how it goes?

              • 4. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                mayerw01

                Which jars do you have in your classpath. The jars are working in my environment:

                jboss-client.jar

                jboss-remoting-4.0.18.Final.jar

                remoting-jmx-2.0.1.Final.jar

                wildfly-naming-10.0.0.Final.jar

                jboss-ejb-client-2.1.4.Final.jar

                 

                Apparently Wildfly doe not accept the "ejb:" prefix anymore. So I'd suggest to remove it from your lookup string.

                • 5. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                  dmlloyd

                  That is incorrect; WildFly does in fact accept the "ejb:" JNDI URI prefix, and has done so since (I believe) around JBoss AS 7.1 or so.  It creates a proxy without performing a lookup (unless the "?stateful" affix is given), which is sometimes desirable for standalone client applications but this also functions inside the application server.

                  • 6. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                    mayerw01

                    This does not reflect my experience when testing this using wildfly-12.0.0.Final. When I do a test using

                     

                    lookup: ejb:/wildfly-ejb-remote-server-side-10.0.0-SNAPSHOT/CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator

                     

                    I get a message: "EJBCLIENT000025: No EJB receiver available for handling ..."

                     

                    But when I run the same program using

                    lookup: /wildfly-ejb-remote-server-side-10.0.0-SNAPSHOT/CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator

                     

                    it works correctly

                    • 7. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                      ftg314159

                      I'll try that lookup string as an experiment, but I'm concerned that it is quite different from the standard one we used to use.  I'm thinking that this one (with the JAR name) is part of the new scheme to avoid traffic with the server during lookup.  I'd really prefer to stick with something not specific to WildFly. 

                       

                      I'm suspecting that the context factory, the provider URL, and the lookup string all have to be in sync for a particular style of lookup and they're not.  I've probably mixed-and-matched in trying to get this to work.  Specifically, I suspect that my adding "ejb:" to the lookup string is causing the use of the new no-server lookup style.

                      • 8. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                        ftg314159

                        Trying the string you gave gets a different error:

                         

                        Exception caught:

                        Absent Code attribute in method that is not native or abstract in class file javax/ejb/EJBException

                             java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ejb/EJBException

                                 at java.lang.ClassLoader.defineClass1(Native Method)

                                 at java.lang.ClassLoader.defineClass(ClassLoader.java:763)

                                 at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)

                                 at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)

                                 at java.net.URLClassLoader.access$100(URLClassLoader.java:73)

                                 at java.net.URLClassLoader$1.run(URLClassLoader.java:368)

                                 at java.net.URLClassLoader$1.run(URLClassLoader.java:362)

                                 at java.security.AccessController.doPrivileged(Native Method)

                                 at java.net.URLClassLoader.findClass(URLClassLoader.java:361)

                                 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

                                 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)

                                 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

                                 at org.jboss.ejb.client.EJBClient.createProxy(EJBClient.java:161)

                                 at org.jboss.ejb.client.EJBRootContext.lookupNative(EJBRootContext.java:163)

                                 at org.wildfly.naming.client.AbstractContext.lookup(AbstractContext.java:84)

                                 at org.wildfly.naming.client.WildFlyRootContext.lookup(WildFlyRootContext.java:144)

                                 at javax.naming.InitialContext.lookup(InitialContext.java:417)

                                 at org.profsoftsvcs.dbutils.DVD.DBUtDVDDisks.init(DBUtDVDDisks.java:363)

                                 at org.profsoftsvcs.dbutils.DVD.DBUtDVDDisks.main(DBUtDVDDisks.java:210)

                         

                        I also tried with a single slash after SNAPSHOT - same result

                        • 9. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                          ftg314159

                          The classpath is a possible source of error.  This is a Maven project which inherits from a project I used for all JBoss applications which had a dependency of jbossall-client.  I've changed that to wildfly-ejb-client-bom and rebuilt it, but it still shows a ton of JBoss-specific stuff.  At some point, I'll create a clean WildFly version of this project and have the DVD project inherit from that.

                          • 10. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                            ftg314159

                            This is making more sense.  Apparently by including "ejb:" I'm triggering the new non-server lookup style.  So the question now is what provider URL and Context Factory I should be using to get the old style lookup.

                            • 11. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                              ftg314159

                              Another interesting thing.  When I search for Maven depencies using "wildfly-ejb-client" I get three hits:

                               

                              wildfly-ejb-client-bom

                              wildfly-ejb-client-legacy-bom

                              wildfly-http-ejb-client

                               

                              Should I be using legacy ?

                              • 12. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                                dmlloyd

                                You are correct that you have a classpath problem.  In particular, you have some kind of stub EJB client JAR in the classpath that definitely should not be there.

                                 

                                If you're trying to invoke EJBs remotely then you normally would only want either the "wildfly-ejb-client-bom" with specific depenendencies (such as jboss-ejb-client), or more simply, just use the org.wildfly:wildfly-client-all:12.0.0.Final JAR and do not include any other dependencies related to Java EE (not even EJB API JARs or anything like that; it's all in there already).

                                • 13. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                                  dmlloyd

                                  ftg314159  wrote:

                                   

                                  This is making more sense.  Apparently by including "ejb:" I'm triggering the new non-server lookup style.  So the question now is what provider URL and Context Factory I should be using to get the old style lookup.

                                  It's not really a distinction between "old" and "new" per se; the "ejb:" lookups are new(er) but functionally distinct from the "remote JNDI" style of lookup where the proxy is actually fetched from the server.  To use remote JNDI, you would look up "dvd-ear/dvd-ejb-1.0-SNAPSHOT/DBUtDVDSessionBean!org.profsoftsvcs.dbutils.DVD.DBUtDVDSessionBeanRemote" or similar.  Basically any name bound under "java:jboss/exported/xxxx" can be looked up via remote JNDI as "xxxx".  You can see which bindings exist for EJBs from the log messages you've pasted above.

                                   

                                  Also, unrelatedly, I'd recommend setting your application's module name to be just "dvd-ejb" or similar in your "application.xml" (IOW exclude that version number), so that your binding names don't change every time you make a new release in Maven.

                                  • 14. Re: Remote EJB Lookup returns a RelativeContext that can't be cast to the EJB
                                    ftg314159

                                    David, I assume you saw some class in a stacktrace that shouldn't be there.  Can you identify which one(s) so I can determine where they're coming from ?

                                    1 2 Previous Next