jersey
  1. jersey
  2. JERSEY-1883

@PostConstruct method called twice on @Singleton

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-rc2
    • Fix Version/s: 2.17
    • Component/s: containers
    • Labels:
      None
    • Environment:

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

      Description

      Originally reported as: https://java.net/jira/browse/GLASSFISH-20505

      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 @PostConstruct void 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.]]
      
      1. 1883.diff
        23 kB
        Libor Kramolis

        Activity

        Hide
        agksmehx added a comment - - edited

        Note Jersey in stack trace for creating second singleton. 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 - - edited Note Jersey in stack trace for creating second singleton. 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
        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 -

        Assigning to Jakub - is this still valid issue?

        Show
        Marek Potociar added a comment - Assigning to Jakub - is this still valid issue?
        Hide
        Libor Kramolis added a comment -

        Issue is still valid and it also 'works' with common javax.inject.Singleton. No need to use EJB to reproduce the bug.

        Show
        Libor Kramolis added a comment - Issue is still valid and it also 'works' with common javax.inject.Singleton . No need to use EJB to reproduce the bug.
        Hide
        Libor Kramolis added a comment -

        Reproducible test case diff attached.

        Show
        Libor Kramolis added a comment - Reproducible test case diff attached.

          People

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

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 3 hours Original Estimate - 3 hours
              3h
              Remaining:
              Time Spent - 2 hours Remaining Estimate - 3 hours
              3h
              Logged:
              Time Spent - 2 hours Remaining Estimate - 3 hours
              2h