3 Replies Latest reply on Apr 11, 2006 3:51 AM by jboss2005_01

    ClassCastException for remote acccess of entity bean

    pieterjan

      Hi,

      I'm working on JBoss 4.0.3SP1 and I'm trying to access an entity bean deployed in one.ear one from two.ear.

      I've been messing around a bit because I can't get it to work. I've deployed both ears, and have put a jar-file containing all classes from one.ear in the lib directory of the server. (otherwise two.ear didn't find the classes it needed)

      But now, when I try to get the entity bean from one.ear and use it in two.ear I get a ClassCastException.

      The strange thing is when I do a findAll() of the entity beans in two.ear, and show the number of entities that are found, the correct number is shown. But from the moment I actually want to use the entity object, the error is thrown.

      Anyone have an idea how I can get this thing to run?
      And how I can deploy my two.ear so that it does find all classes it needs and without putting the jar-file in the lib folder?

      tnx

        • 1. Re: ClassCastException for remote acccess of entity bean
          jboss2005_01

          Hi PieterJan,


          Be carefull by putting application code in het lib folder. This is not the place to be for this kind of code. It should be under the deploy folder and only there unless you are using libraries used by multiple applications to share the same code. In this case you should put it into your configuration's lib folder instead of the server's lib folder.

          You could add one.ear to two.ear to have all code available, but there are much better ways to do this.
          By adding only the EJB class files needed by one.ear from two.ear into one.ear. There is, as far as I remember, a way to provide them in a bootstrap mechanism, called RMI classloading but I have to admit that I am not familiar with this way of working.
          Anyone who can explain this approach? Feel free to do so, I'm also very interested in this solutions too :-)

          The ClassCastException might get caused by two reasons:
          1. First you retrieve a reference to a local interface while a remote interface is needed in your application or vice versa. Since you run on the same server, use local interface to retrieve EJB references instead of remote interfaces. Therefor check if you are retrieving a remote interace from your InitialContext and using a local interface in your code. Remember that if you use remote interface, a standard cast will not work, you have to use the narrowing mechanism on the PortableRemoteObject to cast successfully.

          2. The type of class in the RMI registry and the one you want to use in your code do not match. Probably there is something wrong in your deployment descriptor where you specify the JNDI name together with the appropriate class. Check the objects types in the JNDI registry. (tip : JNDIView in the jmx-console)


          I hope this might solve your problem and you get things up and running... :-)


          Regards,
          Kurt

          • 2. Re: ClassCastException for remote acccess of entity bean
            pieterjan

            Can an entity bean have a local and remote interface or doest that only apply to session beans?

            Anyway, I'm accessing the entity bean through an SLSB (using the dao-pattern found in Hibernate in action). A call to findAll().size() will return the correct amount of records in my table. But the call findById() throws the ClassCastException when I try to assign the returnvalue to an object of the entity bean's class.

            Here is how my packages roughly look like:

            One.ear:
            - entity bean (to oracle, no interface)
            - stateless session bean (dao implementation and interface)

            Two.ear:
            - stateless session bean (a facade that calls the dao from one.ear causing the exception at the cast)

            So far no luck using PortableRemoteObject.


            Thanks for the help Kurt ... but keep it coming ;-)
            Or any idea where I can find an example where multiple ear files are deployed where this kind of remoting is used?

            • 3. Re: ClassCastException for remote acccess of entity bean
              jboss2005_01

              Local and remote interface apply to all kinds of EJBs, entity and session. Are you using BMP or CMP for your entity beans? Under normal circumstances there can be up to 5 classes defining your EJB : 2 home interfaces (defining create, finders,...), 2 remote interfaces (containing your business methods) and the bean implementation class. Both remote and home interfaces have a local variant and a "remote" variant (see below).

              The return type for your finder method should be Collection, Iterator or your EJB itself and depends on the type of interface, the local accessable and the remote accessable.


              Typically the home interface (accessable outside the container) looks something like

              public interface TestEJBHome extends javax.ejb.EJBHome {
               public Test.TestEJB findByPrimaryKey(java.lang.String aKey)
               throws javax.ejb.FinderException, java.rmi.RemoteException;
              
               public TestEJB findById() throws java.rmi.RemoteException, javax.ejb.FinderException;
              }
              


              The local home interface (accessable only from within the container, other EJBs, servlets,...) looks like
              public interface LocalTestEJBHome extends javax.ejb.EJBLocalHome {
               public Test.LocalTestEJB findByPrimaryKey(java.lang.String Key) throws javax.ejb.FinderException;
              
               public LocalTestEJB findById() throws javax.ejb.FinderException;
              }
              


              Notice the difference in return type for the different interfaces !!
              Local interfaces are preferred if you only want to access your EJB from within the container (application server) and not from the outsite (swing client application for example). In fact, local interface are more performant since they don't have RMI overhead. So think well, before you start coding ;-)

              Since you are accessing your entity beans from within session beans in your project, local interfaces will be sufficient. What you get in your code is typically something like
              LocalTestEJBHome home = context.lookup("ejb/TestEJB");
              LocalTestEJB bean = home.create();


              In your deployment descriptors, ejb/TestEJB must be linked to the LocalTestEJB off course.

              This is probably not much information, but if you like I could take a look at a piece of code, specifically the part where you access your entity bean and the entity bean itself.
              The corresponding deployment descriptor looks like
              <ejb-jar>
               <enterprise-beans>
               <entity>
               <display-name>TestEJB</display-name>
               <ejb-name>TestEJB</ejb-name>
               <home>Test.TestEJBHome</home>
               <remote>Test.TestEJB</remote>
               <local-home>Test.LocalTestEJBHome</local-home>
               <local>Test.LocalTestEJB</local>
               <ejb-class>Test.TestEJBBean</ejb-class>
               <persistence-type>Container</persistence-type>
               <prim-key-class>java.lang.String</prim-key-class>
               <reentrant>False</reentrant>
               <abstract-schema-name>TestEJB</abstract-schema-name>
               <cmp-field>
               <field-name>defaultField</field-name>
               </cmp-field>
               <primkey-field>defaultField</primkey-field>
               <query>
               <query-method>
               <method-name>findById</method-name>
               <method-params/>
               </query-method>
               <ejb-ql>SELECT Object(o) FROM TestEJB o</ejb-ql>
               </query>
               </entity>
               </enterprise-beans>
              </ejb-jar>


              I don't have an example with me with multiple EARs, perhaps the J2EE tutorial found at Sun might be something useful for you...

              I myself also run/ran into ClassCastExceptions, but mostly they were caused by JNDI reference errors in my descriptors.

              Isn't it irritating to notice that the computer is always right ;-)

              Cheers,
              Kurt

              Good luck in your search :-)