This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch camel-2.21.x in repository https://gitbox.apache.org/repos/asf/camel.git
commit cbcf30d19e30d95d3ce54a6d13805f12f80bc7f4 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Aug 6 20:07:35 2018 +0200 CAMEL-12565: Added unit tests. Fixed a little issue in validator to ensure exception is set on exchange to allow advice to keep executing the next ones. --- .../org/apache/camel/model/RouteDefinition.java | 2 +- .../org/apache/camel/processor/ContractAdvice.java | 55 ++++++----- .../validator/BeanValidatorInputValidateTest.java | 97 +++++++++++++++++++ .../validator/BeanValidatorOutputValidateTest.java | 104 +++++++++++++++++++++ 4 files changed, 235 insertions(+), 23 deletions(-) diff --git a/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java b/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java index ddb3fb9..985afe7 100644 --- a/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/RouteDefinition.java @@ -756,7 +756,7 @@ public class RouteDefinition extends ProcessorDefinition<RouteDefinition> { /** * Declare the expected data type of the output message with content validation enabled. - * If the actual message type is different at runtime, camel look for a required + * If the actual message type is different at runtime, Camel look for a required * {@link Transformer} and apply if exists, and then applies {@link Validator} as well. * The type name consists of two parts, 'scheme' and 'name' connected with ':'. For Java type 'name' * is a fully qualified class name. For example {@code java:java.lang.String}, {@code json:ABCOrder}. diff --git a/camel-core/src/main/java/org/apache/camel/processor/ContractAdvice.java b/camel-core/src/main/java/org/apache/camel/processor/ContractAdvice.java index f2e792a..521ea12 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/ContractAdvice.java +++ b/camel-core/src/main/java/org/apache/camel/processor/ContractAdvice.java @@ -61,19 +61,24 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { if (!(exchange.getIn() instanceof DataTypeAware)) { return null; } - DataType to = contract.getInputType(); - if (to != null) { - DataTypeAware target = (DataTypeAware)exchange.getIn(); - DataType from = target.getDataType(); - if (!to.equals(from)) { - LOG.debug("Looking for transformer for INPUT: from='{}', to='{}'", from, to); - doTransform(exchange.getIn(), from, to); - target.setDataType(to); - } - if (contract.isValidateInput()) { - doValidate(exchange.getIn(), to); + try { + DataType to = contract.getInputType(); + if (to != null) { + DataTypeAware target = (DataTypeAware) exchange.getIn(); + DataType from = target.getDataType(); + if (!to.equals(from)) { + LOG.debug("Looking for transformer for INPUT: from='{}', to='{}'", from, to); + doTransform(exchange.getIn(), from, to); + target.setDataType(to); + } + if (contract.isValidateInput()) { + doValidate(exchange.getIn(), to); + } } + } catch (Exception e) { + exchange.setException(e); } + return null; } @@ -88,18 +93,22 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { if (!(target instanceof DataTypeAware)) { return; } - DataType to = contract.getOutputType(); - if (to != null) { - DataTypeAware typeAwareTarget = (DataTypeAware)target; - DataType from = typeAwareTarget.getDataType(); - if (!to.equals(from)) { - LOG.debug("Looking for transformer for OUTPUT: from='{}', to='{}'", from, to); - doTransform(target, from, to); - typeAwareTarget.setDataType(to); - } - if (contract.isValidateOutput()) { - doValidate(target, to); + try { + DataType to = contract.getOutputType(); + if (to != null) { + DataTypeAware typeAwareTarget = (DataTypeAware)target; + DataType from = typeAwareTarget.getDataType(); + if (!to.equals(from)) { + LOG.debug("Looking for transformer for OUTPUT: from='{}', to='{}'", from, to); + doTransform(target, from, to); + typeAwareTarget.setDataType(to); + } + if (contract.isValidateOutput()) { + doValidate(target, to); + } } + } catch (Exception e) { + exchange.setException(e); } } @@ -154,6 +163,7 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { } return false; } + private boolean applyMatchedTransformer(Message message, DataType from, DataType to) throws Exception { Transformer transformer = message.getExchange().getContext().resolveTransformer(from, to); return applyTransformer(transformer, message, from, to); @@ -186,4 +196,5 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { throw new ValidationException(message.getExchange(), String.format("No Validator found for '%s'", type)); } } + } \ No newline at end of file diff --git a/camel-core/src/test/java/org/apache/camel/impl/validator/BeanValidatorInputValidateTest.java b/camel-core/src/test/java/org/apache/camel/impl/validator/BeanValidatorInputValidateTest.java new file mode 100644 index 0000000..886fb99 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/impl/validator/BeanValidatorInputValidateTest.java @@ -0,0 +1,97 @@ +/** + * 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.impl.validator; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Message; +import org.apache.camel.ValidationException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.spi.DataType; +import org.apache.camel.spi.Validator; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BeanValidatorInputValidateTest extends ContextTestSupport { + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + validator() + .type("toValidate") + .withBean("testValidator"); + + onException(ValidationException.class) + .handled(true) + .log("Invalid validation: ${exception.message}") + .to("mock:invalid"); + + from("direct:in") + .inputTypeWithValidate("toValidate") + .to("mock:out"); + } + }; + } + + public static class TestValidator extends Validator { + private static final Logger LOG = LoggerFactory.getLogger(TestValidator.class); + + @Override + public void validate(Message message, DataType type) throws ValidationException { + Object body = message.getBody(); + LOG.info("Validating : [{}]", body); + if (body instanceof String && body.equals("valid")) { + LOG.info("OK"); + } else { + throw new ValidationException(message.getExchange(), "Wrong content"); + } + } + } + + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry registry = super.createRegistry(); + + registry.bind("testValidator", new TestValidator()); + + return registry; + } + + @Test + public void testValid() throws InterruptedException { + getMockEndpoint("mock:out").expectedMessageCount(1); + getMockEndpoint("mock:invalid").expectedMessageCount(0); + + template.sendBody("direct:in", "valid"); + + assertMockEndpointsSatisfied(); + } + + @Test + public void testInvalid() throws InterruptedException { + getMockEndpoint("mock:out").expectedMessageCount(0); + getMockEndpoint("mock:invalid").expectedMessageCount(1); + + template.sendBody("direct:in", "wrong"); + + assertMockEndpointsSatisfied(); + } +} diff --git a/camel-core/src/test/java/org/apache/camel/impl/validator/BeanValidatorOutputValidateTest.java b/camel-core/src/test/java/org/apache/camel/impl/validator/BeanValidatorOutputValidateTest.java new file mode 100644 index 0000000..ac5ed49 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/impl/validator/BeanValidatorOutputValidateTest.java @@ -0,0 +1,104 @@ +/** + * 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.impl.validator; + +import org.apache.camel.CamelExecutionException; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Message; +import org.apache.camel.ValidationException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.spi.DataType; +import org.apache.camel.spi.Validator; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BeanValidatorOutputValidateTest extends ContextTestSupport { + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + validator() + .type("toValidate") + .withBean("testValidator"); + + onException(ValidationException.class) + .handled(true) + .log("Invalid validation: ${exception.message}") + .to("mock:invalid"); + + from("direct:in") + .outputTypeWithValidate("toValidate") + .to("mock:out"); + } + }; + } + + public static class TestValidator extends Validator { + private static final Logger LOG = LoggerFactory.getLogger(TestValidator.class); + + @Override + public void validate(Message message, DataType type) throws ValidationException { + Object body = message.getBody(); + LOG.info("Validating : [{}]", body); + if (body instanceof String && body.equals("valid")) { + LOG.info("OK"); + } else { + throw new ValidationException(message.getExchange(), "Wrong content"); + } + } + } + + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry registry = super.createRegistry(); + + registry.bind("testValidator", new TestValidator()); + + return registry; + } + + @Test + public void testValid() throws InterruptedException { + getMockEndpoint("mock:out").expectedMessageCount(1); + getMockEndpoint("mock:invalid").expectedMessageCount(0); + + template.sendBody("direct:in", "valid"); + + assertMockEndpointsSatisfied(); + } + + @Test + public void testInvalid() throws InterruptedException { + getMockEndpoint("mock:out").expectedMessageCount(1); + getMockEndpoint("mock:invalid").expectedMessageCount(0); + + try { + template.sendBody("direct:in", "wrong"); + fail("Should have thrown exception"); + } catch (CamelExecutionException e) { + assertIsInstanceOf(ValidationException.class, e.getCause()); + assertTrue(e.getCause().getMessage().startsWith("Wrong content")); + } + + assertMockEndpointsSatisfied(); + } +}