http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/model/validator/CustomValidatorDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/validator/CustomValidatorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/validator/CustomValidatorDefinition.java new file mode 100644 index 0000000..5c1e164 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/validator/CustomValidatorDefinition.java @@ -0,0 +1,98 @@ +/** + * 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.model.validator; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import org.apache.camel.CamelContext; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.Transformer; +import org.apache.camel.spi.Validator; + +/** + * Represents a CustomValidator. One of the bean reference (ref) or fully qualified class name (className) + * of the custom {@link Validator} needs to be specified. + * + * {@see ValidatorDefinition} + * {@see Validator} + */ +@Metadata(label = "validation") +@XmlType(name = "customValidator") +@XmlAccessorType(XmlAccessType.FIELD) +public class CustomValidatorDefinition extends ValidatorDefinition { + + @XmlAttribute + private String ref; + @XmlAttribute + private String className; + + @Override + protected Validator doCreateValidator(CamelContext context) throws Exception { + if (ref == null && className == null) { + throw new IllegalArgumentException("'ref' or 'type' must be specified for customValidator"); + } + Validator validator; + if (ref != null) { + validator = context.getRegistry().lookupByNameAndType(ref, Validator.class); + if (validator == null) { + throw new IllegalArgumentException("Cannot find validator with ref:" + ref); + } + if (validator.getType() != null) { + throw new IllegalArgumentException(String.format("Validator '%s' is already in use. Please check if duplicate validator exists.", ref)); + } + } else { + Class<Validator> validatorClass = context.getClassResolver().resolveMandatoryClass(className, Validator.class); + if (validatorClass == null) { + throw new IllegalArgumentException("Cannot find validator class: " + className); + } + validator = context.getInjector().newInstance(validatorClass); + + } + validator.setCamelContext(context); + return validator.setType(getType()); + } + + public String getRef() { + return ref; + } + + /** + * Set a bean reference of the {@link Validator} + * + * @param ref the bean reference of the Transformer + */ + public void setRef(String ref) { + this.ref = ref; + } + + public String getClassName() { + return className; + } + + /** + * Set a class name of the {@link Validator} + * + * @param className the class name of the Validator + */ + public void setClassName(String className) { + this.className = className; + } + +} +
http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/model/validator/EndpointValidatorDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/validator/EndpointValidatorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/validator/EndpointValidatorDefinition.java new file mode 100644 index 0000000..537216b --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/validator/EndpointValidatorDefinition.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.model.validator; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + +import org.w3c.dom.ls.LSResourceResolver; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.ExchangePattern; +import org.apache.camel.component.validator.ValidatorEndpoint; +import org.apache.camel.component.validator.ValidatorResourceResolverFactory; +import org.apache.camel.impl.validator.ProcessorValidator; +import org.apache.camel.processor.SendProcessor; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.Validator; +import org.apache.camel.util.ObjectHelper; + +/** + * Represents an endpoint {@link Validator} which leverages camel validator component such as + * <a href="http://camel.apache.org/validation.html">Validator Component</a> and + * <a href="http://camel.apache.org/bean-validation.html">Bean Validator Component</a> to + * perform content validation. A {@link ProcessorValidator} will be created internally + * with a {@link SendProcessor} which forwards the message to the validator Endpoint. + * + * {@see ValidatorDefinition} + * {@see Validator} + */ +@Metadata(label = "validation") +@XmlType(name = "endpointValidator") +@XmlAccessorType(XmlAccessType.FIELD) +public class EndpointValidatorDefinition extends ValidatorDefinition { + + @XmlAttribute + private String ref; + @XmlAttribute + private String uri; + + @Override + protected Validator doCreateValidator(CamelContext context) throws Exception { + Endpoint endpoint = uri != null ? context.getEndpoint(uri) + : context.getRegistry().lookupByNameAndType(ref, Endpoint.class); + SendProcessor processor = new SendProcessor(endpoint, ExchangePattern.InOut); + return new ProcessorValidator(context) + .setProcessor(processor) + .setType(getType()); + } + + public String getRef() { + return ref; + } + + /** + * Set the reference of the Endpoint. + * + * @param ref reference of the Endpoint + */ + public void setRef(String ref) { + this.ref = ref; + } + + public String getUri() { + return uri; + } + + /** + * Set the URI of the Endpoint. + * + * @param uri URI of the Endpoint + */ + public void setUri(String uri) { + this.uri = uri; + } + +} + http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/model/validator/PredicateValidatorDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/validator/PredicateValidatorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/validator/PredicateValidatorDefinition.java new file mode 100644 index 0000000..89f72a5 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/validator/PredicateValidatorDefinition.java @@ -0,0 +1,76 @@ +/** + * 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.model.validator; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlType; +import org.apache.camel.CamelContext; +import org.apache.camel.Expression; +import org.apache.camel.Predicate; +import org.apache.camel.impl.validator.ProcessorValidator; +import org.apache.camel.model.ExpressionNodeHelper; +import org.apache.camel.model.language.ExpressionDefinition; +import org.apache.camel.processor.validation.PredicateValidatingProcessor; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.Transformer; +import org.apache.camel.spi.Validator; + +/** + * Represents a predicate {@link Validator} which leverages expression or predicates to + * perform content validation. A {@link ProcessorValidator} will be created internally + * with a {@link PredicateValidatingProcessor} which validates the message according to specified expression/predicates. + * + * {@see ValidatorDefinition} + * {@see Validator} + */ +@Metadata(label = "validation") +@XmlType(name = "predicateValidator") +@XmlAccessorType(XmlAccessType.FIELD) +public class PredicateValidatorDefinition extends ValidatorDefinition { + + @XmlElementRef + private ExpressionDefinition expression; + + @Override + protected Validator doCreateValidator(CamelContext context) throws Exception { + Predicate pred = getExpression().createPredicate(context); + PredicateValidatingProcessor processor = new PredicateValidatingProcessor(pred); + return new ProcessorValidator(context) + .setProcessor(processor) + .setType(getType()); + } + + public ExpressionDefinition getExpression() { + return expression; + } + + public void setExpression(ExpressionDefinition expression) { + // favour using the helper to set the expression as it can unwrap some unwanted builders when using Java DSL + if (expression instanceof Expression) { + this.expression = ExpressionNodeHelper.toExpressionDefinition((Expression) expression); + } else if (expression instanceof Predicate) { + this.expression = ExpressionNodeHelper.toExpressionDefinition((Predicate) expression); + } else { + this.expression = expression; + } + } + +} + http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorDefinition.java b/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorDefinition.java new file mode 100644 index 0000000..0a0db9f --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorDefinition.java @@ -0,0 +1,80 @@ +/** + * 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.model.validator; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import org.apache.camel.CamelContext; +import org.apache.camel.model.InputTypeDefinition; +import org.apache.camel.model.OutputTypeDefinition; +import org.apache.camel.spi.DataType; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.Validator; + +/** + * <p>Represents a {@link Validator} which declaratively validates message content + * according to the input type declared by {@link InputTypeDefinition} and/or output type + * declared by {@link OutputTypeDefinition}.</p> + * <p>If you specify type='xml:ABC', the validator + * will be picked up when current message type is 'xml:ABC'. + * If you specify type='json', then it will be picked up for all of json validation. + * + * {@see Validator} + * {@see InputTypeDefinition} + * {@see OutputTypeDefinition} + */ +@Metadata(label = "validation") +@XmlType(name = "validator") +@XmlAccessorType(XmlAccessType.FIELD) +public abstract class ValidatorDefinition { + + @XmlAttribute + private String type; + + public Validator createValidator(CamelContext context) throws Exception { + return doCreateValidator(context); + }; + + protected abstract Validator doCreateValidator(CamelContext context) throws Exception; + + public String getType() { + return type; + } + + /** + * Set the data type name. + * If you specify 'xml:XYZ', the validator will be picked up if message type is + * 'xml:XYZ'. If you specify just 'xml', the validator matches with all of + * 'xml' message type like 'xml:ABC' or 'xml:DEF'. + * + * @param type data type name + */ + public void setType(String type) { + this.type = type; + } + + /** + * Set the data type using Java class. + * @param clazz Java class + */ + public void setType(Class<?> clazz) { + this.type = new DataType(clazz).toString(); + } +} + http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorsDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorsDefinition.java b/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorsDefinition.java new file mode 100644 index 0000000..cb90c2c --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/validator/ValidatorsDefinition.java @@ -0,0 +1,54 @@ +/** + * 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.model.validator; + +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.camel.spi.Metadata; + +/** + * To configure validators. + */ +@Metadata(label = "validation", title = "Validations") +@XmlRootElement(name = "validators") +@XmlAccessorType(XmlAccessType.FIELD) +public class ValidatorsDefinition { + + @XmlElements({ + @XmlElement(required = false, name = "endpointValidator", type = EndpointValidatorDefinition.class), + @XmlElement(required = false, name = "predicateValidator", type = PredicateValidatorDefinition.class), + @XmlElement(required = false, name = "customValidator", type = CustomValidatorDefinition.class)} + ) + private List<ValidatorDefinition> validators; + + /** + * The configured transformers + */ + public void setValidators(List<ValidatorDefinition> validators) { + this.validators = validators; + } + + public List<ValidatorDefinition> getValidators() { + return validators; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/model/validator/package-info.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/validator/package-info.java b/camel-core/src/main/java/org/apache/camel/model/validator/package-info.java new file mode 100644 index 0000000..14173ec --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/validator/package-info.java @@ -0,0 +1,24 @@ +/** + * 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. + */ + +/** + * The JAXB POJOs for the + * <a href="http://camel.apache.org/transformer.html">Transformers</a> used to transform message contents + * according to declared data types inside <a href="http://camel.apache.org/components.html">components</a> + */ [email protected](namespace = "http://camel.apache.org/schema/spring", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package org.apache.camel.model.validator; http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/processor/ContractAdvice.java ---------------------------------------------------------------------- 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 a3dad33..6a53e7b 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 @@ -19,9 +19,11 @@ package org.apache.camel.processor; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Message; +import org.apache.camel.ValidationException; import org.apache.camel.spi.Contract; import org.apache.camel.spi.DataType; import org.apache.camel.spi.Transformer; +import org.apache.camel.spi.Validator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,7 +31,6 @@ import org.slf4j.LoggerFactory; * A {@code CamelInternalProcessorAdvice} which performs Transformation and Validation * according to the data type Contract. * - * TODO add declarative validation * @see CamelInternalProcessor, CamelInternalProcessorAdvice */ public class ContractAdvice implements CamelInternalProcessorAdvice { @@ -45,58 +46,66 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { public Object before(Exchange exchange) throws Exception { DataType from = getCurrentType(exchange, Exchange.INPUT_TYPE); DataType to = contract.getInputType(); - if (to != null && !to.equals(from)) { - LOG.debug("Looking for transformer for INPUT: from='{}', to='{}'", from, to); - doTransform(exchange.getIn(), from, to); - exchange.setProperty(Exchange.INPUT_TYPE, to); + if (to != null) { + if (!to.equals(from)) { + LOG.debug("Looking for transformer for INPUT: from='{}', to='{}'", from, to); + doTransform(exchange.getIn(), from, to); + exchange.setProperty(Exchange.INPUT_TYPE, to); + } + if (contract.isValidateInput()) { + doValidate(exchange.getIn(), to); + } } return null; } @Override public void after(Exchange exchange, Object data) throws Exception { + if (exchange.isFailed()) { + // TODO can we add FAULT_TYPE processing? + return; + } + Message target = exchange.hasOut() ? exchange.getOut() : exchange.getIn(); if (!exchange.hasOut() && exchange.getProperty(Exchange.OUTPUT_TYPE) == null) { exchange.setProperty(Exchange.OUTPUT_TYPE, exchange.getProperty(Exchange.INPUT_TYPE)); } DataType from = getCurrentType(exchange, Exchange.OUTPUT_TYPE); DataType to = contract.getOutputType(); - if (to != null && !to.equals(from)) { - LOG.debug("Looking for transformer for OUTPUT: from='{}', to='{}'", from, to); - doTransform(target, from, to); - exchange.setProperty(Exchange.OUTPUT_TYPE, to); + if (to != null) { + if (!to.equals(from)) { + LOG.debug("Looking for transformer for OUTPUT: from='{}', to='{}'", from, to); + doTransform(target, from, to); + exchange.setProperty(Exchange.OUTPUT_TYPE, to); + } + if (contract.isValidateOutput()) { + doValidate(target, to); + } } } private void doTransform(Message message, DataType from, DataType to) throws Exception { + if (from == null) { + // If 'from' is null, only Java-Java convertion is performed. + // It means if 'to' is other than Java, it's assumed to be already in expected shape. + convertIfRequired(message, to); + return; + } + // transform into 'from' type before performing declared transformation convertIfRequired(message, from); - if (applyExactlyMatchedTransformer(message, from, to)) { - // Found exactly matched transformer. Java-Java transformer is also allowed. + if (applyMatchedTransformer(message, from, to)) { + // Found matched transformer. Java-Java transformer is also allowed. return; - } else if (from == null || from.isJavaType()) { + } else if (from.isJavaType()) { if (convertIfRequired(message, to)) { // Java->Java transformation just relies on TypeConverter if no explicit transformer return; - } else if (from == null) { - // use body class as a from type, or do nothing with assuming it's already in expected shape - applyTransformerByClass(message, to); - return; - } else if (applyTransformerByToModel(message, from, to)) { - // Java->Other transformation - found a transformer supports 'to' data model - return; - } - } else if (from != null) { - if (to.isJavaType()) { - if (applyTransformerByFromModel(message, from, to)) { - // Other->Java transformation - found a transformer supprts 'from' data model - return; - } - } else if (applyTransformerChain(message, from, to)) { - // Other->Other transformation - found a transformer chain - return; } + } else if (applyTransformerChain(message, from, to)) { + // Other->Other transformation - found a transformer chain + return; } throw new IllegalArgumentException("No Transformer found for [from='" + from + "', to='" + to + "']"); @@ -125,27 +134,11 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { } return false; } - private boolean applyExactlyMatchedTransformer(Message message, DataType from, DataType to) throws Exception { + 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); } - private boolean applyTransformerByClass(Message message, DataType to) throws Exception { - DataType from = new DataType(message.getBody().getClass()); - Transformer transformer = message.getExchange().getContext().resolveTransformer(from, to); - return applyTransformer(transformer, message, from, to); - } - - private boolean applyTransformerByToModel(Message message, DataType from, DataType to) throws Exception { - Transformer transformer = message.getExchange().getContext().resolveTransformer(to.getModel()); - return applyTransformer(transformer, message, from, to); - } - - private boolean applyTransformerByFromModel(Message message, DataType from, DataType to) throws Exception { - Transformer transformer = message.getExchange().getContext().resolveTransformer(from.getModel()); - return applyTransformer(transformer, message, from, to); - } - private boolean applyTransformerChain(Message message, DataType from, DataType to) throws Exception { CamelContext context = message.getExchange().getContext(); Transformer fromTransformer = context.resolveTransformer(from.getModel()); @@ -175,4 +168,14 @@ public class ContractAdvice implements CamelInternalProcessorAdvice { } return null; } + + private void doValidate(Message message, DataType type) throws ValidationException { + Validator validator = message.getExchange().getContext().resolveValidator(type); + if (validator != null) { + LOG.debug("Applying validator: type='{}', validator='{}'", type, validator); + validator.validate(message, type); + } else { + throw new ValidationException(message.getExchange(), String.format("No Validator found for '%s'", type)); + } + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/spi/Contract.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/Contract.java b/camel-core/src/main/java/org/apache/camel/spi/Contract.java index 8cc90c9..b9de3bf 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/Contract.java +++ b/camel-core/src/main/java/org/apache/camel/spi/Contract.java @@ -23,6 +23,8 @@ public class Contract { private DataType inputType; private DataType outputType; + private boolean validateInput; + private boolean validateOutput; private String contractString; public DataType getInputType() { @@ -69,6 +71,38 @@ public class Contract { this.contractString = null; } + /** + * + * @return + */ + public boolean isValidateInput() { + return validateInput; + } + + /** + * + * @param validate + */ + public void setValidateInput(boolean validate) { + this.validateInput = validate; + } + + /** + * + * @return + */ + public boolean isValidateOutput() { + return validateOutput; + } + + /** + * + * @param validate + */ + public void setValidateOutput(boolean validate) { + this.validateOutput = validate; + } + @Override public String toString() { if (contractString == null) { http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/spi/TransformerRegistry.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/TransformerRegistry.java b/camel-core/src/main/java/org/apache/camel/spi/TransformerRegistry.java index 85acd1c..c4d73d4 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/TransformerRegistry.java +++ b/camel-core/src/main/java/org/apache/camel/spi/TransformerRegistry.java @@ -16,10 +16,12 @@ */ package org.apache.camel.spi; +import java.util.List; import java.util.Map; import org.apache.camel.Endpoint; import org.apache.camel.StaticService; +import org.apache.camel.model.transformer.TransformerDefinition; /** * Registry to cache transformers in memory. @@ -40,6 +42,14 @@ import org.apache.camel.StaticService; public interface TransformerRegistry<K> extends Map<K, Transformer>, StaticService { /** + * Lookup a {@link Transformer} in the registry which supports the transformation for + * the data types represented by the key. + * @param key a key represents the from/to data types to transform + * @return {@link Transformer} if matched, otherwise null + */ + Transformer resolveTransformer(K key); + + /** * Number of transformers in the static registry. */ int staticSize(); @@ -85,7 +95,7 @@ public interface TransformerRegistry<K> extends Map<K, Transformer>, StaticServi boolean isDynamic(String scheme); /** - * Whether the given transformer is stored in the dynamic cache + * Whether the given {@link Transformer} is stored in the dynamic cache * * @param from 'from' data type * @param to 'to' data type http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/spi/Validator.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/Validator.java b/camel-core/src/main/java/org/apache/camel/spi/Validator.java new file mode 100644 index 0000000..1ba2998 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/spi/Validator.java @@ -0,0 +1,96 @@ +/** + * 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.spi; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.ValidationException; +import org.apache.camel.model.InputTypeDefinition; +import org.apache.camel.model.OutputTypeDefinition; +import org.apache.camel.support.ServiceSupport; + +/** + * <a href="http://camel.apache.org/transformer.html">Transformer</a> + * performs message transformation according to the declared data type. + * There are two Exchange property indicates current message type, {@link Exchange#INPUT_TYPE} + * holds input message type and {@link Exchange#OUTPUT_TYPE} holds output message type. If the + * input type and/or output type declared by {@link InputTypeDefinition} + * and/or {@link OutputTypeDefinition} in the route definition is different from those property + * at runtime, camel internal processor look for a Transformer which transforms from + * the current message type to the expected message type. + * + * @see InputTypeDefinition + * @see OutputTypeDefinition + */ +public abstract class Validator extends ServiceSupport implements CamelContextAware { + + private CamelContext camelContext; + private DataType type; + + /** + * Perform data validation with specified type. + * + * @param message message to apply validation + * @param type the data type + * @throws ValidationException thrown if any validation error is detected + */ + public abstract void validate(Message message, DataType type) throws ValidationException; + + /** + * Get 'from' data type. + */ + public DataType getType() { + return type; + }; + + /** + * Set data type. + * + * @param type data type + */ + public Validator setType(String type) { + this.type = new DataType(type); + return this; + } + + @Override + public CamelContext getCamelContext() { + return this.camelContext; + } + + @Override + public void setCamelContext(CamelContext context) { + this.camelContext = context; + } + + @Override + public String toString() { + return String.format("%s[type='%s']", this.getClass().getSimpleName(), type); + } + + @Override + protected void doStart() throws Exception { + // no-op + } + + @Override + protected void doStop() throws Exception { + // no-op + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/spi/ValidatorRegistry.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/ValidatorRegistry.java b/camel-core/src/main/java/org/apache/camel/spi/ValidatorRegistry.java new file mode 100644 index 0000000..82d1020 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/spi/ValidatorRegistry.java @@ -0,0 +1,93 @@ +/** + * 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.spi; + +import java.util.List; +import java.util.Map; + +import org.apache.camel.Endpoint; +import org.apache.camel.StaticService; +import org.apache.camel.model.validator.ValidatorDefinition; + +/** + * Registry to cache validators in memory. + * <p/> + * The registry contains two caches: + * <ul> + * <li>static - which keeps all the validators in the cache for the entire lifecycle</li> + * <li>dynamic - which keeps the validators in a {@link org.apache.camel.util.LRUCache} and may evict validators which hasn't been requested recently</li> + * </ul> + * The static cache stores all the validators that are created as part of setting up and starting routes. + * The static cache has no upper limit. + * <p/> + * The dynamic cache stores the validators that are created and used ad-hoc, such as from custom Java code that creates new validators etc. + * The dynamic cache has an upper limit, that by default is 1000 entries. + * + * @param <K> validator key + */ +public interface ValidatorRegistry<K> extends Map<K, Validator>, StaticService { + + /** + * Lookup a {@link Validator} in the registry which supports the validation for + * the data type represented by the key. + * @param key a key represents the data type + * @return {@link Validator} if matched, otherwise null + */ + Validator resolveValidator(K key); + + /** + * Number of validators in the static registry. + */ + int staticSize(); + + /** + * Number of validators in the dynamic registry + */ + int dynamicSize(); + + /** + * Maximum number of entries to store in the dynamic registry + */ + int getMaximumCacheSize(); + + /** + * Purges the cache (removes validators from the dynamic cache) + */ + void purge(); + + /** + * Whether the given {@link Validator} is stored in the static cache + * + * @param type the data type + * @return <tt>true</tt> if in static cache, <tt>false</tt> if not + */ + boolean isStatic(DataType type); + + /** + * Whether the given {@link Validator} is stored in the dynamic cache + * + * @param type the data type + * @return <tt>true</tt> if in dynamic cache, <tt>false</tt> if not + */ + boolean isDynamic(DataType type); + + /** + * Cleanup the cache (purging stale entries) + */ + void cleanUp(); + +} http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java b/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java index 8be19d7..a133b73 100644 --- a/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java +++ b/camel-core/src/main/java/org/apache/camel/util/CamelContextHelper.java @@ -254,6 +254,68 @@ public final class CamelContextHelper { } /** + * Gets the maximum transformer cache size. + * <p/> + * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_TRANSFORMER_CACHE_SIZE}. + * If no property has been set, then it will fallback to return a size of 1000. + * + * @param camelContext the camel context + * @return the maximum cache size + * @throws IllegalArgumentException is thrown if the property is illegal + */ + public static int getMaximumTransformerCacheSize(CamelContext camelContext) throws IllegalArgumentException { + if (camelContext != null) { + String s = camelContext.getGlobalOption(Exchange.MAXIMUM_TRANSFORMER_CACHE_SIZE); + if (s != null) { + // we cannot use Camel type converters as they may not be ready this early + try { + Integer size = Integer.valueOf(s); + if (size == null || size <= 0) { + throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_TRANSFORMER_CACHE_SIZE + " must be a positive number, was: " + s); + } + return size; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_TRANSFORMER_CACHE_SIZE + " must be a positive number, was: " + s, e); + } + } + } + + // 1000 is the default fallback + return 1000; + } + + /** + * Gets the maximum validator cache size. + * <p/> + * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_VALIDATOR_CACHE_SIZE}. + * If no property has been set, then it will fallback to return a size of 1000. + * + * @param camelContext the camel context + * @return the maximum cache size + * @throws IllegalArgumentException is thrown if the property is illegal + */ + public static int getMaximumValidatorCacheSize(CamelContext camelContext) throws IllegalArgumentException { + if (camelContext != null) { + String s = camelContext.getGlobalOption(Exchange.MAXIMUM_VALIDATOR_CACHE_SIZE); + if (s != null) { + // we cannot use Camel type converters as they may not be ready this early + try { + Integer size = Integer.valueOf(s); + if (size == null || size <= 0) { + throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_VALIDATOR_CACHE_SIZE + " must be a positive number, was: " + s); + } + return size; + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_VALIDATOR_CACHE_SIZE + " must be a positive number, was: " + s, e); + } + } + } + + // 1000 is the default fallback + return 1000; + } + + /** * Parses the given text and handling property placeholders as well * * @param camelContext the camel context http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/main/resources/org/apache/camel/model/validator/jaxb.index ---------------------------------------------------------------------- diff --git a/camel-core/src/main/resources/org/apache/camel/model/validator/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/validator/jaxb.index new file mode 100644 index 0000000..7cdaef6 --- /dev/null +++ b/camel-core/src/main/resources/org/apache/camel/model/validator/jaxb.index @@ -0,0 +1,21 @@ +## ------------------------------------------------------------------------ +## 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. +## ------------------------------------------------------------------------ +CustomValidatorDefinition +EndpointValidatorDefinition +PredicateValidatorDefinition +ValidatorDefinition +ValidatorsDefinition http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/builder/TransformerBuilderTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/builder/TransformerBuilderTest.java b/camel-core/src/test/java/org/apache/camel/builder/TransformerBuilderTest.java index 9a7e895..1cdd30a 100644 --- a/camel-core/src/test/java/org/apache/camel/builder/TransformerBuilderTest.java +++ b/camel-core/src/test/java/org/apache/camel/builder/TransformerBuilderTest.java @@ -59,9 +59,11 @@ public class TransformerBuilderTest extends TestSupport { @Override public void configure() throws Exception { transformer().fromType("xml:foo").toType("json:bar").withDataFormat(new StringDataFormat()); + from("direct:input").log("test"); } }; ctx.addRoutes(builder); + ctx.start(); Transformer transformer = ctx.resolveTransformer(new DataType("xml:foo"), new DataType("json:bar")); assertNotNull(transformer); assertEquals(DataFormatTransformer.class, transformer.getClass()); @@ -78,10 +80,11 @@ public class TransformerBuilderTest extends TestSupport { @Override public void configure() throws Exception { transformer().fromType("json:foo").toType("xml:bar").withUri("direct:transformer"); - from("direct:transformer"); + from("direct:transformer").log("test"); } }; ctx.addRoutes(builder); + ctx.start(); Transformer transformer = ctx.resolveTransformer(new DataType("json:foo"), new DataType("xml:bar")); assertNotNull(transformer); assertEquals(ProcessorTransformer.class, transformer.getClass()); @@ -100,9 +103,11 @@ public class TransformerBuilderTest extends TestSupport { @Override public void configure() throws Exception { transformer().scheme("other").withJava(MyTransformer.class); + from("direct:input").log("test"); } }; ctx.addRoutes(builder); + ctx.start(); Transformer transformer = ctx.resolveTransformer("other"); assertNotNull(transformer); assertEquals(MyTransformer.class, transformer.getClass()); http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java b/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java index 2bab7f3..40ef701 100644 --- a/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java +++ b/camel-core/src/test/java/org/apache/camel/impl/MultipleLifecycleStrategyTest.java @@ -51,7 +51,7 @@ public class MultipleLifecycleStrategyTest extends TestSupport { context.stop(); List<String> expectedEvents = Arrays.asList("onContextStart", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", - "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onComponentAdd", "onEndpointAdd", "onComponentRemove", "onContextStop"); + "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onServiceAdd", "onComponentAdd", "onEndpointAdd", "onComponentRemove", "onContextStop"); assertEquals(expectedEvents, dummy1.getEvents()); assertEquals(expectedEvents, dummy2.getEvents()); http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorContractTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorContractTest.java b/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorContractTest.java new file mode 100644 index 0000000..8633010 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorContractTest.java @@ -0,0 +1,115 @@ +/** + * 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 java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Converter; +import org.apache.camel.Exchange; +import org.apache.camel.TypeConverters; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.model.DataFormatDefinition; +import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.RouteContext; +import org.junit.Test; + +public class ValidatorContractTest extends ContextTestSupport { + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void testInputTypeOnly() throws Exception { + context.getTypeConverterRegistry().addTypeConverters(new MyTypeConverters()); + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + validator() + .type(A.class) + .withUri("direct:validator"); + from("direct:a") + .inputType(A.class, true) + .to("mock:a"); + from("direct:validator") + .to("mock:validator"); + } + }); + context.start(); + + MockEndpoint mocka = context.getEndpoint("mock:a", MockEndpoint.class); + MockEndpoint mockv = context.getEndpoint("mock:validator", MockEndpoint.class); + mocka.setExpectedCount(1); + mockv.setExpectedCount(1); + Object answer = template.requestBody("direct:a", "foo"); + mocka.assertIsSatisfied(); + mockv.assertIsSatisfied(); + Exchange exa = mocka.getExchanges().get(0); + assertEquals(A.class, exa.getIn().getBody().getClass()); + Exchange exv = mockv.getExchanges().get(0); + assertEquals(A.class, exv.getIn().getBody().getClass()); + assertEquals(A.class, answer.getClass()); + } + + @Test + public void testOutputTypeOnly() throws Exception { + context.getTypeConverterRegistry().addTypeConverters(new MyTypeConverters()); + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + validator() + .type(A.class) + .withUri("direct:validator"); + from("direct:a") + .outputType(A.class, true) + .to("mock:a"); + from("direct:validator") + .to("mock:validator"); + } + }); + context.start(); + + MockEndpoint mocka = context.getEndpoint("mock:a", MockEndpoint.class); + MockEndpoint mockv = context.getEndpoint("mock:validator", MockEndpoint.class); + mocka.setExpectedCount(1); + mockv.setExpectedCount(1); + Object answer = template.requestBody("direct:a", "foo"); + mocka.assertIsSatisfied(); + mockv.assertIsSatisfied(); + Exchange exa = mocka.getExchanges().get(0); + assertEquals("foo", exa.getIn().getBody()); + Exchange exv = mockv.getExchanges().get(0); + assertEquals(A.class, exv.getIn().getBody().getClass()); + assertEquals(A.class, answer.getClass()); + } + + public static class MyTypeConverters implements TypeConverters { + @Converter + public A toA(String in) { + return new A(); + } + } + + public static class A { } +} http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorRouteTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorRouteTest.java b/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorRouteTest.java new file mode 100644 index 0000000..3d3f7f1 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/impl/validator/ValidatorRouteTest.java @@ -0,0 +1,187 @@ +/** + * 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 java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.Map; + +import org.apache.camel.AsyncCallback; +import org.apache.camel.Consumer; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Converter; +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.ExchangePattern; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.TypeConverters; +import org.apache.camel.ValidationException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.impl.DefaultAsyncProducer; +import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.impl.DefaultEndpoint; +import org.apache.camel.impl.DefaultExchange; +import org.apache.camel.model.DataFormatDefinition; +import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.DataType; +import org.apache.camel.spi.RouteContext; +import org.apache.camel.spi.Transformer; +import org.apache.camel.spi.Validator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A ValidatorRouteTest demonstrates contract based declarative validation via Java DSL. + */ +public class ValidatorRouteTest extends ContextTestSupport { + + protected static final Logger LOG = LoggerFactory.getLogger(ValidatorRouteTest.class); + private static final String VALIDATOR_INVOKED = "validator-invoked"; + + public void testPredicateValidator() throws Exception { + Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); + exchange.getIn().setBody("{name:XOrder}"); + Exchange answerEx = template.send("direct:predicate", exchange); + if (answerEx.getException() != null) { + throw answerEx.getException(); + } + assertEquals("{name:XOrderResponse}", answerEx.getOut().getBody(String.class)); + } + + public void testEndpointValidator() throws Exception { + Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); + exchange.getIn().setBody("<XOrder/>"); + Exchange answerEx = template.send("direct:endpoint", exchange); + if (answerEx.getException() != null) { + throw answerEx.getException(); + } + assertEquals("<XOrderResponse/>", answerEx.getOut().getBody(String.class)); + assertEquals(MyXmlEndpoint.class, answerEx.getProperty(VALIDATOR_INVOKED)); + } + + public void testCustomValidator() throws Exception { + Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); + exchange.getIn().setBody("name=XOrder"); + Exchange answerEx = template.send("direct:custom", exchange); + if (answerEx.getException() != null) { + throw answerEx.getException(); + } + assertEquals("name=XOrderResponse", answerEx.getOut().getBody(String.class)); + assertEquals(OtherXOrderResponseValidator.class, answerEx.getProperty(VALIDATOR_INVOKED)); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + + validator() + .type("json") + .withExpression(bodyAs(String.class).contains("{name:XOrder}")); + from("direct:predicate") + .inputType("json:JsonXOrder", true) + .outputType("json:JsonXOrderResponse") + .setBody(simple("{name:XOrderResponse}")) + .setProperty(Exchange.OUTPUT_TYPE, constant("json:JsonXOrderResponse")); + + context.addComponent("myxml", new MyXmlComponent()); + validator() + .type("xml:XmlXOrderResponse") + .withUri("myxml:endpoint"); + from("direct:endpoint") + .inputType("xml:XmlXOrder") + .outputType("xml:XmlXOrderResponse", true) + .validate(exchangeProperty(VALIDATOR_INVOKED).isNull()) + .setBody(simple("<XOrderResponse/>")) + .setProperty(Exchange.OUTPUT_TYPE, constant("xml:XmlXOrderResponse")); + + validator() + .type("other:OtherXOrder") + .withJava(OtherXOrderValidator.class); + validator() + .type("other:OtherXOrderResponse") + .withJava(OtherXOrderResponseValidator.class); + from("direct:custom") + .inputType("other:OtherXOrder", true) + .outputType("other:OtherXOrderResponse", true) + .validate(exchangeProperty(VALIDATOR_INVOKED).isEqualTo(OtherXOrderValidator.class)) + .setBody(simple("name=XOrderResponse")) + .setProperty(Exchange.OUTPUT_TYPE, constant("other:OtherXOrderResponse")); + } + }; + } + + public static class MyXmlComponent extends DefaultComponent { + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + return new MyXmlEndpoint(); + } + + } + + public static class MyXmlEndpoint extends DefaultEndpoint { + @Override + public Producer createProducer() throws Exception { + return new DefaultAsyncProducer(this) { + @Override + public boolean process(Exchange exchange, AsyncCallback callback) { + exchange.setProperty(VALIDATOR_INVOKED, MyXmlEndpoint.class); + assertEquals("<XOrderResponse/>", exchange.getIn().getBody()); + callback.done(true); + return true; + } + }; + } + @Override + public Consumer createConsumer(Processor processor) throws Exception { + return null; + } + @Override + public boolean isSingleton() { + return false; + } + @Override + protected String createEndpointUri() { + return "myxml:endpoint"; + } + } + + public static class OtherXOrderValidator extends Validator { + @Override + public void validate(Message message, DataType type) throws ValidationException { + message.getExchange().setProperty(VALIDATOR_INVOKED, OtherXOrderValidator.class); + assertEquals("name=XOrder", message.getBody()); + LOG.info("Java validation: other XOrder"); + } + } + + public static class OtherXOrderResponseValidator extends Validator { + @Override + public void validate(Message message, DataType type) throws ValidationException { + message.getExchange().setProperty(VALIDATOR_INVOKED, OtherXOrderResponseValidator.class); + assertEquals("name=XOrderResponse", message.getBody()); + LOG.info("Java validation: other XOrderResponse"); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/management/ManagedNonManagedServiceTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedNonManagedServiceTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedNonManagedServiceTest.java index c3fcaad..b24957b 100644 --- a/camel-core/src/test/java/org/apache/camel/management/ManagedNonManagedServiceTest.java +++ b/camel-core/src/test/java/org/apache/camel/management/ManagedNonManagedServiceTest.java @@ -48,7 +48,7 @@ public class ManagedNonManagedServiceTest extends ManagementTestSupport { MBeanServer mbeanServer = getMBeanServer(); Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=services,*"), null); - assertEquals(10, set.size()); + assertEquals(11, set.size()); } public void testNonManagedService() throws Exception { @@ -69,7 +69,7 @@ public class ManagedNonManagedServiceTest extends ManagementTestSupport { MBeanServer mbeanServer = getMBeanServer(); Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=services,*"), null); - assertEquals(9, set.size()); + assertEquals(10, set.size()); } @Override http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java index 55bd69f..b2b58e5 100644 --- a/camel-core/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java +++ b/camel-core/src/test/java/org/apache/camel/management/ManagedProducerRouteAddRemoveRegisterAlwaysTest.java @@ -29,7 +29,7 @@ import org.apache.camel.component.mock.MockEndpoint; */ public class ManagedProducerRouteAddRemoveRegisterAlwaysTest extends ManagementTestSupport { - private int services = 9; + private int services = 10; @Override protected CamelContext createCamelContext() throws Exception { http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java index f00528f..f4804a6 100644 --- a/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java +++ b/camel-core/src/test/java/org/apache/camel/management/ManagedRouteAddRemoveTest.java @@ -33,7 +33,7 @@ import org.apache.camel.component.mock.MockEndpoint; */ public class ManagedRouteAddRemoveTest extends ManagementTestSupport { - private int services = 9; + private int services = 10; @Override protected RouteBuilder createRouteBuilder() throws Exception { http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/management/ManagedTransformerRegistryTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedTransformerRegistryTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedTransformerRegistryTest.java index 96918a6..e26d3c8 100644 --- a/camel-core/src/test/java/org/apache/camel/management/ManagedTransformerRegistryTest.java +++ b/camel-core/src/test/java/org/apache/camel/management/ManagedTransformerRegistryTest.java @@ -33,9 +33,6 @@ import org.apache.camel.spi.Transformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** - * @version - */ public class ManagedTransformerRegistryTest extends ManagementTestSupport { private static final Logger LOG = LoggerFactory.getLogger(ManagedTransformerRegistryTest.class); @@ -51,11 +48,6 @@ public class ManagedTransformerRegistryTest extends ManagementTestSupport { assertMockEndpointsSatisfied(); - // resolve transformers explicitly as the route doesn't actually use them - context.resolveTransformer(new DataType("xml:foo"), new DataType("json:bar")); - context.resolveTransformer(new DataType(ManagedTransformerRegistryTest.class), new DataType("xml:test")); - context.resolveTransformer("custom"); - // get the stats for the route MBeanServer mbeanServer = getMBeanServer(); Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=services,*"), null); http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/camel-core/src/test/java/org/apache/camel/management/ManagedValidatorRegistryTest.java ---------------------------------------------------------------------- diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedValidatorRegistryTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedValidatorRegistryTest.java new file mode 100644 index 0000000..7ceb111 --- /dev/null +++ b/camel-core/src/test/java/org/apache/camel/management/ManagedValidatorRegistryTest.java @@ -0,0 +1,134 @@ +/** + * 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.management; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularData; + +import org.apache.camel.Message; +import org.apache.camel.ValidationException; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.dataformat.StringDataFormat; +import org.apache.camel.spi.DataType; +import org.apache.camel.spi.Validator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ManagedValidatorRegistryTest extends ManagementTestSupport { + private static final Logger LOG = LoggerFactory.getLogger(ManagedValidatorRegistryTest.class); + + public void testManageValidatorRegistry() throws Exception { + // JMX tests dont work well on AIX CI servers (hangs them) + if (isPlatform("aix")) { + return; + } + + getMockEndpoint("mock:result").expectedMessageCount(1); + + template.sendBody("direct:start", "Hello World"); + + assertMockEndpointsSatisfied(); + + // get the stats for the route + MBeanServer mbeanServer = getMBeanServer(); + Set<ObjectName> set = mbeanServer.queryNames(new ObjectName("*:type=services,*"), null); + List<ObjectName> list = new ArrayList<ObjectName>(set); + ObjectName on = null; + for (ObjectName name : list) { + if (name.getCanonicalName().contains("DefaultValidatorRegistry")) { + on = name; + break; + } + } + + assertNotNull("Should have found ValidatorRegistry", on); + + Integer max = (Integer) mbeanServer.getAttribute(on, "MaximumCacheSize"); + assertEquals(1000, max.intValue()); + + Integer current = (Integer) mbeanServer.getAttribute(on, "Size"); + assertEquals(3, current.intValue()); + + current = (Integer) mbeanServer.getAttribute(on, "StaticSize"); + assertEquals(0, current.intValue()); + + current = (Integer) mbeanServer.getAttribute(on, "DynamicSize"); + assertEquals(3, current.intValue()); + + String source = (String) mbeanServer.getAttribute(on, "Source"); + assertTrue(source.startsWith("ValidatorRegistry")); + assertTrue(source.endsWith("capacity: 1000")); + + + TabularData data = (TabularData) mbeanServer.invoke(on, "listValidators", null, null); + for (Object row : data.values()) { + CompositeData composite = (CompositeData)row; + String type = (String)composite.get("type"); + String description = (String)composite.get("description"); + boolean isStatic = (boolean)composite.get("static"); + boolean isDynamic = (boolean)composite.get("dynamic"); + LOG.info("[{}][{}][{}][{}]", type, isStatic, isDynamic, description); + if (description.startsWith("ProcessorValidator")) { + if (description.contains("direct://transformer")) { + assertEquals("xml:foo", type); + } else if (description.contains("validate(simple{${body}} is not null")) { + assertEquals("json:test", type); + } else { + fail("Unexpected validator:" + description); + } + } else if (description.startsWith("MyValidator")) { + assertEquals("custom", type); + } else { + fail("Unexpected validator:" + description); + } + } + assertEquals(3, data.size()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + validator() + .type("xml:foo") + .withUri("direct:transformer"); + validator() + .type("json:test") + .withExpression(body().isNotNull()); + validator() + .type("custom") + .withJava(MyValidator.class); + + from("direct:start").to("mock:result"); + } + }; + } + + public static class MyValidator extends Validator { + @Override + public void validate(Message message, DataType type) throws ValidationException { + // empty + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java index 717665a..31b54de 100644 --- a/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java +++ b/components/camel-blueprint/src/main/java/org/apache/camel/blueprint/CamelContextFactoryBean.java @@ -64,6 +64,7 @@ import org.apache.camel.model.dataformat.DataFormatsDefinition; import org.apache.camel.model.rest.RestConfigurationDefinition; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.transformer.TransformersDefinition; +import org.apache.camel.model.validator.ValidatorsDefinition; import org.apache.camel.spi.PackageScanFilter; import org.apache.camel.spi.Registry; import org.osgi.framework.BundleContext; @@ -177,6 +178,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Blu private DataFormatsDefinition dataFormats; @XmlElement(name = "transformers") private TransformersDefinition transformers; + @XmlElement(name = "validators") + private ValidatorsDefinition validators; @XmlElement(name = "redeliveryPolicyProfile") private List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies; @XmlElement(name = "onException") @@ -696,6 +699,14 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Blu return transformers; } + public void setValidators(ValidatorsDefinition validators) { + this.validators = validators; + } + + public ValidatorsDefinition getValidators() { + return validators; + } + public List<OnExceptionDefinition> getOnExceptions() { return onExceptions; } http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java index d5336ed..d91605b 100644 --- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java +++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/xml/CamelContextFactoryBean.java @@ -64,6 +64,7 @@ import org.apache.camel.model.dataformat.DataFormatsDefinition; import org.apache.camel.model.rest.RestConfigurationDefinition; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.transformer.TransformersDefinition; +import org.apache.camel.model.validator.ValidatorsDefinition; import org.apache.camel.spi.PackageScanFilter; @XmlRootElement(name = "camelContext") @@ -208,6 +209,9 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def @XmlElement(name = "transformers") private TransformersDefinition transformers; + @XmlElement(name = "validators") + private ValidatorsDefinition validators; + @XmlElement(name = "redeliveryPolicyProfile") private List<RedeliveryPolicyFactoryBean> redeliveryPolicies; @@ -702,6 +706,14 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Def this.transformers = transformers; } + public ValidatorsDefinition getValidators() { + return validators; + } + + public void setValidators(ValidatorsDefinition validators) { + this.validators = validators; + } + public List<OnExceptionDefinition> getOnExceptions() { return onExceptions; } http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java index 0c2c8b9..1b89a39 100644 --- a/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java +++ b/components/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java @@ -75,6 +75,7 @@ import org.apache.camel.model.rest.RestConfigurationDefinition; import org.apache.camel.model.rest.RestContainer; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.transformer.TransformersDefinition; +import org.apache.camel.model.validator.ValidatorsDefinition; import org.apache.camel.processor.interceptor.BacklogTracer; import org.apache.camel.processor.interceptor.HandleFault; import org.apache.camel.processor.interceptor.TraceFormatter; @@ -776,6 +777,8 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex public abstract TransformersDefinition getTransformers(); + public abstract ValidatorsDefinition getValidators(); + public abstract List<OnExceptionDefinition> getOnExceptions(); public abstract List<OnCompletionDefinition> getOnCompletions(); @@ -858,7 +861,10 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex ctx.setDataFormats(getDataFormats().asMap()); } if (getTransformers() != null) { - ctx.setTransformers(getTransformers().getTransforms()); + ctx.setTransformers(getTransformers().getTransformers()); + } + if (getValidators() != null) { + ctx.setValidators(getValidators().getValidators()); } if (getTypeConverterStatisticsEnabled() != null) { ctx.setTypeConverterStatisticsEnabled(getTypeConverterStatisticsEnabled()); http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java index 6c2f2d0..e0a3f07 100644 --- a/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java +++ b/components/camel-spring/src/main/java/org/apache/camel/spring/CamelContextFactoryBean.java @@ -63,6 +63,7 @@ import org.apache.camel.model.dataformat.DataFormatsDefinition; import org.apache.camel.model.rest.RestConfigurationDefinition; import org.apache.camel.model.rest.RestDefinition; import org.apache.camel.model.transformer.TransformersDefinition; +import org.apache.camel.model.validator.ValidatorsDefinition; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.PackageScanFilter; import org.apache.camel.spi.Registry; @@ -186,6 +187,8 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr private DataFormatsDefinition dataFormats; @XmlElement(name = "transformers") private TransformersDefinition transformers; + @XmlElement(name = "validators") + private ValidatorsDefinition validators; @XmlElement(name = "redeliveryPolicyProfile") private List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies; @XmlElement(name = "onException") @@ -908,6 +911,17 @@ public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<Spr } /** + * Configuration of validators. + */ + public void setValidators(ValidatorsDefinition validators) { + this.validators = validators; + } + + public ValidatorsDefinition getValidators() { + return validators; + } + + /** * Configuration of redelivery settings. */ public void setRedeliveryPolicies(List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies) { http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java index e0ef322..04737cf 100644 --- a/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java +++ b/components/camel-spring/src/main/java/org/apache/camel/spring/handler/CamelNamespaceHandler.java @@ -384,6 +384,7 @@ public class CamelNamespaceHandler extends NamespaceHandlerSupport { builder.addPropertyValue("interceptSendToEndpoints", factoryBean.getInterceptSendToEndpoints()); builder.addPropertyValue("dataFormats", factoryBean.getDataFormats()); builder.addPropertyValue("transformers", factoryBean.getTransformers()); + builder.addPropertyValue("validators", factoryBean.getValidators()); builder.addPropertyValue("onCompletions", factoryBean.getOnCompletions()); builder.addPropertyValue("onExceptions", factoryBean.getOnExceptions()); builder.addPropertyValue("builderRefs", factoryBean.getBuilderRefs()); http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-spring/src/test/java/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.java new file mode 100644 index 0000000..56cb106 --- /dev/null +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.java @@ -0,0 +1,35 @@ +/** + * 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.spring.impl.validator; + +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.impl.validator.ValidatorRouteTest; + +import static org.apache.camel.spring.processor.SpringTestHelper.createSpringCamelContext; + +/** + * A SpringValidatorRouteTest demonstrates contract based declarative validation via Spring DSL. + */ +public class SpringValidatorRouteTest extends ValidatorRouteTest { + + protected CamelContext createCamelContext() throws Exception { + return createSpringCamelContext(this, "org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.xml"); + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.xml new file mode 100644 index 0000000..4e6c090 --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/impl/validator/SpringValidatorRouteTest.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + "> + + <bean id="myxml" class="org.apache.camel.impl.validator.ValidatorRouteTest.MyXmlComponent"/> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + + <validators> + <predicateValidator type="json"><simple>${body} contains '{name:XOrder'</simple></predicateValidator> + <endpointValidator type="xml:XmlXOrderResponse" uri="myxml:endpoint"/> + <customValidator type="other:OtherXOrder" className="org.apache.camel.impl.validator.ValidatorRouteTest$OtherXOrderValidator"/> + <customValidator type="other:OtherXOrderResponse" className="org.apache.camel.impl.validator.ValidatorRouteTest$OtherXOrderResponseValidator"/> + </validators> + + <route> + <from uri="direct:predicate"/> + <inputType urn="json:JsonXOrder" validate="true"/> + <outputType urn="json:JsonXOrderResponse"/> + <setBody><constant>{name:XOrderResponse}</constant></setBody> + <setProperty propertyName="CamelOutputType"><constant>json:JsonXOrderResponse</constant></setProperty> + </route> + + <route> + <from uri="direct:endpoint"/> + <inputType urn="xml:XmlXOrder"/> + <outputType urn="xml:XmlXOrderResponse" validate="true"/> + <validate> + <simple>${exchangeProperty.validator-invoked} == null</simple> + </validate> + <setBody><constant><XOrderResponse/></constant></setBody> + <setProperty propertyName="CamelOutputType"><constant>xml:XmlXOrderResponse</constant></setProperty> + </route> + + <route> + <from uri="direct:custom"/> + <inputType urn="other:OtherXOrder" validate="true"/> + <outputType urn="other:OtherXOrderResponse" validate="true"/> + <validate> + <simple>${exchangeProperty.validator-invoked} == 'org.apache.camel.impl.validator.ValidatorRouteTest$OtherXOrderValidator'</simple> + </validate> + <setBody><constant>name=XOrderResponse</constant></setBody> + <setProperty propertyName="CamelOutputType"><constant>other:OtherXOrderResponse</constant></setProperty> + </route> + + </camelContext> + +</beans>
