5 Replies Latest reply: Feb 7, 2012 7:00 AM by Daniel Straub RSS

Multiple @Singleton Instances

Bernd Eckenfels Novice

If I deploy my Test MessageDrivenBean on 7.0.1 standalone-preview profile with a @EJB dependency to a @Singleton, I can see, that the Singleton class (constructor) is called on each instanciation of a MDB, therefore I have more than one java class, not a real singleton.

 

However the postContruct() Method is only called for the first Singleton.

 

13:15:37,864 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() Startup...13084479
13:15:37,864 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) EJB3MDB.initialize()
13:15:37,864 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) onMessage() START
13:15:37,895 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() Startup...23965508
13:15:37,895 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() Post Construct...23965508
13:15:37,958 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() returning hash....23965508
13:15:37,958 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) my singleton: 23965508
13:15:39,958 INFO  [stdout] (Thread-6049 (group:HornetQ-client-global-threads-3178554)) onMessage() DONE

13:16:05,381 INFO  [stdout] (Thread-6031 (group:HornetQ-client-global-threads-3178554)) onMessage() START
13:16:05,396 INFO  [stdout] (Thread-6031 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() returning hash....23965508
13:16:05,396 INFO  [stdout] (Thread-6031 (group:HornetQ-client-global-threads-3178554)) my singleton: 23965508
13:16:07,396 INFO  [stdout] (Thread-6031 (group:HornetQ-client-global-threads-3178554)) onMessage() DONE

13:16:11,162 INFO  [stdout] (Thread-6050 (group:HornetQ-client-global-threads-3178554)) onMessage() START
13:16:11,162 INFO  [stdout] (Thread-6050 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() returning hash....23965508
13:16:11,162 INFO  [stdout] (Thread-6050 (group:HornetQ-client-global-threads-3178554)) my singleton: 23965508
13:16:11,303 INFO  [stdout] (Thread-6051 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() Startup...26566365
13:16:11,303 INFO  [stdout] (Thread-6051 (group:HornetQ-client-global-threads-3178554)) EJB3MDB.initialize()
13:16:11,303 INFO  [stdout] (Thread-6051 (group:HornetQ-client-global-threads-3178554)) onMessage() START
13:16:11,303 INFO  [stdout] (Thread-6051 (group:HornetQ-client-global-threads-3178554)) EJB3Singleton() returning hash....23965508
13:16:11,303 INFO  [stdout] (Thread-6051 (group:HornetQ-client-global-threads-3178554)) my singleton: 23965508
13:16:13,162 INFO  [stdout] (Thread-6050 (group:HornetQ-client-global-threads-3178554)) onMessage() DONE
13:16:13,303 INFO  [stdout] (Thread-6051 (group:HornetQ-client-global-threads-3178554)) onMessage() DONE

 

 

As you can see in 13:15:37,864; 13:15:37,895 and 13:16:11,303 a new Java Class (constructor) was created, but only the second instance have been "postConstructed" and injected. Is this a problem with the dependency injector? The EJB 3.1 spec is not clear if the container is actualy allowed to instanciate and default-construct more than one singleton instance.

 

Singleton looks like:

 

@Singleton
@LocalBean
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
//@Startup
@Lock(LockType.READ)
public class EJB3Singleton
{
    public EJB3Singleton() {
        System.out.println("EJB3Singleton() Startup..." + this.hashCode());
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("EJB3Singleton() Post Construct..." + this.hashCode());
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("EJB3Singleton() Pre Destroy..." + this.hashCode());
    }

    public int getHash() {
        System.out.println("EJB3Singleton() returning hash...." + this.hashCode());
        return this.hashCode();
    }
}

 

 

Markup fix: Bernd Eckenfels

  • 1. Re: Multiple @Singleton Instances
    Carlo de Wolf Master

    The EJB3Singleton class also serves as the class for the no-interface view of the EJB3Singleton EJB.

     

    So the Singleton EJB is initialized once, while you'll see multiple proxies being instantiated for servicing the no-interface view.

  • 2. Re: Multiple @Singleton Instances
    Bernd Eckenfels Novice

    Ok, why does it have to be multiple proxies? Would it help to use a business Interface here? Is this covered by the EJB spec?

  • 3. Re: Multiple @Singleton Instances
    jaikiran pai Master

    From the spec:

    The developer of an enterprise bean that exposes a no-interface view must not make any assumptions about the number of times the bean class  no-arg constructor will be called. For example, it is possible that the acquisition of a client reference to the no-interface view will result in the invocation of the bean-class constructor.

  • 4. Re: Multiple @Singleton Instances
    Bernd Eckenfels Novice

    Thanks, I just made the test with a Business Interface for the Singleton Class, and indeed, the default constructor is only called once, anymore.

  • 5. Re: Multiple @Singleton Instances
    Daniel Straub Newbie

    We run in the same problem (with 7.1.0CR1b) :

    Using a @Singleton (with Business Interface) as a @Producer for a Cache, the Cache is injected in other @Singleton/@Startup EJB's in different jars.

    Every time the cache is injected, a new instance of the @Singleton is created.

     

     

    @Singleton

    @Startup

    @Local(CacheProvider.class)

    public class CacheProviderImpl implements CacheProvider {

     

        private static final Log LOG = LogFactory.getLog(CacheProviderImpl.class);

     

        private Cache<?, ?> cache;

     

        public CacheProviderImpl() {

            LOG.info("CacheProvider created " + this);

            startCache();

        }

     

        @Produces

        public Cache getCache() {

            return cache;

        }

     

        //@PostConstruct -> https://issues.jboss.org/browse/AS7-2785

        public void startCache() {

        ...

     

     

    [CacheProviderImpl] CacheProvider created CacheProviderImpl@c5cd1a

    ...

    [CacheProviderImpl] CacheProvider created CacheProviderImpl@150f2ec

    ...

    [CacheProviderImpl] CacheProvider created CacheProviderImpl@eff6e7

     

     

    What is wrong in this scenario ?