9 Replies Latest reply on Mar 14, 2007 5:24 PM by Alex Turetsky

    Using beans from other spring module

    Jussi Pöri Newbie

      I guess to is pretty newbie question, but I will ask it anyway...

      How to use beans from other spring module?

      I have 2 spring modules, where the other module need beans from the other.

      ear/
      core.spring
      application.spring

      Here the application.spring need a bean from the core.spring.

      Bean configuration from the application.spring spring-jboss.xml:

      <description>BeanFactory=(core)</description>
      <bean id="MessageManager"
       class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="cache">
       <value>true</value>
       </property>
       <property name="proxyInterface">
       <value>com.core.MessageManager</value>
       </property>
       <property name="jndiName">
       <value>a_spring-core</value>
       </property>
       <property name="expectedType" value="com.core.MessageManagerImpl"/>
       </bean>


      This does not work, because the bean in JNDI tree is the ApplicationContext. So how I can use the ApplicationContext to create the reference to the right bean( other words, get the bean from the ApplicationContext)?
      I know that I could make inside bean( give context in and get it from there), but I want to do it in onfiguration file.

        • 1. Re: Using beans from other spring module
          Ales Justin Master

           

          "jussi_po" wrote:

          <description>BeanFactory=(core)</description>
          



          Instead of BeanFactory you must use ParentBeanFactory - to reference parent BF, which core.spring is to application.spring.
          --> http://java.sys-con.com/read/180386.htm


          • 2. Re: Using beans from other spring module
            Jussi Pöri Newbie

            Ok, that helped and I got bit ahead.

            But now, when I use those classes in another spring module, the second spring module is bind to the first modules application context. Meaning that the classes from second module are actually inside first.

            2 spring modules:
            core.spring
            second.spring

            First module(core.spring) jboss-spring.xml:

            <?xml version="1.0" encoding="UTF-8" ?>
            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
            <beans>
            
            <bean name="MessageManager"
             class="com.core.MessageManagerImpl">
             <property name="hibernateTemplate">
             <ref bean="hibernateTemplate" />
             </property>
             </bean>
            </beans>


            The jndi config file of this(I'm not sure that I'm doing this right):
            <?xml version="1.0" encoding="UTF-8" ?>
            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
            <beans>
            
             <description>ParentBeanFactory=(a_spring-core)</description>
            <bean id="MessageManager"
             class="org.springframework.jndi.JndiObjectFactoryBean">
             <property name="cache">
             <value>true</value>
             </property>
             <property name="proxyInterface">
             <value>com.core.MessageManager</value>
             </property>
             <property name="jndiName">
             <value>a_spring-core</value>
             </property>
             </bean>
            
            </beans>


            And then In other spring module(second.spring), I try to use the beans from the first module:
            <?xml version="1.0" encoding="UTF-8" ?>
            <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
            <beans>
            
             <import resource="jndi_core.xml" />
            <bean name="MbloxConverter"
             class="com.converter.MbloxConverterImpl">
             <property name="messageManager">
             <ref bean="MessageManager" />
             </property>
            
             </bean>
            </beans>


            This second.spring module is actually bind to the JNDI as "core.spring", and I guess it is because of the import in config file.

            And also I have other module(spring) which uses the beans from both of those modules, and it won't find the bean from second.spring module.

            Or should I just make a one spring module?(I prefer to keep them separate)

            • 3. Re: Using beans from other spring module
              Ales Justin Master

              First, do not use this - import resource="jndi_core.xml".

              There is a straight hierarchy, as in Java hierarchy model - just a single extend.

              Read the article: http://java.sys-con.com/read/180386.htm

              Name your contexts (via BeanFactory=(name1)), and the reference them in child context via ParentBeanFactory=(name1).
              The order of hierarchy deployment is important!

              If you do this as it should be done, this is not true:
              "Meaning that the classes from second module are actually inside first."

              • 4. Re: Using beans from other spring module
                Ales Justin Master

                Ok, I aleady pointed you to the article - never mind (if you read it, otherwise do it :-).

                It is pretty simple, simple tree name + ordered deployment.

                • 5. Re: Using beans from other spring module
                  Jussi Pöri Newbie

                  Now it works. ( Should have really read the article..).

                  But one thing is still unclear. To use beans in web application, like in ejb3, InjectionInterceptor is use to inject beans. Should I use that in web application or is there easier way to get the Application Context from jndi in war?

                  • 6. Re: Using beans from other spring module
                    Ales Justin Master

                    As you are probably aware it is trivial to get Spring application context into web layer.
                    JBoss/Spring is mainly integration between Spring application context and EJB layer.
                    But you can always have common Spring beans and integrate them with both layers - some utils, resources, ...
                    But this can be replaced with injecting this beans into EJB layer and then do a lookup from web to EJB and use EJB as a facade / delegation for acessing those Spring beans.

                    • 7. Re: Using beans from other spring module
                      Jussi Pöri Newbie

                      I was just thinking that would it work if I would create a bean with ApplicationContext awareness, and then add the application context from JNDI as parent context to that bean's context... All this in war. It could mess things up, but I will test it.

                      Or otherwise I will do a delegate classes or some kind of proxy classes.

                      • 8. Re: Using beans from other spring module
                        Jussi Pöri Newbie

                        I solved this by using Delegate class from web application to access Spring module beans. I defined business services for the web application, I tried to make the web application as slim as possible.

                        Made a delegate class which extends the business interface. And for that class I get the business class from the Application Context.

                        public class BusinessSearchDelegateImpl implements BusinessSearch {
                         private ApplicationContext springModuleContext;
                         private final String BEAN = "BusinessSearchService";
                        
                         public void setSpringModuleContext(ApplicationContext springModuleContext) {
                         this.springModuleContext = springModuleContext;
                         }
                        
                         private BusinessSearch getSearchService()
                         throws TechnicalException {
                        
                         if (springModuleContext.containsBean(BEAN)) {
                        
                         BusinessSearch service = (GenericSearchService) springModuleContext
                         .getBean(BEAN);
                         return service;
                         } else {
                         LOG.error("Component with name(" + BEAN + ") not found. ");
                         throw new TechnicalException("Component with name(" + BEAN
                         + ") not found. ");
                         }
                         }
                        
                        public Customer findCustomer(String id) throws TechnicalException {
                         return getSearchService().findCustomer(id);
                         }
                        
                        }


                        This class is configured in web application context as following:
                        <!-- Business Service beans -->
                         <bean id="BusinessContext"
                         class="org.springframework.jndi.JndiObjectFactoryBean">
                         <property name="cache">
                         <value>true</value>
                         </property>
                         <property name="jndiName">
                         <value>d_business-enabler</value>
                         </property>
                         </bean>
                        
                         <bean id="BusinessSearchDelegate"
                         class="com.som.pac.web.BusinessSearchDelegateImpl">
                         <property name="springModuleContext">
                         <ref bean="BusinessContext" />
                         </property>
                         </bean>


                        And then that BusinessSearchDelegate is given to those controllers which needs the business services.

                        I made it his way, and best thing was that I could add this delegate class to our utility jar, which is a jar module in ear file.


                        • 9. Re: Using beans from other spring module
                          Alex Turetsky Newbie

                          jussi_po

                          I'm trying to use your approach with delegation.
                          I'm running JBoss 4.0.4 and Spring 2.0.2
                          But when it comes to the injection of the BusinessContext into BusinessSearchDelegateImpl I got a strange exception:
                          java.lang.IllegalArgumentException:
                          Cannot convert value of type
                          [org.jboss.spring.factory.NamedXmlApplicationContext] to required
                          type [org.springframework.context.ApplicationContext] for property
                          'springModuleContext': no matching editors or conversion strategy found

                          I assume that smth is wrong with my deployment and/or class loading. Do you have any kind of a working sample (lie JBoss-Stpring.ear) that you can send me?

                          Probably I just need to compile the deployer against my runtime, but honestly, I got lost in the build script....

                          Any help would be very appreciated.