diff --git a/jpa/subsystem/src/main/java/org/jboss/as/jpa/container/TransactionScopedEntityManager.java b/jpa/subsystem/src/main/java/org/jboss/as/jpa/container/TransactionScopedEntityManager.java index 3c4e2bd0bdd0..f7d696aba8e6 100644 --- a/jpa/subsystem/src/main/java/org/jboss/as/jpa/container/TransactionScopedEntityManager.java +++ b/jpa/subsystem/src/main/java/org/jboss/as/jpa/container/TransactionScopedEntityManager.java @@ -198,6 +198,11 @@ protected boolean skipQueryDetach() { return skipQueryDetach.booleanValue(); } + @Override + public void setProperty(String propertyName, Object value) { + properties.put(propertyName, value); + super.setProperty(propertyName, value); + } /** diff --git a/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/JPAAnnotationProcessor.java b/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/JPAAnnotationProcessor.java index 79f3a5da7ebc..be0e572d3c85 100644 --- a/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/JPAAnnotationProcessor.java +++ b/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/JPAAnnotationProcessor.java @@ -292,16 +292,13 @@ private InjectionSource getBindingSource(final DeploymentUnit deploymentUnit, fi (stType == null || SynchronizationType.SYNCHRONIZED.name().equals(stType.asString()))? SynchronizationType.SYNCHRONIZED: SynchronizationType.UNSYNCHRONIZED; - Map properties; + final Map properties = new HashMap<>(); AnnotationValue value = annotation.value("properties"); AnnotationInstance[] props = value != null ? value.asNestedArray() : null; if (props != null) { - properties = new HashMap<>(); for (int source = 0; source < props.length; source++) { properties.put(props[source].value("name").asString(), props[source].value("value").asString()); } - } else { - properties = null; } // get deployment settings from top level du (jboss-all.xml is only parsed at the top level). final JPADeploymentSettings jpaDeploymentSettings = DeploymentUtils.getTopDeploymentUnit(deploymentUnit).getAttachment(JpaAttachments.DEPLOYMENT_SETTINGS_KEY); diff --git a/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/PersistenceUnitServiceHandler.java b/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/PersistenceUnitServiceHandler.java index 103d1496688c..3e5bb834c80d 100644 --- a/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/PersistenceUnitServiceHandler.java +++ b/jpa/subsystem/src/main/java/org/jboss/as/jpa/processor/PersistenceUnitServiceHandler.java @@ -12,7 +12,6 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -718,7 +717,7 @@ public void inject(final PersistenceUnitServiceImpl value) throws binderService.getManagedObjectInjector().inject(new ValueManagedReferenceFactory( new TransactionScopedEntityManager( pu.getScopedPersistenceUnitName(), - Collections.emptyMap(), + new HashMap(), // WFLY-19973: pass empty HashMap that can be modified by application code. value.getEntityManagerFactory(), SynchronizationType.SYNCHRONIZED, transactionSynchronizationRegistry, transactionManager))); } diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/CdiJpaInjectingBean.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/CdiJpaInjectingBean.java index 0fb6020252a2..84c3aeed2129 100644 --- a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/CdiJpaInjectingBean.java +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/CdiJpaInjectingBean.java @@ -7,17 +7,38 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; +import jakarta.persistence.PersistenceProperty; import jakarta.persistence.Query; + public class CdiJpaInjectingBean { - @PersistenceContext(unitName = "cdiPu") + + @PersistenceContext(unitName = "cdiPu", properties = { @PersistenceProperty(name = "CdiJpaInjectingBean", value = "true")}) EntityManager em; + @PersistenceContext(unitName = "cdiPu") + EntityManager emEmptyProperties; + public Employee queryEmployeeName(int id) { Query q = em.createQuery("SELECT e FROM Employee e where e.id=:employeeId"); q.setParameter("employeeId", id); return (Employee) q.getSingleResult(); } + public String getInitialPropertyValue() { + return (String) em.getProperties().get("CdiJpaInjectingBean"); + } + public void setAdditionalPropertyValue(String value) { + em.setProperty("CdiJpaInjectingBean.additional", value); + } + + public String getAdditionalPropertyValue() { + return (String) em.getProperties().get("CdiJpaInjectingBean.additional"); + } + + public String addPropertyToEmptyPropertyMap(String value) { + emEmptyProperties.setProperty("CdiJpaInjectingBean.addToEmptyPropertyMap", value); + return (String) emEmptyProperties.getProperties().get("CdiJpaInjectingBean.addToEmptyPropertyMap"); + } } diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/WeldJpaInjectionScopeTestCase.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/WeldJpaInjectionScopeTestCase.java index d8a50ef27b63..16e773e7c101 100644 --- a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/WeldJpaInjectionScopeTestCase.java +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/jpa/scoping/WeldJpaInjectionScopeTestCase.java @@ -73,5 +73,25 @@ public void testOrmXmlDefinedEmployeeEntity() throws Exception { } Assert.fail("NoResultException should occur but didn't!"); } + + // [WFLY-19973] (Weld injected) @PersistenceContext (initial) properties attribute should be processed + @Test + public void testInitialPersistenceContextPropertiesAreSet() throws Exception { + Assert.assertEquals("true",bean.getInitialPropertyValue()); + } + + // [WFLY-19973] (Weld injected) @PersistenceContext (later set) properties attribute should be available + @Test + public void testEntityManagerPropertiesAreSaved() throws Exception { + bean.setAdditionalPropertyValue("WeldJpaInjectionScopeTestCase.testproperty"); + Assert.assertEquals("WeldJpaInjectionScopeTestCase.testproperty",bean.getAdditionalPropertyValue()); + } + + // [WFLY-19973] (Weld injected) @PersistenceContext (later set) ensure that property can be added to empty property map + @Test + public void testEntityManagerPropertiesEmptyCase() throws Exception { + Assert.assertEquals("AddedToEmptyHashMap", bean.addPropertyToEmptyPropertyMap("AddedToEmptyHashMap")); + } + } diff --git a/weld/jpa/src/main/java/org/jboss/as/weld/services/bootstrap/WeldJpaInjectionServices.java b/weld/jpa/src/main/java/org/jboss/as/weld/services/bootstrap/WeldJpaInjectionServices.java index 70b1a09a7211..73e15c974062 100644 --- a/weld/jpa/src/main/java/org/jboss/as/weld/services/bootstrap/WeldJpaInjectionServices.java +++ b/weld/jpa/src/main/java/org/jboss/as/weld/services/bootstrap/WeldJpaInjectionServices.java @@ -11,6 +11,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -18,6 +19,7 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.PersistenceContext; +import jakarta.persistence.PersistenceProperty; import jakarta.persistence.PersistenceUnit; import jakarta.transaction.TransactionManager; import jakarta.transaction.TransactionSynchronizationRegistry; @@ -71,7 +73,7 @@ public ResourceReferenceFactory registerPersistenceContextInjecti public EntityManager call() throws Exception { return new TransactionScopedEntityManager( scopedPuName, - new HashMap<>(), + getProperties(context), persistenceUnitService.getEntityManagerFactory(), context.synchronization(), deploymentUnit.getAttachment(JpaAttachments.TRANSACTION_SYNCHRONIZATION_REGISTRY), @@ -122,6 +124,15 @@ private String getScopedPUName(final DeploymentUnit deploymentUnit, final String return scopedPu.getScopedPersistenceUnitName(); } + private static Map getProperties(PersistenceContext context) { + HashMap map = new HashMap(); + for (PersistenceProperty property : context.properties()) { + map.put(property.name(), property.value()); + } + return map; + } + + private static class EntityManagerResourceReferenceFactory implements ResourceReferenceFactory { private final String scopedPuName; private final EntityManagerFactory entityManagerFactory; @@ -139,9 +150,10 @@ public EntityManagerResourceReferenceFactory(String scopedPuName, EntityManagerF @Override public ResourceReference createResource() { - final TransactionScopedEntityManager result = new TransactionScopedEntityManager(scopedPuName, new HashMap<>(), entityManagerFactory, context.synchronization(), transactionSynchronizationRegistry, transactionManager); + final TransactionScopedEntityManager result = new TransactionScopedEntityManager(scopedPuName, getProperties(context), entityManagerFactory, context.synchronization(), transactionSynchronizationRegistry, transactionManager); return new SimpleResourceReference(result); } + } private static class LazyFactory implements ResourceReferenceFactory {