7 Replies Latest reply on Jan 26, 2007 10:21 AM by gavin.king

    @Startup help...

      Hello,

      I am trying to do the following:

      On startup of my application, create an EJB Timer (javax.ejb.Timer) using the EJB TimerService (javax.ejb.TimerService).

      The timer bean that I am trying to install is a stateless session bean.

      I initially tried to use @PostConstruct on a method that would use the TimerService (@Resource private TimerService timerService) to create my timer. This didn't work immediately, so I figured, no instances of my stateless session bean have been created - fine, I turned to @Startup to create bootstrap component that gets a handle to the stateless session bean and invokes its starter method. Now I'm not sure what dependencies I need to add to the @Startup(depends={...}) list.

      I know that I need the following resources available before my @Startup component's @Create method is called:

      - my stateless session bean needs to be deployed
      - the persistence context for my EJB jar needs to be available for injection

      I've noticed that the @In annotation doesn't seem to work for my @Startup component (i.e. I can't get a reference to my stateless session bean); so I looked up the reference manually:

       MyBean myBean = null;
       try {
       myBean = (MyBean)Naming.getInitialContext().lookup("my-ear/MyBean/local");
       mailReader.startReading();
       } catch (NamingException e) {
       log.error(e,e);
       }
      


      I can get a reference but invariably some other dependency fails (a @Factory component, etc...).

      Is there someway of telling @Startup something to the effect of:

      "start me up after everything else" ?

      Is there a better way of installing a timer in Seam?

      Thanks,
      Brad Smith

        • 1. Re: @Startup help...
          gavin.king

          The @Startup annotation has a list of dependencies, ie. names of other component which must be started first.

          • 2. Re: @Startup help...

            Code:

            @Name("mailReaderStarter")
            @Scope(ScopeType.APPLICATION) // required for the @Startup to work
            @Startup(depends={"mailReader"})
            @Install(
             dependencies = {"mailReader"}
            )
            public class MailReaderStarter {
            
             @Logger
             private Log log;
            
             @In(create=true)
             private MailReader mailReader; // a Stateless session bean...
            
             @Create
             public void startup() {
             log.info("startup()");
             mailReader.startReading();
             }
            
            }
            
            


            Log:
            13:28:30,173 INFO [Component] Component: mailReader, scope: STATELESS, type: STATELESS_SESSION_BEAN, class: com.evergreen.accesscontrol.impl.MailReaderBean, JNDI: access-control-1.0/MailReaderBean/lo
            cal
            ...
            13:28:30,220 INFO [Component] Component: mailReaderStarter, scope: APPLICATION, type: JAVA_BEAN, class: com.evergreen.accesscontrol.mail.MailReaderStarter
            ...
            13:28:37,955 ERROR [[/access]] Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener
            java.lang.UnsupportedOperationException: Stateless psuedo-scope does not have a Context object
             at org.jboss.seam.ScopeType.getContext(ScopeType.java:95)
             at org.jboss.seam.contexts.Lifecycle.startup(Lifecycle.java:150)
             at org.jboss.seam.contexts.Lifecycle.startup(Lifecycle.java:145)
             at org.jboss.seam.contexts.Lifecycle.endInitialization(Lifecycle.java:126)
             at org.jboss.seam.init.Initialization.init(Initialization.java:430)
             at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:33)
             at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3729)
             at org.apache.catalina.core.StandardContext.start(StandardContext.java:4187)
             at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:759)
             at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:739)
             at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:524)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
             at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.apache.commons.modeler.BaseModelMBean.invoke(BaseModelMBean.java:503)
             at org.jboss.mx.server.RawDynamicInvoker.invoke(RawDynamicInvoker.java:164)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.apache.catalina.core.StandardContext.init(StandardContext.java:5116)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
             at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.apache.commons.modeler.BaseModelMBean.invoke(BaseModelMBean.java:503)
             at org.jboss.mx.server.RawDynamicInvoker.invoke(RawDynamicInvoker.java:164)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.jboss.web.tomcat.tc5.TomcatDeployer.performDeployInternal(TomcatDeployer.java:297)
             at org.jboss.web.tomcat.tc5.TomcatDeployer.performDeploy(TomcatDeployer.java:103)
             at org.jboss.web.AbstractWebDeployer.start(AbstractWebDeployer.java:371)
             at org.jboss.web.WebModule.startModule(WebModule.java:83)
             at org.jboss.web.WebModule.startService(WebModule.java:61)
             at org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:289)
             at org.jboss.system.ServiceMBeanSupport.jbossInternalLifecycle(ServiceMBeanSupport.java:245)
             at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
             at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
             at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.jboss.system.ServiceController$ServiceProxy.invoke(ServiceController.java:978)
             at $Proxy0.start(Unknown Source)
             at org.jboss.system.ServiceController.start(ServiceController.java:417)
             at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
             at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
             at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
             at $Proxy44.start(Unknown Source)
             at org.jboss.web.AbstractWebContainer.start(AbstractWebContainer.java:466)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
             at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
             at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
             at org.jboss.mx.interceptor.AbstractInterceptor.invoke(AbstractInterceptor.java:133)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
             at org.jboss.mx.interceptor.ModelMBeanOperationInterceptor.invoke(ModelMBeanOperationInterceptor.java:142)
             at org.jboss.mx.interceptor.DynamicInterceptor.invoke(DynamicInterceptor.java:97)
             at org.jboss.system.InterceptorServiceMBeanSupport.invokeNext(InterceptorServiceMBeanSupport.java:238)
             at org.jboss.ws.server.WebServiceDeployer.start(WebServiceDeployer.java:117)
             at org.jboss.deployment.SubDeployerInterceptorSupport$XMBeanInterceptor.start(SubDeployerInterceptorSupport.java:188)
             at org.jboss.deployment.SubDeployerInterceptor.invoke(SubDeployerInterceptor.java:95)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
             at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
             at $Proxy45.start(Unknown Source)
             at org.jboss.deployment.MainDeployer.start(MainDeployer.java:1007)
             at org.jboss.deployment.MainDeployer.start(MainDeployer.java:997)
             at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:808)
             at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:771)
             at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
             at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
             at java.lang.reflect.Method.invoke(Method.java:585)
             at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
             at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
             at org.jboss.mx.interceptor.AbstractInterceptor.invoke(AbstractInterceptor.java:133)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
             at org.jboss.mx.interceptor.ModelMBeanOperationInterceptor.invoke(ModelMBeanOperationInterceptor.java:142)
             at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
             at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
             at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
             at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
             at $Proxy6.deploy(Unknown Source)
             at org.jboss.deployment.scanner.URLDeploymentScanner.deploy(URLDeploymentScanner.java:421)
             at org.jboss.deployment.scanner.URLDeploymentScanner.scan(URLDeploymentScanner.java:610)
             at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.doScan(AbstractDeploymentScanner.java:263)
             at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.loop(AbstractDeploymentScanner.java:274)
             at org.jboss.deployment.scanner.AbstractDeploymentScanner$ScannerThread.run(AbstractDeploymentScanner.java:225)
            


            help?

            • 3. Re: @Startup help...
              gavin.king

              So you have designated a *stateless* bean as a @Startup object?! This doesn't really make sense. Only stateful objects can be meaningfully "created".

              • 4. Re: @Startup help...

                Huh?

                I designated an APPLICATION scoped bean as the startup object - I have the startup object get a handle to a stateless bean and invoke a method which subsequently creates timer object.

                Going back to the start of this thread...I am trying to start an EJB Timer on startup of the application - it doesn't seem like an unreasonable thing to do - it's pretty darn simple to start a timer using Spring (via JDK Timers or Quartz) or a good-ole-fashioned ServletContextListener, etc. I hoped that Seam would be helpful in this regards since I am already using Seam in this application.

                So given that "This doesn't really make sense. ", do you have any suggestions for starting a Timer process on startup in an EJB3 / Seam application?

                As an alternative, I can simply put a link or button on page that invokes the method which creates the timer - this works fine - I've tested it. But really I would like to be able to achieve the 'startup behavior'.

                Thanks,
                Brad Smith

                PS: It's interesting you say that:

                Only stateful objects can be meaningfully "created".


                because in this thread http://www.jboss.com/index.html?module=bb&op=viewtopic&t=98545&postdays=0&postorder=asc&start=0
                everybody seems to insist that a stateless bean must be 'created' - how confusing!?!

                • 5. Re: @Startup help...
                  pmuir

                  If you can use JavaBeans rather than EJB3 this will work (with Seam from CVS since Gavin fixed http://jira.jboss.com/jira/browse/JBSEAM-679)

                  @Startup(depends="manager")
                  @Scope(ScopeType.APPLICATION)
                  public class Controller {
                  
                   @In(create=true)
                   private Manager manager;
                  
                   @Create
                   public void create() throws Exception {
                   // Schedule
                   manager.schedule(...);
                   }
                  
                  }


                  @Name("manager")
                  @Scope(ScopeType.EVENT)
                  public class Manager {
                  
                   @Transactional
                   @Asynchronous
                   public void schedule(...) {
                   ...
                   }
                  }


                  • 6. Re: @Startup help...

                    this is a helpful suggestion - thanks.

                    Unfortunately - I'll probably going live with Seam 1.1.0 so I am reluctant to work with a nightly build right now.

                    I still would like to hear any suggestions for building EJB Timer solutions in a Seam-EJB3 app - with ideas for kickstarting the timers on startup of the application.


                    Thanks,
                    Brad Smith

                    • 7. Re: @Startup help...
                      gavin.king

                       

                      "bsmithjj" wrote:
                      Huh?

                      I designated an APPLICATION scoped bean as the startup object - I have the startup object get a handle to a stateless bean and invoke a method which subsequently creates timer object.


                      You have:

                      @Startup(depends={"mailReader"})


                      This tells seam to "start" the mailReader component before starting the "mailReaderStarter" component. But its not meaningful to "start" a stateless component. If you remove the depends, your code will probably work as written.

                      "bsmithjj" wrote:
                      Going back to the start of this thread...I am trying to start an EJB Timer on startup of the application - it doesn't seem like an unreasonable thing to do - it's pretty darn simple to start a timer using Spring (via JDK Timers or Quartz) or a good-ole-fashioned ServletContextListener, etc. I hoped that Seam would be helpful in this regards since I am already using Seam in this application.


                      Slow down, I have a lot of posts to answer every day. I thought I had given you enough of a hint, but apparently not.

                      PS: It's interesting you say that:

                      Only stateful objects can be meaningfully "created".


                      because in this thread http://www.jboss.com/index.html?module=bb&op=viewtopic&t=98545&postdays=0&postorder=asc&start=0
                      everybody seems to insist that a stateless bean must be 'created' - how confusing!?!


                      This is an artefact of representing something that is conceptually stateless in an object-oriented language where components have state and lifecycle.

                      What I shoudl have typed is: Only stateful objects can be meaningfully "started".