CAMEL-7619: Rest DSL - adding support for xml/json binding using Camel's data formats.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/d8d03016 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/d8d03016 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/d8d03016 Branch: refs/heads/master Commit: d8d03016533d21ce85de466a081489a489f609c7 Parents: 1284015 Author: Claus Ibsen <davscl...@apache.org> Authored: Fri Jul 25 17:03:52 2014 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Fri Jul 25 17:03:52 2014 +0200 ---------------------------------------------------------------------- .../camel/model/rest/RestBindingDefinition.java | 134 ++++++++++--------- .../model/rest/RestConfigurationDefinition.java | 79 +++++++++++ .../apache/camel/model/rest/RestDefinition.java | 81 ++++++++--- .../processor/binding/RestBindingProcessor.java | 26 +++- .../org/apache/camel/spi/RestConfiguration.java | 57 ++++++++ .../camel-example-spark-rest-tomcat/README.txt | 3 + .../camel-example-spark-rest-tomcat/pom.xml | 6 + .../example/spark/MySparkRouteBuilder.java | 48 ------- .../org/apache/camel/example/spark/User.java | 47 +++++++ .../camel/example/spark/UserRouteBuilder.java | 49 +++++++ .../apache/camel/example/spark/UserService.java | 64 +++++++++ .../src/main/resources/camel-config.xml | 10 +- .../src/main/webapp/index.html | 34 +++-- 13 files changed, 480 insertions(+), 158 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java index e0a0c32..7099c90 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingDefinition.java @@ -16,6 +16,8 @@ */ package org.apache.camel.model.rest; +import java.util.HashMap; +import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -27,6 +29,7 @@ import org.apache.camel.Processor; import org.apache.camel.model.NoOutputDefinition; import org.apache.camel.processor.binding.RestBindingProcessor; import org.apache.camel.spi.DataFormat; +import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RouteContext; import org.apache.camel.util.IntrospectionSupport; @@ -44,12 +47,6 @@ public class RestBindingDefinition extends NoOutputDefinition { private RestBindingMode bindingMode; @XmlAttribute - private String jsonDataFormat; - - @XmlAttribute - private String xmlDataFormat; - - @XmlAttribute private String type; @XmlAttribute @@ -68,7 +65,7 @@ public class RestBindingDefinition extends NoOutputDefinition { @Override public String getShortName() { - return "rest"; + return "restBinding"; } @Override @@ -88,75 +85,98 @@ public class RestBindingDefinition extends NoOutputDefinition { } // setup json data format - String name = jsonDataFormat; + String name = context.getRestConfiguration().getJsonDataFormat(); if (name == null) { name = "json-jackson"; } DataFormat json = context.resolveDataFormat(name); + DataFormat outJson = context.resolveDataFormat(name); // is json binding required? if (mode.contains("json") && json == null) { throw new IllegalArgumentException("JSon DataFormat " + name + " not found."); } - Class<?> clazz = null; - if (type != null) { - clazz = context.getClassResolver().resolveMandatoryClass(type); - } - if (clazz != null) { - IntrospectionSupport.setProperty(context.getTypeConverter(), json, "unmarshalType", clazz); - IntrospectionSupport.setProperty(context.getTypeConverter(), json, "useList", list != null ? list : false); - } - context.addService(json); - DataFormat outJson = context.resolveDataFormat(name); - Class<?> outClazz = null; - if (outType != null) { - outClazz = context.getClassResolver().resolveMandatoryClass(outType); - } - if (outClazz != null) { - IntrospectionSupport.setProperty(context.getTypeConverter(), outJson, "unmarshalType", outClazz); - IntrospectionSupport.setProperty(context.getTypeConverter(), outJson, "useList", outList != null ? outList : false); + if (json != null) { + Class<?> clazz = null; + if (type != null) { + clazz = context.getClassResolver().resolveMandatoryClass(type); + } + if (clazz != null) { + IntrospectionSupport.setProperty(context.getTypeConverter(), json, "unmarshalType", clazz); + IntrospectionSupport.setProperty(context.getTypeConverter(), json, "useList", list != null ? list : false); + } + setAdditionalConfiguration(context, json); + context.addService(json); + + Class<?> outClazz = null; + if (outType != null) { + outClazz = context.getClassResolver().resolveMandatoryClass(outType); + } + if (outClazz != null) { + IntrospectionSupport.setProperty(context.getTypeConverter(), outJson, "unmarshalType", outClazz); + IntrospectionSupport.setProperty(context.getTypeConverter(), outJson, "useList", outList != null ? outList : false); + } + setAdditionalConfiguration(context, outJson); + context.addService(outJson); } - context.addService(outJson); // setup xml data format - name = xmlDataFormat; + name = context.getRestConfiguration().getXmlDataFormat(); if (name == null) { name = "jaxb"; } DataFormat jaxb = context.resolveDataFormat(name); + DataFormat outJaxb = context.resolveDataFormat(name); // is xml binding required? if (mode.contains("xml") && jaxb == null) { throw new IllegalArgumentException("XML DataFormat " + name + " not found."); } - clazz = null; - if (type != null) { - clazz = context.getClassResolver().resolveMandatoryClass(type); - } - if (clazz != null) { - JAXBContext jc = JAXBContext.newInstance(clazz); - IntrospectionSupport.setProperty(context.getTypeConverter(), jaxb, "context", jc); - } - context.addService(jaxb); - DataFormat outJaxb = context.resolveDataFormat(name); - outClazz = null; - if (outType != null) { - outClazz = context.getClassResolver().resolveMandatoryClass(outType); + if (jaxb != null) { + Class<?> clazz = null; + if (type != null) { + clazz = context.getClassResolver().resolveMandatoryClass(type); + } + if (clazz != null) { + JAXBContext jc = JAXBContext.newInstance(clazz); + IntrospectionSupport.setProperty(context.getTypeConverter(), jaxb, "context", jc); + } + if (context.getRestConfiguration().getDataFormatProperties() != null) { + IntrospectionSupport.setProperties(context.getTypeConverter(), jaxb, context.getRestConfiguration().getDataFormatProperties()); + } + setAdditionalConfiguration(context, jaxb); + context.addService(jaxb); + + Class<?> outClazz = null; + if (outType != null) { + outClazz = context.getClassResolver().resolveMandatoryClass(outType); + } + if (outClazz != null) { + JAXBContext jc = JAXBContext.newInstance(outClazz); + IntrospectionSupport.setProperty(context.getTypeConverter(), outJaxb, "context", jc); + } else if (clazz != null) { + // fallback and use the context from the input + JAXBContext jc = JAXBContext.newInstance(clazz); + IntrospectionSupport.setProperty(context.getTypeConverter(), outJaxb, "context", jc); + } + setAdditionalConfiguration(context, outJaxb); + context.addService(outJaxb); } - if (outClazz != null) { - JAXBContext jc = JAXBContext.newInstance(outClazz); - IntrospectionSupport.setProperty(context.getTypeConverter(), outJaxb, "context", jc); - } else if (clazz != null) { - // fallback and use the context from the input - JAXBContext jc = JAXBContext.newInstance(clazz); - IntrospectionSupport.setProperty(context.getTypeConverter(), outJaxb, "context", jc); - } - context.addService(outJaxb); return new RestBindingProcessor(json, jaxb, outJson, outJaxb, consumes, produces, mode); } + private void setAdditionalConfiguration(CamelContext context, DataFormat dataFormat) throws Exception { + if (context.getRestConfiguration().getDataFormatProperties() != null && !context.getRestConfiguration().getDataFormatProperties().isEmpty()) { + // must use a copy as otherwise the options gets removed during introspection setProperties + Map<String, Object> copy = new HashMap<String, Object>(); + copy.putAll(context.getRestConfiguration().getDataFormatProperties()); + + IntrospectionSupport.setProperties(context.getTypeConverter(), dataFormat, copy); + } + } + public String getConsumes() { return consumes; } @@ -181,22 +201,6 @@ public class RestBindingDefinition extends NoOutputDefinition { this.bindingMode = bindingMode; } - public String getJsonDataFormat() { - return jsonDataFormat; - } - - public void setJsonDataFormat(String jsonDataFormat) { - this.jsonDataFormat = jsonDataFormat; - } - - public String getXmlDataFormat() { - return xmlDataFormat; - } - - public void setXmlDataFormat(String xmlDataFormat) { - this.xmlDataFormat = xmlDataFormat; - } - public String getType() { return type; } http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java index ac2c8c9..758a099 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestConfigurationDefinition.java @@ -52,6 +52,12 @@ public class RestConfigurationDefinition { @XmlAttribute private RestBindingMode bindingMode; + @XmlAttribute + private String jsonDataFormat; + + @XmlAttribute + private String xmlDataFormat; + @XmlElement(name = "componentProperty") private List<RestPropertyDefinition> componentProperties = new ArrayList<RestPropertyDefinition>(); @@ -61,6 +67,9 @@ public class RestConfigurationDefinition { @XmlElement(name = "consumerProperty") private List<RestPropertyDefinition> consumerProperties = new ArrayList<RestPropertyDefinition>(); + @XmlElement(name = "dataFormatProperty") + private List<RestPropertyDefinition> dataFormatProperties = new ArrayList<RestPropertyDefinition>(); + public String getComponent() { return component; } @@ -101,6 +110,22 @@ public class RestConfigurationDefinition { this.bindingMode = bindingMode; } + public String getJsonDataFormat() { + return jsonDataFormat; + } + + public void setJsonDataFormat(String jsonDataFormat) { + this.jsonDataFormat = jsonDataFormat; + } + + public String getXmlDataFormat() { + return xmlDataFormat; + } + + public void setXmlDataFormat(String xmlDataFormat) { + this.xmlDataFormat = xmlDataFormat; + } + public List<RestPropertyDefinition> getComponentProperties() { return componentProperties; } @@ -125,6 +150,14 @@ public class RestConfigurationDefinition { this.consumerProperties = consumerProperties; } + public List<RestPropertyDefinition> getDataFormatProperties() { + return dataFormatProperties; + } + + public void setDataFormatProperties(List<RestPropertyDefinition> dataFormatProperties) { + this.dataFormatProperties = dataFormatProperties; + } + // Fluent API //------------------------------------------------------------------------- @@ -177,6 +210,26 @@ public class RestConfigurationDefinition { } /** + * To use a specific json data format + * + * @param name name of the data format to {@link org.apache.camel.CamelContext#resolveDataFormat(java.lang.String) resolve} + */ + public RestConfigurationDefinition jsonDataFormat(String name) { + setJsonDataFormat(name); + return this; + } + + /** + * To use a specific XML data format + * + * @param name name of the data format to {@link org.apache.camel.CamelContext#resolveDataFormat(java.lang.String) resolve} + */ + public RestConfigurationDefinition xmlDataFormat(String name) { + setXmlDataFormat(name); + return this; + } + + /** * For additional configuration options on component level */ public RestConfigurationDefinition componentProperty(String key, String value) { @@ -209,6 +262,17 @@ public class RestConfigurationDefinition { return this; } + /** + * For additional configuration options on data format level + */ + public RestConfigurationDefinition dataFormatProperty(String key, String value) { + RestPropertyDefinition prop = new RestPropertyDefinition(); + prop.setKey(key); + prop.setValue(value); + getDataFormatProperties().add(prop); + return this; + } + // Implementation //------------------------------------------------------------------------- @@ -236,6 +300,12 @@ public class RestConfigurationDefinition { if (bindingMode != null) { answer.setBindingMode(bindingMode.name()); } + if (jsonDataFormat != null) { + answer.setJsonDataFormat(jsonDataFormat); + } + if (xmlDataFormat != null) { + answer.setXmlDataFormat(xmlDataFormat); + } if (!componentProperties.isEmpty()) { Map<String, Object> props = new HashMap<String, Object>(); for (RestPropertyDefinition prop : componentProperties) { @@ -263,6 +333,15 @@ public class RestConfigurationDefinition { } answer.setConsumerProperties(props); } + if (!dataFormatProperties.isEmpty()) { + Map<String, Object> props = new HashMap<String, Object>(); + for (RestPropertyDefinition prop : dataFormatProperties) { + String key = prop.getKey(); + String value = CamelContextHelper.parseText(context, prop.getValue()); + props.put(key, value); + } + answer.setDataFormatProperties(props); + } return answer; } http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java index 2186993..b7bf16d 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestDefinition.java @@ -41,6 +41,16 @@ public class RestDefinition { @XmlAttribute private String uri; + + @XmlAttribute + private String consumes; + + @XmlAttribute + private String produces; + + @XmlAttribute + private RestBindingMode bindingMode; + @XmlElementRef private List<VerbDefinition> verbs = new ArrayList<VerbDefinition>(); @@ -52,6 +62,30 @@ public class RestDefinition { this.uri = uri; } + public String getConsumes() { + return consumes; + } + + public void setConsumes(String consumes) { + this.consumes = consumes; + } + + public String getProduces() { + return produces; + } + + public void setProduces(String produces) { + this.produces = produces; + } + + public RestBindingMode getBindingMode() { + return bindingMode; + } + + public void setBindingMode(RestBindingMode bindingMode) { + this.bindingMode = bindingMode; + } + public List<VerbDefinition> getVerbs() { return verbs; } @@ -120,26 +154,26 @@ public class RestDefinition { } public RestDefinition consumes(String mediaType) { - // add to last verb if (getVerbs().isEmpty()) { - throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); + this.consumes = mediaType; + } else { + // add on last verb as that is how the Java DSL works + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setConsumes(mediaType); } - VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); - verb.setConsumes(mediaType); - return this; } public RestDefinition produces(String mediaType) { - // add to last verb if (getVerbs().isEmpty()) { - throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); + this.produces = mediaType; + } else { + // add on last verb as that is how the Java DSL works + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setProduces(mediaType); } - VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); - verb.setProduces(mediaType); - return this; } @@ -190,13 +224,14 @@ public class RestDefinition { } public RestDefinition bindingMode(RestBindingMode mode) { - // add to last verb if (getVerbs().isEmpty()) { - throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); + this.bindingMode = mode; + } else { + // add on last verb as that is how the Java DSL works + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setBindingMode(mode); } - VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); - verb.setBindingMode(mode); return this; } @@ -297,9 +332,21 @@ public class RestDefinition { binding.setOutType(verb.getOutType()); binding.setList(verb.getList()); binding.setOutList(verb.getOutList()); - binding.setConsumes(verb.getConsumes()); - binding.setProduces(verb.getProduces()); - binding.setBindingMode(verb.getBindingMode()); + if (verb.getConsumes() != null) { + binding.setConsumes(verb.getConsumes()); + } else { + binding.setConsumes(getConsumes()); + } + if (verb.getProduces() != null) { + binding.setProduces(verb.getProduces()); + } else { + binding.setProduces(getProduces()); + } + if (verb.getBindingMode() != null) { + binding.setBindingMode(verb.getBindingMode()); + } else { + binding.setBindingMode(getBindingMode()); + } route.getOutputs().add(0, binding); // the route should be from this rest endpoint http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java index 9d53959..1c76b1e 100644 --- a/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java +++ b/camel-core/src/main/java/org/apache/camel/processor/binding/RestBindingProcessor.java @@ -29,6 +29,7 @@ import org.apache.camel.support.SynchronizationAdapter; import org.apache.camel.util.AsyncProcessorHelper; import org.apache.camel.util.ExchangeHelper; import org.apache.camel.util.MessageHelper; +import org.apache.camel.util.ObjectHelper; /** * A {@link org.apache.camel.Processor} that binds the REST DSL incoming and outgoing messages @@ -126,10 +127,15 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess isJson = consumes != null && consumes.toLowerCase(Locale.US).contains("json"); } - // if we do not know explicit if its json or xml, then need to check the message body to be sure what it is + // we have binding enabled, so we need to know if there body is empty or not\ + // so force reading the body as a String which we can work with + String body = MessageHelper.extractBodyAsString(exchange.getIn()); + if (body != null) { + exchange.getIn().setBody(body); + } + + // if we do not know if its xml/json then try check if the body is xml if (!isXml && !isJson || isXml && isJson) { - // read the content into memory so we can determine if its xml or json - String body = MessageHelper.extractBodyAsString(exchange.getIn()); if (body != null) { isXml = body.startsWith("<"); isJson = !isXml; @@ -143,11 +149,21 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess if (isXml && xmlUnmarshal != null) { // add reverse operation exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal)); - return xmlUnmarshal.process(exchange, callback); + if (ObjectHelper.isNotEmpty(body)) { + return xmlUnmarshal.process(exchange, callback); + } else { + callback.done(true); + return true; + } } else if (isJson && jsonUnmarshal != null) { // add reverse operation exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal)); - return jsonUnmarshal.process(exchange, callback); + if (ObjectHelper.isNotEmpty(body)) { + return jsonUnmarshal.process(exchange, callback); + } else { + callback.done(true); + return true; + } } // we could not bind http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java index 78bf4d2..f821036 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java +++ b/camel-core/src/main/java/org/apache/camel/spi/RestConfiguration.java @@ -33,9 +33,12 @@ public class RestConfiguration { private String host; private int port; private RestBindingMode bindingMode = RestBindingMode.off; + private String jsonDataFormat; + private String xmlDataFormat; private Map<String, Object> componentProperties; private Map<String, Object> endpointProperties; private Map<String, Object> consumerProperties; + private Map<String, Object> dataFormatProperties; /** * Gets the name of the Camel component to use as the REST consumer @@ -137,6 +140,42 @@ public class RestConfiguration { } /** + * Gets the name of the json data format. + * + * @return the name, or <tt>null</tt> to use default + */ + public String getJsonDataFormat() { + return jsonDataFormat; + } + + /** + * Sets a custom json data format to be used + * + * @param name name of the data format + */ + public void setJsonDataFormat(String name) { + this.jsonDataFormat = name; + } + + /** + * Gets the name of the xml data format. + * + * @return the name, or <tt>null</tt> to use default + */ + public String getXmlDataFormat() { + return xmlDataFormat; + } + + /** + * Sets a custom xml data format to be used + * + * @param name name of the data format + */ + public void setXmlDataFormat(String name) { + this.xmlDataFormat = name; + } + + /** * Gets additional options on component level * * @return additional options @@ -189,4 +228,22 @@ public class RestConfiguration { public void setConsumerProperties(Map<String, Object> consumerProperties) { this.consumerProperties = consumerProperties; } + + /** + * Gets additional options on data format level + * + * @return additional options + */ + public Map<String, Object> getDataFormatProperties() { + return dataFormatProperties; + } + + /** + * Sets additional options on data format level + * + * @param dataFormatProperties the options + */ + public void setDataFormatProperties(Map<String, Object> dataFormatProperties) { + this.dataFormatProperties = dataFormatProperties; + } } http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/README.txt ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/README.txt b/examples/camel-example-spark-rest-tomcat/README.txt index 70a2ce6..b1f350b 100644 --- a/examples/camel-example-spark-rest-tomcat/README.txt +++ b/examples/camel-example-spark-rest-tomcat/README.txt @@ -11,6 +11,9 @@ Spark requires Java 8, so you will need to use Java 8. To run the example deploy it in Apache Tomcat by copying the .war to the deploy folder of Apache Tomcat. +You can also try the example from maven using + mvn jetty:run + And then hit this url from a web browser which has further instructions (use correct version number) http://localhost:8080/camel-example-spark-rest-tomcat-{version} http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/pom.xml b/examples/camel-example-spark-rest-tomcat/pom.xml index c181982..e5dd2c4 100755 --- a/examples/camel-example-spark-rest-tomcat/pom.xml +++ b/examples/camel-example-spark-rest-tomcat/pom.xml @@ -54,6 +54,12 @@ </exclusions> </dependency> + <!-- use for json binding --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jackson</artifactId> + </dependency> + <!-- we need spring web --> <dependency> <groupId>org.springframework</groupId> http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/MySparkRouteBuilder.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/MySparkRouteBuilder.java b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/MySparkRouteBuilder.java deleted file mode 100644 index 7f5a6ca..0000000 --- a/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/MySparkRouteBuilder.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * 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.example.spark; - -import org.apache.camel.builder.RouteBuilder; - -/** - * Define REST services using the Camel REST DSL - */ -public class MySparkRouteBuilder extends RouteBuilder { - - @Override - public void configure() throws Exception { - - // configure we want to use spark-rest as the component for the rest DSL - restConfiguration().component("spark-rest"); - - // use the rest DSL to define rest services, and use embedded routes - rest("/hello/{me}") - .get().consumes("text/plain") - .route() - .to("log:input") - .transform().simple("Hello ${header.me}").endRest() - .get().consumes("application/json") - .route() - .to("log:input") - .transform().simple("{ \"message\": \"Hello ${header.me}\" }").endRest() - .get().consumes("text/xml") - .route() - .to("log:input") - .transform().simple("<message>Hello ${header.me}</message>"); - } - -} http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/User.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/User.java b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/User.java new file mode 100644 index 0000000..fbe2b04 --- /dev/null +++ b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/User.java @@ -0,0 +1,47 @@ +/** + * 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.example.spark; + +public class User { + + private int id; + private String name; + + public User() { + } + + public User(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserRouteBuilder.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserRouteBuilder.java b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserRouteBuilder.java new file mode 100644 index 0000000..0f859d5 --- /dev/null +++ b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserRouteBuilder.java @@ -0,0 +1,49 @@ +/** + * 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.example.spark; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.rest.RestBindingMode; + +/** + * Define REST services using the Camel REST DSL + */ +public class UserRouteBuilder extends RouteBuilder { + + @Override + public void configure() throws Exception { + + // configure we want to use spark-rest as the component for the rest DSL + // and we enable json binding mode + restConfiguration().component("spark-rest").bindingMode(RestBindingMode.json) + // and output using pretty print + .dataFormatProperty("prettyPrint", "true"); + + // this user REST service is json only + rest("/user").consumes("application/json").produces("application/json") + + .get("/view/{id}").outType(User.class) + .to("bean:userService?method=getUser(${header.id})") + + .get("/list").outTypeList(User.class) + .to("bean:userService?method=listUsers") + + .put("/update").type(User.class).outType(User.class) + .to("bean:userService?method=updateUser"); + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserService.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserService.java b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserService.java new file mode 100644 index 0000000..ad4a801 --- /dev/null +++ b/examples/camel-example-spark-rest-tomcat/src/main/java/org/apache/camel/example/spark/UserService.java @@ -0,0 +1,64 @@ +/** + * 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.example.spark; + +import java.util.Collection; +import java.util.Map; +import java.util.TreeMap; + +/** + * A {@link org.apache.camel.example.spark.User} service which we rest enable from the {@link org.apache.camel.example.spark.UserRouteBuilder}. + */ +public class UserService { + + // use a tree map so they become sorted + private final Map<String, User> users = new TreeMap<String, User>(); + + public UserService() { + users.put("123", new User(123, "John Doe")); + users.put("456", new User(456, "Donald Duck")); + } + + /** + * Gets a user by the given id + * + * @param id the id of the user + * @return the user, or <tt>null</tt> if no user exists + */ + public User getUser(String id) { + return users.get(id); + } + + /** + * List all users + * + * @return the list of all users + */ + public Collection<User> listUsers() { + return users.values(); + } + + /** + * Updates or creates the given user + * + * @param user the user + * @return the old user before it was updated, or <tt>null</tt> if creating a new user + */ + public User updateUser(User user) { + return users.put("" + user.getId(), user); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/src/main/resources/camel-config.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/src/main/resources/camel-config.xml b/examples/camel-example-spark-rest-tomcat/src/main/resources/camel-config.xml index fb98fce..ee1dbdb 100755 --- a/examples/camel-example-spark-rest-tomcat/src/main/resources/camel-config.xml +++ b/examples/camel-example-spark-rest-tomcat/src/main/resources/camel-config.xml @@ -23,12 +23,14 @@ 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="mySparkRoutes" class="org.apache.camel.example.spark.MySparkRouteBuilder"/> + <!-- a rest service which uses binding to/from pojos --> + <bean id="userRoutes" class="org.apache.camel.example.spark.UserRouteBuilder"/> - <camelContext xmlns="http://camel.apache.org/schema/spring"> - - <routeBuilder ref="mySparkRoutes"/> + <!-- a bean for user services --> + <bean id="userService" class="org.apache.camel.example.spark.UserService"/> + <camelContext xmlns="http://camel.apache.org/schema/spring"> + <routeBuilder ref="userRoutes"/> </camelContext> </beans> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/d8d03016/examples/camel-example-spark-rest-tomcat/src/main/webapp/index.html ---------------------------------------------------------------------- diff --git a/examples/camel-example-spark-rest-tomcat/src/main/webapp/index.html b/examples/camel-example-spark-rest-tomcat/src/main/webapp/index.html index d163f7e..c2559c4 100644 --- a/examples/camel-example-spark-rest-tomcat/src/main/webapp/index.html +++ b/examples/camel-example-spark-rest-tomcat/src/main/webapp/index.html @@ -22,34 +22,30 @@ This example shows how to use Spark REST to define REST endpoints in Camel routes using the CamelSparkRouteBuilder DSL <br/> -The routes are defined in Java code, in the <tt>org.apache.camel.example.sparkrest.MySparkRouteBuilder</tt> class. +The routes are defined in Java code, in the <tt>org.apache.camel.example.sparkrest.UserRouteBuilder</tt> class. <p/> -There is a <i>hello</i> REST service that supports different content-type +There is a <i>user</i> REST service that supports the following operations <ul> - <li>text/plain</li> - <li>text/xml</li> - <li>application/xml</li> + <li>view/<i>id</i> - to view a user with the given id </li> + <li>list - to view all users</li> + <li>update - to update/create an user</li> </ul> -The REST service is defined using Spark syntax as <tt>hello/:me</tt> which means that it starts with a fixed <tt>hello/</tt> -path, and then accepts a parameter which is named <b>:me</b> which will be mapped to a Camel header with key <b>me</b>. +The view and list operations are HTTP GET, and update is using HTTP PUT. -<br/> -This allows you to access the REST service and include a parameter, for example -<p/> - <tt>hello/world</tt> -<p/> -This means that world is the parameter. +From a web browser you can access the first two services using the following links -<p/> -You can access the <i>text/plain</i> service from the web browser by clicking <a href="hello/yourname">this link</a>. -<p/> -You can try the <i>text/xml</i> or <i>application/json</i> from the command line using <b>curl</b> or similar tool. +<ul> + <li><a href="/user/view/123">user/view/123</a> - to view the user with id 123</li> + <li><a href="/user/list">user/list</a> - to list all users</li> +</ul> +From the command shell you can use curl to access the service as shown below: <pre> - curl -H "Accept: application/json" http://localhost:8080/camel-example-spark-rest-tomcat-{version}/hello/you - curl -H "Accept: text/xml" http://localhost:8080/camel-example-spark-rest-tomcat-{version}/hello/you + curl -X GET -H "Accept: application/json" http://localhost:8080/camel-example-spark-rest-tomcat-{version}/user/view/123 + curl -X GET -H "Accept: application/json" http://localhost:8080/camel-example-spark-rest-tomcat-{version}/user/list + curl -X PUT -d "{ \"id\": 666, \"name\": \"The devil\"}" -H "Accept: application/json" http://localhost:8080/camel-example-spark-rest-tomcat-{version}/user/update </pre> This assume you installed the example by copying the .war as <tt>camel-example-spark-rest-tomcat-VERSION.war</tt>