CAMEL-8799: Make it possible for JsonPath to suppress PathNotFoundException. CAMEL-8820: Allow to do post logic when creating expression/predicate from routes
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/2a285211 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/2a285211 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/2a285211 Branch: refs/heads/master Commit: 2a2852117c094f2bc2778f5e9a8a404e2e395e6f Parents: 9732938 Author: Claus Ibsen <davscl...@apache.org> Authored: Sat May 30 11:27:19 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sat May 30 11:27:19 2015 +0200 ---------------------------------------------------------------------- .../apache/camel/AfterPropertiesConfigured.java | 32 ++++++++++ .../apache/camel/builder/ExpressionClause.java | 27 +++++++++ .../model/language/ExpressionDefinition.java | 13 ++++ .../language/NamespaceAwareExpression.java | 2 + .../model/language/XMLTokenizerExpression.java | 4 +- .../camel/model/language/XPathExpression.java | 1 - .../camel/model/language/XQueryExpression.java | 4 +- .../camel/jsonpath/JsonPathExpression.java | 26 ++++---- .../apache/camel/jsonpath/JsonPathLanguage.java | 15 ++++- .../camel/jsonpath/JsonPathSuppressTest.java | 63 ++++++++++++++++++++ .../jsonpath/SpringJsonPathSuppressTest.java | 55 +++++++++++++++++ .../jsonpath/SpringJsonPathSuppressTest.xml | 39 ++++++++++++ 12 files changed, 264 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/AfterPropertiesConfigured.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/AfterPropertiesConfigured.java b/camel-core/src/main/java/org/apache/camel/AfterPropertiesConfigured.java new file mode 100644 index 0000000..5b95ceb --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/AfterPropertiesConfigured.java @@ -0,0 +1,32 @@ +/** + * 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; + +/** + * To perform optional initialization on an element after its properties has been configured. + */ +public interface AfterPropertiesConfigured { + + /** + * Callback invoked after the element have configured its properties. + * <p/> + * This allows to perform any post init work. + * + * @param camelContext the Camel Context + */ + void afterPropertiesConfigured(CamelContext camelContext); +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java index 2fc59bc..85edb58 100644 --- a/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java +++ b/camel-core/src/main/java/org/apache/camel/builder/ExpressionClause.java @@ -304,6 +304,19 @@ public class ExpressionClause<T> extends ExpressionDefinition { * expression</a> * * @param text the expression to be evaluated + * @param suppressExceptions whether to suppress exceptions such as PathNotFoundException + * @return the builder to continue processing the DSL + */ + public T jsonpath(String text, boolean suppressExceptions) { + return delegate.jsonpath(text, suppressExceptions); + } + + /** + * Evaluates a <a + * href="http://camel.apache.org/jsonpath.html">Json Path + * expression</a> + * + * @param text the expression to be evaluated * @param resultType the return type expected by the expression * @return the builder to continue processing the DSL */ @@ -312,6 +325,20 @@ public class ExpressionClause<T> extends ExpressionDefinition { } /** + * Evaluates a <a + * href="http://camel.apache.org/jsonpath.html">Json Path + * expression</a> + * + * @param text the expression to be evaluated + * @param suppressExceptions whether to suppress exceptions such as PathNotFoundException + * @param resultType the return type expected by the expression + * @return the builder to continue processing the DSL + */ + public T jsonpath(String text, boolean suppressExceptions, Class<?> resultType) { + return delegate.jsonpath(text, suppressExceptions, resultType); + } + + /** * Evaluates a <a href="http://commons.apache.org/jxpath/">JXPath expression</a> * * @param text the expression to be evaluated http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java b/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java index 2a0b294..86ea52e 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/ExpressionDefinition.java @@ -28,6 +28,7 @@ import javax.xml.bind.annotation.XmlValue; import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import org.apache.camel.AfterPropertiesConfigured; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; @@ -265,10 +266,22 @@ public class ExpressionDefinition implements Expression, Predicate { this.expressionType = expressionType; } + @SuppressWarnings("unchecked") protected void configurePredicate(CamelContext camelContext, Predicate predicate) { + // allows to perform additional logic after the properties has been configured which may be needed + // in the various camel components outside camel-core + if (predicate instanceof AfterPropertiesConfigured) { + ((AfterPropertiesConfigured) predicate).afterPropertiesConfigured(camelContext); + } } + @SuppressWarnings("unchecked") protected void configureExpression(CamelContext camelContext, Expression expression) { + // allows to perform additional logic after the properties has been configured which may be needed + // in the various camel components outside camel-core + if (expression instanceof AfterPropertiesConfigured) { + ((AfterPropertiesConfigured) expression).afterPropertiesConfigured(camelContext); + } } /** http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/model/language/NamespaceAwareExpression.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/NamespaceAwareExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/NamespaceAwareExpression.java index f3d9eb6..c549e16 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/NamespaceAwareExpression.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/NamespaceAwareExpression.java @@ -61,11 +61,13 @@ public abstract class NamespaceAwareExpression extends ExpressionDefinition impl @Override protected void configureExpression(CamelContext camelContext, Expression expression) { configureNamespaceAware(expression); + super.configureExpression(camelContext, expression); } @Override protected void configurePredicate(CamelContext camelContext, Predicate predicate) { configureNamespaceAware(predicate); + super.configurePredicate(camelContext, predicate); } protected void configureNamespaceAware(Object builder) { http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java index d85e79d..8d9c266 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/XMLTokenizerExpression.java @@ -96,7 +96,6 @@ public class XMLTokenizerExpression extends NamespaceAwareExpression { @Override protected void configureExpression(CamelContext camelContext, Expression expression) { - super.configureExpression(camelContext, expression); if (headerName != null) { setProperty(expression, "headerName", headerName); } @@ -106,11 +105,11 @@ public class XMLTokenizerExpression extends NamespaceAwareExpression { if (group != null) { setProperty(expression, "group", group); } + super.configureExpression(camelContext, expression); } @Override protected void configurePredicate(CamelContext camelContext, Predicate predicate) { - super.configurePredicate(camelContext, predicate); if (headerName != null) { setProperty(predicate, "headerName", headerName); } @@ -120,6 +119,7 @@ public class XMLTokenizerExpression extends NamespaceAwareExpression { if (group != null) { setProperty(predicate, "group", group); } + super.configurePredicate(camelContext, predicate); } @Override http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/model/language/XPathExpression.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/XPathExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/XPathExpression.java index 4a01417..609a9e4 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/XPathExpression.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/XPathExpression.java @@ -234,7 +234,6 @@ public class XPathExpression extends NamespaceAwareExpression { } // moved the super configuration to the bottom so that the namespace init picks up the newly set XPath Factory super.configureExpression(camelContext, expression); - } @Override http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/camel-core/src/main/java/org/apache/camel/model/language/XQueryExpression.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/language/XQueryExpression.java b/camel-core/src/main/java/org/apache/camel/model/language/XQueryExpression.java index 763dfc8..0513d8e 100644 --- a/camel-core/src/main/java/org/apache/camel/model/language/XQueryExpression.java +++ b/camel-core/src/main/java/org/apache/camel/model/language/XQueryExpression.java @@ -107,24 +107,24 @@ public class XQueryExpression extends NamespaceAwareExpression { @Override protected void configureExpression(CamelContext camelContext, Expression expression) { - super.configureExpression(camelContext, expression); if (resultType != null) { setProperty(expression, "resultType", resultType); } if (ObjectHelper.isNotEmpty(getHeaderName())) { setProperty(expression, "headerName", getHeaderName()); } + super.configureExpression(camelContext, expression); } @Override protected void configurePredicate(CamelContext camelContext, Predicate predicate) { - super.configurePredicate(camelContext, predicate); if (resultType != null) { setProperty(predicate, "resultType", resultType); } if (ObjectHelper.isNotEmpty(getHeaderName())) { setProperty(predicate, "headerName", getHeaderName()); } + super.configurePredicate(camelContext, predicate); } } http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java index 3f84938..5a8bbe6 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathExpression.java @@ -17,12 +17,14 @@ package org.apache.camel.jsonpath; import com.jayway.jsonpath.Option; +import org.apache.camel.AfterPropertiesConfigured; +import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.ExpressionEvaluationException; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.support.ExpressionAdapter; -public class JsonPathExpression extends ExpressionAdapter { +public class JsonPathExpression extends ExpressionAdapter implements AfterPropertiesConfigured { private final String expression; private JsonPathEngine engine; @@ -35,14 +37,6 @@ public class JsonPathExpression extends ExpressionAdapter { this.expression = expression; } - public void init() { - try { - engine = new JsonPathEngine(expression, suppressExceptions, options); - } catch (Exception e) { - throw new ExpressionIllegalSyntaxException(expression, e); - } - } - public Class<?> getResultType() { return resultType; } @@ -91,6 +85,19 @@ public class JsonPathExpression extends ExpressionAdapter { } @Override + public void afterPropertiesConfigured(CamelContext camelContext) { + init(); + } + + public void init() { + try { + engine = new JsonPathEngine(expression, suppressExceptions, options); + } catch (Exception e) { + throw new ExpressionIllegalSyntaxException(expression, e); + } + } + + @Override public String toString() { return "jsonpath[" + expression + "]"; } @@ -98,5 +105,4 @@ public class JsonPathExpression extends ExpressionAdapter { private Object evaluateJsonPath(Exchange exchange, JsonPathEngine engine) throws Exception { return engine.read(exchange); } - } http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java index 7f25e70..297823b 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java @@ -24,6 +24,7 @@ import org.apache.camel.support.LanguageSupport; public class JsonPathLanguage extends LanguageSupport { private Class<?> resultType; + private boolean suppressExceptions; private Option[] options; public Class<?> getResultType() { @@ -34,6 +35,14 @@ public class JsonPathLanguage extends LanguageSupport { this.resultType = resultType; } + public boolean isSuppressExceptions() { + return suppressExceptions; + } + + public void setSuppressExceptions(boolean suppressExceptions) { + this.suppressExceptions = suppressExceptions; + } + public Option[] getOptions() { return options; } @@ -50,8 +59,9 @@ public class JsonPathLanguage extends LanguageSupport { public Predicate createPredicate(final String predicate) { JsonPathExpression answer = new JsonPathExpression(predicate); answer.setResultType(resultType); + answer.setSuppressExceptions(suppressExceptions); answer.setOptions(options); - answer.init(); + answer.afterPropertiesConfigured(getCamelContext()); return answer; } @@ -59,8 +69,9 @@ public class JsonPathLanguage extends LanguageSupport { public Expression createExpression(final String expression) { JsonPathExpression answer = new JsonPathExpression(expression); answer.setResultType(resultType); + answer.setSuppressExceptions(suppressExceptions); answer.setOptions(options); - answer.init(); + answer.afterPropertiesConfigured(getCamelContext()); return answer; } http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSuppressTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSuppressTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSuppressTest.java new file mode 100644 index 0000000..8a7d9fb --- /dev/null +++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathSuppressTest.java @@ -0,0 +1,63 @@ +/** + * 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.jsonpath; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class JsonPathSuppressTest extends CamelTestSupport { + + @Test + public void testMiddle() throws Exception { + String json = "{\"person\" : {\"firstname\" : \"foo\", \"middlename\" : \"foo2\", \"lastname\" : \"bar\"}}"; + + getMockEndpoint("mock:middle").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBody("direct:start", json); + + assertMockEndpointsSatisfied(); + } + + @Test + public void testNoMiddle() throws Exception { + String json = "{\"person\" : {\"firstname\" : \"foo\", \"lastname\" : \"bar\"}}"; + + getMockEndpoint("mock:middle").expectedMessageCount(0); + getMockEndpoint("mock:other").expectedMessageCount(1); + + template.sendBody("direct:start", json); + + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start") + .choice() + .when().jsonpath("person.middlename", true) + .to("mock:middle") + .otherwise() + .to("mock:other"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.java new file mode 100644 index 0000000..4ca789d --- /dev/null +++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.java @@ -0,0 +1,55 @@ +/** + * 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.jsonpath; + +import org.apache.camel.test.spring.CamelSpringTestSupport; +import org.junit.Test; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class SpringJsonPathSuppressTest extends CamelSpringTestSupport { + + @Override + protected AbstractApplicationContext createApplicationContext() { + return new ClassPathXmlApplicationContext("org/apache/camel/jsonpath/SpringJsonPathSuppressTest.xml"); + } + + @Test + public void testMiddle() throws Exception { + String json = "{\"person\" : {\"firstname\" : \"foo\", \"middlename\" : \"foo2\", \"lastname\" : \"bar\"}}"; + + getMockEndpoint("mock:middle").expectedMessageCount(1); + getMockEndpoint("mock:other").expectedMessageCount(0); + + template.sendBody("direct:start", json); + + assertMockEndpointsSatisfied(); + } + + @Test + public void testNoMiddle() throws Exception { + String json = "{\"person\" : {\"firstname\" : \"foo\", \"lastname\" : \"bar\"}}"; + + getMockEndpoint("mock:middle").expectedMessageCount(0); + getMockEndpoint("mock:other").expectedMessageCount(1); + + template.sendBody("direct:start", json); + + assertMockEndpointsSatisfied(); + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/2a285211/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.xml b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.xml new file mode 100644 index 0000000..be89973 --- /dev/null +++ b/components/camel-jsonpath/src/test/resources/org/apache/camel/jsonpath/SpringJsonPathSuppressTest.xml @@ -0,0 +1,39 @@ +<?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://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + + <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> + <route> + <from uri="direct:start"/> + <choice> + <when> + <jsonpath suppressExceptions="true">person.middlename</jsonpath> + <to uri="mock:middle"/> + </when> + <otherwise> + <to uri="mock:other"/> + </otherwise> + </choice> + </route> + </camelContext> + +</beans> \ No newline at end of file