9 Replies Latest reply on Apr 6, 2011 9:12 AM by viggo.navarsete

    Using ejb-jar.xml for @Singleton bean

    benoit.heinrich

      Hi everyone,

       

      I'm new to EJB3.1 and I'm not sure if I'm posting the question to the right forum, so be nice with me to redirect me to the right section if you think it's not ok here.

       

      I'm converting an old jboss @Service (that was running on jboss 4.2.3) to the new @Singleton pattern that I'm deploying to jboss 6.0.0.Final.

       

      My singleton has a lot of dependencies to a lot of beans and to prevent to workaround the issue with dependency resolution for transitive relationships (https://issues.jboss.org/browse/EJBTHREE-2227) I've moved my Singleton to a separate ear file and then I've set my ears to deploy the one after the other.

       

      Both ears are using the same jboss-app.xml to share the same classloader and I've got two deployment scenario where one work and the other fails.

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

      <!DOCTYPE jboss-app PUBLIC

              "-//JBoss//DTD Java EE Application 5.0//EN"

              "http://www.jboss.org/j2ee/dtd/jboss-app_5_0.dtd">

      <jboss-app>

        <loader-repository>

          com.example:loader=01-services

          <loader-repository-config>java2ParentDelegation=false</loader-repository-config>

        </loader-repository>

      </jboss-app>

       

       

      To reproduce the problem I've created a small example:

       

      Scenario 1, no ejb-jar.xml

      Here I'm not using ejb-jar.xml and I'm setting the lookup name inside the @EJB annotation

       

      package com.example.services.startup;

       

      import com.example.services.version.VersionManager;

      import org.apache.commons.logging.Log;

      import org.apache.commons.logging.LogFactory;

       

      import javax.annotation.PostConstruct;

      import javax.ejb.EJB;

      import javax.ejb.Singleton;

      import javax.ejb.Startup;

       

      @Singleton

      @Startup

      public class StartupBean {

          private static final Log log = LogFactory.getLog(StartupBean.class);

       

          @EJB(lookup = "01-services/VersionManagerBean/local")

          private VersionManager versionManager;

       

          @PostConstruct

          public void startup() {

              log.info("System started (version " + versionManager.getVersion() + ")");

          }

      }

       

      When I deploy this to jboss 6 it sucessfully logs the message and so:

      This one works

       

       

      Scenario 2, jndi mapping done through ejb-jar.xml

      In this scenario I've got the same @Singleton bean but now the @EJB is using a name to reference the ejb from the ejb-jar.xml

      package com.example.services.startup;

       

      import com.example.services.version.VersionManager;

      import org.apache.commons.logging.Log;

      import org.apache.commons.logging.LogFactory;

       

      import javax.annotation.PostConstruct;

      import javax.ejb.EJB;

      import javax.ejb.Singleton;

      import javax.ejb.Startup;

       

      @Singleton

      @Startup

      public class StartupBean {

          private static final Log log = LogFactory.getLog(StartupBean.class);

       

          @EJB(name = "ejb/VersionManager")

          private VersionManager versionManager;

       

          @PostConstruct

          public void startup() {

              log.info("System started (version " + versionManager.getVersion() + ")");

          }

      }

       

      And here is the ejb-jar.xml:

       

      ejb-jar.xml
      <ejb-jar
      version="3.1">

       

          <enterprise-beans>

              <session>

                  <ejb-name>StartupBean</ejb-name>

                  <ejb-class>com.example.services.startup.StartupBean</ejb-class>

                  <ejb-local-ref>

                      <ejb-ref-name>ejb/VersionManager</ejb-ref-name>

                      <local>com.example.services.version.VersionManager</local>

                      <lookup-name>01-services/VersionManagerBean/local</lookup-name>

                  </ejb-local-ref>

              </session>

          </enterprise-beans>

      </ejb-jar>

      end

      The ejb-jar.xml is supposed to show just above... but for some reasons it doesn't show... but when I edit I can see the content of it.

      Any idea how I can show the ejb-jar.xml

       

      The ejb-jar.xml is then attached to the post

       

      This one fails

      And here are the logs from JBoss:

      21:34:04,762 INFO  [org.jboss.deployment.dependency.ContainerDependencyMetaData] addJndiDependency, JndiDependencyMetaData@ae8e56{01-services/VersionManagerBean/local}

      21:34:04,762 WARN  [org.jboss.deployment.MappedReferenceMetaDataResolverDeployer] Unresolved references exist in JBossMetaData:[startup-1.19.0-SNAPSHOT.jar#StartupBean:AnnotatedEJBReferenceMetaData{name=ejb/VersionManager,ejb-ref-type=null,link=null,ignore-dependecy=false,mapped/jndi-name=null,resolved-jndi-name=null,beanInterface=interface com.example.services.version.VersionManager}]

      21:34:04,763 INFO  [org.jboss.ejb3.deployers.Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@10013305{vfs:///opt/src/jboss-6.0.0.Final/server/default/deploy/99-example-startup.ear/startup-1.19.0-SNAPSHOT.jar/}

      21:34:04,763 INFO  [org.jboss.ejb3.deployers.Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@10013305{vfs:///opt/src/jboss-6.0.0.Final/server/default/deploy/99-example-startup.ear/startup-1.19.0-SNAPSHOT.jar/}

      21:34:04,767 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to Real: name=vfs:///opt/src/jboss-6.0.0.Final/server/default/deploy/99-example-startup.ear state=PreReal mode=Manual requiredState=Real: org.jboss.deployers.spi.DeploymentException: Error during deploy: org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData.StartupBean

          at org.jboss.deployers.spi.DeploymentException.rethrowAsDeploymentException(DeploymentException.java:49) [:2.2.0.GA]

          at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(DeployerWrapper.java:185) [:2.2.0.GA]

      ...

      Caused by: java.lang.RuntimeException: Could not resolve @EJB reference: [EJB Reference: beanInterface 'com.example.services.version.VersionManager', beanName 'null', mappedName 'null', lookupName 'null', owning unit 'ComponentDeploymentContext@7745010{org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData.StartupBean}'] for environment entry: env/ejb/VersionManager in unit ComponentDeploymentContext@7745010{org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData.StartupBean}

          at org.jboss.ejb3.jndi.deployers.resource.provider.AnnotatedEJBRefResourceProvider.provide(AnnotatedEJBRefResourceProvider.java:99) [:0.1.7]

          at org.jboss.ejb3.jndi.deployers.resource.provider.AnnotatedEJBRefResourceProvider.provide(AnnotatedEJBRefResourceProvider.java:50) [:0.1.7]

          at org.jboss.switchboard.mc.JndiEnvironmentProcessor.process(JndiEnvironmentProcessor.java:68) [:1.0.0-alpha-15]

          at org.jboss.switchboard.mc.deployer.AbstractSwitchBoardDeployer.process(AbstractSwitchBoardDeployer.java:119) [:1.0.0-alpha-15]

          at org.jboss.switchboard.mc.deployer.EJBEnvironmentSwitchBoardDeployer.internalDeploy(EJBEnvironmentSwitchBoardDeployer.java:87) [:1.0.0-alpha-15]

          at org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer.deploy(AbstractRealDeployer.java:55) [:2.2.0.GA]

          at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(DeployerWrapper.java:179) [:2.2.0.GA]

          ... 39 more

       

      So I'm probably doing something wrong here, but really I don't see what it is.

      Do I need to provide more information in the ejb-jar.xml?  Is it ok to reference a @Singleton bean from the ejb-jar.xml?

       

      I'm really lost here, so any help will be greatly appreciated.

       

       

      Cheers,

      /Benoit

        • 1. Re: Using ejb-jar.xml for @Singleton bean
          jaikiran

          This looks like a bug. Can you try removing that @EJB(name = "ejb/VersionManager") altogether from the code and you this new ejb-jar.xml instead:

           

          <?xml version="1.0" encoding="UTF-8"?>
          <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
              version="3.1">
          
              <enterprise-beans>
                  <session>
                      <ejb-name>StartupBean</ejb-name>
                      <ejb-class>com.example.services.startup.StartupBean</ejb-class>
                      <ejb-local-ref>
                          <ejb-ref-name>ejb/VersionManager</ejb-ref-name>
                          <local>com.example.services.version.VersionManager</local>
                          <injection-target>
                              <injection-target-class>com.example.services.startup.StartupBean</injection-target-class>
                              <injection-target-name>versionManager</injection-target-name>
                          </injection-target>
          
                          <lookup-name>01-services/VersionManagerBean/local</lookup-name>
                      </ejb-local-ref>
                  </session>
              </enterprise-beans>
          
          </ejb-jar>
          

           

          Note that I have added the injection-target element in the ejb-jar.xml, to do the injection. See if that works.

          • 2. Re: Using ejb-jar.xml for @Singleton bean
            benoit.heinrich

            Hi Jaikiran,

             

            I've tried the suggested approach but unfortunately it doesn't work.

            There is no error in the logs, but the startup postcontruct method isn't fired.

             

            Here is the new class I've used:

            package com.example.services.startup;

             

            import com.example.services.version.VersionManager;

            import org.apache.commons.logging.Log;

            import org.apache.commons.logging.LogFactory;

             

            import javax.annotation.PostConstruct;

            import javax.ejb.Singleton;

            import javax.ejb.Startup;

             

            @Singleton

            @Startup

            public class StartupBean {

                      private static final Log log = LogFactory.getLog(StartupBean.class);

             

                      private VersionManager versionManager;

             

                      @PostConstruct

                      public void startup() {

                                log.info("System started (version " + versionManager.getVersion() + ")");

                      }

            }

             

            And here is the output from jboss:

            10:15:19,793 INFO  [org.jboss.deployment.dependency.ContainerDependencyMetaData] addJndiDependency, JndiDependencyMetaData@e32434{01-services/VersionManagerBean/local}

            10:15:19,795 INFO  [org.jboss.ejb3.deployers.Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@22312589{vfs:///opt/src/jboss-6.0.0.Final/server/default/deploy/99-startup.ear/startup-1.19.0-SNAPSHOT.jar/}

            10:15:19,795 INFO  [org.jboss.ejb3.deployers.Ejb3DependenciesDeployer] Encountered deployment AbstractVFSDeploymentContext@22312589{vfs:///opt/src/jboss-6.0.0.Final/server/default/deploy/99-startup.ear/startup-1.19.0-SNAPSHOT.jar/}

            10:15:19,811 INFO  [org.jboss.ejb3.instantiator.deployer.BeanInstantiatorDeployerBase] Installed org.jboss.ejb3.instantiator.impl.Ejb31SpecBeanInstantiator@42791a into MC at org.jboss.ejb.bean.instantiator/99-startup/startup-1.19.0-SNAPSHOT/StartupBean

            10:15:19,811 WARN  [org.jboss.ejb3.interceptor.InterceptorInfoRepository] EJBTHREE-1852: InterceptorInfoRepository is deprecated

            10:15:19,841 INFO  [org.jboss.ejb3.singleton.deployer.SingletonContainerDeployer] Installing container for EJB StartupBean

            10:15:19,841 INFO  [org.jboss.ejb3.singleton.deployer.SingletonContainerDeployer] with dependencies:

            10:15:19,841 INFO  [org.jboss.ejb3.singleton.deployer.SingletonContainerDeployer] with demands:

            10:15:19,841 INFO  [org.jboss.ejb3.singleton.deployer.SingletonContainerDeployer] jboss-injector:topLevelUnit=99-startup.ear,unit=startup-1.19.0-SNAPSHOT.jar,bean=StartupBean

            10:15:19,841 INFO  [org.jboss.ejb3.singleton.deployer.SingletonContainerDeployer] with supplies:

            10:15:19,843 INFO  [org.jboss.ejb3.singleton.deployer.SingletonBeanJNDIBinderDeployer] Binding the following entries in JNDI for singleton bean: StartupBean

            10:15:19,875 INFO  [org.jboss.ejb3.session.SessionSpecContainer] Starting jboss.j2ee:ear=99-startup.ear,jar=startup-1.19.0-SNAPSHOT.jar,name=StartupBean,service=EJB3

            10:15:19,875 WARN  [org.jboss.ejb3.session.SessionSpecContainer] EJBTHREE-2126: container jboss.j2ee:ear=99-startup.ear,jar=startup-1.19.0-SNAPSHOT.jar,name=StartupBean,service=EJB3 does not verify the businessObjectFactory

            10:15:19,876 INFO  [org.jboss.ejb3.EJBContainer] STARTED EJB: com.example.services.startup.StartupBean ejbName: StartupBean

            10:15:19,876 WARN  [org.jboss.ejb3.TimerServiceContainer] EJBTHREE-2193: using deprecated TimerServiceFactory for restoring timers

            10:15:19,898 INFO  [org.jboss.ejb3.nointerface.impl.jndi.AbstractNoInterfaceViewBinder] Binding the following entry in Global JNDI for bean:StartupBean

             

             

                      99-startup/StartupBean/no-interface -> EJB3.1 no-interface view

             

            Do you see anything wrong I'am doing here?

            • 3. Re: Using ejb-jar.xml for @Singleton bean
              jaikiran

              Everything looks fine. Are you sure the @PostConstruct isn't really called? Or is it just that the log message isn't being printed? Can you instead try using System.out.println or maybe attach a breakpoint in that method and see if it is called? I see that you are using commons-logging, so just want to make sure that it isn't just a case of missing logs.

              • 4. Re: Using ejb-jar.xml for @Singleton bean
                benoit.heinrich

                Still no luck

                 

                I'm currently trying to create a small maven project to reproduce the problem, maybe it'll help you to see what I'm doing wrong

                 

                Thanks a lot for your help

                • 5. Re: Using ejb-jar.xml for @Singleton bean
                  benoit.heinrich

                  Ok, here we are.

                   

                  I hope I've forgot nothing in the zip

                  If you have any problem running the example just let me know.

                   

                  The only thing you need to do is:

                   

                  1. unzip the archive
                  2. go to the startup-example directory.
                  3. mvn clean install
                  4. cp services-dist/target/01-services.ear to your deploy dir
                  5. cp startup-dist/target/02-startup.ear to your deploy dir

                   

                  The example is using the System.out instead of log4j and as you'll see the message doesn't show up.

                  Again, thanks a lot for all your help

                   

                  /Benoit

                  • 6. Re: Using ejb-jar.xml for @Singleton bean
                    jaikiran

                    Looks like there's a problem merging the xml metadata and the annotations with respect to the @Startup annotation. Use this ejb-jar.xml as a workaround (I have explicitly added the init-on-startup to true in that xml):

                     

                     

                    <?xml version="1.0" encoding="UTF-8"?>
                    <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
                        version="3.1">
                    
                        <enterprise-beans>
                            <session>
                                <ejb-name>StartupBean</ejb-name>
                                <ejb-class>com.example.services.startup.StartupBean</ejb-class>
                                <session-type>Singleton</session-type>
                                <init-on-startup>true</init-on-startup>
                                <ejb-local-ref>
                                    <ejb-ref-name>ejb/VersionManager</ejb-ref-name>
                                    <local>com.example.services.version.VersionManager</local>
                                    <injection-target>
                                        <injection-target-class>com.example.services.startup.StartupBean</injection-target-class>
                                        <injection-target-name>versionManager</injection-target-name>
                                    </injection-target>
                    
                                    <lookup-name>${services.loader}/VersionManagerBean/local</lookup-name>
                                </ejb-local-ref>
                            </session>
                        </enterprise-beans>
                    
                    </ejb-jar>
                    

                     

                     

                    Could you please create a JIRA here https://jira.jboss.org/browse/JBMETA about the @Startup issue and point to this thread?

                    • 7. Re: Using ejb-jar.xml for @Singleton bean
                      benoit.heinrich

                      Jira bug opened, I hope it'll be fixed in next release.

                       

                      https://issues.jboss.org/browse/JBMETA-329

                       

                      Thanks a lot for the workaround, I'll use that for now

                       

                       

                      Cheers,

                      /Benoit

                      • 8. Using ejb-jar.xml for @Singleton bean
                        viggo.navarsete

                        Did you ever get this to work? I have a Singleton bean like this:

                         

                        @Singleton

                        public class DummySingleton implements Dummy {

                         

                         

                                  public String getHello() {

                                            return "Hello Dummy!";

                                  }

                        }

                         

                         

                        and an interface like this:

                         

                        public interface Dummy {

                                  public String getHello();

                        }

                         

                        I've tried this in ejb-jar.xml (everything is packaged into an EAR file):

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

                         

                         

                        <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.1"

                                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                                  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">

                                            <enterprise-beans>

                                <session>

                                    <ejb-name>DummySingleton</ejb-name>

                                    <ejb-class>com.tracetracker.global.aps.DummySingleton</ejb-class>

                                    <session-type>Singleton</session-type>

                                    <init-on-startup>false</init-on-startup>

                                    <ejb-local-ref>

                                        <ejb-ref-name>ejb3/hub/DummySingleton</ejb-ref-name>

                                        <local>com.tracetracker.global.aps.Dummy</local>

                                     </ejb-local-ref>

                                </session>

                                            </enterprise-beans>

                        </ejb-jar>

                         

                        I've also tried to add it to jboss.xml like this:

                        <session>

                             <ejb-name>DummySingleton</ejb-name>

                             <local-jndi>ejb3/hub/DummySingleton</local-jndi>

                        </session>

                         

                        but no matter what I try it will not end up in JNDI bound to ejb3/hub/DummySingleton.

                        I can have normal session beans, and they will bind to ejb3/hub/xxxxx, but not when it's a singleton.

                         

                        What am I doing wrong?

                        • 9. Using ejb-jar.xml for @Singleton bean
                          viggo.navarsete

                          Since the provided workaround doesn't work, I suppose this is another new problem, and I've created a new issue for it: https://issues.jboss.org/browse/JBAS-9249