7 Replies Latest reply on Aug 16, 2005 3:14 AM by George Taylor

    Stateless Sessionbeans via lookup.

    George Taylor Newbie

      I have a session bean that i am testing, and cannot get the session bean to load correctly, I keep getting a class cast in my struts action.

      The code is as follows:

      UserSessionBean.java
      ==============
      package com.flytxt.session;
      import java.util.Iterator;
      import javax.ejb.Local;
      import javax.ejb.Remote;
      import javax.ejb.Stateless;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      import com.flytxt.global.intf.session.UserSessionLocal;
      import com.flytxt.global.intf.session.UserSessionRemote;
      import com.flytxt.global.vo.ContactVO;

      @Stateless
      @Remote(UserSessionRemote.class)
      @Local(UserSessionLocal.class)
      public class UserSessionBean implements UserSessionLocal, UserSessionRemote {
      @PersistenceContext (name="globalManager")
      private EntityManager manager;

      public ContactVO getContact(Integer id) {
      System.out.println("got here");
      return new ContactVO();
      }
      }


      UserSessionLocal.java
      ==============
      package com.flytxt.global.intf.session;
      import javax.ejb.Local;

      @Local
      public interface UserSessionLocal extends UserSession
      {
      }

      UserSessionRemote.java
      package com.flytxt.global.intf.session;
      import javax.ejb.Remote;

      @Remote
      public interface UserSessionRemote extends UserSession{
      }

      UserSession.java
      ===========
      package com.flytxt.global.intf.session;
      import com.flytxt.global.vo.ContactVO;

      public interface UserSession {
      public ContactVO getContact(Integer id);
      }


      My action class is very basic, and looks to me exactly like the example classes. Both the ejb and web app are running in the same instance of jboss.

      WelcomeAction.java
      =============
      package com.flytxt.admin.actions;

      import javax.naming.InitialContext;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import org.apache.struts.action.Action;
      import org.apache.struts.action.ActionForm;
      import org.apache.struts.action.ActionForward;
      import org.apache.struts.action.ActionMapping;
      import com.flytxt.global.intf.session.UserSession;
      import com.flytxt.global.intf.session.UserSessionLocal;
      import com.flytxt.global.intf.session.UserSessionRemote;

      public class WelcomeAction extends Action {
      public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception {
      InitialContext ctx = new InitialContext();
      Object o = ctx.lookup(UserSessionLocal.class.getName());
      System.out.println(o + "==" + o.getClass().getName());
      System.out.println("UserSessionLocal: " + (o instanceof UserSessionLocal));
      System.out.println("UserSessionRemote: " + (o instanceof UserSessionRemote));
      System.out.println("UserSession: " + (o instanceof UserSession));
      UserSession us = (UserSession) ctx.lookup(UserSessionLocal.class.getName());
      us.getContact(new Integer(1));

      return actionMapping.findForward("menuframe");
      }

      }



      The output from running this is:
      16:01:56,046 INFO [STDOUT] com.flytxt.session.UserSessionBean==$Proxy70
      16:01:56,046 INFO [STDOUT] UserSessionLocal: false
      16:01:56,046 INFO [STDOUT] UserSessionRemote: false
      16:01:56,046 INFO [STDOUT] UserSession: false
      16:01:56,078 WARN [RequestProcessor] Unhandled Exception thrown: class java.lang.ClassCastException
      16:01:56,078 ERROR [[admin]] Servlet.service() for servlet admin threw exception
      java.lang.ClassCastException: $Proxy70
      at com.flytxt.admin.actions.WelcomeAction.execute(WelcomeAction.java:48)
      at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
      at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
      at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
      at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:507)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:697)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
      at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
      at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
      at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:153)
      at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
      at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
      at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
      at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
      at java.lang.Thread.run(Thread.java:595)


      Any help as to why this does not work would be much appreciated.

      I don't have a jboss.xml file, but my understanding is that it is not needed with EJB3.0

        • 1. Re: Stateless Sessionbeans via lookup.
          Khalid Hajsaleh Newbie

          The refrence is bound to interface not to the actual imlemeting class. You should use either interfaces to do the JNDI lookup. and then execute your methods from either interfaces.
          So your lookup should look something like:

          UserSessionLocal a = ctx.lookup(UserSessionLocal.class.getName());
          or
          UserSessionRemote a =
          (UserSessionRemote.class.getName());
          
          a.getContact(id);



          • 2. Re: Stateless Sessionbeans via lookup.
            George Taylor Newbie

            yes, but the both interfaces UserSessionLocal and UserSessionRemote extend UserSession, so it should be ok.

            Also, as you will see in the debug when i check the instanceof, it comes up with false for UserSessionLocal

            as in

            Object o = ctx.lookup(UserSessionLocal.class.getName());
            System.out.println(o + "==" + o.getClass().getName()); // [STDOUT] com.flytxt.session.UserSessionBean==$Proxy70
            System.out.println("UserSessionLocal: " + (o instanceof UserSessionLocal)); // [STDOUT] UserSessionLocal: false
            System.out.println("UserSessionRemote: " + (o instanceof UserSessionRemote)); //[STDOUT] UserSessionRemote: false
            System.out.println("UserSession: " + (o instanceof UserSession)); //[STDOUT] UserSession: false


            I took most of this code pretty much straight out of the jboss tutorials.

            I have jboss 4.0.3RC1 and java 1.5.0_04-b05

            • 3. Re: Stateless Sessionbeans via lookup.
              George Taylor Newbie

              also, the ejb and web are deployed in different ear files.

              I have run the sample dvd application up and that seems to run fine, but is deployed in a single ear file. I will attempt to merge the 2 projects and see if that is the cause of the problem

              • 4. Re: Stateless Sessionbeans via lookup.
                George Taylor Newbie

                I have modified the classes and it still is not working :(

                @Stateless
                public class UserSessionBean implements UserSession {
                @PersistenceContext (name="globalManager")
                private EntityManager manager;


                so i am only using a single interface now.

                public class WelcomeAction extends Action {


                /* (non-Javadoc)
                * @see com.afl.struts.AflSecureAction#aflExecute(com.afl.struts.security.AflSecurity, org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
                */
                public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception {
                InitialContext ctx = new InitialContext();
                Object o = ctx.lookup(UserSession.class.getName());
                System.out.println(o + "==" + o.getClass().getName());
                System.out.println("UserSession: " + (o instanceof UserSession));
                Class subclass = o.getClass();
                Class superclass = subclass.getSuperclass();
                while (superclass != null) {
                String className = superclass.getName();
                System.out.println(className);
                subclass = superclass;
                superclass = subclass.getSuperclass();
                }

                Class c = o.getClass();
                Class[] theInterfaces = c.getInterfaces();
                for (int i = 0; i < theInterfaces.length; i++) {
                String interfaceName = theInterfaces.getName();
                System.out.println(interfaceName);
                }
                Method[] theMethods = c.getMethods();
                for (int i = 0; i < theMethods.length; i++) {
                String methodString = theMethods
                .getName();
                System.out.println("Name: " + methodString);
                String returnString =
                theMethods.getReturnType().getName();
                System.out.println(" Return Type: " + returnString);
                Class[] parameterTypes = theMethods
                .getParameterTypes();
                System.out.print(" Parameter Types:");
                for (int k = 0; k < parameterTypes.length; k ++) {
                String parameterString = parameterTypes[k].getName();
                System.out.print(" " + parameterString);
                }
                System.out.println();
                }


                UserSession us = (UserSession) ctx.lookup(UserSession.class.getName());
                us.getContact(new Integer(1));

                return actionMapping.findForward("menuframe");
                }

                }

                As you can see i am getting the object by the single interface and printing as much info out as possible.

                Here is the output.

                10:56:37,310 INFO [STDOUT] com.flytxt.session.UserSessionBean==$Proxy85
                10:56:37,310 INFO [STDOUT] UserSession: false
                10:56:37,310 INFO [STDOUT] java.lang.reflect.Proxy
                10:56:37,310 INFO [STDOUT] java.lang.Object
                10:56:37,310 INFO [STDOUT] com.flytxt.global.intf.session.UserSession
                10:56:37,310 INFO [STDOUT] org.jboss.ejb3.JBossProxy
                10:56:37,310 INFO [STDOUT] Name: hashCode
                10:56:37,310 INFO [STDOUT] Return Type: int
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] Name: equals
                10:56:37,310 INFO [STDOUT] Return Type: boolean
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] java.lang.Object
                10:56:37,310 INFO [STDOUT] Name: toString
                10:56:37,310 INFO [STDOUT] Return Type: java.lang.String
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] Name: getAsynchronousProxy
                10:56:37,310 INFO [STDOUT] Return Type: java.lang.Object
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] Name: getContact
                10:56:37,310 INFO [STDOUT] Return Type: com.flytxt.global.vo.ContactVO
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] java.lang.Integer
                10:56:37,310 INFO [STDOUT] Name: isProxyClass
                10:56:37,310 INFO [STDOUT] Return Type: boolean
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] java.lang.Class
                10:56:37,310 INFO [STDOUT] Name: getProxyClass
                10:56:37,310 INFO [STDOUT] Return Type: java.lang.Class
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] java.lang.ClassLoader
                10:56:37,310 INFO [STDOUT] [Ljava.lang.Class;
                10:56:37,310 INFO [STDOUT] Name: newProxyInstance
                10:56:37,310 INFO [STDOUT] Return Type: java.lang.Object
                10:56:37,310 INFO [STDOUT] Parameter Types:
                10:56:37,310 INFO [STDOUT] java.lang.ClassLoader
                10:56:37,310 INFO [STDOUT] [Ljava.lang.Class;
                10:56:37,310 INFO [STDOUT] java.lang.reflect.InvocationHandler
                10:56:37,310 INFO [STDOUT] Name: getInvocationHandler
                10:56:37,310 INFO [STDOUT] Return Type: java.lang.reflect.InvocationHandler
                10:56:37,325 INFO [STDOUT] Parameter Types:
                10:56:37,325 INFO [STDOUT] java.lang.Object
                10:56:37,325 INFO [STDOUT] Name: getClass
                10:56:37,325 INFO [STDOUT] Return Type: java.lang.Class
                10:56:37,325 INFO [STDOUT] Parameter Types:
                10:56:37,325 INFO [STDOUT] Name: wait
                10:56:37,325 INFO [STDOUT] Return Type: void
                10:56:37,325 INFO [STDOUT] Parameter Types:
                10:56:37,325 INFO [STDOUT] long
                10:56:37,325 INFO [STDOUT] Name: wait
                10:56:37,325 INFO [STDOUT] Return Type: void
                10:56:37,325 INFO [STDOUT] Parameter Types:
                10:56:37,325 INFO [STDOUT] Name: wait
                10:56:37,325 INFO [STDOUT] Return Type: void
                10:56:37,325 INFO [STDOUT] Parameter Types:
                10:56:37,325 INFO [STDOUT] long
                10:56:37,325 INFO [STDOUT] int
                10:56:37,325 INFO [STDOUT] Name: notify
                10:56:37,325 INFO [STDOUT] Return Type: void
                10:56:37,325 INFO [STDOUT] Parameter Types:
                10:56:37,325 INFO [STDOUT] Name: notifyAll
                10:56:37,325 INFO [STDOUT] Return Type: void
                10:56:37,325 INFO [STDOUT] Parameter Types:


                as you can see, the output shows that it is using the correct interface, but it still throws a class cast exception

                • 5. Re: Stateless Sessionbeans via lookup.
                  George Taylor Newbie

                  I seem to have figured out the problem, but am not sure if this is a feature of EJB 3, Jboss, or a bug.

                  the basic answer is this:

                  in my ejb deployment i had the following files

                  global-ejb (ejb files)
                  global-ejb-client (client files and interfaces)

                  in my war deployment i had
                  admin.war
                  global-ejb-client (same one as deployed in the global deployment)

                  when i deploy like this it failes. If i take the global-ejb-client out of the deployment of the war file, it deploys and works fine.

                  Can someone please tell me if i am doing something wrong, as this was a standard way of building my applications so that i could deploy the war file either on the same server, or remotley.

                  thanks in advance.

                  George.

                  • 6. Re: Stateless Sessionbeans via lookup.
                    Joachim Van der Auwera Expert

                    Are you using Local access to the beans?
                    In short, yur client jar was loaded by different classloaders, thus serialization is necessary (slows everything down). However I don't think the system serializes when using local access. Apart from that, servlet spec requires a specific lookup order in the classloader which causes to use the different jar first (this can be configured).
                    Easiest solution to most classloader problems is to put everything in one ear.

                    Joachim

                    • 7. Re: Stateless Sessionbeans via lookup.
                      George Taylor Newbie

                      this is quite strange as it has been the standard by which i developed ejb 2.

                      the jar file that is in the ejb ear file, and the one in the war ear file are the same, so i wouldn't have thought that a problem. I have got around it by leaving out the jar file from the war distribution, however i feel this is a hack as i should be able to have the library files in either place.