6 Replies Latest reply on Feb 24, 2004 5:18 AM by kevinconner

    ClassCastException

    meerkat512

      Hi,

      I realize that the ClassCastException problem has already been much-discussed, but I couldn't find a post that helped me solve my issue or addressed the specific situation that I am experiencing:

      I am using Jboss 3.2.3. My classes are all deployed in a jar in the Jboss deploy directory. None of my classes reside in a webapp.

      Object o = context.lookup("FooHome");
      FooHome home = (FooHome)o;
      


      The above code, when run through the SAME JVM as the JBoss/Tomcat bundle (specifically, a servlet) works correctly.

      However, when I run it from a DIFFERENT JVM (i.e. a JUnit class started from the command line), I get "java.lang.ClassCastException: $Proxy0" when trying to cast the object to the FooHome interface. Through symbolic debugging, I can see that the JNDI lookup is indeed returning an object (of type $Proxy0). There is no stack trace of any kind on the JBoss console when this exception occurs.

      I have double-checked that the EJB classes in the client classpath and in the JBoss deploy directory are exactly the same, so this is not a class compatibility problem.

      Does anyone know the solution for this?

      Thanks much.



        • 1. Re: ClassCastException
          meerkat512

          OK,

          I have found a workaround from this post:

          http://www.jboss.org/index.html?module=bb&op=viewtopic&t=9102&watch=topic&start=0

          When I added the line

          Thread.currentThread().setContextClassLoader(FooHome.class.getClassLoader());
          


          before my lookup, the code started working.

          Is this a bug with JBoss? It seems like an excessive hack to have to put a line like this before every JNDI lookup. Does anyone know a better solution for this problem?

          Thanks.

          • 2. Re: ClassCastException
            triathlon98

             

            "meerkat512" wrote:

            Object o = context.lookup("FooHome");
            FooHome home = (FooHome)o;
            



            You should not just cast remote objects, that does not work. Use something like this:

            object o=context.lookup(jndiName);
            FooHome home=javax.rmi.PortableRemoteObject.narrow(o, FooHome.class);
            


            That should do the trick.

            Joachim

            • 3. Re: ClassCastException
              meerkat512

              Hi,

              Using PortableRemoteObject.narrow() also results in a ClassCastException.

              Does this definitely work for you in the situation where you have an entity EJB and the client is running in a different JVM than the server?

              When you write that I should not cast remote objects, is that a general J2EE principle, or something specifically that is not recommended because it doesn't work in JBoss?

              Thanks,
              Dan

              • 4. Re: ClassCastException
                triathlon98

                 

                "meerkat512" wrote:

                Using PortableRemoteObject.narrow() also results in a ClassCastException.

                Does this definitely work for you in the situation where you have an entity EJB and the client is running in a different JVM than the server?

                When you write that I should not cast remote objects, is that a general J2EE principle, or something specifically that is not recommended because it doesn't work in JBoss?


                This definately works and is in all the books about J2EE. It is not JBoss specific. However, you have to be careful that your client jars match the server jars exactly. If you recompile your program and the server and client side jars are not bases on the same compiled classes, then you will never get this to work.

                For in-VM JNDI lookup, a simple cast is sufficient (though probably only in JBoss with both client and server using the same UnifiedClassLoader.
                In principle the PortableRemoteObject.narrow makes sure that the differences between classloaders can be overcome.

                Joachim

                • 5. Re: ClassCastException
                  pilhuhn

                  My experience so far is, that also for remote interfaces and calls, the simple cast is enough in JBoss.

                  • 6. Re: ClassCastException
                    kevinconner

                    The purpose of the PortableRemoteObject.narrow method is to handle the casting when the object uses IIOP as the transport mechanism (corba or RMI/IIOP) and has nothing to do with your problem. You should use this whenever downcast an object that may be using IIOP, the lookup of a home interface being one such occassion.

                    The fact that you can get it to work when you set the thread context loader suggests that you have multiple copies of that interface in different class loaders. The cast will only work if you are casting to a class/interface loaded with the same classloader.

                    Add some debug before the cast to walk the class and interface hierarchy of the objects, printing out the class AND classloader in each case.

                    My guess is that you will find your FooHome interface loaded by multiple classloaders, perhaps in multiple jars.

                    Identify and remove the duplicate entries and your problem will be solved. :-)