TOMEE-4650 - Guard undeploy against a closed EMF and add JPA 3.2 CDI qualifier beans#2847
Open
jungm wants to merge 1 commit into
Open
TOMEE-4650 - Guard undeploy against a closed EMF and add JPA 3.2 CDI qualifier beans#2847jungm wants to merge 1 commit into
jungm wants to merge 1 commit into
Conversation
…qualifier beans Two independent problems, both reproducing on Plume (EclipseLink) and the webprofile distribution (OpenJPA), so neither is a provider defect. 1. When an application closes a container-managed EntityManagerFactory itself, TomEE's undeploy path closed it again, and Assembler.destroyApplication then failed with "Attempting to execute an operation on a closed EntityManagerFactory". ReloadableEntityManagerFactory.close() now checks isOpen() before delegating. 2. TomEE did not register the CDI beans required by the Jakarta Persistence 3.2 / Jakarta EE 11 CDI integration for persistence.xml-declared units, so injecting a qualified EntityManagerFactory / EntityManager / PersistenceUnitUtil failed with UnsatisfiedResolutionException. A new JpaCDIExtension registers, per persistence unit, an @ApplicationScoped EntityManagerFactory (bean name = PU name), an EntityManager in the <scope> element's scope (default TransactionScoped), and @dependent CriteriaBuilder, PersistenceUnitUtil, Cache, SchemaManager and Metamodel beans, all carrying the <qualifier> elements or @default when none is declared. Supporting this, <qualifier>/<scope> are added to the persistence.xml JAXB model (PersistenceUnit), to PersistenceUnitInfo, and copied through AppInfoBuilder, which also honours the jakarta.persistence.qualifiers / jakarta.persistence.scope override properties. Bean-registration contract verified against the Jakarta EE 11 Platform spec (CDI-JPA) and the Persistence 3.2 schema rather than from memory. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes TOMEE-4650. Two independent problems, both reproducing on Plume (EclipseLink) and the webprofile distribution (OpenJPA) — so neither is a persistence-provider defect.
1. Undeploy closes an already-closed EntityManagerFactory
When a test (or application) closes a container-managed
EntityManagerFactoryitself, TomEE's undeploy path calledclose()on it again, andAssembler.destroyApplicationthen failed with "Attempting to execute an operation on a closed EntityManagerFactory". The test method passed; only the undeploy step errored.ReloadableEntityManagerFactory.close()now checksisOpen()before delegating to the underlying EMF.2. Missing Jakarta Persistence 3.2 CDI qualifier beans
TomEE did not register the CDI beans that the Jakarta EE 11 / Persistence 3.2 CDI integration requires for
persistence.xml-declared units. Injecting a qualifiedEntityManagerFactory,EntityManager, orPersistenceUnitUtil(e.g.@Inject @CtsEm2Qualifier) failed at deploy time withUnsatisfiedResolutionException.A new
JpaCDIExtensionregisters, for each persistence unit:EntityManagerFactory—@ApplicationScoped, bean name = persistence-unit nameEntityManager— in the scope given by<scope>, defaulting tojakarta.transaction.TransactionScopedCriteriaBuilder,PersistenceUnitUtil,Cache,SchemaManager,Metamodel—@Dependent, each obtained from the matching getter of the EMFAll of them carry the qualifiers declared by the
<qualifier>elements, or@Defaultwhen none is declared. The bean-registration contract (scopes, qualifiers, bean name) was checked against the Jakarta EE 11 Platform spec (CDI-JPA) and the Persistence 3.2 schema rather than from memory.Supporting plumbing:
<qualifier>/<scope>added to thepersistence.xmlJAXB model (PersistenceUnit) in the XSD-mandated position. This model is hand-maintained, not generated (the xjc profile does not cover persistence schemas), and TomEE does not validatepersistence.xmlagainst a bundled XSD, so no schema files needed updating.PersistenceUnitInfoandAppInfoBuilder, which also honours thejakarta.persistence.qualifiers/jakarta.persistence.scopeoverride properties per the spec.OptimizedLoaderService, alongside the analogousConcurrencyCDIExtensionit is modeled on.Tests
ReloadableEntityManagerFactoryCloseTest— verifies a secondclose()is a no-op. Confirmed it fails against the unpatched code (2 close calls instead of 1).JpaCDIExtensionTest— verifies qualified and@DefaultEMF/PersistenceUnitUtilinjection across two persistence units. Confirmed it fails against the unpatched code with the exactUnsatisfiedResolutionExceptionfrom the issue.Notes for reviewers
entityManagerFactoryCloseExceptions/ClientP{m,u}servletTest,ee.cdi.ServletEMLookupTest) live in the separateapache/tomee-tckharness repo; their exclusion lines still need removing there once this merges. That change is not in this PR.SchemaManager/Metamodel/CriteriaBuilder/Cachebeans are registered per spec but onlyEntityManagerFactoryandPersistenceUnitUtilare exercised in the unit tests — the others eagerly trigger OpenJPA entity enhancement, which the unenhanced test setup in this module cannot satisfy. The full validation is a TCK run.🤖 Generated with Claude Code