4 Replies Latest reply on Mar 21, 2011 11:09 AM by dlmiles

    AS6 & Snowdrop2 multiple queries


      I am using JBoss AS6 with Snowdrop 2.0.0-MP1-SP1, I have updated the spring implementation with 3.0.5.RELEASE (although I wish either that all JARs were named with the version "spring-core-3.0.5.RELEASE.jar", yes you can get them like that from Maven, or you at least put them in a directory of their version "3.0.5.RELEASE/spring-core.jar", which might lend itself to OSGi based version selection for AS7).


      I have a number of queries.



      My project layout is a straight forward EAR with a JPA jar, with a EJB jar, with a WAR.


      EAR has META-INF/earApplicationContext-spring.xml

      JPA has META-INF/jpaApplicationContext-spring.xml

      EJB has META-INF/ejbApplicationContext-spring.xml

      WAR has WEB-INF/classes/spring-context/warApplicationContext-spring.xml and WEB-INF/classes/spring-servlet/servlet-spring.xml


      Each of these has a http://www.springframework.org/schema/beans/spring-beans-3.0.xsd and a <description> element with the BeanFactory=(label) and ParentBeanFactory=(label).  I have verified in JNDI the name of the bindings for the (label) parts.  these are the files names without -spring.xml suffix like "earApplicationContext".



      Problem 1)


      However I have not been able to verify the parent/child relationships are being correctly setup by spring.deployer.  I can see in org.jboss.spring.factory.NamedXmlBeanDefinitionParser the new BeanFactory get #setParentBeanFactory() called.


      There is also a <description> element variable Instantiation(true) which by default is set to false (which I think should be true) but I can't see how or where it is used by the spring.deployer.



      Problem 2)


      How is the WAR handled, should both the outside ApplicationContext and the child servlet's be setup in the traditional (WAR only) way and using the <listener> and <servlet> settings in web.xml.


      Since the JBoss VFS can see inside of the EAR and all the classpaths, is the WAR packaged correctly or should a certain naming convention not be used.



      Problem 3)


      If my EAR was a little more complex.  How is it possible to control the order in which both JBoss AS brings up each JAR  (so we're talking JPA, EJB and regular JARs) all inside EAR.  Does this order also affect how and when SNOWDROP creates the parent/child relationships ?  To me it would seem that SNOPDROP should scan for all possible ApplicationContext's to instate just the skeleton factory itself (no beans inside yet), it should create them all and name each.  Then once all are created another pass to fixup the parent/child relationship.  Then on another pass walking the BeanFactory top-down it would then process the non-lazy beans within.



      Problem 4)


      Does BeanFactoryLocator work within an EAR context like (I think) it should.  When I query it, I find it empty.   I believe this mechanism could be used to allow 2 sibling BeanFactorys in a hierarchy to find each other.  There is some overlap with JNDI in this function but which this is Spring's own method.



      Problem 5)


      I'm sure older version of SNOPWDROP allowed arbitrary naming and bindings to JNDI, such as "spring/myenterprise-mymodule-ear" (note the use of the "spring/" path prefix), this does not seem to be allowed anymore.  What/why is the change of policy on this ?



      Last question)


      Is there any suitably complex example of multiple ApplicationContexts inside different JEE deployables all wrapped in an EAR to demonstrate/test such functionality ?

        • 1. AS6 & Snowdrop2 multiple queries

          Hi Darryl,


          1) Some logging in that area could help, but if the parent-child relationships aren't established the bootstrap process of the children will fail  (since I am assuming that the parents will provide beans for the children).


          2) The ContextLoaderListener mechanism is completely separate from spring.deployer. Can you explain what you meant by "Since the JBoss VFS can see inside of the EAR and all the classpaths, is the WAR packaged correctly or should a certain naming convention not be used?"


          3) It is not possible to control the order in which the deployment units are deployed, but there is an order in which the various modules are deployed (due to the EAR structure). However, I like better the idea of bootstrapping contexts in an order defined by the dependency graph - which can be done by bootstrapping all contexts from the top-level dependency unit. One idea for 2.0 is to create the contexts parent-children hierarchy based on the deployment unit structure (by default in the least). Feel free to add a JIRA item to track this and/or contribute with more insight.


          4) What does your beanRefContext.xml definition look like?


          5) Could you file a bug for that, perhaps with a small project reproducing the issue?


          Last) Not right now. We do have a Sportsclub example which is fairly complex, however it only has one context definition. Needless to say, contributions are welcome

          • 2. AS6 & Snowdrop2 multiple queries

            First thanks for your  reply.


            1) Yes I agree from looking at the spring.deploy codebase (and testing by creating deliberate failure scenarios, like using the wrong label) that the parent/child must be getting setup at the time that code runs.  But accoridng to my code inside the WAR which uses JNDI and examines the WAR ApplicationContext those settings do not stick, something is nulling the parent/parentBeanFactory out.  I create this WAR code after my posting to this thread, so I shall paste the code and output in a new reply shortly.


            2) Through trial-and-error/testing I found that the spring.deploy does not look inside the WAR.  It was my understanding the JBoss VFS could see descriptors nested inside a mix of dirs/JARs, so JARs inside JARs are transparent from a scan for a valid deployment descritpor and for spring this means my WEB-INF/spring-context/warApplicationContext-spring.xml _SHOULD_ match and spring.deploy should see it.  But my testing indicates that even so it does not attempt to deploy it.  In some ways I am not expecting to but I could not see how it was being skipped.  My EAR has an exploded EJB and WAR directory which makes it even more apparent, since even without JBoss VFS code a file-scan would find it.


            So getting back to the question "Should a certain naming convention not be used" ?  This means the file $JBOSS_HOME/server/default/my.domain.ear/my.domain.war/WEB-INF/classes/spring-context-warApplicationContext-spring.xml being a filre on the filesystem I would have expected it to be found by the spring.deployer.  Since I know the Instantiaion(false) does not work.  I wondered why it was being missed by the JBoss VFS code, if it is meant to be able to see descriptors from inside nested deloyments.  This would make using /WEB-INF/classes/spring-context/warApplicationContext-spring.xml a _BAD_ choice of filename.  Changing the -spring.xml would be a good chocie.  However it appears to make no difference, since it is never looked at by spring.deployer so why is this ?


            3) I'd like to come back to this point at a later date.  After establishing my better understanding of the other points.


            4) beanRefContext.xml I need to understand this better, I have not been using it in any projects I've created so far.


            5) This is easy to observe, simply prepend the BeanFactory(label) with spring/ making it BeanFactory(spring/label) this used to bind to JNDI hierarchically.  I'll try to knock out a simple EAR for JIRA later this week.


            Last) http://docs.redhat.com/docs/en-US/JBoss_Web_Framework_Kit/1.1/html/Snowdrop_Sportsclub_Example/index.html this looks to be a relevant URL.

            • 3. Re: AS6 & Snowdrop2 multiple queries


              InitialContext ctxt;

                      try {

                          ctxt = new InitialContext();

                          NamingEnumeration<Binding> bindings = ctxt.listBindings((String)"");

                          while(bindings.hasMore()) {

                              Binding b = bindings.next();

                              sb.append(";" + b.toString() + "\n");


                          String[] jndiPathList = { "earApplicationContext", "jpaApplicationContext", "ejbApplicationContext", "warApplicationContext", "//Helper" };

                          for(String jndiPath : jndiPathList) {

                              //String jndiPath = "ejbApplicationContext";

                              //jndiPath = "jpaApplicationContext";

                              //jndiPath = "earApplicationContext";

                              try {

                                  Object o;

                                  if(jndiPath.equals("//Helper")) {

                                      javax.servlet.ServletContext sc = WicketApplication.get().getServletContext();

                                      o = WebApplicationContextUtils.getWebApplicationContext(sc);

                                  } else {

                                      o = ctxt.lookup(jndiPath);


                                  sb.append(">>> jndiPath=" + jndiPath + "\n");

                                  sb.append(">>> type=" + ((o != null)? o.getClass().getName() : "unknown") + "\n");

                                  sb.append(">>> toString=" + ((o != null) ? o.toString() : "null") + "\n");

                                  BeanFactory bf = (BeanFactory)o;

                                  ApplicationContext ac = (ApplicationContext)bf;

                                  sb.append(">>> getId=" + ac.getId() + "\n");

                                  sb.append(">>> displayName=" + ac.getDisplayName() + "\n");

                                  sb.append(">>> parent=" + ac.getParent() + "\n");

                                  sb.append(">>> parentBeanFactory=" + ac.getParentBeanFactory() + "\n");

                              } catch(NameNotFoundException e) {

                                  sb.append(">>> jndiPath=" + jndiPath + "\n");

                                  sb.append(">>> NameNotFoundException=" + e.getMessage() + "\n");


                              //sb.append(">>> " + ac. + "\n");


                              //bf = (BeanFactory) applicationContext;




                      } catch (NamingException e) {

                          // TODO Auto-generated catch block





              Returns data:




              ;UserTransactionSessionFactory: $Proxy102:org.jboss.invocation.unified.interfaces.UnifiedInvokerProxy@5872ee46

              ;UUIDKeyGeneratorFactory: org.jboss.ejb.plugins.keygenerator.uuid.UUIDKeyGeneratorFactory:org.jboss.ejb.plugins.keygenerator.uuid.UUIDKeyGeneratorFactory@2ffd6b29

              ;com.domain.ear: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@53e7ec65

              ;HiLoKeyGeneratorFactory: org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory:org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory@76da70d4

              ;SecureDeploymentManager: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@1f5105ec

              ;SecureManagementView: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@5bd904

              ;DeploymentManager: org.jboss.aop.generatedproxies.AOPProxy$4:org.jboss.aop.generatedproxies.AOPProxy$4@12e9aaf5

              ;XAConnectionFactory: org.hornetq.jms.client.HornetQConnectionFactory:Reference Class Name: org.hornetq.jms.client.HornetQConnectionFactory

              Type: HornetQ-CF

              Content: [B@e0495cb


              ;persistence.unit:unitName=com.domain.ear.ear: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@4f06499d

              ;persistence.unit:unitName=jboss-ejb3-timerservice-mk2.jar#timerdb: org.hibernate.impl.SessionFactoryImpl:Reference Class Name: org.hibernate.impl.SessionFactoryImpl

              Type: uuid

              Content: 7c0ac58c-5bca-469a-9fc0-69cd1d690f02


              ;ProfileService: org.jboss.aop.generatedproxies.AOPProxy$2:org.jboss.aop.generatedproxies.AOPProxy$2@19b8db54

              ;jpaApplicationContext: org.jboss.spring.factory.NamedXmlApplicationContext:Reference Class Name: org.jboss.spring.factory.NamedXmlApplicationContext

              Type: nns

              Content: jpaApplicationContext


              ;SecureProfileService: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@25cb0af3;queue: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@353beae7

              ;UserTransction: org.jboss.tm.usertx.client.ClientUserTransaction:Reference Class Name: org.jboss.tm.usertx.client.ClientUserTransaction


              ;ConnectionFactory: org.hornetq.jms.client.HornetQConnectionFactory:Reference Class Name: org.hornetq.jms.client.HornetQConnectionFactory

              Type: HornetQ-CF

              Content: [B@70bafefe


              ;jmx: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@4bb0f84;ProxyFactory: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@14f7a589

              ;BeanValidatorFactories: org.jnp.interfaces.NamingContext:org.jnp.interfaces.NamingContext@e94d020

              ;earApplicationContext: org.jboss.spring.factory.NamedXmlApplicationContext:Reference Class Name: org.jboss.spring.factory.NamedXmlApplicationContext

              Type: nns

              Content: earApplicationContext


              ;ejbApplicationContext: org.jboss.spring.factory.NamedXmlApplicationContext:Reference Class Name: org.jboss.spring.factory.NamedXmlApplicationContext

              Type: nns

              Content: ejbApplicationContext


              ;TomcatAuthenticators: java.util.Properties:{FORM=org.apache.catalina.authenticator.FormAuthenticator, BASIC=org.apache.catalina.authenticator.BasicAuthenticator, DIGEST=org.apache.catalina.authenticator.DigestAuthenticator, CLIENT-CERT=org.apache.catalina.authenticator.SSLAuthenticator, NONE=org.apache.catalina.authenticator.NonLoginAuthenticator}

              ;XAThroughputConnectionFactory: org.hornetq.jms.client.HornetQConnectionFactory:Reference Class Name: org.hornetq.jms.client.HornetQConnectionFactory

              Type: HornetQ-CF

              Content: [B@4bebec5a


              ;ManagementView: org.jboss.aop.generatedproxies.AOPProxy$3:org.jboss.aop.generatedproxies.AOPProxy$3@26bba826

              ;ThroughputConnectionFactory: org.hornetq.jms.client.HornetQConnectionFactory:Reference Class Name: org.hornetq.jms.client.HornetQConnectionFactory

              Type: HornetQ-CF

              Content: [B@6dea2fa6


              >>> jndiPath=earApplicationContext

              >>> type=org.jboss.spring.factory.NamedXmlApplicationContext

              >>> toString=org.jboss.spring.factory.NamedXmlApplicationContext@4a814c0d: startup date [Mon Mar 21 14:35:47 GMT 2011]; root of context hierarchy

              >>> getId=org.jboss.spring.factory.NamedXmlApplicationContext@4a814c0d

              >>> displayName=org.jboss.spring.factory.NamedXmlApplicationContext@4a814c0d

              >>> parent=null

              >>> parentBeanFactory=null



              >>> jndiPath=jpaApplicationContext

              >>> type=org.jboss.spring.factory.NamedXmlApplicationContext

              >>> toString=org.jboss.spring.factory.NamedXmlApplicationContext@18b706c8: startup date [Mon Mar 21 14:35:48 GMT 2011]; root of context hierarchy

              >>> getId=org.jboss.spring.factory.NamedXmlApplicationContext@18b706c8

              >>> displayName=org.jboss.spring.factory.NamedXmlApplicationContext@18b706c8

              >>> parent=null

              >>> parentBeanFactory=null



              >>> jndiPath=ejbApplicationContext

              >>> type=org.jboss.spring.factory.NamedXmlApplicationContext

              >>> toString=org.jboss.spring.factory.NamedXmlApplicationContext@4c47a353: startup date [Mon Mar 21 14:35:48 GMT 2011]; root of context hierarchy

              >>> getId=org.jboss.spring.factory.NamedXmlApplicationContext@4c47a353

              >>> displayName=org.jboss.spring.factory.NamedXmlApplicationContext@4c47a353

              >>> parent=null

              >>> parentBeanFactory=null



              >>> jndiPath=warApplicationContext

              >>> NameNotFoundException=warApplicationContext not bound



              >>> jndiPath=//Helper

              >>> type=org.springframework.web.context.support.XmlWebApplicationContext

              >>> toString=Root WebApplicationContext: startup date [Mon Mar 21 14:36:51 GMT 2011]; root of context hierarchy

              >>> getId=org.springframework.web.context.WebApplicationContext:/webapp.wicket

              >>> displayName=Root WebApplicationContext

              >>> parent=null

              >>> parentBeanFactory=null




              • 4. Re: AS6 & Snowdrop2 multiple queries

                The jndiPath for earApplicationContext, jpaApplicationContext and ejbApplicationContext were deployed by spring.deployer.  They have configured a parent/child relationship (in their respective <description> elements), with the EAR being toplevel, the JPA and EJB being direct children of the EAR.  However you can see parent/parentBeanFactory are null like that configuration did nothing to the initial state.  I have confirmed the context.setParentBeanFactory() it being called, by breaking the labels so I see an exception and EAR deployment failure occur.  So this is why I question matters in this thread, 1) is this expect behaviour ?  2) Have I misunderstood/missconfigured something ?  3) Do you know about this ?


                Also to add... spring.deployer also sets up displayName to be the JNDI name, from what I can make out, but this is also getting reset.



                The warApplicationContext is delpoyed by the standard spring WAR <listener>.  JBoss AS spring.deployer did not see or touch it.  I have never been able to make it (spring.deployer) see it.  You can see the warApplicationContext not bound to JNDI but clearly exists when you look it up via normal spring means from inside the WAR.  The WAR is inside the EAR.


                The Java code was executed for a webpage inside the WAR and the output printed.  The whole EAR was deployted to JBoss AS 6.