[
https://issues.apache.org/jira/browse/TOMEE-4655?focusedWorklogId=1032657&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1032657
]
ASF GitHub Bot logged work on TOMEE-4655:
-----------------------------------------
Author: ASF GitHub Bot
Created on: 28/Jul/26 19:48
Start Date: 28/Jul/26 19:48
Worklog Time Spent: 10m
Work Description: jungm commented on PR #2850:
URL: https://github.com/apache/tomee/pull/2850#issuecomment-5108932683
Thanks for the careful review — both points confirmed, and both are
addressed in e4e60f8.
**1. ERROR-level NPE noise on the pre-`startEjbs` rollback — fixed.**
Reproduced exactly as you described. The root cause is an asymmetry:
`EjbJarBuilder:83` assigns the container at *build* time, while `containerData`
is only set inside `Container.deploy()`. So after a CDI failure the rollback
holds a non-null container for a bean the container never saw, and
`SingletonInstanceManager.freeInstance:216` (`data.singleton`) plus
`StatefulContainer.undeploy:292` (`data.jmxNames`) both dereference a null
`Data`.
Notably `SingletonInstanceManager.undeploy:341`,
`StatelessInstanceManager.undeploy` and `ManagedContainer.undeploy` already
have precisely this guard — these two were simply the ones that lacked it, so
the fix follows the existing idiom rather than inventing one. I swept every
`Container.undeploy` implementation; no others are missing it.
A third variant showed up once those were guarded: `Assembler`'s
stop/undeploy loops NPE'd on `getContainer()` itself for beans whose container
had already been cleared, so those are null-checked too. The rollback is now
completely silent — 0 NPEs.
**2. Webapp smoke test — done, and it is not a regression.**
Deployed a war with an unsatisfied `@Inject` (plus a stateful and a
singleton bean) into a real TomEE Plus, then ran the same war against a
pristine pre-fix `openejb-core` for a controlled A/B on freshly unpacked
servers:
| | pristine | with fix |
|---|---|---|
| deploy attempts | 1 | 1 |
| `NullPointerException` | 0 | 0 |
| `Error destroying child` | 1 | 1 |
| `invalid Lifecycle transition` | 1 | 1 |
| SEVERE total | 4 | 4 |
The normalized SEVERE lines are identical between the two; only their
ordering shifts, since the rollback now runs slightly earlier relative to
`TomcatWebAppBuilder`'s own message. The `removeChild`/`before_destroy`
interaction you spotted is real, but it is **pre-existing upstream behaviour**
on the webapp path — `TomcatWebAppBuilder`'s catch at :1341 already undeploys
before the caller does, and the second undeploy is idempotent as you suspected.
The server stays healthy afterwards (`/` returns 200, the failed app is
correctly absent). Worth noting I first measured 2× these counts and had to
discard that run — a stale exploded dir in `work`/`temp` had caused the war to
deploy twice, so the control was invalid rather than the fix.
**3. Nit — fixed.** The test now catches `DeploymentException` rather than
`Exception`, so it still guards the branch it was written for. Added
`undeployingABeanThatWasNeverDeployedIsQuiet`, which fails without the
container guards with `NullPointerException: Cannot read field "jmxNames"
because "data" is null` and passes with them.
One thing to flag: `StatefulDecoratorInjectionTest`,
`StatefulConversationScopedTOMEE1138Test` and `StatefulDependentInjectionTest`
fail in `openejb-core`, but they fail identically on pristine `a3e8806a9d` with
no changes applied, so they are unrelated to this PR.
_🤖 Addressed by [Claude Code](https://claude.com/claude-code)_
Issue Time Tracking
-------------------
Worklog Id: (was: 1032657)
Time Spent: 0.5h (was: 20m)
> A failed CDI/EJB deployment leaks its deployment ID into later apps
> -------------------------------------------------------------------
>
> Key: TOMEE-4655
> URL: https://issues.apache.org/jira/browse/TOMEE-4655
> Project: TomEE
> Issue Type: Bug
> Reporter: Markus Jung
> Assignee: Markus Jung
> Priority: Major
> Time Spent: 0.5h
> Remaining Estimate: 0h
>
> When a CDI or EJB deployment fails, TomEE does not clean up the deployment ID
> it registered for that app. The stale ID stays registered, so the next app
> that reuses it fails with {{DuplicateDeploymentIdException}} before its own
> lifecycle, managed-bean, or concurrency checks even run.
> This turns one bad deployment into a cascade of unrelated test failures in
> whichever app deploys next with a matching ID.
> h2. Steps to reproduce / TCK reference
> Excluded in {{runner-webprofile/exclusions/enterprise-beans-30.txt}} in the
> apache/tomee-tck harness repo:
> * {{**/interceptor/singleton/lifecycle/descriptor/*Test.java}}
> * {{**/packaging/war/mbean/interceptor/lifecycleejbcdi/*Test.java}}
> * {{**/singleton/concurrency/container/annotated/*Test.java}}
> * {{**/singleton/concurrency/container/inheritance/*Test.java}}
> Once fixed, remove the matching lines and confirm a deployment that follows a
> failed one with the same ID no longer fails with
> {{DuplicateDeploymentIdException}}.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)