This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch val in repository https://gitbox.apache.org/repos/asf/camel.git
commit 97e3fdb6073c13d06c49bccc8fe5c0ba015c1590 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Oct 29 14:29:06 2025 +0100 CAMEL-22608: camel-core - Using multiple validate EIP in Java DSL and end confusion --- .../apache/camel/model/ProcessorDefinition.java | 30 ++++++-- .../camel/processor/SplitMultipleValidateTest.java | 79 ++++++++++++++++++++++ .../ValidatePredicateExceptionFactoryTest.java | 2 +- .../ROOT/pages/camel-4x-upgrade-guide-4_16.adoc | 23 +++++++ 4 files changed, 126 insertions(+), 8 deletions(-) diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java index 1c9908a08994..3f9f059129fc 100644 --- a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java +++ b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java @@ -67,6 +67,7 @@ import org.apache.camel.spi.IdempotentRepository; import org.apache.camel.spi.InterceptStrategy; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.Policy; +import org.apache.camel.spi.PredicateExceptionFactory; import org.apache.camel.spi.Resource; import org.apache.camel.spi.ResourceAware; import org.apache.camel.support.ExpressionAdapter; @@ -1427,10 +1428,10 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type> * @param expression the expression * @return the builder */ - public ValidateDefinition validate(@AsPredicate Expression expression) { + public Type validate(@AsPredicate Expression expression) { ValidateDefinition answer = new ValidateDefinition(expression); addOutput(answer); - return answer; + return asType(); } /** @@ -1440,10 +1441,10 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type> * @param predicate the predicate * @return the builder */ - public ValidateDefinition validate(@AsPredicate Predicate predicate) { + public Type validate(@AsPredicate Predicate predicate) { ValidateDefinition answer = new ValidateDefinition(predicate); addOutput(answer); - return answer; + return asType(); } /** @@ -1453,10 +1454,25 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type> * @return the builder */ @AsPredicate - public ExpressionClause<ValidateDefinition> validate() { - ValidateDefinition answer = new ValidateDefinition(); + public ExpressionClause<ProcessorDefinition<Type>> validate() { + ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<>(this); + ValidateDefinition answer = new ValidateDefinition((Expression) clause); addOutput(answer); - return createAndSetExpression(answer); + return clause; + } + + /** + * Creates a validation expression which only if it is <tt>true</tt> then the exchange is forwarded to the + * destination. Otherwise a {@link org.apache.camel.support.processor.PredicateValidationException} is thrown. + * + * @return the builder + */ + public ExpressionClause<ProcessorDefinition<Type>> validate(PredicateExceptionFactory predicateExceptionFactory) { + ExpressionClause<ProcessorDefinition<Type>> clause = new ExpressionClause<>(this); + ValidateDefinition answer = new ValidateDefinition((Expression) clause); + answer.predicateExceptionFactory(predicateExceptionFactory); + addOutput(answer); + return clause; } /** diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/SplitMultipleValidateTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/SplitMultipleValidateTest.java new file mode 100644 index 000000000000..b12bb3517c96 --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/processor/SplitMultipleValidateTest.java @@ -0,0 +1,79 @@ +/* + * 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; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.builder.RouteBuilder; +import org.junit.jupiter.api.Test; + +public class SplitMultipleValidateTest extends ContextTestSupport { + + @Test + public void testMultipleValidate() throws Exception { + getMockEndpoint("mock:split1").expectedMessageCount(1); + getMockEndpoint("mock:line1").expectedMessageCount(3); + getMockEndpoint("mock:split2").expectedMessageCount(1); + getMockEndpoint("mock:line2").expectedMessageCount(3); + getMockEndpoint("mock:split3").expectedMessageCount(1); + getMockEndpoint("mock:line3").expectedMessageCount(3); + + template.sendBody("direct:start1", "Hello World"); + template.sendBody("direct:start2", "Hello World"); + template.sendBody("direct:start3", "Hello World"); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start1") + .split(constant("123").tokenize("")) + .filter(body().isNotNull()) + .log("Item ${body}") + .to("mock:line1") + .end() // filter end + .end() // split end + .to("mock:split1"); + + from("direct:start2") + .split(constant("123").tokenize("")) + .filter(body().isNotNull()) + .validate(body().isNotNull()) + .log("Item ${body}") + .to("mock:line2") + .end() // filter end + .end() // split end + .to("mock:split2"); + + from("direct:start3") + .split(constant("123").tokenize("")) + .filter(body().isNotNull()) + .validate(body().isNotNull()) + .validate(body().isInstanceOf(String.class)) + .validate(body().isGreaterThan("0")) + .log("Item ${body}") + .to("mock:line3") + .end() // filter end + .end() // split end + .to("mock:split3"); + } + }; + } +} diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/ValidatePredicateExceptionFactoryTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/ValidatePredicateExceptionFactoryTest.java index 45cf54441a5b..1f1221f58039 100644 --- a/core/camel-core/src/test/java/org/apache/camel/processor/ValidatePredicateExceptionFactoryTest.java +++ b/core/camel-core/src/test/java/org/apache/camel/processor/ValidatePredicateExceptionFactoryTest.java @@ -90,7 +90,7 @@ public class ValidatePredicateExceptionFactoryTest extends ContextTestSupport { return new RouteBuilder() { public void configure() { from("direct:start") - .validate().simple("${body} contains 'Camel'").predicateExceptionFactory(new MyExceptionFactory()) + .validate(new MyExceptionFactory()).simple("${body} contains 'Camel'") .id("myValidate") .to("mock:result"); } diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc index dab3621d792a..e503b9196bca 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_16.adoc @@ -13,6 +13,29 @@ See the xref:camel-upgrade-recipes-tool.adoc[documentation] page for details. == Upgrading Camel 4.15 to 4.16 +=== EIPs + +The `validate` EIP in Java DSL has changed avoid having to use `.end()` to correctly continue building the route. +Other EIPs such as `setBody` and `transform` does not require to use `.end()` and as such we are making this the same behavior. + +For example if stacking multiple validates then you would have to end `.end()` each time: + +[source,java] +---- + .validate(body().isNotNull()).end() + .validate(body().isInstanceOf(String.class)).end() + .validate(body().isGreaterThan("0")).end() +---- + +Should now be: + +[source,java] +---- + .validate(body().isNotNull()) + .validate(body().isInstanceOf(String.class)) + .validate(body().isGreaterThan("0")) +---- + === camel-core The `tryConvertTo` method in Camel type converters will no longer in case of no converter suitable,
