10 Replies Latest reply on Aug 24, 2011 6:00 AM by benkirby

    Seam Config injected values not available in Singleton PostConstruct on AS7

    benkirby

      I have an EJB Singleton, annotated with @Startup. I'd like to populate the values of some of its fields using Seam Config.


      Following the documentation, I set this up, and it works a treat on JBoss AS6 - values are injected. However, I've now migrated to AS7, and the Seam Config behaviour seems different.


      The configuration is all correct, I believe - XmlConfigExtension tells me it's Adding XML Defined Bean for the correct class, and I don't get any errors about the fields not being in the namespace, so all tallies up. It's just that, in the PostConstruct of the singleton bean, I can see that the injected fields still have null values. With AS6, they were populated at this point.


      When I use Seam Config on a plain managed bean - not an EJB - that I've injected onto the Singleton, I can see that Seam Config is Wrapping InjectionTarget to set field values, and, sure enough, the injected bean's values are populated.


      So, do you have to explicitly Inject the bean you're configuring values for in order for those values to be injected? i.e. you can't use Seam Config on @Startup beans? Or is it problematic using it on ANY EJBs? Like I say, this was working fine on AS6, using the same version of Seam Config (3.0.0.Final).


      Thanks,
      Ben

        • 1. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
          lightguard

          That's a good question, I've asked Stuart if he can comment.

          • 2. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
            swd847

            This should be fixed in the upcoming 7.0.1 release, which should be released in the next few days.

            • 3. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
              benkirby

              Thanks both. Will look out for JBoss AS 7.0.1, and try again then.

              • 4. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                benkirby

                Still having issues with Seam Config on AS7, using AS 7.1.0.Alpha1-SNAPSHOT from the early hours of 18/08.


                I've got a simple test to check Seam Config is working (this approach worked in AS6):


                import static org.junit.Assert.assertEquals;
                
                import javax.inject.Inject;
                
                import org.jboss.arquillian.container.test.api.Deployment;
                import org.jboss.arquillian.junit.Arquillian;
                import org.jboss.shrinkwrap.api.Archive;
                import org.jboss.shrinkwrap.api.ShrinkWrap;
                import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
                import org.jboss.shrinkwrap.api.spec.JavaArchive;
                import org.junit.Ignore;
                import org.junit.Test;
                import org.junit.runner.RunWith;
                
                import uk.co.magus.jam.core.testutil.MavenArtifactResolver;
                
                
                @RunWith(Arquillian.class)
                public class TestSeamConfig {
                
                     /** This has to be the same as the text for the description field in the beans.xml */
                     private static final String EXPECTED_DESCRIPTION = "This has been injected by Seam Config";
                
                     protected final static String[] libraries = new String[] {
                          "org.jboss.seam.persistence:seam-persistence:3.0.0.Final",
                          "org.jboss.seam.solder:seam-solder:3.0.0.Final",
                          "org.jboss.seam.config:seam-config-xml:3.0.0.Final",
                     };
                
                     @Inject SeamConfigService service;
                
                     @Deployment
                     public static Archive<?> createDeployment() {
                
                          EnterpriseArchive mainArchive = ShrinkWrap.create(EnterpriseArchive.class, "seam-config-test.ear");
                          mainArchive.addAsLibraries(MavenArtifactResolver.resolve(libraries));
                
                          JavaArchive innerJar = ShrinkWrap.create(JavaArchive.class, "inner-test.jar");
                          innerJar.addPackage(TestSeamConfig.class.getPackage());
                          /*innerJar.addClass(TestSeamConfig.class);
                          innerJar.addClass(SeamConfigService.class);*/
                          innerJar.addAsManifestResource("beans.xml", "beans.xml");
                          mainArchive.addAsModule(innerJar);
                
                          System.out.println(innerJar.toString(true));
                          System.out.println(mainArchive.toString(true));
                
                          return mainArchive;
                     }
                
                
                     @Ignore // Seam config not yet working
                     @Test
                     public void testDefaultServiceDescriptionValueFromBeansXML(){
                          assertEquals("serviceDescription field on service is not as expected, from beans.xml",
                                    EXPECTED_DESCRIPTION, service.getServiceDescription());
                     }
                }
                



                The SeamConfigService injected on the test is replaced in the beans.xml, which looks like this:


                <?xml version="1.0" encoding="UTF-8"?>
                <beans xmlns="http://java.sun.com/xml/ns/javaee"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xmlns:s="urn:java:ee" 
                    xmlns:m="urn:java:uk.co.magus.jam.concept.config"
                    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                    http://docs.jboss.org/cdi/beans_1_0.xsd">     
                
                     <interceptors>
                         <class>org.jboss.seam.transaction.TransactionInterceptor</class>
                     </interceptors>
                   
                     <m:SeamConfigService>
                          <s:replaces/>
                          <m:serviceDescription>This has been injected by Seam Config</m:serviceDescription>
                     </m:SeamConfigService>
                </beans>
                



                However, when the Arquillian test deploys, Weld can't seem to find the class:


                13:08:02,095 INFO  [org.jboss.as.arquillian] (MSC service thread 1-2) Arquillian deployment detected: ArquillianConfig[service=jboss.arquillian.config."inner-test.jar",unit=inner-test.jar,tests=[uk.co.magus.jam.concept.config.TestSeamConfig]]
                13:08:02,096 DEBUG [org.jboss.as.arquillian] (MSC service thread 1-23) Register Arquillian config: service jboss.arquillian.config."inner-test.jar"
                13:08:02,107 INFO  [org.jboss.seam.solder.Version] (MSC service thread 1-6) Seam Solder null (build id: null)
                13:08:02,110 INFO  [org.jboss.seam.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Seam Config XML provider starting...
                13:08:02,111 INFO  [org.jboss.seam.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Loading XmlDocumentProvider: org.jboss.seam.config.xml.bootstrap.ResourceLoaderXmlDocumentProvider
                13:08:02,114 INFO  [org.jboss.seam.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Reading XML file: vfs:/C:/Windows/System32/content/seam-config-test.ear/inner-test.jar/META-INF/beans.xml
                13:08:02,126 INFO  [org.jboss.seam.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Reading XML file: vfs:/C:/Windows/System32/content/seam-config-test.ear/lib/seam-solder-3.0.0.Final.jar/META-INF/beans.xml
                13:08:02,131 INFO  [org.jboss.seam.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Adding XML Defined Bean: uk.co.magus.jam.concept.config.SeamConfigService
                13:08:02,147 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.transaction.UTTransaction from being installed as bean due to @Veto annotation
                13:08:02,159 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.transaction.SeSynchronizations from being installed as bean due to @Veto annotation
                13:08:02,165 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.transaction.CMTTransaction from being installed as bean due to @Veto annotation
                13:08:02,167 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.transaction.EntityTransaction from being installed as bean due to @Veto annotation
                13:08:02,180 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.persistence.hibernate.HibernateManagedSessionExtensionImpl from being installed as bean due to @Veto annotation
                13:08:02,181 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.transaction.NoTransaction from being installed as bean due to @Veto annotation
                13:08:02,328 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.solder.core.VersionLoggerUtil from being installed as bean due to @Veto annotation
                13:08:02,405 INFO  [org.jboss.seam.solder.core.CoreExtension] (MSC service thread 1-6) Preventing class org.jboss.seam.solder.resourceLoader.ResourceProvider from being installed as bean due to @Veto annotation
                13:08:02,476 INFO  [org.jboss.seam.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Preventing installation of default bean: uk.co.magus.jam.concept.config.SeamConfigService
                13:08:02,552 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-6) MSC00001: Failed to start service jboss.deployment.unit."seam-config-test.ear".WeldService: org.jboss.msc.service.StartException in service jboss.deployment.unit."seam-config-test.ear".WeldService: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [SeamConfigService] with qualifiers [@Default] at injection point [[field] @Inject uk.co.magus.jam.concept.config.TestSeamConfig.service]
                     at org.jboss.as.weld.services.WeldService.start(WeldService.java:96)
                     at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1765)
                     at org.jboss.msc.service.ServiceControllerImpl$ClearTCCLTask.run(ServiceControllerImpl.java:2291)
                     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885) [:1.6.0_07]
                     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907) [:1.6.0_07]
                     at java.lang.Thread.run(Thread.java:619) [:1.6.0_07]
                Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [SeamConfigService] with qualifiers [@Default] at injection point [[field] @Inject uk.co.magus.jam.concept.config.TestSeamConfig.service]
                     at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:270)
                     at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:106)
                     at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:129)
                     at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:351)
                     at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:336)
                     at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:404)
                     at org.jboss.as.weld.WeldContainer.start(WeldContainer.java:82)
                     at org.jboss.as.weld.services.WeldService.start(WeldService.java:89)
                     ... 5 more
                



                Even though we can SEE that Seam Config is stopping the default bean and adding the XML defined bean.


                Any idea what's going on here? Thanks again for your help.



                • 5. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                  smurfs.smurfsturf.googlemail.com

                  Ben, I don't think this is an AS7 issue as I have a similar use case which works fine in an older AS7 build, although I must point out my arquillian deployment is packaged as a war file (not that that should make a difference).


                  Your stacktrace indicates there is an unsatisfied dependency. You probably don't see this in AS6 as it bundles every library under the sun so the dependency is probably resolved when the test runs in that environment. Unfortunately Arquillian doesn't give any clue as to which dependency is missing which is frustrating. I'd suggest you re-check your packaged classes do not depend on libraries not included in the bundle, and that all dependent classes are included. Obvious I know, but I'm often tripped up!


                  It looks like you have the correct libraries packaged (I use seam-config-xml which has a dependency on seam-solder, but don't use seam-persistence).


                  Another gotcha is unused import statements in classes which may create dependencies you are not taking account of, so it's worth checking you have none.


                  If this does not work I will I will try find time to put together a basic test case, but it would be useful to see the code for uk.co.magus.jam.concept.config.SeamConfigService at some point.

                  • 6. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                    benkirby

                    Thanks a lot for the response, Andrew, good ideas! Good to know what other people are using it for too.


                    I've had a check over my included classes. The type that Weld can't find is SeamConfigService itself, I think:


                    WELD-001408 Unsatisfied dependencies for type [SeamConfigService] with qualifiers [@Default] at injection point [[field] @Inject uk.co.magus.jam.concept.config.TestSeamConfig.service]
                    



                    as referenced by the test class. This is definitely packaged in the test archive. In fact, if I comment out the the replacement bean definition in the beans.xml, the test archive deploys fine, so it still seems to me like it's the definition of a replacement bean in the XML which causes the bean not to be seen by Weld, and the archive therefore not to deploy.


                    So Seam Config is working fine for you with AS7, yeah? I've yet to be able to get the values populated, although I've only been working with it on EJB Singletons.


                    Good point about SeamConfigService code, here it is:


                    package uk.co.magus.jam.concept.config;
                    
                    import javax.ejb.LocalBean;
                    import javax.ejb.Singleton;
                    import javax.ejb.Startup;
                    
                    
                    @LocalBean
                    @Startup
                    @Singleton
                    public class SeamConfigService {
                    
                         private String serviceDescription = null;
                    
                         public SeamConfigService(){
                              System.out.println("serviceDescription: "+serviceDescription);
                         }
                    
                         public String getServiceDescription() {
                              return serviceDescription;
                         }
                    
                         public void setServiceDescription(String serviceDescription) {
                              this.serviceDescription = serviceDescription;
                         }
                    }
                    

                    • 7. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                      smurfs.smurfsturf.googlemail.com

                      I've run your code. You need to change @Inject SeamConfigService service; in your test class to use the @EJB annotation and that will get rid of the unsatified dependency problem. Unfortunately the original problem remains, that is, the serviceDescription property is still null. This may well be related to the issue Stuart says has been fixed upstream.


                      My usage of seam-config-xml is slightly different in that I am using a managed bean, not an ejb, so sorry for the confusion.


                      If you want to try my set-up then change the annotations on SeamConfigService.java to javax.enterprise.context.ApplicationScoped and javax.annotation.ManagedBean, and in your test class leave @Inject SeamConfigService service; as is. The code will work as expected however this approach may not be want you want, especially if you require container managed transactions etc. that come with using ejbs. If that's the case you may just have to sit it out until AS7 is fixed.


                      • 8. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                        lightguard

                        If you're still having issues, please submit the test as an attachment to a new JIRA.

                        • 9. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                          smurfs.smurfsturf.googlemail.com

                          Ben, I hacked around a bit more last night as I may also need to implement an ejb singleton soon. What I discovered is as follows (perhaps a seam/weld/as7 guru can join the dots to explain what is happening):



                          1. Your code runs in a packaged ear by commenting out @Singleton in SeamConfigService.java. This isolates the problem but is not very useful to do if you need a singleton.

                          2. Your unmodified code runs in a packaged war, but requires an identier annotation on SeamConfigService.java to suppress a WELD-001409 Ambiguous dependencies exception. Strangely the injection point @Inject SeamConfigService service; in the test class should not be annotated with the identifer otherwise the test fails.



                          Here are the changes and hacks I made to get it to work in my environment (AS7 build 1522).


                          Changed @Deployment in TestSeamConfig.java to...
                          
                              @Deployment
                              public static Archive<?> createDeployment() {
                                  return ShrinkWrap
                                          .create(WebArchive.class, "seam-config-test.war")
                                          .addPackage(TestSeamConfig.class.getPackage())
                                          .addAsLibraries(MavenArtifactResolver.resolveAll(libraries))
                                          .addAsResource("beans.xml", "META-INF/beans.xml");
                              }
                          


                          Created a qualifier annotation...


                          package uk.co.magus.jam.concept.config;
                          
                          import static java.lang.annotation.ElementType.METHOD;
                          import static java.lang.annotation.ElementType.PARAMETER;
                          import static java.lang.annotation.ElementType.TYPE;
                          import static java.lang.annotation.ElementType.FIELD;
                          import static java.lang.annotation.RetentionPolicy.RUNTIME;
                          
                          import java.lang.annotation.Retention;
                          import java.lang.annotation.Target;
                          
                          import javax.inject.Qualifier;
                          
                          @Qualifier
                          @Retention(RUNTIME)
                          @Target({ TYPE, METHOD, FIELD, PARAMETER })
                          public @interface MagusConfig {
                          
                          }
                          



                          ... and added it to SeamConfigService.java


                          @LocalBean
                          @Startup
                          @Singleton
                          @MagusConfig
                          public class SeamConfigService implements Serializable {
                           //...
                          }
                          



                          I trust this gives you a little more insight and will assist in creating the test case requested by Jason.


                          • 10. Re: Seam Config injected values not available in Singleton PostConstruct on AS7
                            benkirby

                            Fantastic - thanks for all your help, Andrew, in this and the previous post.


                            I'll play aaround with test WARs and also the @EJB annotation, see if I have any luck. If not, I'll do that JIRA.