1 2 Previous Next 18 Replies Latest reply on Jul 26, 2013 6:27 PM by Tejas Mehta

    Accessing spring beans that are deployed in a war.

    Bas Ven Newbie

      We are converting a huge Spring 3 based application to eventually be a JEE application using jBoss 7.1.1.Final.

      As a first step we wrapped our application inside a war file which deploys inside jboss and works well.

      I am trying to see if I can inject some of the spring beans inside this jar into a simple EJB. Both the war and EJB are packaged in an ear and I moved all jars from the war to the ear lib.

       

      My war file has the META-INF/jboss-spring.xml file:

       

       

      <?xml version="1.0" encoding="UTF-8"?>

      <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

       

      <beans>

       

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

          <bean id="dataSourceManager" class="database.DataSourceManagerImpl" />

      </beans>

       

      and I see in the jboss log file at startup what looks like it is being read:

       

       

      09:01:46,210 INFO  [org.jboss.spring.factory.NamedXmlApplicationContext] (MSC service thread 1-2) Refreshing org.jboss.spring.factory.NamedXmlApplicationContext@1daef240: startup date [Wed Jul 24 09:01:46 MDT 2013]; root of context hierarchy

      09:01:46,211 INFO  [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (MSC service thread 1-2) Loading XML bean definitions from "/content/assembly.ear/commander.war/META-INF/jboss-spring.xml"

      09:01:46,217 INFO  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (MSC service thread 1-2) Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@330ec996: defining beans [dataSourceManager]; root of factory hierarchy

       

      I try to inject this bean in my EJB as follows:

       

       

      @Spring(bean = "dataSourceManager", jndiName = "Commander")

       

      However when I try to call into my EJB I am getting a huge stacktrace that in the end tells me snowdrop couldn't find the 'Commander' factory:

       

       

      Caused by: java.lang.IllegalStateException: javax.naming.NameNotFoundException: Commander -- service jboss.naming.context.java.jboss.Commander

          at org.jboss.spring.support.SpringInjectionSupport.lookup(SpringInjectionSupport.java:180) [snowdrop-deployers.jar:2.1.0.Final]

          at org.jboss.spring.support.SpringInjectionSupport.getObjectFromBeanFactory(SpringInjectionSupport.java:136) [snowdrop-deployers.jar:2.1.0.Final]

       

       

      Any ideas?  Is this setup even supported or instead of wrapping our spring application inside a servlet should we 'just' make its jars avaliable and have some dummy EJB or sar start the application?

       

      As a side note, I tried to build the sportsclub example but it can't find the jpl-util 1.0 (which is not avaliable on maven central); it also looks very outdated and I am wondering if there is a newer example distribution for snowdrop 2.x?

        • 1. Re: Accessing spring beans that are deployed in a war.
          Bas Ven Newbie

          Quick update.  Adding the META-INF/jboss-spring.xml file caused my war to stop deploying because it couldn't find other beans it uses to start.  So I guess that changes my question to 'why?'

          I am suspecting that there is some conflict with the spring jars that are in the snowdrop module and the spring jars that are packaged with the war.

          • 2. Re: Accessing spring beans that are deployed in a war.
            Tejas Mehta Newbie

            Hello Bas Ven,

             

            For your first post could you check in your jboss management (http://127.0.0.1:9990/management) to make sure that the Commander factory is indeed registered with JNDI. Also for sportsclub, I am not sure where you downloaded the sportsclub example, but you could try from here: https://github.com/snowdrop/snowdrop-examples/tree/master/sportsclub (with the spring version you are using), these are the most up to date.

             

            As for the spring jars conflicting, you could try adding a jboss-deployment-structure.xml file in your WEB-INF dir, with contents:

             

            <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">

                <deployment>

                    <exclusions>

                        <module name="org.springframework.spring" slot="snowdrop"/>

                    </exclusions>

                </deployment>

            </jboss-deployment-structure>

             

            Cheers,

             

            Tejas M.

            • 3. Re: Accessing spring beans that are deployed in a war.
              Bas Ven Newbie

              Thanks for the response.  I downloaded the example from your main page: http://downloads.jboss.org/snowdrop/examples/sportsclub/1.0/sportsclub-1.0.zip

              When I go to http://localhost:9990/console/App.html#naming I do not see that the commander factory is registered.
              But I think that might be because my spring application never starts when I enable snowdrop scanning.  In its bootstrap it first creates an AnnotationConfigApplicationContext.  The first time it does an action on it, it gets a BeanException coming from the snowdrop module:

               

               

              java.lang.ClassNotFoundException: org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor from [Module "org.springframework.spring:snowdrop" from local module loader @6c7779d2 (roots: /home/bven/devel/jboss/modules)]

               

              The class it is complaining about is part of the spring-core jar which is defined in the snowdrop module above.

               

              At first I thought that maybe that was because that jar also lived in my ear, but I both removed it from the ear lib and I used your suggestion regarding the jboss structure file, and still get this exception.

              • 4. Re: Accessing spring beans that are deployed in a war.
                Tejas Mehta Newbie

                Thanks for pointing out the example was out of date, we will upload the latest version asap.

                 

                The error is because incompatibility of spring versions or the presence of spring-asm.jar. If I recall correctly this the same error message as seen because of this: https://issues.jboss.org/browse/SNOWDROP-59. I believe you can rectify this by downloading the latest version of snowdrop with the spring modules: http://downloads.jboss.org/snowdrop/2.1.0.Final/jboss-spring-subsystem-as7-2.1.0.Final.zip, and using the spring version that matches the one your project uses.

                • 5. Re: Accessing spring beans that are deployed in a war.
                  Bas Ven Newbie

                  We are indeed using spring version 3.2.3 which has inlined spring-asm in its core jar and we don't have the spring-asm.jar nor did I defined it in the snowdrop module.  Are you saying that snowdrop does not support spring 3.2.x ?   Your zip seems to have modules for 2.5, 3 and 3.1 but nothing higher.

                  On github however I do see a 3.2 module defined.  Should I try to build from source?

                   

                  I am trying to figure out if for our situation snowdrop is the way to go, or if we should try the SpringBeanAutowiringInterceptor interceptor.

                  Thanks for all the help.

                  • 6. Re: Accessing spring beans that are deployed in a war.
                    Bas Ven Newbie

                    Scratch that last one; I double checked and my module did have spring-asm in it; I must have re-installed over it.  I removed those lines and at least it is going further.  Now complaining about:

                     

                     

                    Caused by: java.lang.ClassNotFoundException: org.springframework.transaction.TransactionException from [Module "org.springframework.spring:snowdrop" from local module loader @17df01a0 (roots: /home/bven/devel/jboss/modules)]

                    At least I am getting further.

                    • 7. Re: Accessing spring beans that are deployed in a war.
                      Tejas Mehta Newbie

                      Sorry I didn't realize 2.1.0.Final did not contain the 3.2 modules, another thing to be fixed . Could you try with this: http://downloads.jboss.org/snowdrop/2.0.5.Final/jboss-spring-subsystem-as7-2.0.5.Final.zip, I checked it does contain the spring 3.2 modules. As far as I know snowdrop should not require a class from spring-tx, but if for some reason your project makes it reference something from it then you could download it (http://search.maven.org/remotecontent?filepath=org/springframework/spring-tx/3.2.3.RELEASE/spring-tx-3.2.3.RELEASE.jar) and put it in $JBOSS_HOME/modules/org/springframework/spring/snowdrop. Finally add <resource-root path="spring-tx.jar" /> to module.xml.

                       

                      Hopefully that will get you past that error.

                       

                      Cheers,

                       

                      Tejas M.

                      • 8. Re: Accessing spring beans that are deployed in a war.
                        Bas Ven Newbie

                        Making some progress and the war does get deployed succesfully, but I still see nothing being registered in JNDI and when I call an EJB where a spring bean should get injected I see a naming exception that the beanfactory ('SpringCommander') could not be found:

                         

                        java.lang.IllegalStateException: javax.naming.NameNotFoundException: SpringCommander -- service jboss.naming.context.java.jboss.SpringCommander

                        org.jboss.spring.support.SpringInjectionSupport.lookup(SpringInjectionSupport.java:180)

                        org.jboss.spring.support.SpringInjectionSupport.getObjectFromBeanFactory(SpringInjectionSupport.java:136)

                        org.jboss.spring.support.SpringInjectionSupport.injectToField(SpringInjectionSupport.java:202)

                        org.jboss.spring.support.SpringInjectionSupport.inject(SpringInjectionSupport.java:80)

                        org.jboss.spring.callback.SpringLifecycleInterceptor.postConstruct(SpringLifecycleInterceptor.java:43)

                         

                        I do see in the log file that at startup the jboss-spring.xml is found:

                         

                         

                        09:36:53,492 INFO  [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] (MSC service thread 1-14) Loading XML bean definitions from "/content/commander-server.war/META-INF/jboss-spring.xml"

                        09:36:53,526 INFO  [org.springframework.beans.factory.support.DefaultListableBeanFactory] (MSC service thread 1-14) Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6e9e2a8a: defining beans [dataSourceManager,commanderServer]; root of factory hierarchy

                         

                        Although that does seem to come from the spring framework.  Is there anything I can turn on logging wise to see if snowdrop is actually trying to register beans with JNDI?

                        • 10. Re: Accessing spring beans that are deployed in a war.
                          Bas Ven Newbie

                          Ok, getting furhter once again.  The problem about the BeanFactory not being registered was due to the fact that your jboss-spring.xml definition has changed from the examples I found on the site to what is actually needed.

                          As posted before, I had this defined as:

                           

                           

                          <?xml version="1.0" encoding="UTF-8"?>

                          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

                           

                          <beans>

                           

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

                              <bean id="dataSourceManager" class="database.DataSourceManagerImpl" />

                          </beans>

                           

                           

                          I looked thru some of the newer source and noticed that you defined them differently and I updated my jboss-spring.xml file to reflect that change:

                           

                           

                          <?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.xsd" default-lazy-init="true">

                           

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

                              <bean id="dataSourceManager" class="database.DataSourceManagerImpl" />

                              <bean id="commanderServer" class="server.CommanderServerImpl" />

                           

                          </beans>

                           

                           

                          Now when I look in the jBoss console I indeed see that the factory is registered with JNDI.

                           

                          However I still get an exception when I actually try to have the spring bean injected in my EJB and I hope you can help me out there.  This is the exception:

                          java.lang.IllegalArgumentException: Cannot retrieve an org.springframework.beans.factory.BeanFactory from java:jboss/SpringCommander - a org.jboss.spring.factory.NamedXmlApplicationContext found instead

                          org.jboss.spring.support.SpringInjectionSupport.lookup(SpringInjectionSupport.java:175)

                          org.jboss.spring.support.SpringInjectionSupport.getObjectFromBeanFactory(SpringInjectionSupport.java:136)

                          org.jboss.spring.support.SpringInjectionSupport.injectToField(SpringInjectionSupport.java:202)

                          org.jboss.spring.support.SpringInjectionSupport.inject(SpringInjectionSupport.java:80)

                          org.jboss.spring.callback.SpringLifecycleInterceptor.postConstruct(SpringLifecycleInterceptor.java:43)

                          • 11. Re: Accessing spring beans that are deployed in a war.
                            Joshua Wilson Newbie

                            Do you have "server" and "database" at the root level of your package structure?  I would guess you had something like "org.companyname.projectname.server".  If this is the case then you will want to use the full class path in the jboss-spring.xml.

                            • 12. Re: Accessing spring beans that are deployed in a war.
                              Bas Ven Newbie

                              I do have that but just removed it from the posting to protect the innocent :-)

                               

                              To me the exception looks like the lookup of the BeanFactory itself is not returning the correct type and it doesn't return the bean factory but its application context.

                              Then again I am not spring savvy at all.

                              • 13. Re: Accessing spring beans that are deployed in a war.
                                Joshua Wilson Newbie

                                And here I thought I solved all your problems.   We'll keep looking into this.

                                • 14. Re: Accessing spring beans that are deployed in a war.
                                  Bas Ven Newbie

                                  So am I :-).  I got past the exceptions by (I think) copying your jars into the jboss module and making sure that my ear is using that module (and does not provide its own snowdrop jar for the annotations).

                                  However, now the Spring beans that get injected in the EJB are null objects.

                                  1 2 Previous Next