You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/05/15 11:22:22 UTC
[camel] branch camel-3.x updated: CAMEL-19350: outputTarget in camel-jpa (3.x) (#10079)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-3.x by this push:
new 483d7b86a75 CAMEL-19350: outputTarget in camel-jpa (3.x) (#10079)
483d7b86a75 is described below
commit 483d7b86a75c2e46e43069d3dcbe05249967811c
Author: jacekszymanski <ja...@gmail.com>
AuthorDate: Mon May 15 13:22:12 2023 +0200
CAMEL-19350: outputTarget in camel-jpa (3.x) (#10079)
* JPA: add outputTarget to send result to a header/property
* refactor test: pull @Query and @Find up
* refactor tests
* more test refactoring
* test output target
* rename AdditionalQueryParameters to AdditionalEndpointParameters
* change proeprty prefix to property:
---
.../camel/component/jpa/JpaEndpointConfigurer.java | 6 ++
.../camel/component/jpa/JpaEndpointUriFactory.java | 3 +-
.../org/apache/camel/component/jpa/jpa.json | 1 +
.../apache/camel/component/jpa/JpaEndpoint.java | 14 ++++
.../apache/camel/component/jpa/JpaProducer.java | 46 ++++++-----
...ters.java => AdditionalEndpointParameters.java} | 2 +-
.../camel/component/jpa/JpaOutputTargetTest.java | 86 ++++++++++++++++++++
.../camel/component/jpa/JpaOutputTypeTest.java | 75 +++--------------
.../apache/camel/component/jpa/JpaPagingTest.java | 20 ++---
.../component/jpa/JpaWithOptionsTestSupport.java | 95 ++++++++++++++++++++--
10 files changed, 242 insertions(+), 106 deletions(-)
diff --git a/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointConfigurer.java b/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointConfigurer.java
index 8155acd62a5..58906922346 100644
--- a/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointConfigurer.java
+++ b/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointConfigurer.java
@@ -65,6 +65,8 @@ public class JpaEndpointConfigurer extends PropertyConfigurerSupport implements
case "namedQuery": target.setNamedQuery(property(camelContext, java.lang.String.class, value)); return true;
case "nativequery":
case "nativeQuery": target.setNativeQuery(property(camelContext, java.lang.String.class, value)); return true;
+ case "outputtarget":
+ case "outputTarget": target.setOutputTarget(property(camelContext, java.lang.String.class, value)); return true;
case "parameters": target.setParameters(property(camelContext, java.util.Map.class, value)); return true;
case "persistenceunit":
case "persistenceUnit": target.setPersistenceUnit(property(camelContext, java.lang.String.class, value)); return true;
@@ -157,6 +159,8 @@ public class JpaEndpointConfigurer extends PropertyConfigurerSupport implements
case "namedQuery": return java.lang.String.class;
case "nativequery":
case "nativeQuery": return java.lang.String.class;
+ case "outputtarget":
+ case "outputTarget": return java.lang.String.class;
case "parameters": return java.util.Map.class;
case "persistenceunit":
case "persistenceUnit": return java.lang.String.class;
@@ -250,6 +254,8 @@ public class JpaEndpointConfigurer extends PropertyConfigurerSupport implements
case "namedQuery": return target.getNamedQuery();
case "nativequery":
case "nativeQuery": return target.getNativeQuery();
+ case "outputtarget":
+ case "outputTarget": return target.getOutputTarget();
case "parameters": return target.getParameters();
case "persistenceunit":
case "persistenceUnit": return target.getPersistenceUnit();
diff --git a/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointUriFactory.java b/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointUriFactory.java
index 7c748ec540a..b8bd1613dbc 100644
--- a/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointUriFactory.java
+++ b/components/camel-jpa/src/generated/java/org/apache/camel/component/jpa/JpaEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class JpaEndpointUriFactory extends org.apache.camel.support.component.En
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(47);
+ Set<String> props = new HashSet<>(48);
props.add("backoffErrorThreshold");
props.add("backoffIdleThreshold");
props.add("backoffMultiplier");
@@ -46,6 +46,7 @@ public class JpaEndpointUriFactory extends org.apache.camel.support.component.En
props.add("maximumResults");
props.add("namedQuery");
props.add("nativeQuery");
+ props.add("outputTarget");
props.add("parameters");
props.add("persistenceUnit");
props.add("pollStrategy");
diff --git a/components/camel-jpa/src/generated/resources/org/apache/camel/component/jpa/jpa.json b/components/camel-jpa/src/generated/resources/org/apache/camel/component/jpa/jpa.json
index ced7dfba7aa..0af0c02895d 100644
--- a/components/camel-jpa/src/generated/resources/org/apache/camel/component/jpa/jpa.json
+++ b/components/camel-jpa/src/generated/resources/org/apache/camel/component/jpa/jpa.json
@@ -64,6 +64,7 @@
"findEntity": { "kind": "parameter", "displayName": "Find Entity", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If enabled then the producer will find a single entity by using the message body as key and entityType as the class type. This can be used instead of a query to find a single entity." },
"firstResult": { "kind": "parameter", "displayName": "First Result", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": -1, "description": "Set the position of the first result to retrieve." },
"flushOnSend": { "kind": "parameter", "displayName": "Flush On Send", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Flushes the EntityManager after the entity bean has been persisted." },
+ "outputTarget": { "kind": "parameter", "displayName": "Output Target", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To put the query (or find) result in a header or property instead of the body. If the value starts with the prefix property:, put the result into the so named property, otherwise into the header." },
"remove": { "kind": "parameter", "displayName": "Remove", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Indicates to use entityManager.remove(entity)." },
"singleResult": { "kind": "parameter", "displayName": "Single Result", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If enabled, a query or a find which would return no results or more than one result, will throw an exception instead." },
"useExecuteUpdate": { "kind": "parameter", "displayName": "Use Execute Update", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "description": "To configure whether to use executeUpdate() when producer executes a query. When you use INSERT, UPDATE or DELETE statement as a named query, you need to specify this option to 'true'." },
diff --git a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaEndpoint.java b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaEndpoint.java
index d0041b49412..59a8a1bc494 100644
--- a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaEndpoint.java
+++ b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaEndpoint.java
@@ -114,6 +114,8 @@ public class JpaEndpoint extends ScheduledPollEndpoint {
private boolean findEntity;
@UriParam(label = "producer", defaultValue = "false")
private boolean singleResult;
+ @UriParam(label = "producer")
+ private String outputTarget;
@UriParam(label = "advanced", prefix = "emf.", multiValue = true)
private Map<String, Object> entityManagerProperties;
@@ -571,6 +573,18 @@ public class JpaEndpoint extends ScheduledPollEndpoint {
this.singleResult = singleResult;
}
+ public String getOutputTarget() {
+ return outputTarget;
+ }
+
+ /**
+ * To put the query (or find) result in a header or property instead of the body. If the value starts with the
+ * prefix "property:", put the result into the so named property, otherwise into the header.
+ */
+ public void setOutputTarget(String outputTarget) {
+ this.outputTarget = outputTarget;
+ }
+
// Implementation methods
// -------------------------------------------------------------------------
diff --git a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
index 1bf4a6cdbc5..5847472a0f5 100644
--- a/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
+++ b/components/camel-jpa/src/main/java/org/apache/camel/component/jpa/JpaProducer.java
@@ -40,6 +40,9 @@ public class JpaProducer extends DefaultProducer {
private static final Logger LOG = LoggerFactory.getLogger(JpaProducer.class);
+ /* prefix for marking property in outputTarget */
+ private static final String PROPERTY_PREFIX = "property:";
+
private final EntityManagerFactory entityManagerFactory;
private final TransactionStrategy transactionStrategy;
private final Expression expression;
@@ -182,15 +185,6 @@ public class JpaProducer extends DefaultProducer {
entityManager.joinTransaction();
}
- Message target;
- if (ExchangeHelper.isOutCapable(exchange)) {
- target = exchange.getMessage();
- // preserve headers
- target.getHeaders().putAll(exchange.getIn().getHeaders());
- } else {
- target = exchange.getIn();
- }
-
final Object answer;
if (isUseExecuteUpdate()) {
answer = innerQuery.executeUpdate();
@@ -200,7 +194,7 @@ public class JpaProducer extends DefaultProducer {
answer = innerQuery.getResultList();
}
- target.setBody(answer);
+ putAnswer(exchange, answer, getEndpoint().getOutputTarget());
if (getEndpoint().isFlushOnSend()) {
entityManager.flush();
@@ -261,15 +255,7 @@ public class JpaProducer extends DefaultProducer {
key));
}
- Message target;
- if (ExchangeHelper.isOutCapable(exchange)) {
- target = exchange.getMessage();
- // preserve headers
- target.getHeaders().putAll(exchange.getIn().getHeaders());
- } else {
- target = exchange.getIn();
- }
- target.setBody(answer);
+ putAnswer(exchange, answer, getEndpoint().getOutputTarget());
if (getEndpoint().isFlushOnSend()) {
entityManager.flush();
@@ -383,4 +369,26 @@ public class JpaProducer extends DefaultProducer {
}
}
+ private static void putAnswer(final Exchange exchange, final Object answer, final String outputTarget) {
+ if (outputTarget == null || outputTarget.isBlank()) {
+ getTargetMessage(exchange).setBody(answer);
+ } else if (outputTarget.startsWith(PROPERTY_PREFIX)) {
+ exchange.setProperty(outputTarget.substring(PROPERTY_PREFIX.length()), answer);
+ } else {
+ getTargetMessage(exchange).setHeader(outputTarget, answer);
+ }
+ }
+
+ private static Message getTargetMessage(Exchange exchange) {
+ final Message target;
+ if (ExchangeHelper.isOutCapable(exchange)) {
+ target = exchange.getMessage();
+ // preserve headers
+ target.getHeaders().putAll(exchange.getIn().getHeaders());
+ } else {
+ target = exchange.getIn();
+ }
+ return target;
+ }
+
}
diff --git a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/AdditionalQueryParameters.java b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/AdditionalEndpointParameters.java
similarity index 96%
rename from components/camel-jpa/src/test/java/org/apache/camel/component/jpa/AdditionalQueryParameters.java
rename to components/camel-jpa/src/test/java/org/apache/camel/component/jpa/AdditionalEndpointParameters.java
index d966268b4b2..7e6c45b56d1 100644
--- a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/AdditionalQueryParameters.java
+++ b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/AdditionalEndpointParameters.java
@@ -23,7 +23,7 @@ import java.lang.annotation.Target;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD })
-@interface AdditionalQueryParameters {
+@interface AdditionalEndpointParameters {
String value();
diff --git a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTargetTest.java b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTargetTest.java
new file mode 100644
index 00000000000..9bf419f022e
--- /dev/null
+++ b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTargetTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.component.jpa;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.jpa.JpaWithOptionsTestSupport.Query;
+import org.apache.camel.examples.Customer;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@Query
+public class JpaOutputTargetTest extends JpaWithOptionsTestSupport {
+
+ private static final String TARGET_NAME = "__target";
+ private static final String PROP_MARK = "property:";
+
+ @Test
+ @AdditionalEndpointParameters("outputTarget=" + TARGET_NAME)
+ public void testQueryToHeader() throws Exception {
+ final Exchange result = doRunQueryTest();
+
+ Assertions.assertNotNull(result.getIn().getHeader(TARGET_NAME));
+ }
+
+ @Test
+ @AdditionalEndpointParameters("outputTarget=" + TARGET_NAME)
+ public void testBodyRemainsUnchanged() throws Exception {
+ final Object body = new Object();
+ final Exchange result = doRunQueryTest(withBody(body));
+
+ Assertions.assertEquals(body, result.getIn().getBody());
+ }
+
+ @Test
+ @AdditionalEndpointParameters("outputTarget=" + PROP_MARK + TARGET_NAME)
+ public void testQueryToProperty() throws Exception {
+ final Exchange result = doRunQueryTest();
+
+ Assertions.assertNotNull(result.getProperty(TARGET_NAME));
+ }
+
+ @Test
+ @Find
+ @AdditionalEndpointParameters("outputTarget=" + TARGET_NAME)
+ public void testFindToHeader() throws Exception {
+ final Long customerId = validCustomerId(entityManager);
+ final Exchange result = doRunQueryTest(withBody(customerId));
+
+ Assertions.assertEquals(customerId, result.getIn().getHeader(TARGET_NAME, Customer.class).getId());
+ }
+
+ @Test
+ @Find
+ @AdditionalEndpointParameters("outputTarget=" + TARGET_NAME)
+ public void testFindBodyRemainsUnchanged() throws Exception {
+ final Object body = new Object();
+ final Exchange result = doRunQueryTest(withBody(body));
+
+ Assertions.assertEquals(body, result.getIn().getBody());
+ }
+
+ @Test
+ @Find
+ @AdditionalEndpointParameters("outputTarget=" + PROP_MARK + TARGET_NAME)
+ public void testFindToProperty() throws Exception {
+ final Long customerId = validCustomerId(entityManager);
+ final Exchange result = doRunQueryTest(withBody(customerId));
+
+ Assertions.assertEquals(customerId, result.getProperty(TARGET_NAME, Customer.class).getId());
+ }
+
+}
diff --git a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTypeTest.java b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTypeTest.java
index 25ae0e299e8..518aeac914e 100644
--- a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTypeTest.java
+++ b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaOutputTypeTest.java
@@ -16,32 +16,22 @@
*/
package org.apache.camel.component.jpa;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.AnnotatedElement;
-
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import org.apache.camel.Exchange;
+import org.apache.camel.component.jpa.JpaWithOptionsTestSupport.Query;
import org.apache.camel.examples.Customer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtensionContext;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+@Query("select c from Customer c where c.name like :seq")
public class JpaOutputTypeTest extends JpaWithOptionsTestSupport {
- private static final String ENDPOINT_URI = "jpa://" + Customer.class.getName();
-
- private String queryOrFind;
-
@Test
- @Query
- @AdditionalQueryParameters("singleResult=true¶meters.seq=% 001")
+ @AdditionalEndpointParameters("singleResult=true¶meters.seq=% 001")
public void testSingleCustomerOKQuery() throws Exception {
final Customer customer = runQueryTest(Customer.class);
@@ -50,7 +40,7 @@ public class JpaOutputTypeTest extends JpaWithOptionsTestSupport {
@Test
@Query("select c from Customer c")
- @AdditionalQueryParameters("singleResult=true")
+ @AdditionalEndpointParameters("singleResult=true")
public void testTooMuchResults() throws Exception {
final Exchange result = doRunQueryTest();
@@ -58,8 +48,7 @@ public class JpaOutputTypeTest extends JpaWithOptionsTestSupport {
}
@Test
- @Query
- @AdditionalQueryParameters("singleResult=true¶meters.seq=% xxx")
+ @AdditionalEndpointParameters("singleResult=true¶meters.seq=% xxx")
public void testNoCustomersQuery() throws Exception {
final Exchange result = doRunQueryTest();
@@ -68,73 +57,29 @@ public class JpaOutputTypeTest extends JpaWithOptionsTestSupport {
@Test
@Find
- @AdditionalQueryParameters("singleResult=true")
+ @AdditionalEndpointParameters("singleResult=true")
public void testSingleCustomerOKFind() throws Exception {
// ids in the db are not known, so query for a known element and use its id.
- super.setUp(getEndpointUri());
+ Long customerId = validCustomerId(entityManager);
- final Customer fromDb = (Customer) entityManager
- .createQuery("select c from Customer c where c.name like '% 001'")
- .getSingleResult();
-
- final Exchange result = template.send("direct:start", withBody(fromDb.getId()));
+ final Exchange result = template.send("direct:start", withBody(customerId));
assertNotNull(result.getIn().getBody(Customer.class));
}
@Test
@Find
- @AdditionalQueryParameters("singleResult=true")
+ @AdditionalEndpointParameters("singleResult=true")
public void testNoCustomerFind() throws Exception {
final Exchange result = doRunQueryTest(withBody(Long.MAX_VALUE));
Assertions.assertInstanceOf(NoResultException.class, getException(result));
}
- @Override
- protected String getEndpointUri() {
- return String.format("%s?%s%s",
- ENDPOINT_URI,
- queryOrFind,
- createAdditionalQueryParameters());
- }
-
- @Override
- public void beforeEach(ExtensionContext context) throws Exception {
- super.beforeEach(context);
-
- // a query or a find is necessary - without the annotation test can't continue
- final AnnotatedElement annotatedElement = context.getElement().get();
-
- final Find find = annotatedElement.getAnnotation(Find.class);
- final Query query = annotatedElement.getAnnotation(Query.class);
-
- if ((find == null) == (query == null)) {
- throw new IllegalStateException("Test must be annotated with EITHER Find OR Query");
- }
-
- if (find != null) {
- queryOrFind = "findEntity=" + true;
- } else { // query != null
- queryOrFind = "query=" + query.value();
- }
-
- }
-
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- private @interface Find {
- }
-
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- private @interface Query {
- String value() default "select c from Customer c where c.name like :seq";
- }
-
private static Exception getException(final Exchange exchange) {
final Exception exception = exchange.getException();
return exception != null ? exception : exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
}
+
}
diff --git a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaPagingTest.java b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaPagingTest.java
index 32aaf4d3d1a..a1bef8192d6 100644
--- a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaPagingTest.java
+++ b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaPagingTest.java
@@ -18,17 +18,16 @@ package org.apache.camel.component.jpa;
import java.util.List;
+import org.apache.camel.component.jpa.JpaWithOptionsTestSupport.Query;
import org.apache.camel.examples.Customer;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+@Query("select c from Customer c order by c.name")
public class JpaPagingTest extends JpaWithOptionsTestSupport {
- private static final String ENDPOINT_URI = "jpa://" + Customer.class.getName() +
- "?query=select c from Customer c order by c.name";
-
// both should be less than JpaWithOptionsTestSupport.ENTRIES_COUNT / 2
private static final int FIRST_RESULT = 5;
private static final int MAXIMUM_RESULTS = 10;
@@ -41,7 +40,7 @@ public class JpaPagingTest extends JpaWithOptionsTestSupport {
}
@Test
- @AdditionalQueryParameters("firstResult=" + FIRST_RESULT)
+ @AdditionalEndpointParameters("firstResult=" + FIRST_RESULT)
public void testFirstResultInUri() throws Exception {
final List<Customer> customers = runQueryTest();
@@ -57,7 +56,7 @@ public class JpaPagingTest extends JpaWithOptionsTestSupport {
}
@Test
- @AdditionalQueryParameters("maximumResults=" + MAXIMUM_RESULTS)
+ @AdditionalEndpointParameters("maximumResults=" + MAXIMUM_RESULTS)
public void testFirstInHeaderMaxInUri() throws Exception {
final List<Customer> customers = runQueryTest(
withHeader(JpaConstants.JPA_FIRST_RESULT, FIRST_RESULT));
@@ -67,7 +66,7 @@ public class JpaPagingTest extends JpaWithOptionsTestSupport {
}
@Test
- @AdditionalQueryParameters("maximumResults=" + MAXIMUM_RESULTS)
+ @AdditionalEndpointParameters("maximumResults=" + MAXIMUM_RESULTS)
public void testMaxHeaderPrevailsOverUri() throws Exception {
final List<Customer> customers = runQueryTest(
withHeader(JpaConstants.JPA_MAXIMUM_RESULTS, MAXIMUM_RESULTS * 2));
@@ -76,7 +75,7 @@ public class JpaPagingTest extends JpaWithOptionsTestSupport {
}
@Test
- @AdditionalQueryParameters("firstResult=" + FIRST_RESULT)
+ @AdditionalEndpointParameters("firstResult=" + FIRST_RESULT)
public void testFirstHeaderPrevailsOverUri() throws Exception {
final List<Customer> customers = runQueryTest(
withHeader(JpaConstants.JPA_FIRST_RESULT, FIRST_RESULT * 2));
@@ -96,7 +95,7 @@ public class JpaPagingTest extends JpaWithOptionsTestSupport {
}
@Test
- @AdditionalQueryParameters("firstResult=" + JpaWithOptionsTestSupport.ENTRIES_COUNT)
+ @AdditionalEndpointParameters("firstResult=" + JpaWithOptionsTestSupport.ENTRIES_COUNT)
public void testFirstResultAfterTheEnd() throws Exception {
final List<Customer> customers = runQueryTest();
@@ -108,9 +107,4 @@ public class JpaPagingTest extends JpaWithOptionsTestSupport {
String.format(JpaWithOptionsTestSupport.ENTRY_SEQ_FORMAT, firstResult)));
}
- protected String getEndpointUri() {
- return ENDPOINT_URI +
- createAdditionalQueryParameters();
- }
-
}
diff --git a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithOptionsTestSupport.java b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithOptionsTestSupport.java
index 0394799f362..43cd82d3f20 100644
--- a/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithOptionsTestSupport.java
+++ b/components/camel-jpa/src/test/java/org/apache/camel/component/jpa/JpaWithOptionsTestSupport.java
@@ -16,10 +16,22 @@
*/
package org.apache.camel.component.jpa;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import javax.persistence.EntityManager;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
@@ -35,8 +47,12 @@ public abstract class JpaWithOptionsTestSupport extends AbstractJpaMethodSupport
static final int ENTRIES_COUNT = 30;
static final String ENTRY_SEQ_FORMAT = "%03d";
+ private static final String ENDPOINT_URI = "jpa://" + Customer.class.getName();
+
private String additionalQueryParameters = "";
+ private String queryOrFind;
+
protected String createAdditionalQueryParameters() {
return additionalQueryParameters.isBlank() ? "" : "&" + additionalQueryParameters;
}
@@ -52,8 +68,6 @@ public abstract class JpaWithOptionsTestSupport extends AbstractJpaMethodSupport
}
protected Exchange doRunQueryTest(final Processor... preRun) throws Exception {
- setUp(getEndpointUri());
-
return template.send("direct:start", exchange -> {
for (Processor processor : preRun) {
processor.process(exchange);
@@ -92,14 +106,63 @@ public abstract class JpaWithOptionsTestSupport extends AbstractJpaMethodSupport
final Optional<AnnotatedElement> element = context.getElement();
if (element.isPresent()) {
final AnnotatedElement annotatedElement = element.get();
- final AdditionalQueryParameters annotation = annotatedElement.getAnnotation(AdditionalQueryParameters.class);
- if (annotation != null && !annotation.value().isBlank()) {
- additionalQueryParameters = annotation.value();
- }
+
+ setAdditionalParameters(annotatedElement);
+ setQueryOrFind(annotatedElement);
}
+
}
- protected abstract String getEndpointUri();
+ @Override
+ public void beforeTestExecution(ExtensionContext context) throws Exception {
+ super.beforeTestExecution(context);
+ setUp(getEndpointUri());
+ }
+
+ private void setAdditionalParameters(final AnnotatedElement annotatedElement) {
+ final AdditionalEndpointParameters annotation = annotatedElement.getAnnotation(AdditionalEndpointParameters.class);
+ if (annotation != null && !annotation.value().isBlank()) {
+ additionalQueryParameters = annotation.value();
+ }
+ }
+
+ private void setQueryOrFind(final AnnotatedElement annotatedElement) throws IllegalStateException {
+ if (!(annotatedElement instanceof Method)) {
+ return;
+ }
+
+ final Method annotatedMethod = (Method) annotatedElement;
+
+ final Predicate<Annotation> isQueryOrFind
+ = ann -> Stream.of(Query.class, Find.class).anyMatch(foc -> foc.isAssignableFrom(ann.annotationType()));
+
+ final List<Annotation> onMethod = Arrays.stream(annotatedMethod.getAnnotations())
+ .filter(isQueryOrFind)
+ .collect(Collectors.toList());
+ final List<Annotation> onClass = Arrays.stream(annotatedMethod.getDeclaringClass().getAnnotations())
+ .filter(isQueryOrFind)
+ .collect(Collectors.toList());
+
+ if (onMethod.size() > 1 || onClass.size() > 1 || onMethod.size() + onClass.size() == 0) {
+ throw new IllegalStateException("Test (method or class) must be annotated with EITHER Find OR Query");
+ }
+
+ final Annotation queryOrFindAnn = Stream.concat(onMethod.stream(), onClass.stream())
+ .filter(isQueryOrFind).findFirst().get();
+
+ if (queryOrFindAnn instanceof Find) {
+ queryOrFind = "findEntity=" + true;
+ } else { // queryOrFindAnn instanceof Query
+ queryOrFind = "query=" + ((Query) queryOrFindAnn).value();
+ }
+ }
+
+ protected String getEndpointUri() {
+ return String.format("%s?%s%s",
+ ENDPOINT_URI,
+ queryOrFind,
+ createAdditionalQueryParameters());
+ }
protected void createCustomers() {
IntStream.range(0, ENTRIES_COUNT).forEach(idx -> {
@@ -109,6 +172,13 @@ public abstract class JpaWithOptionsTestSupport extends AbstractJpaMethodSupport
});
}
+ static Long validCustomerId(final EntityManager entityManager) {
+ final Customer fromDb
+ = (Customer) entityManager.createQuery("select c from Customer c where c.name like '% 001'").getSingleResult();
+ final Long customerId = fromDb.getId();
+ return customerId;
+ }
+
@Override
protected void setUp(String endpointUri) throws Exception {
super.setUp(endpointUri);
@@ -116,4 +186,15 @@ public abstract class JpaWithOptionsTestSupport extends AbstractJpaMethodSupport
assertEntitiesInDatabase(ENTRIES_COUNT, Customer.class.getName());
}
+ @Target({ ElementType.METHOD, ElementType.TYPE })
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Find {
+ }
+
+ @Target({ ElementType.METHOD, ElementType.TYPE })
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Query {
+ String value() default "select c from Customer c";
+ }
+
}