CAMEL-10164: swagger component for making rest calls with swagger schema 
validation and facade to actual HTTP client in use


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/30ee1a84
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/30ee1a84
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/30ee1a84

Branch: refs/heads/master
Commit: 30ee1a845fc1db3922496a6edbd01dde507f4bd8
Parents: 83a097e
Author: Claus Ibsen <[email protected]>
Authored: Fri Aug 26 12:31:53 2016 +0200
Committer: Claus Ibsen <[email protected]>
Committed: Fri Aug 26 16:53:31 2016 +0200

----------------------------------------------------------------------
 .../camel/component/rest/RestComponent.java     |  5 ++
 .../camel/component/rest/RestEndpoint.java      |  1 -
 .../camel/component/rest/RestProducer.java      | 55 +++++++++++-------
 ...ttyRestProducerGetRestConfigurationTest.java | 54 -----------------
 .../rest/producer/JettyRestProducerGetTest.java |  4 +-
 .../component/restlet/RestletComponent.java     | 33 ++++++++++-
 .../component/restlet/RestletProducer.java      |  2 -
 .../RestRestletProducerGetJettyServerTest.java  | 61 ++++++++++++++++++++
 .../restlet/RestRestletProducerGetTest.java     | 60 +++++++++++++++++++
 9 files changed, 193 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java 
b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
index 67aaaba..d5c471c 100644
--- 
a/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
+++ 
b/camel-core/src/main/java/org/apache/camel/component/rest/RestComponent.java
@@ -47,6 +47,11 @@ public class RestComponent extends UriEndpointComponent {
         String h = resolveAndRemoveReferenceParameter(parameters, "host", 
String.class, host);
         if (h == null && getCamelContext().getRestConfiguration() != null) {
             h = getCamelContext().getRestConfiguration().getHost();
+            int port = getCamelContext().getRestConfiguration().getPort();
+            // is there a custom port number
+            if (port > 0 && port != 80 && port != 443) {
+                h += ":" + port;
+            }
         }
         // host must start with http:// or https://
         if (h != null && !(h.startsWith("http://";) || 
h.startsWith("https://";))) {

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java 
b/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
index 5df59bd..daaa459 100644
--- a/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
+++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestEndpoint.java
@@ -316,7 +316,6 @@ public class RestEndpoint extends DefaultEndpoint {
 
         if (factory != null) {
             LOG.debug("Using RestProducerFactory: {}", factory);
-            String uriTemplate = path;
             Producer producer = factory.createProducer(getCamelContext(), 
host, method, path, uriTemplate, consumes, produces, parameters);
             return new RestProducer(this, producer);
         } else {

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/camel-core/src/main/java/org/apache/camel/component/rest/RestProducer.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/component/rest/RestProducer.java 
b/camel-core/src/main/java/org/apache/camel/component/rest/RestProducer.java
index 154f280..13fed37 100644
--- a/camel-core/src/main/java/org/apache/camel/component/rest/RestProducer.java
+++ b/camel-core/src/main/java/org/apache/camel/component/rest/RestProducer.java
@@ -39,6 +39,8 @@ public class RestProducer extends DefaultAsyncProducer {
     // the producer of the Camel component that is used as the HTTP client to 
call the REST service
     private AsyncProcessor producer;
 
+    private boolean preapreUriTemplate = true;
+
     public RestProducer(Endpoint endpoint, Producer producer) {
         super(endpoint);
         this.producer = AsyncProcessorConverterHelper.convert(producer);
@@ -46,8 +48,9 @@ public class RestProducer extends DefaultAsyncProducer {
 
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        // TODO: bind to consumes context-type
-        // TODO: if binding is turned on/off/auto etc
+        // TODO: request bind to consumes context-type
+        // TODO: response bind to content-type returned in response
+        // TODO: binding
         try {
             prepareExchange(exchange);
             return producer.process(exchange, callback);
@@ -63,6 +66,18 @@ public class RestProducer extends DefaultAsyncProducer {
         return (RestEndpoint) super.getEndpoint();
     }
 
+    public boolean isPreapreUriTemplate() {
+        return preapreUriTemplate;
+    }
+
+    /**
+     * Whether to prepare the uri template and replace {key} with values from 
the exchange, and set
+     * as {@link Exchange#HTTP_URI} header with the resolved uri to use 
instead of uri from endpoint.
+     */
+    public void setPreapreUriTemplate(boolean preapreUriTemplate) {
+        this.preapreUriTemplate = preapreUriTemplate;
+    }
+
     protected void prepareExchange(Exchange exchange) throws Exception {
         boolean hasPath = false;
 
@@ -70,28 +85,28 @@ public class RestProducer extends DefaultAsyncProducer {
         // uri template may be optional and the user have entered the uri 
template in the path instead
         String resolvedUriTemplate = getEndpoint().getUriTemplate() != null ? 
getEndpoint().getUriTemplate() : getEndpoint().getPath();
 
-        if (resolvedUriTemplate.contains("{")) {
-            // resolve template and replace {key} with the values form the 
exchange
-            // each {} is a parameter (url templating)
-            String[] arr = resolvedUriTemplate.split("\\/");
-            CollectionStringBuffer csb = new CollectionStringBuffer("/");
-            for (String a : arr) {
-                if (a.startsWith("{") && a.endsWith("}")) {
-                    String key = a.substring(1, a.length() - 1);
-                    String value = exchange.getIn().getHeader(key, 
String.class);
-                    if (value != null) {
-                        hasPath = true;
-                        // we need to remove the header as they are sent as 
path instead
-                        exchange.getIn().removeHeader(key);
-                        csb.append(value);
+        if (preapreUriTemplate) {
+            if (resolvedUriTemplate.contains("{")) {
+                // resolve template and replace {key} with the values form the 
exchange
+                // each {} is a parameter (url templating)
+                String[] arr = resolvedUriTemplate.split("\\/");
+                CollectionStringBuffer csb = new CollectionStringBuffer("/");
+                for (String a : arr) {
+                    if (a.startsWith("{") && a.endsWith("}")) {
+                        String key = a.substring(1, a.length() - 1);
+                        String value = exchange.getIn().getHeader(key, 
String.class);
+                        if (value != null) {
+                            hasPath = true;
+                            csb.append(value);
+                        } else {
+                            csb.append(a);
+                        }
                     } else {
                         csb.append(a);
                     }
-                } else {
-                    csb.append(a);
                 }
+                resolvedUriTemplate = csb.toString();
             }
-            resolvedUriTemplate = csb.toString();
         }
 
         // resolve uri parameters
@@ -108,8 +123,6 @@ public class RestProducer extends DefaultAsyncProducer {
                         String key = a.substring(1, a.length() - 1);
                         String value = exchange.getIn().getHeader(key, 
String.class);
                         if (value != null) {
-                            // we need to remove the header as they are sent 
in query parameter instead
-                            exchange.getIn().removeHeader(key);
                             params.put(key, value);
                         } else {
                             params.put(entry.getKey(), entry.getValue());

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetRestConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetRestConfigurationTest.java
 
b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetRestConfigurationTest.java
deleted file mode 100644
index e254b1a..0000000
--- 
a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetRestConfigurationTest.java
+++ /dev/null
@@ -1,54 +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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.jetty.rest.producer;
-
-import org.apache.camel.RoutesBuilder;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.component.jetty.BaseJettyTest;
-import org.junit.Test;
-
-public class JettyRestProducerGetRestConfigurationTest extends BaseJettyTest {
-
-    @Test
-    public void testRestGet() throws Exception {
-        getMockEndpoint("mock:result").expectedBodiesReceived("Hello Donald 
Duck");
-
-        template.sendBodyAndHeader("direct:start", null, "name", "Donald 
Duck");
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                String host = "localhost:" + getPort();
-
-                restConfiguration().producerComponent("jetty").host(host);
-
-                from("direct:start")
-                        .to("rest:get:api:hello/hi/{name}")
-                        .to("mock:result");
-
-                
from("jetty:http://localhost:{{port}}/api/hello/hi/?matchOnUriPrefix=true";)
-                    .transform().constant("Hello Donald Duck");
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java
 
b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java
index 9ce781b..58720cd 100644
--- 
a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java
+++ 
b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/rest/producer/JettyRestProducerGetTest.java
@@ -37,9 +37,7 @@ public class JettyRestProducerGetTest extends BaseJettyTest {
         return new RouteBuilder() {
             @Override
             public void configure() throws Exception {
-                String host = "http://localhost:"; + getPort();
-
-                restConfiguration().producerComponent("jetty").host(host);
+                
restConfiguration().producerComponent("jetty").host("localhost").port(getPort());
 
                 from("direct:start")
                         .to("rest:get:api:hello/hi/{name}")

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java
----------------------------------------------------------------------
diff --git 
a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java
 
b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java
index 503e4e8..81469b0 100644
--- 
a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java
+++ 
b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletComponent.java
@@ -33,13 +33,16 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.Consumer;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Processor;
+import org.apache.camel.Producer;
 import org.apache.camel.impl.HeaderFilterStrategyComponent;
 import org.apache.camel.spi.RestApiConsumerFactory;
 import org.apache.camel.spi.RestConfiguration;
 import org.apache.camel.spi.RestConsumerFactory;
+import org.apache.camel.spi.RestProducerFactory;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.HostUtils;
 import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.ServiceHelper;
 import org.apache.camel.util.URISupport;
 import org.apache.camel.util.UnsafeUriCharactersEncoder;
 import org.apache.camel.util.jsse.SSLContextParameters;
@@ -62,7 +65,7 @@ import org.slf4j.LoggerFactory;
  *
  * @version
  */
-public class RestletComponent extends HeaderFilterStrategyComponent implements 
RestConsumerFactory, RestApiConsumerFactory {
+public class RestletComponent extends HeaderFilterStrategyComponent implements 
RestConsumerFactory, RestApiConsumerFactory, RestProducerFactory {
     private static final Logger LOG = 
LoggerFactory.getLogger(RestletComponent.class);
     private static final Object LOCK = new Object();
 
@@ -804,6 +807,34 @@ public class RestletComponent extends 
HeaderFilterStrategyComponent implements R
         return createConsumer(camelContext, processor, "GET", contextPath, 
null, null, null, configuration, parameters);
     }
 
+    @Override
+    public Producer createProducer(CamelContext camelContext, String host,
+                                   String verb, String basePath, String 
uriTemplate,
+                                   String consumes, String produces, 
Map<String, Object> parameters) throws Exception {
+
+        // avoid leading slash
+        basePath = FileUtil.stripLeadingSeparator(basePath);
+        uriTemplate = FileUtil.stripLeadingSeparator(uriTemplate);
+
+        // restlet method must be in upper-case
+        String restletMethod = verb.toUpperCase(Locale.US);
+
+        // get the endpoint
+        String url;
+        if (uriTemplate != null) {
+            url = String.format("restlet:%s/%s/%s?restletMethods=%s", host, 
basePath, uriTemplate, restletMethod);
+        } else {
+            url = String.format("restlet:%s/%s?restletMethods=%s", host, 
basePath, restletMethod);
+        }
+
+        RestletEndpoint endpoint = camelContext.getEndpoint(url, 
RestletEndpoint.class);
+        if (parameters != null && !parameters.isEmpty()) {
+            setProperties(camelContext, endpoint, parameters);
+        }
+
+        return endpoint.createProducer();
+    }
+
     protected static void cleanupConverters(List<String> converters) {
         if (converters != null && !converters.isEmpty()) {
             // To avoid race conditions this operation relies on a global 
lock, we

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletProducer.java
----------------------------------------------------------------------
diff --git 
a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletProducer.java
 
b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletProducer.java
index 4cf83c9..a33b9e6 100644
--- 
a/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletProducer.java
+++ 
b/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/RestletProducer.java
@@ -209,7 +209,6 @@ public class RestletProducer extends DefaultAsyncProducer {
             }
         }
         return answer.toString();
-
     }
 
     protected RestletOperationException 
populateRestletProducerException(Exchange exchange, Response response, int 
responseCode) {
@@ -245,7 +244,6 @@ public class RestletProducer extends DefaultAsyncProducer {
     }
 
     protected Map<String, String> parseResponseHeaders(Object response, 
Exchange camelExchange) {
-
         Map<String, String> answer = new HashMap<String, String>();
         if (response instanceof Response) {
 

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetJettyServerTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetJettyServerTest.java
 
b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetJettyServerTest.java
new file mode 100644
index 0000000..ad5646e
--- /dev/null
+++ 
b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetJettyServerTest.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.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+/**
+ * @version 
+ */
+public class RestRestletProducerGetJettyServerTest extends CamelTestSupport {
+    
+    @Test
+    public void testRestletProducerGet() throws Exception {
+        String out = fluentTemplate.withHeader("id", 
"123").to("direct:start").request(String.class);
+        assertEquals("123;Donald Duck", out);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // find free port
+                int port = AvailablePortFinder.getNextAvailable(22400);
+
+                // configure to use restlet on localhost with the given port
+                
restConfiguration().component("restlet").host("localhost").port(port);
+
+                from("direct:start")
+                    .to("rest:get:users/{id}/basic");
+
+                from("jetty:http://localhost:"; + port + 
"/users/?matchOnUriPrefix=true")
+                    .process(new Processor() {
+                        public void process(Exchange exchange) throws 
Exception {
+                            String id = exchange.getIn().getHeader("id", 
String.class);
+                            exchange.getOut().setBody(id + ";Donald Duck");
+                        }
+                    });
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/30ee1a84/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetTest.java
 
b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetTest.java
new file mode 100644
index 0000000..f557a96
--- /dev/null
+++ 
b/components/camel-restlet/src/test/java/org/apache/camel/component/restlet/RestRestletProducerGetTest.java
@@ -0,0 +1,60 @@
+/**
+ * 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.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.Test;
+
+/**
+ * @version 
+ */
+public class RestRestletProducerGetTest extends RestletTestSupport {
+    
+    @Test
+    public void testRestletProducerGet() throws Exception {
+        String out = fluentTemplate.withHeader("id", 
"123").to("direct:start").request(String.class);
+        assertEquals("123;Donald Duck", out);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // configure to use restlet on localhost with the given port
+                
restConfiguration().component("restlet").host("localhost").port(portNum);
+
+                from("direct:start")
+                    .to("rest:get:users/{id}/basic");
+
+                // use the rest DSL to define the rest services
+                rest("/users/")
+                    .get("{id}/basic")
+                        .route()
+                        .to("mock:input")
+                        .process(new Processor() {
+                            public void process(Exchange exchange) throws 
Exception {
+                                String id = exchange.getIn().getHeader("id", 
String.class);
+                                exchange.getOut().setBody(id + ";Donald Duck");
+                            }
+                        });
+            }
+        };
+    }
+}

Reply via email to