You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/08/26 16:02:38 UTC

[10/23] camel git commit: CAMEL-10164: swagger component for making rest calls with swagger schema validation and facade to actual HTTP client in use

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/69c12a0a
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/69c12a0a
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/69c12a0a

Branch: refs/heads/master
Commit: 69c12a0ab5d7c1f3152f0f2295ce1fa00f87170d
Parents: 2e39b2c
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Aug 25 07:46:53 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Aug 26 16:53:31 2016 +0200

----------------------------------------------------------------------
 .../apache/camel/spi/RestProducerFactory.java   |   8 +-
 .../component/jetty/JettyHttpComponent.java     |  16 +-
 .../swagger/component/SwaggerProducer.java      | 169 +++++++++++--------
 .../component/DummyRestProducerFactory.java     |  20 ++-
 4 files changed, 117 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/69c12a0a/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java b/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java
index 255ea6a..ae7f6f5 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/RestProducerFactory.java
@@ -32,21 +32,17 @@ public interface RestProducerFactory {
      * Creates a new REST producer.
      *
      * @param camelContext        the camel context
-     * @param exchange            the exchange
      * @param scheme              scheme to use such as http or https
      * @param host                host (incl port) of the REST service
      * @param verb                HTTP verb such as GET, POST
      * @param basePath            base path
      * @param uriTemplate         uri template
-     * @param resolvedUriTemplate uri template where path parameters has been resolved
-     * @param queryParameters     query parameters
      * @param consumes            media-types for what the REST service consume as input (accept-type), is <tt>null</tt> or <tt>&#42;/&#42;</tt> for anything
      * @param produces            media-types for what the REST service produces as output, can be <tt>null</tt>
      * @param parameters          additional parameters
      * @return a newly created REST producer
      * @throws Exception can be thrown
      */
-    Producer createProducer(CamelContext camelContext, Exchange exchange, String scheme, String host,
-                            String verb, String basePath, String uriTemplate, String resolvedUriTemplate, String queryParameters,
-                            String consumes, String produces, Map<String, Object> parameters) throws Exception;
+    Producer createProducer(CamelContext camelContext, String scheme, String host,
+                            String verb, String basePath, String uriTemplate, String consumes, String produces, Map<String, Object> parameters) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/69c12a0a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
index 6b9394f..3b3e91d 100644
--- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
+++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
@@ -1151,25 +1151,13 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements
     }
 
     @Override
-    public Producer createProducer(CamelContext camelContext, Exchange exchange, String scheme, String host,
-                                   String verb, String basePath, String uriTemplate, String resolvedUriTemplate, String queryParameters,
+    public Producer createProducer(CamelContext camelContext, String scheme, 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);
-        resolvedUriTemplate = FileUtil.stripLeadingSeparator(resolvedUriTemplate);
-
-        // does the uri template use path parameters?
-        if (uriTemplate.contains("{") && resolvedUriTemplate != null) {
-            // if so us a header for the dynamic uri template so we reuse same endpoint but the header overrides the actual url to use
-            String overrideUri = String.format("%s://%s/%s/%s", scheme, host, basePath, resolvedUriTemplate);
-            exchange.getIn().setHeader(Exchange.HTTP_URI, overrideUri);
-        }
-        if (queryParameters != null) {
-            // use a header for the query parameters
-            exchange.getIn().setHeader(Exchange.HTTP_QUERY, queryParameters);
-        }
 
         // get the endpoint
         String url = "jetty:%s://%s/%s/%s";

http://git-wip-us.apache.org/repos/asf/camel/blob/69c12a0a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java
index a5d0c18..7e1fda2 100644
--- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java
+++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/component/SwaggerProducer.java
@@ -37,7 +37,7 @@ import org.apache.camel.impl.DefaultAsyncProducer;
 import org.apache.camel.spi.RestProducerFactory;
 import org.apache.camel.util.AsyncProcessorConverterHelper;
 import org.apache.camel.util.CollectionStringBuffer;
-import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.ServiceHelper;
 import org.apache.camel.util.StringHelper;
 import org.apache.camel.util.URISupport;
@@ -49,6 +49,8 @@ public class SwaggerProducer extends DefaultAsyncProducer {
     private static final Logger LOG = LoggerFactory.getLogger(SwaggerProducer.class);
 
     private Swagger swagger;
+    private Operation operation;
+    private AsyncProcessor producer;
 
     public SwaggerProducer(Endpoint endpoint) {
         super(endpoint);
@@ -61,29 +63,14 @@ public class SwaggerProducer extends DefaultAsyncProducer {
 
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
-        String verb = getEndpoint().getVerb();
-        String path = getEndpoint().getPath();
-
-        Operation operation = getSwaggerOperation(verb, path);
-        if (operation == null) {
-            exchange.setException(new IllegalArgumentException("Swagger schema does not contain operation for " + verb + ":" + path));
-            callback.done(true);
-            return true;
-        }
+        // TODO: bind to consumes context-type
+        // TODO: if binding is turned on/off/auto etc
 
         try {
-            // TODO: bind to consumes context-type
-            // TODO: if binding is turned on/off/auto etc
-            // TODO: build dynamic uri for component (toD, headers)
-            // create http producer to use for calling the remote HTTP service
-            // TODO: create the producer once and reuse (create HTTP_XXX headers for dynamic values)
-            Producer producer = createHttpProducer(exchange, operation, verb, path);
             if (producer != null) {
-                ServiceHelper.startService(producer);
-                AsyncProcessor async = AsyncProcessorConverterHelper.convert(producer);
-                return async.process(exchange, callback);
+                prepareExchange(exchange);
+                return producer.process(exchange, callback);
             }
-
         } catch (Throwable e) {
             exchange.setException(e);
         }
@@ -93,6 +80,96 @@ public class SwaggerProducer extends DefaultAsyncProducer {
         return true;
     }
 
+    protected void prepareExchange(Exchange exchange) throws Exception {
+        boolean hasPath = false;
+        boolean hasQuery = false;
+
+        // uri template with path parameters resolved
+        String resolvedUriTemplate = getEndpoint().getPath();
+        // for query parameters
+        Map<String, Object> query = new LinkedHashMap<>();
+        for (Parameter param : operation.getParameters()) {
+            if ("query".equals(param.getIn())) {
+                String name = param.getName();
+                if (name != null) {
+                    String value = exchange.getIn().getHeader(name, String.class);
+                    if (value != null) {
+                        hasQuery = true;
+                        // we need to remove the header as they are sent as query instead
+                        // TODO: we could use a header filter strategy to skip these headers
+                        exchange.getIn().removeHeader(param.getName());
+                        query.put(name, value);
+                    } else if (param.getRequired()) {
+                        throw new NoSuchHeaderException(exchange, name, String.class);
+                    }
+                }
+            } else if ("path".equals(param.getIn())) {
+                String value = exchange.getIn().getHeader(param.getName(), String.class);
+                if (value != null) {
+                    hasPath = true;
+                    // we need to remove the header as they are sent as path instead
+                    // TODO: we could use a header filter strategy to skip these headers
+                    exchange.getIn().removeHeader(param.getName());
+                    String token = "{" + param.getName() + "}";
+                    resolvedUriTemplate = StringHelper.replaceAll(resolvedUriTemplate, token, value);
+                } else if (param.getRequired()) {
+                    // the parameter is required but we do not have a header
+                    throw new NoSuchHeaderException(exchange, param.getName(), String.class);
+                }
+            }
+        }
+
+        if (hasQuery) {
+            String queryParameters = URISupport.createQueryString(query);
+            exchange.getIn().setHeader(Exchange.HTTP_QUERY, queryParameters);
+        }
+
+        if (hasPath) {
+            String scheme = swagger.getSchemes() != null && swagger.getSchemes().size() == 1 ? swagger.getSchemes().get(0).toValue() : "http";
+            String host = getEndpoint().getHost() != null ? getEndpoint().getHost() : swagger.getHost();
+            String basePath = swagger.getBasePath();
+            basePath = FileUtil.stripLeadingSeparator(basePath);
+            resolvedUriTemplate = FileUtil.stripLeadingSeparator(resolvedUriTemplate);
+            // if so us a header for the dynamic uri template so we reuse same endpoint but the header overrides the actual url to use
+            String overrideUri = String.format("%s://%s/%s/%s", scheme, host, basePath, resolvedUriTemplate);
+            exchange.getIn().setHeader(Exchange.HTTP_URI, overrideUri);
+        }
+    }
+
+    public Swagger getSwagger() {
+        return swagger;
+    }
+
+    public void setSwagger(Swagger swagger) {
+        this.swagger = swagger;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+
+        String verb = getEndpoint().getVerb();
+        String path = getEndpoint().getPath();
+
+        operation = getSwaggerOperation(verb, path);
+        if (operation == null) {
+            throw new IllegalArgumentException("Swagger schema does not contain operation for " + verb + ":" + path);
+        }
+
+        Producer processor = createHttpProducer(operation, verb, path);
+        if (processor != null) {
+            producer = AsyncProcessorConverterHelper.convert(processor);
+        }
+        ServiceHelper.startService(producer);
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        super.doStop();
+
+        ServiceHelper.stopService(producer);
+    }
+
     private Operation getSwaggerOperation(String verb, String path) {
         Path modelPath = swagger.getPath(path);
         if (modelPath == null) {
@@ -119,15 +196,10 @@ public class SwaggerProducer extends DefaultAsyncProducer {
         return op;
     }
 
-    public Swagger getSwagger() {
-        return swagger;
-    }
+    private Producer createHttpProducer(Operation operation, String verb, String path) throws Exception {
 
-    public void setSwagger(Swagger swagger) {
-        this.swagger = swagger;
-    }
+        LOG.debug("Using Swagger operation: {} with {} {}", operation, verb, path);
 
-    protected Producer createHttpProducer(Exchange exchange, Operation operation, String verb, String path) throws Exception {
         RestProducerFactory factory = null;
         String cname = null;
         if (getEndpoint().getComponentName() != null) {
@@ -172,6 +244,7 @@ public class SwaggerProducer extends DefaultAsyncProducer {
         }
 
         if (factory != null) {
+            LOG.debug("Using RestProducerFactory: {}", factory);
 
             CollectionStringBuffer produces = new CollectionStringBuffer(",");
             List<String> list = operation.getProduces();
@@ -200,46 +273,8 @@ public class SwaggerProducer extends DefaultAsyncProducer {
             String basePath = swagger.getBasePath();
             String uriTemplate = path;
 
-            // uri template with path parameters resolved
-            String resolvedUriTemplate = uriTemplate;
-            // for query parameters
-            Map<String, Object> query = new LinkedHashMap<>();
-            for (Parameter param : operation.getParameters()) {
-                if ("query".equals(param.getIn())) {
-                    String name = param.getName();
-                    if (name != null) {
-                        String value = exchange.getIn().getHeader(name, String.class);
-                        if (value != null) {
-                            // we need to remove the header as they are sent as query instead
-                            // TODO: we could use a header filter strategy to skip these headers
-                            exchange.getIn().removeHeader(param.getName());
-                            query.put(name, value);
-                        } else if (param.getRequired()) {
-                            throw new NoSuchHeaderException(exchange, name, String.class);
-                        }
-                    }
-                } else if ("path".equals(param.getIn())) {
-                    String value = exchange.getIn().getHeader(param.getName(), String.class);
-                    if (value != null) {
-                        // we need to remove the header as they are sent as path instead
-                        // TODO: we could use a header filter strategy to skip these headers
-                        exchange.getIn().removeHeader(param.getName());
-                        String token = "{" + param.getName() + "}";
-                        resolvedUriTemplate = StringHelper.replaceAll(resolvedUriTemplate, token, value);
-                    } else if (param.getRequired()) {
-                        // the parameter is required but we do not have a header
-                        throw new NoSuchHeaderException(exchange, param.getName(), String.class);
-                    }
-                }
-            }
-            // build as query string
-            String queryParameters = null;
-            if (!query.isEmpty()) {
-                queryParameters = URISupport.createQueryString(query);
-            }
-
-            return factory.createProducer(getEndpoint().getCamelContext(), exchange, scheme, host, verb, basePath, uriTemplate, resolvedUriTemplate,
-                    queryParameters, (consumes.isEmpty() ? "" : consumes.toString()), (produces.isEmpty() ? "" : produces.toString()), null);
+            return factory.createProducer(getEndpoint().getCamelContext(), scheme, host, verb, basePath, uriTemplate,
+                    (consumes.isEmpty() ? "" : consumes.toString()), (produces.isEmpty() ? "" : produces.toString()), null);
 
         } else {
             throw new IllegalStateException("Cannot find RestProducerFactory in Registry or as a Component to use");

http://git-wip-us.apache.org/repos/asf/camel/blob/69c12a0a/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java b/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java
index 4f1da5c..499dd7e 100644
--- a/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java
+++ b/components/camel-swagger-java/src/test/java/org/apache/camel/swagger/component/DummyRestProducerFactory.java
@@ -29,8 +29,8 @@ import org.apache.camel.util.ObjectHelper;
 public class DummyRestProducerFactory implements RestProducerFactory {
 
     @Override
-    public Producer createProducer(CamelContext camelContext, Exchange exchange, String scheme, String host,
-                            String verb, String basePath, final String uriTemplate, final String resolvedUriTemplate, final String queryParameters,
+    public Producer createProducer(CamelContext camelContext, String scheme, String host,
+                            String verb, String basePath, final String uriTemplate,
                             String consumes, String produces, Map<String, Object> parameters) throws Exception {
 
         // use a dummy endpoint
@@ -39,15 +39,17 @@ public class DummyRestProducerFactory implements RestProducerFactory {
         return new DefaultProducer(endpoint) {
             @Override
             public void process(Exchange exchange) throws Exception {
-                // for testing purpose, check if we have {name} in template
-                if (uriTemplate.contains("{name}")) {
-                    int pos = resolvedUriTemplate.lastIndexOf('/');
-                    String name = resolvedUriTemplate.substring(pos + 1);
-                    exchange.getIn().setBody("Hello " + name);
-                } else if (queryParameters.contains("name=")) {
-                    String name = ObjectHelper.after(queryParameters, "name=");
+                String query = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);
+                if (query != null) {
+                    String name = ObjectHelper.after(query, "name=");
                     exchange.getIn().setBody("Bye " + name);
                 }
+                String uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class);
+                if (uri != null) {
+                    int pos = uri.lastIndexOf('/');
+                    String name = uri.substring(pos + 1);
+                    exchange.getIn().setBody("Hello " + name);
+                }
             }
         };
     }