Search code examples
javaconcurrencysynchronizationsingletonejb

Container guarantees when putting a singleton session bean with bean concurrency into service


I have the following code:

@ConcurrencyManagement(BEAN)
@Startup
@Singleton
public class MySingletonBean {

    private Object threadSafeObject;

    @PostConstruct
    private void init() {
        threadSafeObject = nonTrivialInitialization();
    }

    private void nonTrivialInitialization() {
        // something with other beans or container resources
    }

    public void accessObject() {
        threadSafeObject.performSomeThreadSafeOperation();
    }

}

The circumstances are as follows:

  • threadSafeObject is accessed concurrently (obviously)
  • threadSafeObject takes care internally of its own synchronization
  • threadSafeObject initialization is not trivial, i.e. it accesses other beans or resources, so it needs to be performed inside container managed code aka @PostConstruct method, not as field initialization at object instantiation
  • bean managed concurrency is required because actual business code behind the singleton bean can be executed from both a JEE environment and a non-managed environment. Because of this, uniform handling of synchronization is preferred, thus, bean managed concurrency

Direct question: do I need to synchronize the initialization of threadSafeObject and therefore all other accesses to it to prevent possible visibility issues, e.g. thread A processes the initialization of the bean, but, afterwards, thread B doesn't see a correct view of threadSafeObject?

More elaborate question: When putting a singleton session bean into service, in case of bean managed concurrency, does the container offer any guarantees with regards to the safe publishing of the state of the singleton session bean? The EJB spec [part that I read] didn't quite give any hints towards this.

More rants from my part: For container managed concurrency, the container synchronizes all access to the singleton session bean, therefore we have the guarantee that all threads see the most recent consistent state of the bean. For bean managed concurrency, I keep reading that all synchronization is left to the implementor of the bean and the story ends there. Nothing more. So, even though, the container doesn't perform synchronization per se, bean initialization and feeding requests to the bean is still container managed, I'd still expect that the container somehow performs a write barrier when putting the bean into service. The JVM offers this guarantee for instance initialization for example and the metaphor goes that a JEE container is a JVM on steroids with ripped abs, right? :D


Solution

  • Great question! I think this is the relevant part of the spec (taken from here):

    Independent of the bean’s concurrency management type, the container must ensure that no concurrent access to the Singleton bean instance occurs until after the instance has successfully completed its initialization sequence, including any @PostConstruct lifecycle callback method(s). The container must temporarily block any Singleton access attempts that arrive while the Singleton is still initializing.

    (section 4.8.5, p109)

    My understanding of "no concurrent access" would be that some container synchronization is required after @PostConstruct completes. Hope that helps?