This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch camel-3.7.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-3.7.x by this push:
     new 6a2df26  CAMEL-16470 - fix for reuse EntityManager (#5349)
6a2df26 is described below

commit 6a2df264f23fe82a9f7c3b35b9fd7f31507964ba
Author: Tom Cassimon <[email protected]>
AuthorDate: Wed Apr 14 10:51:47 2021 +0200

    CAMEL-16470 - fix for reuse EntityManager (#5349)
    
    Co-authored-by: catom1 <[email protected]>
---
 components/camel-jpa/pom.xml                       |   5 +
 .../org/apache/camel/component/jpa/JpaHelper.java  |  46 ++++++---
 .../apache/camel/processor/jpa/JpaRouteTest.java   |   6 +-
 .../jpa/MultipleJpaRouteEndpointTest.java          | 113 +++++++++++++++++++++
 4 files changed, 152 insertions(+), 18 deletions(-)

diff --git a/components/camel-jpa/pom.xml b/components/camel-jpa/pom.xml
index 5ec4912..c2e306c 100644
--- a/components/camel-jpa/pom.xml
+++ b/components/camel-jpa/pom.xml
@@ -97,6 +97,11 @@
             <artifactId>hamcrest</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git 
a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaHelper.java
 
b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaHelper.java
index 556b75b..463c888 100644
--- 
a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaHelper.java
+++ 
b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaHelper.java
@@ -16,6 +16,9 @@
  */
 package org.apache.camel.component.jpa;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 
@@ -54,7 +57,7 @@ public final class JpaHelper {
 
         // then try reuse any entity manager which has been previously created 
and stored on the exchange
         if (em == null && exchange != null) {
-            em = exchange.getProperty(JpaConstants.ENTITY_MANAGER, 
EntityManager.class);
+            em = 
getEntityManagerMap(exchange).get(getKey(entityManagerFactory));
         }
 
         if (em == null && useSharedEntityManager) {
@@ -62,26 +65,39 @@ public final class JpaHelper {
         }
 
         if (em == null) {
-            // create a new entity manager
-            em = entityManagerFactory.createEntityManager();
-            if (exchange != null) {
-                // we want to reuse the EM so store as property and make sure 
we close it when done with the exchange
-                exchange.setProperty(JpaConstants.ENTITY_MANAGER, em);
-                exchange.adapt(ExtendedExchange.class).addOnCompletion(new 
JpaCloseEntityManagerOnCompletion(em));
-            }
+            em = createEntityManager(exchange, entityManagerFactory);
         }
 
         if (allowRecreate && em == null || !em.isOpen()) {
-            // create a new entity manager
-            em = entityManagerFactory.createEntityManager();
-            if (exchange != null) {
-                // we want to reuse the EM so store as property and make sure 
we close it when done with the exchange
-                exchange.setProperty(JpaConstants.ENTITY_MANAGER, em);
-                exchange.adapt(ExtendedExchange.class).addOnCompletion(new 
JpaCloseEntityManagerOnCompletion(em));
-            }
+            em = createEntityManager(exchange, entityManagerFactory);
         }
 
         return em;
     }
 
+    private static EntityManager createEntityManager(Exchange exchange, 
EntityManagerFactory entityManagerFactory) {
+        EntityManager em;
+        em = entityManagerFactory.createEntityManager();
+        if (exchange != null) {
+            // we want to reuse the EM so store as property and make sure we 
close it when done with the exchange
+            Map<String, EntityManager> entityManagers = 
getEntityManagerMap(exchange);
+            entityManagers.put(getKey(entityManagerFactory), em);
+            exchange.adapt(ExtendedExchange.class).addOnCompletion(new 
JpaCloseEntityManagerOnCompletion(em));
+        }
+        return em;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Map<String, EntityManager> getEntityManagerMap(Exchange 
exchange) {
+        Map<String, EntityManager> entityManagers = 
exchange.getProperty(JpaConstants.ENTITY_MANAGER, Map.class);
+        if (entityManagers == null) {
+            entityManagers = new HashMap<>();
+            exchange.setProperty(JpaConstants.ENTITY_MANAGER, entityManagers);
+        }
+        return entityManagers;
+    }
+
+    private static String getKey(EntityManagerFactory entityManagerFactory) {
+        return String.valueOf(entityManagerFactory.hashCode());
+    }
 }
diff --git 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaRouteTest.java
 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaRouteTest.java
index 3d370be..7564c9d 100644
--- 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaRouteTest.java
+++ 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaRouteTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.processor.jpa;
 
-import javax.persistence.EntityManager;
+import java.util.HashMap;
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.jpa.JpaComponent;
@@ -39,8 +39,8 @@ public class JpaRouteTest extends AbstractJpaTest {
 
         MockEndpoint mock = getMockEndpoint("mock:result");
         mock.expectedMessageCount(1);
-        mock.message(0).header(JpaConstants.ENTITY_MANAGER).isNotNull();
-        
mock.message(0).header(JpaConstants.ENTITY_MANAGER).isInstanceOf(EntityManager.class);
+        
mock.message(0).exchangeProperty(JpaConstants.ENTITY_MANAGER).isNotNull();
+        
mock.message(0).exchangeProperty(JpaConstants.ENTITY_MANAGER).isInstanceOf(HashMap.class);
 
         template.sendBody("direct:start", new 
SendEmail("[email protected]"));
 
diff --git 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/MultipleJpaRouteEndpointTest.java
 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/MultipleJpaRouteEndpointTest.java
new file mode 100644
index 0000000..57c08dd4
--- /dev/null
+++ 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/MultipleJpaRouteEndpointTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor.jpa;
+
+import java.util.HashMap;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.jpa.JpaComponent;
+import org.apache.camel.component.jpa.JpaConstants;
+import org.apache.camel.component.jpa.JpaEndpoint;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.examples.SendEmail;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class MultipleJpaRouteEndpointTest extends CamelTestSupport {
+
+    @Mock
+    private final EntityManagerFactory emf1 = mock(EntityManagerFactory.class);
+    @Mock
+    private final EntityManager em1 = mock(EntityManager.class);
+    @Mock
+    private final EntityManagerFactory emf2 = mock(EntityManagerFactory.class);
+    @Mock
+    private final EntityManager em2 = mock(EntityManager.class);
+
+    private final SendEmail value1 = new SendEmail("[email protected]");
+    private final SendEmail value2 = new SendEmail("[email protected]");
+
+    @Test
+    public void testRouteJpa() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        mock.whenAnyExchangeReceived(this::assertEntityManagerMap);
+
+        template.sendBody("direct:start", "start");
+
+        assertMockEndpointsSatisfied();
+        verify(em1).merge(value1);
+        verify(em2).merge(value2);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        when(em1.getTransaction()).thenReturn(mock(EntityTransaction.class));
+        when(emf1.createEntityManager()).thenReturn(em1);
+        when(em2.getTransaction()).thenReturn(mock(EntityTransaction.class));
+        when(emf2.createEntityManager()).thenReturn(em2);
+
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                JpaEndpoint jpa1 = new JpaEndpoint();
+                jpa1.setComponent(new JpaComponent());
+                jpa1.setCamelContext(context);
+                jpa1.setEntityType(SendEmail.class);
+                jpa1.setEntityManagerFactory(emf1);
+
+                JpaEndpoint jpa2 = new JpaEndpoint();
+                jpa2.setComponent(new JpaComponent());
+                jpa2.setCamelContext(context);
+                jpa2.setEntityType(SendEmail.class);
+                jpa2.setEntityManagerFactory(emf2);
+
+                from("direct:start")
+                        .setBody(constant(value1))
+                        .to(jpa1)
+                        .setBody(constant(value2))
+                        .to(jpa2)
+                        .to("mock:result");
+            }
+        };
+    }
+
+    @SuppressWarnings("unchecked")
+    private void assertEntityManagerMap(Exchange exchange) {
+        HashMap<String, EntityManager> entityManagerMap = 
exchange.getProperty(JpaConstants.ENTITY_MANAGER, HashMap.class);
+        assertNotNull(entityManagerMap);
+        assertEquals(entityManagerMap.keySet().size(), 2);
+        
assertTrue(entityManagerMap.containsKey(String.valueOf(emf1.hashCode())));
+        EntityManager entityManager1 = 
entityManagerMap.get(String.valueOf(emf1.hashCode()));
+        
assertTrue(entityManagerMap.containsKey(String.valueOf(emf2.hashCode())));
+        EntityManager entityManager2 = 
entityManagerMap.get(String.valueOf(emf2.hashCode()));
+        assertNotEquals(entityManager1, entityManager2);
+    }
+}

Reply via email to