1 2 Previous Next 21 Replies Latest reply: May 15, 2010 12:26 AM by Vladimir Aguirre RSS

@Autowiring of beans from Spring applicationcontext

J H Newbie

Hi,

 

we want to evaluate JBoss 5.1.0 with Spring 2.5.6. I read a couple of threads in the forum and realized that all of the spring users make use of the -spring.xml files in the META-INFs of the corresponding .jars, .wars etc.

At the moment we have an .ear-structure like this and it went smooth in the GlassFishv3.

 

 

.ear

|

------  servicebeans-01.jar   -> beanRefContext.xml, serviceContext-01.xml

------  servicebeans-02.jar   -> serviceContext-02.xml

------  webservice-A.war

------  webservice-B.war

 

in the web.xml of the wars I use the following config

 

<context-param>

        <param-name>parentContextKey</param-name>

        <param-value>ear.context</param-value>

    </context-param>

    <context-param>

        <param-name>contextClass</param-name>

        <param-value>org.jboss.spring.vfs.context.VFSXmlWebApplicationContext</param-value>

    </context-param>

    <listener>

        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

    <servlet>

        <description>Webservice Endpoint</description>

        <display-name>webservice</display-name>

        <servlet-name>webservice</servlet-name>

        <servlet-class>a.b.c.WebServiceImpl</servlet-class>

    </servlet>

    <servlet-mapping>

        <servlet-name>webservice</servlet-name>

        <url-pattern>/webservice</url-pattern>

    </servlet-mapping>

 

there's a parentApplicationContext, that instantiates the required beans via the given config in beanRefContext.xml (defaultname in Spring) which is looked up in the classpath. Both webservices should use beans from this appCtx. Actually the deployment works fine, all the required beans are instantiated only once. Except one important thing. The wiring between the WebserviceImpl in the .wars and the appCtx with the serviceBeans is not done.

 

According to this presentation http://www.redhat.com/f/pdf/jbw/mbogoevici_1050_spring_on_jboss.pdf, it should be possible. Otherwise I misunderstood this part of the presentation and didn't recognize that it is made clear just to use the -spring.xml files.

 

page 20:

 

Method 1: Spring's SpringBeanAutowiringInterceptor
● EJB3 interceptor
● Uses a BeanFactoryLocator to retrieve the
ApplicationContext
● Recognizes the @Autowired annotation

 

I also used the SpringBeanAutowiringSupport, which worked fine in GlassFishv3 ... no success.

 

So in the end I am looking for a way that allows me to make use of Spring's @Autowiring without using the spring-deployer module for a common appCtx.

Is there any solution to keep the above mentioned .ear-configuration and let the autowiring be done by JBoss (modules)? I know that it is probably possible if i change my config to the corresponding -spring.xml  files but that's only the last solution i want to do. Otherwise I will die of config-management for my app in different ApplicationServers. Any help would be appreciated.

 

johannes

  • 1. Re: @Autowiring of beans from Spring applicationcontext
    Marius Bogoevici Expert

    Johannes,

     

    Thanks for your interest in my presentation! Perhaps you can check JBoss World next June .

     

    You definitely shouldn't need to change your configuration. The Spring Deployer and hence support for META-INF/*-spring.xml is a JBoss-specific facility with its own specific features and benefits, but it's not a mandatory condition for using Spring in JBoss.

     

    My very first suspicion is that there are duplicate jars (Spring jars) in your app, which causes the webservice to fail, as the VFSXmlWebApplicationContext is not recognized as being a successor of the appropriate class. Ideally, you will want to have all the spring jars in the ear/lib folder and keep the war skinny, but if you're using Snowdrop and Maven, transitive dependencies might have sneaked Spring into the war. But, with more information absent, all I can say is just speculation, at this point.

     

    Can you help with a bit more information to figure this one out? What I need to understand is, what exactly do you mean by the fact that the wiring is not done (properties are null or there's a context startup failure since beans are not found)? Also, what jars are included with the ear/war (not all of them, just Spring and Snowdrop, if you're using that). Can you also upload a startup/usage log (with the new forum you can just attach it rather than pasting it to the post) where I can see the error/errors?

     

    Thanks,

    Marius

  • 2. Re: @Autowiring of beans from Spring applicationcontext
    J H Newbie

    Hey Marius,

     

    first of all: thanks for the quick reply. I will try to give you as much information as I can do and provide a small example project, that will reflect the .ear structure. They are all maven and eclipse projects, so it should be easy to reproduce. You will find them in the attached file.

     

    A summary of what infrastructure I use:
    Server: JBoss 5.1.0GA
    OS: Windows 7
    WS-Module: jbossws-metro-3.2.2.GA

     

    The only modifications I did in the run.conf is, that I changed the memory settings of the JVM. The rest is standard JBoss settings.

     

    For packaging the .ear I use the skinny-war settings in the pom, put all the .jars in the /lib dir and as far as I can see there's no duplicate spring jars. Also in the jboss dirs I could NOT find any spring jar.

     

    I created three example projects comprising a .war, .jar and an .ear. The .ear can be deployed and installs a WebService.
    The WebService is listed in the host:port/jbossws site and can be reached under host:port/autowiring_war/AutowiringWebService?wsdl 
    A logfile is also attached. Concerning this everything seems to work fine.

     

    Thanks for your help ....

    johannes

  • 3. Re: @Autowiring of beans from Spring applicationcontext
    Stefan Rufer Novice

    I struggled with a similar problem and solved it with the following configuration in web.xml of the WAR file exposing my SOAP service:

     

         <!--
           The MessageDispatcherServlet is the entry point for all kinds of
           SOAP requests. It implicitely loads an application context file
           /WEB-INF/<servletname>-servlet.xml if not configured otherwise.
           However, as we want component scanning and everything
           we configure an own application context and context loader.
          
           Component scanning did not work if relying on the parent
           Spring context (the parent context is the one loaded via
           ContextLoaderListener). It only works if the default spring-ws
           context mechanism is reconfigured to use the application context
           in the classes directory. If done so, <import .../> and component
              scanning works.
         -->
         <servlet>
              <servlet-name>trxservice</servlet-name>
              <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
              <init-param>
                   <param-name>transformWsdlLocations</param-name>
                   <param-value>true</param-value>
              </init-param>
              <init-param>
                <param-name>contextClass</param-name>
                <param-value>org.jboss.spring.vfs.context.VFSXmlWebApplicationContext</param-value>
              </init-param>
              <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:applicationContext-web.xml</param-value>
              </init-param>
         </servlet>

         <servlet-mapping>
              <servlet-name>trxservice</servlet-name>
              <url-pattern>/*</url-pattern>
         </servlet-mapping>

     

    Hope this helps

    Stefan

  • 4. Re: @Autowiring of beans from Spring applicationcontext
    Martin Borgman Newbie

    Hi Johannes,

     

    Your autowiringtest.zip helped to find out what your problem really is.

    My first question is why you replaced JBossWS Native, the one that is installed by default, with the JBoss Metro implementation? There is no real need to do this. I'm sure it should work, but at this point I think you're adding complexity you don't need.

    The only real issue I found with the webservice is that you repleced org.springframework.web.context.support.SpringBeanAutowiringSupport by org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor. As the class name SpringBeanAutowiringInterceptor implies, it is intended to work in an EJB context, not in a web context.

    Other than some typos here and there the webservice works on a standard JBoss 5.1.0.GA with the three snowdrop jars copied to  ${JBOSS_HOME}/server/default/lib.

    I've include the zip with my fixes.

    The deployment now looks like this:

     

    14:19:41,197 INFO  [DefaultEndpointRegistry] register: jboss.ws:context=autowiring_war,endpoint=autowiring-webservice
    14:19:41,203 INFO  [WebMetaDataModifierImpl] Ignore servlet: my.pkg.AutowiringServlet
    14:19:41,257 INFO  [TomcatDeployment] deploy, ctxPath=/autowiring_war
    14:19:41,326 INFO  [[/autowiring_war]] Initializing Spring root WebApplicationContext
    14:19:41,326 INFO  [ContextLoader] Root WebApplicationContext: initialization started
    14:19:41,364 INFO  [ClassPathXmlApplicationContext] Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@253fd92e: display name [org.springframework.context.support.ClassPathXmlApplicationContext@253fd92e]; startup date [Sun Apr 11 14:19:41 CEST 2010]; root of context hierarchy
    14:19:41,438 INFO  [XmlBeanDefinitionReader] Loading XML bean definitions from URL [vfszip:/Users/martinborgman/jboss-5.1.0.GA/server/default/deploy/autowiring_ear-1.0-SNAPSHOT.ear/beanRefContext.xml]
    14:19:41,495 INFO  [ClassPathXmlApplicationContext] Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@253fd92e]: org.springframework.beans.factory.support.DefaultListableBeanFactory@c0e0960
    14:19:41,514 INFO  [DefaultListableBeanFactory] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c0e0960: defining beans [ear.context]; root of factory hierarchy
    14:19:41,571 INFO  [VFSClassPathXmlApplicationContext] Refreshing org.jboss.spring.vfs.context.VFSClassPathXmlApplicationContext@6651b294: display name [org.jboss.spring.vfs.context.VFSClassPathXmlApplicationContext@6651b294]; startup date [Sun Apr 11 14:19:41 CEST 2010]; root of context hierarchy
    14:19:41,573 INFO  [XmlBeanDefinitionReader] Loading XML bean definitions from ZipEntryHandler@377437762[path=autowiring_ear-1.0-SNAPSHOT.ear/context.xml context=file:/Users/martinborgman/jboss-5.1.0.GA/server/default/deploy/ real=file:/Users/martinborgman/jboss-5.1.0.GA/server/default/deploy/autowiring_ear-1.0-SNAPSHOT.ear/context.xml]
    14:19:41,588 INFO  [VFSClassPathXmlApplicationContext] Bean factory for application context [org.jboss.spring.vfs.context.VFSClassPathXmlApplicationContext@6651b294]: org.springframework.beans.factory.support.DefaultListableBeanFactory@3f3499ef
    14:19:41,590 INFO  [DefaultListableBeanFactory] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3f3499ef: defining beans [myService]; root of factory hierarchy
    14:19:41,602 INFO  [VFSXmlWebApplicationContext] Refreshing org.jboss.spring.vfs.context.VFSXmlWebApplicationContext@214ef1ea: display name [Root WebApplicationContext]; startup date [Sun Apr 11 14:19:41 CEST 2010]; parent: ear.context
    14:19:41,603 INFO  [XmlBeanDefinitionReader] Loading XML bean definitions from FileHandler@529563278[path=WEB-INF/classes/applicationContext.xml context=file:/Users/martinborgman/jboss-5.1.0.GA/server/default/tmp/a002s-x8x9a6-g7vtmr79-1-g7vtnzfi-9r/autowiring_war-1.0-SNAPSHOT.war/ real=file:/Users/martinborgman/jboss-5.1.0.GA/server/default/tmp/a002s-x8x9a6-g7vtmr79-1-g7vtnzfi-9r/autowiring_war-1.0-SNAPSHOT.war/WEB-INF/classes/applicationContext.xml]
    14:19:41,615 INFO  [VFSXmlWebApplicationContext] Bean factory for application context [org.jboss.spring.vfs.context.VFSXmlWebApplicationContext@214ef1ea]: org.springframework.beans.factory.support.DefaultListableBeanFactory@165fb09d
    14:19:41,628 INFO  [DefaultListableBeanFactory] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@165fb09d: defining beans []; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@3f3499ef
    14:19:41,628 INFO  [ContextLoader] Root WebApplicationContext: initialization completed in 302 ms
    14:19:43,595 INFO  [WSDLFilePublisher] WSDL published to: file:/Users/martinborgman/jboss-5.1.0.GA/server/default/data/wsdl/autowiring_ear-1.0-SNAPSHOT.ear/autowiring_war-1.0-SNAPSHOT.war/AutowiringWebService4718254481898707626.wsdl

     

    Kind regards,

     

    Martin

     

    April 13: Added a new version of the zip file

  • 5. Re: @Autowiring of beans from Spring applicationcontext
    J H Newbie

    Thanks for the answer guys ... I will try this out

  • 6. Re: @Autowiring of beans from Spring applicationcontext
    Susana Quintana Newbie

    Hi,

     

    Im using your example to do something similar, but in any case my bean is not wired. Can someone help me to figure out the problem, or could you post your working example.

     

    Thanks:

     

    Im using JBOSS 5.1.0 GA and \jboss-spring-3.2.CR1.deployer

    -------------------------

    Ear structure:

    ------------------------

    <application xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        version="5"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd">
      <display-name>app-server</display-name>
        <module>
        <java>persistence.jar</java>
      </module>
        <module>
        <java>controller.jar</java>
      </module>
    </application>

     

    -------------------------

    dao-context.xml (is in persistence.jar /meta-inf

    ------------------------

        <bean id="trackingRecordDAO">
            <constructor-arg index="0">
                <ref bean="dataSource"/>
            </constructor-arg>
            <constructor-arg index="1" value="-5"/>
        </bean>

     

        <bean id="datasource">
            <property name="jndiName">
                <value>demotracking.databasePool</value>
            </property>
        </bean>
    </beans>

     

    -------------------------

    jboss-spring.xml (is in controller.jar /meta-inf

    ------------------------

    <description>BeanFactory=(SpringDao)</description>
         <import resource="classpath*:dao-context.xml"/>

     

         <bean id="jobDetail">
            <property name="targetObject" ref="gao_receiver02" />
            <property name="targetMethod" value="readTags" />
            <property name="concurrent" value="false" />
        </bean>

     

        <bean id="gao_receiver02">
            <constructor-arg value="100.105.130.224"/>
        </bean>

     

        <bean id="simpleTrigger">
            <property name="jobDetail" ref="jobDetail" />
            <property name="startDelay" value="0" />
            <property name="repeatInterval" value="60" />
        </bean>

     

        <bean>
            <property name="triggers">
                <list>
                    <ref bean="simpleTrigger" />
                </list>
            </property>
        </bean>
    </beans>

     

    --------

     

    ------

     

    I did try the following code line to instatiate the bean in a class which is in the controller.jar but the bean is not wired

     

    @Autowired
        public TrackingRecordDAOImpl dao; 

  • 7. Re: @Autowiring of beans from Spring applicationcontext
    Marius Bogoevici Expert

    Susana,

     

    This seems to be a problem with your Spring configuration. Try adding <context:annotation-config/> to your Spring configuration (you need to use the appropriate namespace - see docs).

     

    Marius

  • 8. Re: @Autowiring of beans from Spring applicationcontext
    Susana Quintana Newbie

    Hi Marius,

     

    Thanks for your reply, after reading some other documentation and taking a look to the sportclub example available in the repository I think I dont need to wire this bean I just need to get an instance of it from the JNDI. So I change my code and configuratio but still not working. I hope you can help me to understand what is wrong.

    Thanks in advance,

     

    Susana -

  • 9. Re: @Autowiring of beans from Spring applicationcontext
    Susana Quintana Newbie

    application.xml

     

    <?xml version="1.0" encoding="UTF-8"?>
    <application xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        version="5"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd">
      <display-name>tracking-server</display-name>
       <module>
        <java>persistence.jar</java>
      </module>
      <module>
        <java>controller.jar</java>
      </module>
    </application>
    

     

    jboss-app.xml


    <?xml version="1.0" encoding="UTF-8"?>
     <!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 5.0//EN"
     "http://www.jboss.org/j2ee/dtd/jboss-app_5_0.dtd" >
    <jboss-app>
        <module-order>strict</module-order>
    </jboss-app>
    


    dao-spring.xml


    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
       <bean id="dataSource" destroy-method="close">
            <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
            <property name="url" value="jdbc:oracle:thin:@12.121.18.85:1521:demotracking"/>
            <property name="username" value="demo_db"/>
            <property name="password" value="passwrd"/>
        </bean>
        <bean id="trackingRecordDAO">
            <constructor-arg index="0">
                <ref bean="dataSource"/>
            </constructor-arg>
            <constructor-arg index="1" value="-5"/>
            <qualifier value="tracking_record"/>
        </bean>
    </beans>
    

     

    jboss-spring.xml

     


    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd">
        <description>BeanFactory=(SpringDao)</description>
        <import resource="classpath*:rfidDAO-spring.xml"/>
        <bean id="gao_receiver02">
            <constructor-arg value="199.181.130.242"/>
        </bean>
        <bean id="jobDetail">
            <property name="targetObject" ref="gao_receiver02" />
            <property name="targetMethod" value="readTags" />
            <property name="concurrent" value="false" />
        </bean>
        <bean id="simpleTrigger">
        <!-- see the example of method invoking job above -->
            <property name="jobDetail" ref="jobDetail" />
        <!-- 10 seconds -->
            <property name="startDelay" value="0" />
        <!-- repeat every 50 seconds -->
            <property name="repeatInterval" value="60" />
        </bean>
        <bean>
            <property name="triggers">
                <list>
                    <ref bean="simpleTrigger" />
                </list>
            </property>
        </bean>
        <context:annotation-config />
    </beans>
    

     

    code.java

     


    import org.jboss.spring.callback.SpringLifecycleInterceptor;
    
    @Interceptors(SpringLifecycleInterceptor.class)
    public class GAOReader {
    
        @Spring(bean = "trackingRecordDAO", jndiName = "SpringDao")
        public TrackingRecordDAOImpl dao;
    
    // later have this
        if (dao!=null)
                dao.insertRecord(bean);
            else
                System.out.println("dao was not wired");
    

     

    I can  deploy the ear without problems but as soon as the job start I get the message that the dao was not wired. How can I know if SpringDao factory is working properly?


    Attached is the log from JBoss

  • 10. Re: @Autowiring of beans from Spring applicationcontext (ejb module)
    Vladimir Aguirre Newbie

    Hi community:

    I have the same problem (my bean is not wired) on ejb module.

    When declarative config in the xml file (<bean id="beanX" ...>) my EJB works fine.

    When the config is only based on component-scan the field is not wired.

     

    Thanks in adavance for your help.

  • 11. Re: @Autowiring of beans from Spring applicationcontext (ejb module)
    Susana Quintana Newbie

    Hi Vladimir,

     

    I get the bean wired at the end just having all the beans definitions on the same file and using @Autowired annotation, what I couldn't solve what the use of @Spring annotation instantiating the bean using the factory and the jndi.

     

    Best,

     

    Susana

  • 12. Re: @Autowiring of beans from Spring applicationcontext
    Marius Bogoevici Expert

    Susana,

     

    Am I under a wrong impression, or GAOReader is not an EJB?

     

    SpringLifecycleInterceptor/@Spring are by design intended to support injection into EJBs and won't work on regular beans.

     

    Marius

  • 13. Re: @Autowiring of beans from Spring applicationcontext (ejb module)
    Marius Bogoevici Expert

    Hey Vladimir,

     

    Can you provide some configuration snippets?

     

    Thanks,

    Marius

  • 14. Re: @Autowiring of beans from Spring applicationcontext (ejb module)
    Daniel Cullender Newbie

    We have successfully used the jboss spring deployer without too much hassle nor configuration.

     

    Please have a look at http://community.jboss.org/wiki/AnexperiencewithIntegratingSpringandJboss to see what we did. I originally extended the deployer to dynamically discover the ear name and changed the interceptor so @Spring was not needed anymore (We wanted to use straight spring with no custom annotations like @Spring). However, these changes ended up not being necessary (please see link)

     

    Have a look at @Configurable (Please remember to configure your application context with the correct configuration as mentioned in a previous reply) - this allows you to spring configure pojo's and not just ejb components.

1 2 Previous Next