jungm opened a new pull request, #2951:
URL: https://github.com/apache/tomee/pull/2951

   ## What
   
   Fixes [TOMEE-4712](https://issues.apache.org/jira/browse/TOMEE-4712): an MDB 
receives messages before the other EJBs of its application are started, and 
calls into an injected `@Stateless` bean fail with
   
   ```
   java.lang.NullPointerException: Cannot invoke 
"org.apache.openejb.core.stateless.StatelessInstanceManager$Data.poolPop()" 
because "data" is null
   ```
   
   Reported on the [users 
list](https://lists.apache.org/thread/pg3vv6xr9yd19wowj6lg31b4w4w19bnn) against 
10.2.0, for messages left on a topic when the server was stopped.
   
   ## Why
   
   `Assembler.startEjbs()` works in two passes: `container.deploy()` for every 
bean, then `container.start()` for every bean. `MdbContainer.deploy()` (and 
`MdbInstanceManager.deploy()` for `Pool=true`) called 
`resourceAdapter.endpointActivation(...)` directly, so the resource adapter 
could deliver during the deploy pass. At that point:
   
   - stateless beans have no instance pool yet: 
`StatelessInstanceManager.deploy()`, which sets the bean's container data, runs 
from `StatelessContainer.start()`
   - `@Startup` singletons are not initialized yet: that happens in 
`SingletonContainer.start()`
   
   `Assembler.sort()` already moves MDBs to the end so the beans they reference 
are available first, but that ordering only helps if activation happens in the 
start pass.
   
   Delivering before `@Startup` singletons are initialized also contradicts 
Jakarta Enterprise Beans 4.0 Core, [4.8.1 Singleton Session Bean 
Initialization](https://jakarta.ee/specifications/enterprise-beans/4.0/jakarta-enterprise-beans-spec-core-4.0.html#singleton-session-bean-initialization)
 ("The container must initialize all such startup-time singleton session beans 
before any external client requests ... are delivered to any enterprise bean 
components in the application"). Jakarta Connectors 2.1, 
[14.4.4](https://jakarta.ee/specifications/connectors/2.1/jakarta-connectors-spec-2.1.html#a2765),
 explicitly allows a resource adapter to deliver during `endpointActivation`, 
so this is not ActiveMQ-specific.
   
   ## The fix
   
   - `MdbContainer` and `MdbInstanceManager` still create the activation 
context and JMX control in `deploy()`, but activate the endpoint in `start()`. 
`MdbContainer.current()` stays available to the resource adapter during 
activation.
   - `MdbActiveOnStartup`/`DeliveryActive=false` keep working. The check both 
containers duplicated is now `BaseMdbContainer.isActiveOnStartup()`.
   - Undeploy only deactivates a started endpoint already, so a bean that fails 
between deploy and start is still cleaned up.
   - For `Pool=true`, the endpoint is now also activated after the MDB's own 
instance pool is filled and started.
   
   ## Testing
   
   New `MdbActivationOrderTest`, parameterized over `Pool=false`/`Pool=true`: a 
resource adapter delivers a pending message inside `endpointActivation`, and 
the MDB calls an injected `@Stateless` bean.
   
   - **Without the fix:** both variants fail with the NPE above
   - **With the fix:** both pass
   - Full `openejb-core` build: `Tests run: 4113, Failures: 0, Errors: 0, 
Skipped: 4`
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to