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);
+ }
+}