In a code base that I’ve inherited, there’s an MDB which is calling SingletonBeanFactoryLocator().getIntance().useBean() to get a factory reference in its ejbCreate(), and then getting a specific bean from this factory and storing it as an MDB instance variable. (The factory is of type ‘ClassPathXmlApplicationContext‘).
The confusing part is: after that bean is obtained, it’s calling ‘release()‘ on this factory reference in that same ejbCreate().
Now, this MDB is pooled with poolsize ‘x‘ and what I’ve observed is, beans defined in the context xml are getting created ‘x‘ number of times. So my guess is, every time the ‘ejbCreate()‘ executes, it’s creating a context and its beans afresh.
I checked Spring doc for ‘release() above which says:
In an EJB usage scenario this would normally be called from `ejbRemove()` and `ejbPassivate()`.
So here’re my questions:
1) is it really creating a new context and new beans everytime ejbCreate() is called?
2) if yes, what happens to the context/beans created in the previous call (e.g. if the beans are singleton themselves, will they be destroyed)?
3) is this the right way to use SingletonBeanFactoryLocator (possibly for thread safety issues) in the context above?
4) if not, what is the right way to use it?
EDIT: one possibility I can think of is to make the concerned beans prototype to make each MDB instance thread-safe, so there’s no need to release and recreate the context. Awaiting other comments/suggestions.
SpringBeanAutowiringInterceptormay or may not be a better alternative.Update:
There is actually a race condition. If the container decides to run the
ejbCreate()of two MDBs in parallel then they both will end up sharing the same application context.Update 2:
I could not find a section that explicitly allows EJB creating through parallel threads but I could also not find a section that explicitly forbids it.
Given the following sections from the spec I assume it would be in the spirit of the spec to do it.
2.4.2 Message-Driven Objects
A typical EJB container provides a scalable runtime environment to execute a large number of mes- sage-driven objects concurrently.
5.2 Goals
A further goal of the message-driven bean model is to allow for the concurrent processing of a stream of messages by means of container-provided pooling of message-driven bean instances.
5.4 Protocol Between a Message-Driven Bean Instance and its Container
It is the container’s responsibility to ensure that the message-driven bean comes into existence when the container is started up and that instances of the bean are ready to receive an asynchronous message delivery before the delivery of messages is started.
5.4.11 Concurrency of Message Processing
A container allows many instances of a message-driven bean class to be executing concurrently, thus allowing for the concurrent processing of a stream of messages. No guarantees are made as to the exact order in which messages are delivered to the instances of the message-driven bean class, although the container should attempt to deliver messages in order when it does not impair the concurrency of mes- sage processing.