CAMEL-8799: Make it possible for JsonPath to suppress PathNotFoundException
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/e6fb2d5d Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/e6fb2d5d Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/e6fb2d5d Branch: refs/heads/master Commit: e6fb2d5d8f0111292bfa318b20165677032568ad Parents: ac67a65 Author: Claus Ibsen <davscl...@apache.org> Authored: Sat May 30 10:04:54 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Sat May 30 10:06:07 2015 +0200 ---------------------------------------------------------------------- .../org/apache/camel/jsonpath/JsonPath.java | 9 ++- .../JsonPathAnnotationExpressionFactory.java | 50 ++++++++++++++++ .../apache/camel/jsonpath/JsonPathEngine.java | 23 ++++--- .../camel/jsonpath/JsonPathExpression.java | 18 +++++- .../apache/camel/jsonpath/JsonPathLanguage.java | 8 ++- .../camel/jsonpath/JsonPathBeanOptionTest.java | 63 ++++++++++++++++++++ .../apache/camel/jsonpath/JsonPathBeanTest.java | 10 +++- 7 files changed, 164 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPath.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPath.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPath.java index 354875c..eae308d 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPath.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPath.java @@ -22,6 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import com.jayway.jsonpath.Option; import org.apache.camel.language.LanguageAnnotation; /** @@ -34,7 +35,13 @@ import org.apache.camel.language.LanguageAnnotation; @Retention(RetentionPolicy.RUNTIME) @Documented @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) -@LanguageAnnotation(language = "jsonpath") +@LanguageAnnotation(language = "jsonpath", factory = JsonPathAnnotationExpressionFactory.class) public @interface JsonPath { + String value(); + + /** + * To configure the json path options to use + */ + Option[] options() default {}; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAnnotationExpressionFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAnnotationExpressionFactory.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAnnotationExpressionFactory.java new file mode 100644 index 0000000..b56257a --- /dev/null +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathAnnotationExpressionFactory.java @@ -0,0 +1,50 @@ +/** + * 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 java.lang.annotation.Annotation; + +import com.jayway.jsonpath.Option; +import org.apache.camel.CamelContext; +import org.apache.camel.Expression; +import org.apache.camel.component.bean.DefaultAnnotationExpressionFactory; +import org.apache.camel.language.LanguageAnnotation; + +public class JsonPathAnnotationExpressionFactory extends DefaultAnnotationExpressionFactory { + + @Override + public Expression createExpression(CamelContext camelContext, Annotation annotation, + LanguageAnnotation languageAnnotation, Class<?> expressionReturnType) { + + String expression = getExpressionFromAnnotation(annotation); + JsonPathExpression answer = new JsonPathExpression(expression); + + if (expressionReturnType != null) { + answer.setResultType(expressionReturnType); + } + + if (annotation instanceof JsonPath) { + JsonPath jsonPathAnnotation = (JsonPath) annotation; + Option[] options = jsonPathAnnotation.options(); + answer.setOptions(options); + } + + answer.init(); + return answer; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java index 6977108..5ed84b4 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java @@ -27,7 +27,6 @@ import com.jayway.jsonpath.Configuration.Defaults; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Option; import com.jayway.jsonpath.internal.DefaultsImpl; - import org.apache.camel.Exchange; import org.apache.camel.InvalidPayloadException; import org.apache.camel.NoTypeConversionAvailableException; @@ -42,7 +41,13 @@ public class JsonPathEngine { public JsonPathEngine(String expression) { Defaults defaults = DefaultsImpl.INSTANCE; - this.configuration = Configuration.builder().jsonProvider(defaults.jsonProvider()).options(Option.SUPPRESS_EXCEPTIONS).build(); + this.configuration = Configuration.builder().jsonProvider(defaults.jsonProvider()).build(); + this.path = JsonPath.compile(expression); + } + + public JsonPathEngine(String expression, Option[] options) { + Defaults defaults = DefaultsImpl.INSTANCE; + this.configuration = Configuration.builder().jsonProvider(defaults.jsonProvider()).options(options).build(); this.path = JsonPath.compile(expression); } @@ -51,26 +56,26 @@ public class JsonPathEngine { if (json instanceof GenericFile) { try { - json = GenericFileConverter.genericFileToInputStream((GenericFile<?>)json, exchange); + json = GenericFileConverter.genericFileToInputStream((GenericFile<?>) json, exchange); } catch (NoTypeConversionAvailableException e) { - json = ((WrappedFile<?>)json).getFile(); + json = ((WrappedFile<?>) json).getFile(); } } else if (json instanceof WrappedFile) { - json = ((WrappedFile<?>)json).getFile(); + json = ((WrappedFile<?>) json).getFile(); } // the message body type should use the suitable read method if (json instanceof String) { - String str = (String)json; + String str = (String) json; return path.read(str, configuration); } else if (json instanceof InputStream) { - InputStream is = (InputStream)json; + InputStream is = (InputStream) json; return path.read(is, Charset.defaultCharset().displayName(), configuration); } else if (json instanceof File) { - File file = (File)json; + File file = (File) json; return path.read(file, configuration); } else if (json instanceof URL) { - URL url = (URL)json; + URL url = (URL) json; return path.read(url, configuration); } http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/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 5a8ee70..d4fa8b3 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 @@ -16,6 +16,7 @@ */ package org.apache.camel.jsonpath; +import com.jayway.jsonpath.Option; import org.apache.camel.Exchange; import org.apache.camel.ExpressionEvaluationException; import org.apache.camel.ExpressionIllegalSyntaxException; @@ -24,13 +25,18 @@ import org.apache.camel.support.ExpressionAdapter; public class JsonPathExpression extends ExpressionAdapter { private final String expression; + private JsonPathEngine engine; + private Class<?> resultType; - private final JsonPathEngine engine; + private Option[] options; public JsonPathExpression(String expression) { this.expression = expression; + } + + public void init() { try { - engine = new JsonPathEngine(expression); + engine = new JsonPathEngine(expression, options); } catch (Exception e) { throw new ExpressionIllegalSyntaxException(expression, e); } @@ -44,6 +50,14 @@ public class JsonPathExpression extends ExpressionAdapter { this.resultType = resultType; } + public Option[] getOptions() { + return options; + } + + public void setOptions(Option[] options) { + this.options = options; + } + @Override public Object evaluate(Exchange exchange) { try { http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/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 e30ad8e..8eb78db 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,12 +24,16 @@ public class JsonPathLanguage extends LanguageSupport { @Override public Predicate createPredicate(final String predicate) { - return new JsonPathExpression(predicate); + JsonPathExpression answer = new JsonPathExpression(predicate); + answer.init(); + return answer; } @Override public Expression createExpression(final String expression) { - return new JsonPathExpression(expression); + JsonPathExpression answer = new JsonPathExpression(expression); + answer.init(); + return answer; } } http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanOptionTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanOptionTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanOptionTest.java new file mode 100644 index 0000000..b8e761a --- /dev/null +++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanOptionTest.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 com.jayway.jsonpath.Option; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class JsonPathBeanOptionTest extends CamelTestSupport { + + @Test + public void testFullName() throws Exception { + String json = "{\"person\" : {\"firstname\" : \"foo\", \"middlename\" : \"foo2\", \"lastname\" : \"bar\"}}"; + getMockEndpoint("mock:result").expectedBodiesReceived("foo foo2 bar"); + template.sendBody("direct:start", json); + assertMockEndpointsSatisfied(); + } + + @Test + public void testFirstAndLastName() throws Exception { + String json = "{\"person\" : {\"firstname\" : \"foo\", \"lastname\" : \"bar\"}}"; + getMockEndpoint("mock:result").expectedBodiesReceived("foo bar"); + template.sendBody("direct:start", json); + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start").bean(FullNameBean.class).to("mock:result"); + } + }; + } + + protected static class FullNameBean { + // middle name is optional + public static String getName(@JsonPath("person.firstname") String first, + @JsonPath(value = "person.middlename", options = Option.SUPPRESS_EXCEPTIONS) String middle, + @JsonPath("person.lastname") String last) { + if (middle != null) { + return first + " " + middle + " " + last; + } + return first + " " + last; + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/e6fb2d5d/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanTest.java ---------------------------------------------------------------------- diff --git a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanTest.java b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanTest.java index fb43643..f53d858 100644 --- a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanTest.java +++ b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathBeanTest.java @@ -16,6 +16,7 @@ */ package org.apache.camel.jsonpath; +import com.jayway.jsonpath.Option; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.test.junit4.CamelTestSupport; import org.junit.Test; @@ -43,13 +44,16 @@ public class JsonPathBeanTest extends CamelTestSupport { return new RouteBuilder() { @Override public void configure() { - from("direct:start").bean(FullnameBean.class).to("mock:result"); + from("direct:start").bean(FullNameBean.class).to("mock:result"); } }; } - protected static class FullnameBean { - public static String getName(@JsonPath("person.firstname") String first, @JsonPath("person.middlename") String middle, @JsonPath("person.lastname") String last) { + protected static class FullNameBean { + // middle name is optional + public static String getName(@JsonPath("person.firstname") String first, + @JsonPath(value = "person.middlename", options = Option.SUPPRESS_EXCEPTIONS) String middle, + @JsonPath("person.lastname") String last) { if (middle != null) { return first + " " + middle + " " + last; }