Announcement Announcement Module
Collapse
No announcement yet.
Injecting Stateless EJB 3 with Spring 2.x Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Injecting Stateless EJB 3 with Spring 2.x

    I'm working on a reference implementation with Spring 2 and EJB 3. I'm using JBoss 4.2.0, Spring 2.0.5 with the new Sun SDK 5.

    I've configured a Spring MVC controller to hold a "service" data member which should be injected with a stateless EJB 3. Here's the "<dispatcher-name>-servlet.xml" file:
    ..................
    <bean id="ManageMemberService"
    class="org.springframework.ejb.access.SimpleRemote StatelessSessionProxyFactoryBean" lazy-init="true">
    <property name="jndiName"
    value="JEEArchitecture-app/ManageMemberEJB/local" />
    <property name="businessInterface"
    value="com.companyName.services.membership.IManage Member" />
    <property name="lookupHomeOnStartup" value="false" />
    </bean>


    <bean id="ManageMemberController"
    class="com.healthnet.membership.web.controller.Man ageMemberController">
    <property name="service" ref="ManageMemberService" />
    <property name="sessionForm"><value>true</value></property>
    <property name="successView"><value>manageMember</value>
    </property>
    <property name="formView"><value>manageMember</value></property>
    </bean>

    ...............................................

    This works perfectly fine when I'm trying to insert a Stateless EJB 2.1 version, however if I switch to a Stateless EJB 3 approach I'm getting the following error:

    org.springframework.ejb.access.EjbAccessException: EJB home [ManageMemberEJB] has no no-arg create() method

    The EJB extends a base POJO class and implements the "IManageMember" interface.

    So, I hope I'm asking a very simple question: how can I inject an Stateless EJB 3 with Spring 2.0 (in both, "remote" and "local" modes) ?

    I'm at a hard-stop right now so any insightful comments would be appreciated.

    Thanks.

  • #2
    I believe you just need to pull it straight from JNDI using the JndiObjectFactoryBean

    Comment


    • #3
      I already tried that (JndiObjectFactoryBean) but unfortunately, it didn't work. I'm getting something similar to "ClassCastException" (I can't recall exactly) as Spring throws an exception in trying to convert the EJB proxy to the business interface.

      I also tried the following settings with no success:

      <jee:jndi-lookup id ="ManageMemberService" jndi-name="ManageMemberEJB/local" resource-ref="true" cache="true"/>

      <jee:local-slsb id="ManageMemberService"
      jndi-name="JEEArchitecture-app/ManageMemberEJB/local"
      business-interface="com.companyName.services.membership.IMa nageMember"
      cache-home="true"
      lookup-home-on-startup="true"
      resource-ref="true"/>

      I also want to make sure that I can inject a Stateless EJB 3 in both a remote or local mode. For example, I could have my controller deployed as part of a "war" on a remote application server trying to access an EJB 3 on another remote application server.

      Is Spring 2.x not ready yet to use/inject Stateless EJB 3 instances ?

      Again, I would appreciate any feedback on this.

      Thanks.

      Comment


      • #4
        To be honest, I haven't really looked into it that much, however the following might help.

        http://forum.springframework.org/sho...ight=EJB3+JNDI

        Comment


        • #5
          Originally posted by yatesco View Post
          To be honest, I haven't really looked into it that much, however the following might help.

          http://forum.springframework.org/sho...ight=EJB3+JNDI
          Thanks for your reply, but if you look at that discussion thread you'll see that I'm the one that posted the last message on that thread asking the same question ! The recommendation to use the plain JndiObjectFactoryBean doesn't work (and that was two years ago, in 2005 !!!) as you get something similar to the "ClassCastException" (I mentioned this in my message above).

          I'm pretty new with Spring and I thought that I was asking a very elementary question: how to inject (remote and/or local) a Stateless EJB 3 with Spring ? I was able to get it going with EJB 2.x but not with EJB 3.

          So, is it something very basic that I'm missing or does Spring NOT support injection of Stateless EJB 3 ?

          I'm trying to make a case for using Spring so I'm looking for all the help I can get from the Spring team to get over this problem. At this point it's a clear show-stopper.

          I don't want to burden everybody with my question but if you find some time to look into it (I can provide you with all my configuration and source code if it's needed) I would really appreciate.

          Thanks again.

          Comment


          • #6
            A quick google turned up this:

            http://www.oracle.com/technology/tec...30-spring.html

            Comment


            • #7
              Originally posted by yatesco View Post
              The article references the same "JndiObjectFactoryBean" approach mentioned above which didn't work for me. If it works for everybody else, apparently I must have some incorrect configuration/setting.

              Personally, I've had enough at this point so I'll abandon this topic for now, hoping that sometime in the future, somebody may find a solution to injecting stateless EJB 3 beans with Spring.

              Yatesco, thank you very much for your time spent in helping me.

              Comment


              • #8
                Originally posted by tirzaman View Post
                The article references the same "JndiObjectFactoryBean" approach mentioned above which didn't work for me. If it works for everybody else, apparently I must have some incorrect configuration/setting.
                Are you setting the proxy interface? In the XML snippets in the previous post (please wrap in code tags ) you aren't. You do when you specify the SLSBPFBean, but that doesn't work for EJB3 (AIUI).

                Playing devil's advocate.....what benefit are you getting from using EJBs instead of plain POJOs (or POJOs and Spring RMI for remoting)? Not wanting to start a flame war, just interested :-)

                Comment


                • #9
                  Originally posted by yatesco View Post
                  Are you setting the proxy interface? In the XML snippets in the previous post (please wrap in code tags ) you aren't. You do when you specify the SLSBPFBean, but that doesn't work for EJB3 (AIUI).

                  Playing devil's advocate.....what benefit are you getting from using EJBs instead of plain POJOs (or POJOs and Spring RMI for remoting)? Not wanting to start a flame war, just interested :-)
                  In the "jee:local-slsb" tag I specify a "business-interface" property which is the interface that my EJB 3 implements. Is this not the correct way of doing it ? Are you saying that "jee:local-slsb" is only for EJB 2.1 and does not work for EJB 3 ? If that's the case, then what is the correct tag/way to use for the stateless EJB 3 lookup and injection ?

                  Maybe an example would work better: assume I have a Spring MVC controller called "MyController" and a Stateless EJB 3 POJO class (annotated with @Stateless) called "MyEJB" which implements "IBusinessInterface" interface (it's irelevant here, but "MyEJB" extends a base POJO class as well). How would I create the bean configuration in the "<dispatcher-name>-servlet.xml" on the web tier to do the lookup and injection of the EJB 3 "MyEJB" into "MyController" ? I have listed my configuration attempt in the first part of this thread.

                  Now going back to your architecture question: for now, I've decided to rely on the JEE container for the facade implementation (EJB), transaction, security, remotability and pooling (scalability). However, my business logic is all in the "service" layer represented by POJOs configured through Spring. The EJBs just do a pass-through call to the service POJO objects. I also don't want to use the Spring EJB base classes as I want to shield my EJBs from Spring in case I need to deploy them somewhere else without Spring (or change from Spring to Pico, etc).

                  So the thread of execution is as follows: a controller on the presentation tier will get injected by Spring with a proxy facade (EJB for now) referenced through a business interface. The controller will make the call on the business interface to the EJB. The EJB will use a home-grown context provider framework to initialize your Spring container with the "applicationContext.xml" and "persistence.xml" files where everything is configured: services, data source, persistence units, daos, etc. Each EJB will have a corresponding POJO service which will be retrieved from Spring through my context provider framework by using the dependency lookup mechanism. The EJB will make a pass-through call to its POJO service which is also implementing the same business interface (the EJB has just a reference to the business interface when talking to its POJO service). The POJO service will get Spring injected with a DAO factory (there are some base classes involved, etc). The POJO service will get the corresponding DAO referenced through a DAO interface and make the call. The specific DAO implementation will be injected with the JPA EntityManager (@PersistenceContext annotation) and use it to call different JPA frameworks (right now I'm trying out Hibernate and TopLink) to complete the execution thread.

                  Overall, I'm trying to use a lot of interfaces and encapsulation to have an easier transition from one framework/technology to another. For example, if I have to get rid of the EJBs for a better alternative, my web tier wouldn't be affected as long as my new approach will implement the same business interface.

                  Comment


                  • #10
                    So what exactly is the error when you do what everyone is recommending and use JndiObjectFactoryBean? Remember, don't use SimpleRemoteStatelessSessionProxyFactoryBean or anything in the jee schema except jndi-lookup. The Oracle article specifically states that "you will not require Spring's proxy classes any more". You probably can't put the @EJB tag on the controller to indicate the dependency either, since Spring controllers aren't managed by the container. Put it on a servlet somewhere or use the web.xml as per the GlassFish FAQ:
                    https://glassfish.dev.java.net/javae...l#POJOLocalEJB

                    Comment


                    • #11
                      Something happened (!) and I finally got it to work. As expected, you guys were right in terms of using the "jee:jndi-lookup" bean to inject an EJB 3. As I mentioned before, I've already tried that and it didn't work for me. The only plausible explanation for the error involves the way my EAR was packaged: I used the MyEclipse default which put every dependent class in the EJB jar. The classpath in the manifest file also refered to some jars within the EAR which contained some overlapping classes which could have caused the "ClassCastException"-type exception.

                      However, there's one thing that I learned from this and suspect it to be true: the "jee:slsb-local" and "jee:slsb-remote" beans only work with EJB 2.x and not EJB 3. Is this correct ?

                      Now, everything seems to be working fine but I still have one question: if the WAR containing the Spring MVC controller which is injected with the stateless EJB3 is packaged and deployed on a physical server separate from the server where the EJB jar is deployed, would the "jee:jndi-lookup" bean still work fine to inject the remote EJB into the controller ?

                      Comment


                      • #12
                        I love these silly forum wars sooo much! Whenever there is a question regarding spring-ejb integration, there always will be 2 people in topic, "throw-away-ejb" guy and "throw-away-spring" guy. What about us, we are happy with both spring and ejb, having all needed features of JBoss server on our hosting (like clustering, JTA, transactional cache, load balancing and remote calls optimization), while having unbeleivable developers performance here, in the office - they are running lightweight Spring container with embedded Jetty directly from their IDEs and do not have to deal with endless "build-deploy-wait" cycle from the EJB world.

                        tirzaman, the JndiObjectFactoryBean works like a charm with EJB3, it looks like you did not specified the proxy interface in your mapping:

                        Code:
                        	<bean id="beanManagerRemote"
                        		class="org.springframework.jndi.JndiObjectFactoryBean">
                        		<property name="jndiName" value="BeanManagerJndiName/remote" />
                        		<property name="proxyInterface" value="com.company.component.BeanManager" />	
                        </bean>
                        You possibly missed the line in bold text.

                        Comment


                        • #13
                          Hi,

                          I don't know if you have solved your problem but have you tried the proxyInterface thing?

                          Code:
                          <bean id="clsUserDetailsService" class="org.springframework.jndi.JndiObjectFactoryBean">
                          		<property name="jndiName" value="xxxxx/YyyEJB/local"/>
                          		<property name="lookupOnStartup" value="false"></property>
                          		<property name="proxyInterface" value="com.hoi.MyClass"></property>
                          	</bean>
                          Cheers,
                          Bora.

                          Comment

                          Working...
                          X