glassfish
  1. glassfish
  2. GLASSFISH-20505

@PostConstruct method called twice on @Singleton

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 4.0_b87_RC3
    • Fix Version/s: 4.1
    • Component/s: jax-rs
    • Labels:
      None
    • Environment:

      Oracle JDK 7, Linux Fedora 18 64-bit, Eclipse Kepler m6

      Description

      I am running a simple .war file under Glassfish 4.0-b87 that was created in Eclipse Kepler M6 using M2E as a simple project with Dynamic Web Module facet added, using Oracle Java 7 JDK/JVM.

      There is essentially a single class for which I expect the `post_construct` method to be called exactly once. But it is called twice, first when the app is deployed, and one more time on the first and only the first HTTP request.

      Here is the class (the log output follows). It should print "hello world" only once but in the log it can be seen twice.

          package com.example.main;
          
          import javax.annotation.PostConstruct;
          import javax.annotation.PreDestroy;
          import javax.ejb.LocalBean;
          import javax.ejb.PostActivate;
          import javax.ejb.PrePassivate;
          import javax.ejb.Singleton;
          import javax.ejb.Startup;
          import javax.enterprise.inject.spi.PassivationCapable;
          import javax.ws.rs.ApplicationPath;
          import javax.ws.rs.GET;
          import javax.ws.rs.Path;
          import javax.ws.rs.core.Application;
          
          @Singleton
          @Startup
          @LocalBean
          @ApplicationPath("/rest")
          @Path("/life")
          public class Life extends Application implements PassivationCapable {
          
            @PostConstruct
            public void post_construct () {
              System.out.println("hello world!");
            }
          
            @PreDestroy
            public void pre_destroy () {
              System.out.println("so long and thanks for the fish!");
            }
          
            @PrePassivate
            public void pre_passivate () {
              System.out.println("taking a break");
            }
          
            @PostActivate
            public void post_activate () {
              System.out.println("back from break");
            }
          
            @Override
            public String getId () {
              return "life";
            }
          
            @GET
            public String greet () {
              return "hi";
            }
          }
      

      The log output is as follows with a dashed line separating the part before the first HTTP call and the part after the HTTP call:

      [2013-05-09T19:42:26.660-1000] [glassfish 4.0] [INFO] [NCLS-DEPLOYMENT-00027] [javax.enterprise.system.tools.deployment.autodeploy] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546660] [levelValue: 800] [[
      Selecting file /usr/local/glassfish4/glassfish/domains/domain1/autodeploy/singleton.war for autodeployment]]

      [2013-05-09T19:42:26.692-1000] [glassfish 4.0] [INFO] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546692] [levelValue: 800] [[
      visiting unvisited references]]

      [2013-05-09T19:42:26.702-1000] [glassfish 4.0] [INFO] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546702] [levelValue: 800] [[
      visiting unvisited references]]

      [2013-05-09T19:42:26.706-1000] [glassfish 4.0] [INFO] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546706] [levelValue: 800] [[
      visiting unvisited references]]

      [2013-05-09T19:42:26.709-1000] [glassfish 4.0] [INFO] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546709] [levelValue: 800] [[
      visiting unvisited references]]

      [2013-05-09T19:42:26.749-1000] [glassfish 4.0] [INFO] [ejb.portable_jndi_names] [javax.enterprise.system.container.ejb.com.sun.ejb.containers] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546749] [levelValue: 800] [[
      EJB5181:Portable JNDI names for EJB Life: [java:global/singleton/Life, java:global/singleton/Life!com.example.main.Life]]]

      [2013-05-09T19:42:26.959-1000] [glassfish 4.0] [WARNING] [] [org.jboss.weld.Bootstrap] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546959] [levelValue: 900] [[
      WELD-001473 javax.enterprise.inject.spi.Bean implementation org.glassfish.jms.injection.JMSCDIExtension$LocalBean@cbcbf4a declared a normal scope but does not implement javax.enterprise.inject.spi.PassivationCapable. It won't be possible to inject this bean into a bean with passivating scope (@SessionScoped, @ConversationScoped). This can be fixed by assigning the Bean implementation a unique id by implementing the PassivationCapable interface.]]

      [2013-05-09T19:42:26.970-1000] [glassfish 4.0] [INFO] [] [] [tid: _ThreadID=59 _ThreadName=Thread-3] [timeMillis: 1368164546970] [levelValue: 800] [[
      hello world!]]

      [2013-05-09T19:42:26.982-1000] [glassfish 4.0] [INFO] [] [org.glassfish.jersey.servlet.init.JerseyServletContainerInitializer] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546982] [levelValue: 800] [[
      Registering the Jersey servlet application, named com.example.main.Life, at the servlet mapping /rest/*, with the Application class of the same name.]]

      [2013-05-09T19:42:26.988-1000] [glassfish 4.0] [INFO] [AS-WEB-GLUE-00172] [javax.enterprise.web] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164546988] [levelValue: 800] [[
      Loading application [singleton] at [/singleton]]]

      [2013-05-09T19:42:27.003-1000] [glassfish 4.0] [INFO] [] [javax.enterprise.system.core] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164547003] [levelValue: 800] [[
      singleton was successfully deployed in 332 milliseconds.]]

      [2013-05-09T19:42:27.006-1000] [glassfish 4.0] [INFO] [NCLS-DEPLOYMENT-00035] [javax.enterprise.system.tools.deployment.autodeploy] [tid: _ThreadID=59 _ThreadName=AutoDeployer] [timeMillis: 1368164547006] [levelValue: 800] [[
      [AutoDeploy] Successfully autodeployed : /usr/local/glassfish4/glassfish/domains/domain1/autodeploy/singleton.war.]]

      -----------------------------AFTER FIRST HTTP CALL-----------------------------

      [2013-05-09T19:42:44.940-1000] [glassfish 4.0] [INFO] [] [] [tid: _ThreadID=21 _ThreadName=Thread-3] [timeMillis: 1368164564940] [levelValue: 800] [[
      hello world!]]

      [2013-05-09T19:42:44.940-1000] [glassfish 4.0] [INFO] [] [org.glassfish.jersey.server.ApplicationHandler] [tid: _ThreadID=21 _ThreadName=http-listener-1(4)] [timeMillis: 1368164564940] [levelValue: 800] [[
      Initiating Jersey application, version Jersey: 2.0-rc2 2013-04-23 12:04:25...]]

      [2013-05-09T19:42:44.956-1000] [glassfish 4.0] [INFO] [] [org.glassfish.jersey.gf.ejb.EjbComponentProvider] [tid: _ThreadID=21 _ThreadName=http-listener-1(4)] [timeMillis: 1368164564956] [levelValue: 800] [[
      The Jersey EJB interceptor is bound. JAX-RS EJB integration support is enabled.]]

        Activity

        Hide
        agksmehx added a comment -

        I got a stack trace of the second singleton creation by making it throw an error if a static boolean was found initialized to true

        java.lang.Error: second singleton
        at com.example.Life.post_construct(Life.java:43)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.glassfish.hk2.utilities.reflection.ReflectionHelper.invoke(ReflectionHelper.java:1010)
        at org.jvnet.hk2.internal.Utilities.justPostConstruct(Utilities.java:735)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.postConstruct(ServiceLocatorImpl.java:818)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:864)
        at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:855)
        at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:293)
        at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:272)
        at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:262)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349)
        at javax.servlet.GenericServlet.init(GenericServlet.java:244)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1583)
        at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:1225)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:237)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
        at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
        at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
        at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
        at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
        at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
        at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
        at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
        at java.lang.Thread.run(Thread.java:722)

        Show
        agksmehx added a comment - I got a stack trace of the second singleton creation by making it throw an error if a static boolean was found initialized to true java.lang.Error: second singleton at com.example.Life.post_construct(Life.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.glassfish.hk2.utilities.reflection.ReflectionHelper.invoke(ReflectionHelper.java:1010) at org.jvnet.hk2.internal.Utilities.justPostConstruct(Utilities.java:735) at org.jvnet.hk2.internal.ServiceLocatorImpl.postConstruct(ServiceLocatorImpl.java:818) at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:864) at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:855) at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:293) at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:272) at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:262) at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167) at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349) at javax.servlet.GenericServlet.init(GenericServlet.java:244) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1583) at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:1225) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:237) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188) at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191) at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168) at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544) at java.lang.Thread.run(Thread.java:722)
        Hide
        marina vatkina added a comment -

        no EJB container code in the stack

        Show
        marina vatkina added a comment - no EJB container code in the stack
        Hide
        agksmehx added a comment -

        Essentially the @Singleton annotation is not playing well the @ApplicationPath + "extends Application" part. When I created a separate class for @ApplicationPath + "extends Application" and left the @Singleton + @Path together, things seemed fine (although I don't know whether Jersey would create more singletons under load).

        What does the standard say about putting @Application, @Singleton, @Path all on the same class?

        Show
        agksmehx added a comment - Essentially the @Singleton annotation is not playing well the @ApplicationPath + "extends Application" part. When I created a separate class for @ApplicationPath + "extends Application" and left the @Singleton + @Path together, things seemed fine (although I don't know whether Jersey would create more singletons under load). What does the standard say about putting @Application, @Singleton, @Path all on the same class?
        Hide
        Marek Potociar added a comment -

        Updated java code formatting in the issue desc.

        Show
        Marek Potociar added a comment - Updated java code formatting in the issue desc.
        Hide
        Jakub Podlesak added a comment - - edited

        JAX-RS/EJB integration does not work fully for Application subclasses. There are some technical difficulties
        as Application subclasses are involved in application bootstrapping. Jersey only makes sure certain scenarios work
        (e.g. @PostConstruct/@PreDestroy annotated methods are invoked at all). The rest (like e.g. this one, that @Singleton annotated
        beans should get created just once per an application) should be resolved
        with future Jersey releases.

        I recommend to stick with the above described workaround (keep separate classes for application and JAX-RS resources/providers)
        until this gets resolved.

        Show
        Jakub Podlesak added a comment - - edited JAX-RS/EJB integration does not work fully for Application subclasses. There are some technical difficulties as Application subclasses are involved in application bootstrapping. Jersey only makes sure certain scenarios work (e.g. @PostConstruct/@PreDestroy annotated methods are invoked at all). The rest (like e.g. this one, that @Singleton annotated beans should get created just once per an application) should be resolved with future Jersey releases. I recommend to stick with the above described workaround (keep separate classes for application and JAX-RS resources/providers) until this gets resolved.
        Hide
        Jakub Podlesak added a comment -

        deferred to 4.0.1

        Show
        Jakub Podlesak added a comment - deferred to 4.0.1
        Hide
        agksmehx added a comment -

        love the formatting: "so long and thanks for the fish", "taking a break"

        seriously, thank you marek for fixing the formatting and thank you jakub and everybody else for your very kind attention. love glassfish + jersey!

        Show
        agksmehx added a comment - love the formatting: "so long and thanks for the fish", "taking a break " seriously, thank you marek for fixing the formatting and thank you jakub and everybody else for your very kind attention. love glassfish + jersey!
        Hide
        rdelaplante added a comment -

        I'm getting @PostConstruct called twice in a row on this class in GlassFish 4.0 release:

        @Singleton
        @Startup
        public class LoggingService {

        @Inject @Cached
        private SystemSettings systemSettings;

        @PostConstruct
        public void initializeLogAppenders()

        { LogManager.resetConfiguration(); PropertyConfigurator.configure( systemSettings.getRuntimeDataPath() + "logging.properties"); }

        @PreDestroy
        public void closeLogAppenders()

        { LogManager.shutdown(); }

        }

        Show
        rdelaplante added a comment - I'm getting @PostConstruct called twice in a row on this class in GlassFish 4.0 release: @Singleton @Startup public class LoggingService { @Inject @Cached private SystemSettings systemSettings; @PostConstruct public void initializeLogAppenders() { LogManager.resetConfiguration(); PropertyConfigurator.configure( systemSettings.getRuntimeDataPath() + "logging.properties"); } @PreDestroy public void closeLogAppenders() { LogManager.shutdown(); } }

          People

          • Assignee:
            Jakub Podlesak
            Reporter:
            agksmehx
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: