Repository: camel Updated Branches: refs/heads/master 68793857c -> 966846055
CAMEL-7619: Rest DSL - adding support for xml/json binding using Camel's data formats. Work in progress. Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/96684605 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/96684605 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/96684605 Branch: refs/heads/master Commit: 966846055e335431a378502ad4878d20a38b5b12 Parents: 4669b17 Author: Claus Ibsen <davscl...@apache.org> Authored: Wed Jul 23 17:08:07 2014 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Wed Jul 23 17:37:59 2014 +0200 ---------------------------------------------------------------------- .../camel/model/rest/RestBindingDefinition.java | 72 +++++++++++++-- .../camel/model/rest/RestBindingMode.java | 28 ++++++ .../model/rest/RestConfigurationDefinition.java | 22 +++++ .../apache/camel/model/rest/RestDefinition.java | 14 +++ .../apache/camel/model/rest/VerbDefinition.java | 11 +++ .../processor/binding/RestBindingProcessor.java | 94 ++++++++++++++++---- .../org/apache/camel/spi/RestConfiguration.java | 34 ++++++- .../org/apache/camel/model/rest/jaxb.index | 1 + .../restlet/RestRestletBindingModeJsonTest.java | 61 +++++++++++++ .../restlet/RestRestletBindingModeXmlTest.java | 61 +++++++++++++ 10 files changed, 376 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/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 045c7e7..229cf6f 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 @@ -26,6 +26,7 @@ import javax.xml.bind.annotation.XmlTransient; import org.apache.camel.CamelContext; import org.apache.camel.Processor; import org.apache.camel.model.NoOutputDefinition; +import org.apache.camel.model.ProcessorDefinition; import org.apache.camel.processor.binding.RestBindingProcessor; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.RouteContext; @@ -37,6 +38,15 @@ import org.apache.camel.util.ObjectHelper; public class RestBindingDefinition extends NoOutputDefinition { @XmlAttribute + private String consumes; + + @XmlAttribute + private String produces; + + @XmlAttribute + private RestBindingMode bindingMode; + + @XmlAttribute private String jsonDataFormat; @XmlAttribute @@ -75,14 +85,24 @@ public class RestBindingDefinition extends NoOutputDefinition { CamelContext context = routeContext.getCamelContext(); + // the default binding mode can be overriden per rest verb + String mode = context.getRestConfiguration().getBindingMode().name(); + if (bindingMode != null) { + mode = bindingMode.name(); + } + + // auto, off, json, xml, json_xml + // setup json data format String name = jsonDataFormat; if (name == null) { name = "json-jackson"; } DataFormat json = context.resolveDataFormat(name); - if (json == null) { - throw new IllegalArgumentException("DataFormat " + name + " not found."); + + // is json binding required? + if (mode.contains("json") && json == null) { + throw new IllegalArgumentException("JSon DataFormat " + name + " not found."); } if (classType == null && type != null) { classType = context.getClassResolver().resolveMandatoryClass(type); @@ -102,8 +122,9 @@ public class RestBindingDefinition extends NoOutputDefinition { name = "jaxb"; } DataFormat jaxb = context.resolveDataFormat(name); - if (jaxb == null) { - throw new IllegalArgumentException("DataFormat " + name + " not found."); + // is xml binding required? + if (mode.contains("xml") && jaxb == null) { + throw new IllegalArgumentException("XML DataFormat " + name + " not found."); } if (classType == null && type != null) { classType = context.getClassResolver().resolveMandatoryClass(type); @@ -117,7 +138,47 @@ public class RestBindingDefinition extends NoOutputDefinition { } context.addService(jaxb); - return new RestBindingProcessor(json, jaxb); + return new RestBindingProcessor(json, jaxb, consumes, produces, mode); + } + + 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 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() { @@ -153,4 +214,5 @@ public class RestBindingDefinition extends NoOutputDefinition { public void setUseList(boolean useList) { this.useList = useList; } + } http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingMode.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingMode.java b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingMode.java new file mode 100644 index 0000000..c2c669b --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/model/rest/RestBindingMode.java @@ -0,0 +1,28 @@ +/** + * 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.rest; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + +@XmlType +@XmlEnum(String.class) +public enum RestBindingMode { + + auto, off, json, xml, json_xml + +} http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/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 2c27311..ac2c8c9 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 @@ -49,6 +49,9 @@ public class RestConfigurationDefinition { @XmlAttribute private String port; + @XmlAttribute + private RestBindingMode bindingMode; + @XmlElement(name = "componentProperty") private List<RestPropertyDefinition> componentProperties = new ArrayList<RestPropertyDefinition>(); @@ -90,6 +93,14 @@ public class RestConfigurationDefinition { this.port = port; } + public RestBindingMode getBindingMode() { + return bindingMode; + } + + public void setBindingMode(RestBindingMode bindingMode) { + this.bindingMode = bindingMode; + } + public List<RestPropertyDefinition> getComponentProperties() { return componentProperties; } @@ -158,6 +169,14 @@ public class RestConfigurationDefinition { } /** + * To specify the binding mode + */ + public RestConfigurationDefinition bindingMode(RestBindingMode bindingMode) { + setBindingMode(bindingMode); + return this; + } + + /** * For additional configuration options on component level */ public RestConfigurationDefinition componentProperty(String key, String value) { @@ -214,6 +233,9 @@ public class RestConfigurationDefinition { if (port != null) { answer.setPort(CamelContextHelper.parseInteger(context, port)); } + if (bindingMode != null) { + answer.setBindingMode(bindingMode.name()); + } if (!componentProperties.isEmpty()) { Map<String, Object> props = new HashMap<String, Object>(); for (RestPropertyDefinition prop : componentProperties) { http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/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 2c3c4b5..52947a5 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 @@ -189,6 +189,17 @@ public class RestDefinition { return this; } + public RestDefinition bindingMode(RestBindingMode mode) { + // add to last verb + if (getVerbs().isEmpty()) { + throw new IllegalArgumentException("Must add verb first, such as get/post/delete"); + } + + VerbDefinition verb = getVerbs().get(getVerbs().size() - 1); + verb.setBindingMode(mode); + return this; + } + /** * Routes directly to the given endpoint. * <p/> @@ -287,6 +298,9 @@ public class RestDefinition { binding.setTypeList(verb.getTypeList()); binding.setClassType(verb.getClassType()); binding.setUseList(verb.isUseList()); + binding.setConsumes(verb.getConsumes()); + binding.setProduces(verb.getProduces()); + binding.setBindingMode(verb.getBindingMode()); route.getOutputs().add(0, binding); } http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java index 4f7ebd3..c2bc7fd 100644 --- a/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java +++ b/camel-core/src/main/java/org/apache/camel/model/rest/VerbDefinition.java @@ -45,6 +45,9 @@ public class VerbDefinition { private String produces; @XmlAttribute + private RestBindingMode bindingMode; + + @XmlAttribute private String type; @XmlAttribute @@ -104,6 +107,14 @@ public class VerbDefinition { this.produces = produces; } + public RestBindingMode getBindingMode() { + return bindingMode; + } + + public void setBindingMode(RestBindingMode bindingMode) { + this.bindingMode = bindingMode; + } + public String getType() { return type; } http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/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 7bb9b39..4ca249c 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 @@ -43,12 +43,18 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess private final AsyncProcessor xmlUnmarshal; private final AsyncProcessor jsonMmarshal; private final AsyncProcessor xmlMmarshal; + private final String consumes; + private final String produces; + private final String bindingMode; - public RestBindingProcessor(DataFormat jsonDataFormat, DataFormat xmlDataFormat) { + public RestBindingProcessor(DataFormat jsonDataFormat, DataFormat xmlDataFormat, String consumes, String produces, String bindingMode) { this.jsonUnmarshal = jsonDataFormat != null ? new UnmarshalProcessor(jsonDataFormat) : null; this.jsonMmarshal = jsonDataFormat != null ? new MarshalProcessor(jsonDataFormat) : null; this.xmlUnmarshal = xmlDataFormat != null ? new UnmarshalProcessor(xmlDataFormat) : null; this.xmlMmarshal = xmlDataFormat != null ? new MarshalProcessor(xmlDataFormat) : null; + this.consumes = consumes; + this.produces = produces; + this.bindingMode = bindingMode; } @Override @@ -58,23 +64,46 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess @Override public boolean process(Exchange exchange, final AsyncCallback callback) { + if (bindingMode == null || "off".equals(bindingMode)) { + // binding is off + callback.done(true); + return true; + } + // is there any unmarshaller at all if (jsonUnmarshal == null && xmlUnmarshal == null) { callback.done(true); return true; } - // check the header first if its xml or json + boolean isXml = false; + boolean isJson = false; + + // content type takes precedence, over consumes String contentType = ExchangeHelper.getContentType(exchange); - boolean isXml = contentType != null && contentType.toLowerCase(Locale.US).contains("xml"); - boolean isJson = contentType != null && contentType.toLowerCase(Locale.US).contains("json"); + if (contentType != null) { + isXml = contentType.toLowerCase(Locale.US).contains("xml"); + isJson = contentType.toLowerCase(Locale.US).contains("json"); + } + // if content type could not tell us if it was json or xml, then fallback to if the binding was configured with + // that information in the consumes + if (!isXml && !isJson) { + isXml = consumes != null && consumes.toLowerCase(Locale.US).contains("xml"); + isJson = consumes != null && consumes.toLowerCase(Locale.US).contains("json"); + } + + // only allow xml/json if the binding mode allows that + isXml &= bindingMode.equals("auto") || bindingMode.contains("xml"); + isJson &= bindingMode.equals("auto") || bindingMode.contains("json"); + + // check the header first if its xml or json if (isXml && xmlUnmarshal != null) { // add reverse operation - exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal, true)); + exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal)); return xmlUnmarshal.process(exchange, callback); } else if (isJson && jsonUnmarshal != null) { // add reverse operation - exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal, false)); + exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal)); return jsonUnmarshal.process(exchange, callback); } @@ -84,14 +113,25 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess if (isXml && xmlUnmarshal != null) { // add reverse operation - exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal, true)); + exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal)); return xmlUnmarshal.process(exchange, callback); } else if (jsonUnmarshal != null) { // add reverse operation - exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal, false)); + exchange.addOnCompletion(new RestBindingMarshalOnCompletion(jsonMmarshal, xmlMmarshal)); return jsonUnmarshal.process(exchange, callback); + } + + // we could not bind + if (bindingMode.equals("auto")) { + // okay for auto we do not mind if we could not bind + callback.done(true); + return true; } else { - // noop + if (bindingMode.contains("xml")) { + exchange.setException(new IllegalArgumentException("Cannot bind to xml as message body is not xml compatible")); + } else { + exchange.setException(new IllegalArgumentException("Cannot bind to json as message body is not json compatible")); + } callback.done(true); return true; } @@ -120,27 +160,49 @@ public class RestBindingProcessor extends ServiceSupport implements AsyncProcess private final AsyncProcessor jsonMmarshal; private final AsyncProcessor xmlMmarshal; - private final boolean wasXml; - private RestBindingMarshalOnCompletion(AsyncProcessor jsonMmarshal, AsyncProcessor xmlMmarshal, boolean wasXml) { + private RestBindingMarshalOnCompletion(AsyncProcessor jsonMmarshal, AsyncProcessor xmlMmarshal) { this.jsonMmarshal = jsonMmarshal; this.xmlMmarshal = xmlMmarshal; - this.wasXml = wasXml; } @Override public void onComplete(Exchange exchange) { // only marshal if we succeeded + boolean isXml = false; + boolean isJson = false; + + String contentType = ExchangeHelper.getContentType(exchange); + if (contentType != null) { + isXml = contentType.toLowerCase(Locale.US).contains("xml"); + isJson = contentType.toLowerCase(Locale.US).contains("json"); + } + // if content type could not tell us if it was json or xml, then fallback to if the binding was configured with + // that information in the consumes + if (!isXml && !isJson) { + isXml = produces != null && produces.toLowerCase(Locale.US).contains("xml"); + isJson = produces != null && produces.toLowerCase(Locale.US).contains("json"); + } + // need to prepare exchange first ExchangeHelper.prepareOutToIn(exchange); - // TODO: add logic to detect what content-type is now - // also when we add support for @Produces then use that to determine if we should marshal to xml or json + if (!isXml && !isJson) { + // read the content into memory so we can determine if its xml or json + String body = MessageHelper.extractBodyAsString(exchange.getIn()); + isXml = body.startsWith("<") || body.contains("xml"); + isJson = !isXml; + } + + // only allow xml/json if the binding mode allows that + isXml &= bindingMode.equals("auto") || bindingMode.contains("xml"); + isJson &= bindingMode.equals("auto") || bindingMode.contains("json"); + try { - if (wasXml) { + if (isXml && xmlMmarshal != null) { xmlMmarshal.process(exchange); - } else { + } else if (isJson && jsonMmarshal != null) { jsonMmarshal.process(exchange); } } catch (Throwable e) { http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/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 4ac5835..fc5367b 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 @@ -24,10 +24,15 @@ import java.util.Map; */ public class RestConfiguration { + public enum RestBindingMode { + auto, off, json, xml, json_xml + } + private String component; private String scheme; private String host; private int port; + private RestBindingMode bindingMode = RestBindingMode.auto; private Map<String, Object> componentProperties; private Map<String, Object> endpointProperties; private Map<String, Object> consumerProperties; @@ -96,7 +101,7 @@ public class RestConfiguration { } /** - * Gets the port to use by the REST consumer + * Sets the port to use by the REST consumer * * @param port the port number */ @@ -105,6 +110,33 @@ public class RestConfiguration { } /** + * Gets the binding mode used by the REST consumer + * + * @return the binding mode + */ + public RestBindingMode getBindingMode() { + return bindingMode; + } + + /** + * Sets the binding mode to be used by the REST consumer + * + * @param bindingMode the binding mode + */ + public void setBindingMode(RestBindingMode bindingMode) { + this.bindingMode = bindingMode; + } + + /** + * Sets the binding mode to be used by the REST consumer + * + * @param bindingMode the binding mode + */ + public void setBindingMode(String bindingMode) { + this.bindingMode = RestBindingMode.valueOf(bindingMode); + } + + /** * Gets additional options on component level * * @return additional options http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/camel-core/src/main/resources/org/apache/camel/model/rest/jaxb.index ---------------------------------------------------------------------- diff --git a/camel-core/src/main/resources/org/apache/camel/model/rest/jaxb.index b/camel-core/src/main/resources/org/apache/camel/model/rest/jaxb.index index 66ead80..a23c2d5 100644 --- a/camel-core/src/main/resources/org/apache/camel/model/rest/jaxb.index +++ b/camel-core/src/main/resources/org/apache/camel/model/rest/jaxb.index @@ -20,6 +20,7 @@ HeadVerbDefinition PostVerbDefinition PutVerbDefinition RestBindingDefinition +RestBindingMode RestConfigurationDefinition RestDefinition RestPropertyDefinition http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeJsonTest.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeJsonTest.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeJsonTest.java new file mode 100644 index 0000000..8b29f13 --- /dev/null +++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeJsonTest.java @@ -0,0 +1,61 @@ +/** + * 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.component.restlet; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.model.rest.RestBindingMode; +import org.junit.Test; + +/** + * @version + */ +public class RestRestletBindingModeJsonTest extends RestletTestSupport { + + @Test + public void testBindingMode() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:input"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(UserJaxbPojo.class); + + String body = "{\"id\": 123, \"name\": \"Donald Duck\"}"; + template.sendBody("http://localhost:" + portNum + "/users/new", body); + + assertMockEndpointsSatisfied(); + + UserJaxbPojo user = mock.getReceivedExchanges().get(0).getIn().getBody(UserJaxbPojo.class); + assertNotNull(user); + assertEquals(123, user.getId()); + assertEquals("Donald Duck", user.getName()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // binding mode is json only + restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.json); + + // use the rest DSL to define the rest services + rest("/users/") + .post("new").type(UserJaxbPojo.class) + .to("mock:input"); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/96684605/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeXmlTest.java ---------------------------------------------------------------------- diff --git a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeXmlTest.java b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeXmlTest.java new file mode 100644 index 0000000..d9c28d8 --- /dev/null +++ b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletBindingModeXmlTest.java @@ -0,0 +1,61 @@ +/** + * 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.component.restlet; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.model.rest.RestBindingMode; +import org.junit.Test; + +/** + * @version + */ +public class RestRestletBindingModeXmlTest extends RestletTestSupport { + + @Test + public void testBindingMode() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:input"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(UserJaxbPojo.class); + + String body = "<user name=\"Donald Duck\" id=\"123\"></user>"; + template.sendBody("http://localhost:" + portNum + "/users/new", body); + + assertMockEndpointsSatisfied(); + + UserJaxbPojo user = mock.getReceivedExchanges().get(0).getIn().getBody(UserJaxbPojo.class); + assertNotNull(user); + assertEquals(123, user.getId()); + assertEquals("Donald Duck", user.getName()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // binding mode is json only + restConfiguration().component("restlet").host("localhost").port(portNum).bindingMode(RestBindingMode.xml); + + // use the rest DSL to define the rest services + rest("/users/") + .post("new").type(UserJaxbPojo.class) + .to("mock:input"); + } + }; + } +}