Announcement Announcement Module
Collapse
No announcement yet.
Accessing local EJB from Servlet throws Exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Accessing local EJB from Servlet throws Exception

    Hi,

    I have problems using the Spring EJB access class to access a local EJB from a servlet.
    My application server is JBoss4RC1.

    I get the following Exception:
    =============================
    18:12:21,538 ERROR [Engine] StandardWrapperValve[HelloWorld]: Servlet.service()
    for servlet HelloWorld threw exception
    java.lang.IllegalArgumentException: object is not an instance of declaring class

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at org.springframework.ejb.access.LocalSlsbInvokerInt erceptor.invoke(LocalSlsbInvokerInterceptor.java:6 0)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :138)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:152)
    at $Proxy69.sayHello(Unknown Source)
    at HelloWorld.doGet(HelloWorld.java:48)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:697)


    My EJB consists of the following classes:
    ========================================
    -local interface LocalHello.java
    -bean LocalHelloBean.java
    -home interface LocalHelloHome.java
    In addition I have defined a business interface Local.java, my bean class implements
    this interface.

    My applicationContext.xml:
    ==========================
    <beans>
    <bean id="local" class="org.springframework.ejb.access.LocalStatele ssSessionProxyFactoryBean">
    <property name="jndiName"><value>MeinEJB</value></property>
    <property name="businessInterface"><value>test.Local</value></property>
    </bean>


    <bean id="myBD" class = "HelloWorld">
    <property name="local"><ref bean="local"/></property>
    </bean>
    </beans>


    My servlet:
    ===========
    public class HelloWorld extends HttpServlet {

    private static Local local=null;


    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {


    // working version without Springs EJB Access classes
    try {

    InitialContext jndiContext= new InitialContext();
    Object ref = jndiContext.lookup("MeinEJB");

    LocalHelloHome home = (LocalHelloHome)PortableRemoteObject.narrow(ref,Lo calHelloHome.class);
    LocalHello myLocal = home.create();
    System.out.println(myLocal.sayHello("Test1234"));

    } catch (Exception e) {
    e.printStackTrace();
    }
    // version with Springs EJB access classes throws an exception
    System.out.println(local.sayHello("Test789"));

    }


    public void init(){
    ServletContext ctx=this.getServletContext();
    ApplicationContext app=WebApplicationContextUtils.getWebApplicationCo ntext(ctx);
    }

    public void setLocal(Local hello){
    this.local=hello;
    }
    }

    I checked that init, setLocal were invoked. The version without Spring works fine, but
    the line System.out.println(local.sayHello("Test789")); throws the exception.

    Can you please tell me what's wrong?

    Thanks and best regards
    Nicole Wengatz

  • #2
    First of all you should not use DI to inject resources into Servlets:
    <bean id="myBD" class = "HelloWorld">
    <property name="local"><ref bean="local"/></property>
    </bean>
    ...
    public void setLocal(Local hello){
    this.local=hello;
    }
    you can however use attribute app to lookup resources from Spring ApplicationContext from within your Servlet.
    I have two questions with regards to your code:
    1. is sayHello member of LocalHello or Local interfaces?
    2. could you show the "version with spring"?

    Comment


    • #3
      >First of all you should not use DI to inject resources into Servlets:
      Why not? That's what I understood from the Spring documentation, see Chapter 15.1.2. 'Accessing local SLSBs.
      In my case MyComponent is the class Local and my Servlet offers a method setLocal.

      >you can however use attribute app to lookup resources from Spring ApplicationContext from within your Servlet.
      >I have two questions with regards to your code:
      >1. is sayHello member of LocalHello or Local interfaces?
      sayHello is member of both interfaces.

      public interface Local {
      public java.lang.String sayHello(String name);
      }

      public interface LocalHello extends javax.ejb.EJBLocalObject {

      public java.lang.String sayHello(String name);

      }
      >2. could you show the "version with spring"?
      It is already there in my posting. The init method of my Servlet will be invoked,
      and when executing this line ApplicationContext app=WebApplicationContextUtils.getWebApplicationCo ntext(ctx);
      Spring JNDI looks up my EJB 'MeinEJB' with business interface Local as defined in the applicationContext.xml.

      After this the method setLocal of myServlet will be invoked and the member variable local is set.

      I tried it out with EJB remote interface, there this way works fine.
      What's the problem with local interface here?

      Thanks and Best regards
      Nicole

      Comment


      • #4
        Nicole,

        1. EJB, Servlets and Spring DI
        Injecting EJB references into classes is what Spring EJB Integration is for. However, in your case you are trying to inject the reference into a servlet. This can not be managed by Spring since Spring does not manage the Servlet life cycle. As I said, you can use Spring as a singleton to retrieve the reference to your EJB:
        Code:
        public void init&#40;&#41;&#123; 
        ServletContext ctx=this.getServletContext&#40;&#41;; 
        ApplicationContext app=WebApplicationContextUtils.getWebApplicationContext&#40;ctx&#41;; 
        &#125;
        then just call
        Code:
        HelloLocal myLocal = &#40;HelloLocal&#41; app.getBean&#40;"local"&#41;;
        to access your EJB.
        2. Spring support for EJBs
        When you configure a LocalStatelessSessionProxyFactoryBean into your applicationContext.xml, Spring implements the plumbing to access the EJB (initialContext, loockup, Home caching ...). With that said, you no longer need to use the following code inside your client (servlet):
        InitialContext jndiContext= new InitialContext();
        Object ref = jndiContext.lookup("MeinEJB");

        LocalHelloHome home = (LocalHelloHome)PortableRemoteObject.narrow(ref,Lo calHelloHome.class);
        LocalHello myLocal = home.create();
        The following line of code will do the job for you:
        Code:
        HelloLocal myLocal = &#40;HelloLocal&#41; app.getBean&#40;"local"&#41;;
        HTH

        Comment


        • #5
          Hi Omar,

          thank you very much for your help, the solution you proposed works fine :-)

          BUT, I still have some severe doubts:

          1) Now my Servlet has to know the interface LocalHello which extends javax.ejb.EJBLocalObject,
          so it's not longer independent from EJB technology. That was one of my reasons (the main reason)
          to start evaluating Spring :-(

          2) When I access an EJB via the remote interface using the SimpleRemoteStatelessSessionProxyFactoryBean
          my servlet/client DOES NOT need to know the EJB remote interface class.
          In this scenario I can use the (EJB independent) business interface
          public interface Hello {
          public java.lang.String sayHello(String name);
          }

          So could you please explain me why there is such a big difference in the design of the two
          classes?

          Thank you very much!
          Nicole

          Comment


          • #6
            Originally posted by wengatz_n
            1) Now my Servlet has to know the interface LocalHello which extends javax.ejb.EJBLocalObject,
            so it's not longer independent from EJB technology.
            That can be mended quite easily

            You can provide two interfaces, where the EJB local interface inherits from your buisness interface. That way your client is agnostic of EJB.

            Example:

            public interface Hello {
            void sayHello();
            }

            public interface LocalHello extends Hello, EJBLocalObject {}


            So you can use Hello instead of LocalHello in your servlet.

            Regards,
            Andreas

            Comment


            • #7
              Thanks a lot for your help.
              That works fine and I'm happy :-)

              Comment

              Working...
              X