You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by je...@apache.org on 2021/08/16 20:21:13 UTC

[camel] 01/02: CAMEL-15864: camel-graphql - Supply variables in header or body.

This is an automated email from the ASF dual-hosted git repository.

jeremyross pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit dff5afbeee7f9fa6c85fad899837ae3272704736
Author: Jeremy Ross <je...@gmail.com>
AuthorDate: Mon Aug 16 09:24:40 2021 -0500

    CAMEL-15864: camel-graphql - Supply variables in header or body.
---
 .../camel/catalog/docs/graphql-component.adoc      | 18 +++++++++++++--
 .../graphql/GraphqlEndpointConfigurer.java         |  6 +++++
 .../graphql/GraphqlEndpointUriFactory.java         |  3 ++-
 .../apache/camel/component/graphql/graphql.json    |  1 +
 .../src/main/docs/graphql-component.adoc           | 18 +++++++++++++--
 .../camel/component/graphql/GraphqlEndpoint.java   | 12 ++++++++++
 .../camel/component/graphql/GraphqlProducer.java   | 14 ++++++++++-
 .../component/graphql/GraphqlComponentTest.java    | 27 ++++++++++++++++++++++
 .../dsl/GraphqlEndpointBuilderFactory.java         | 15 ++++++++++++
 .../modules/ROOT/pages/graphql-component.adoc      | 18 +++++++++++++--
 10 files changed, 124 insertions(+), 8 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc
index 8a1e1a4..289f573 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc
@@ -100,7 +100,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (10 parameters):
+=== Query Parameters (11 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -112,6 +112,7 @@ with the following path and query parameters:
 | *query* (producer) | The query text. |  | String
 | *queryFile* (producer) | The query file name located in the classpath. |  | String
 | *variables* (producer) | The JsonObject instance containing the operation variables. |  | JsonObject
+| *variablesHeader* (producer) | The name of a header containing a JsonObject instance containing the operation variables. |  | String
 | *accessToken* (security) | The access token sent in the Authorization header. |  | String
 | *jwtAuthorizationType* (security) | The JWT Authorization type. Default is Bearer. | Bearer | String
 | *password* (security) | The password for Basic authentication. |  | String
@@ -122,7 +123,7 @@ with the following path and query parameters:
 
 == Message Body
 
-Camel will store the GraphQL response from the external server on the OUT message body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.
+If the `variables` and `variablesHeader` parameters are not used and the IN body is a JsonObject instance, Camel will use it for the operation's variables. Camel will store the GraphQL response from the external server on the OUT message body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.
 
 == Examples
 
@@ -177,6 +178,19 @@ from("direct:start")
     .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variables=#bookByIdQueryVariables")
 ----
 
+A query that accesses variables via the variablesHeader parameter:
+
+[source,java]
+----
+from("direct:start")
+    .setHeader("myVariables", () -> {
+        JsonObject variables = new JsonObject();
+        variables.put("id", "book-1");
+        return variables;
+    })
+    .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variablesHeader=myVariables")
+----
+
 === Mutations
 
 Mutations are like queries with variables. They specify a query and a reference to a variables bean:
diff --git a/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointConfigurer.java b/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointConfigurer.java
index 93da2da..13d6e61 100644
--- a/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointConfigurer.java
+++ b/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointConfigurer.java
@@ -37,6 +37,8 @@ public class GraphqlEndpointConfigurer extends PropertyConfigurerSupport impleme
         case "queryFile": target.setQueryFile(property(camelContext, java.lang.String.class, value)); return true;
         case "username": target.setUsername(property(camelContext, java.lang.String.class, value)); return true;
         case "variables": target.setVariables(property(camelContext, org.apache.camel.util.json.JsonObject.class, value)); return true;
+        case "variablesheader":
+        case "variablesHeader": target.setVariablesHeader(property(camelContext, java.lang.String.class, value)); return true;
         default: return false;
         }
     }
@@ -60,6 +62,8 @@ public class GraphqlEndpointConfigurer extends PropertyConfigurerSupport impleme
         case "queryFile": return java.lang.String.class;
         case "username": return java.lang.String.class;
         case "variables": return org.apache.camel.util.json.JsonObject.class;
+        case "variablesheader":
+        case "variablesHeader": return java.lang.String.class;
         default: return null;
         }
     }
@@ -84,6 +88,8 @@ public class GraphqlEndpointConfigurer extends PropertyConfigurerSupport impleme
         case "queryFile": return target.getQueryFile();
         case "username": return target.getUsername();
         case "variables": return target.getVariables();
+        case "variablesheader":
+        case "variablesHeader": return target.getVariablesHeader();
         default: return null;
         }
     }
diff --git a/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointUriFactory.java b/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointUriFactory.java
index 3379db5..b7d8a1c 100644
--- a/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointUriFactory.java
+++ b/components/camel-graphql/src/generated/java/org/apache/camel/component/graphql/GraphqlEndpointUriFactory.java
@@ -20,7 +20,7 @@ public class GraphqlEndpointUriFactory extends org.apache.camel.support.componen
     private static final Set<String> PROPERTY_NAMES;
     private static final Set<String> SECRET_PROPERTY_NAMES;
     static {
-        Set<String> props = new HashSet<>(11);
+        Set<String> props = new HashSet<>(12);
         props.add("lazyStartProducer");
         props.add("queryFile");
         props.add("variables");
@@ -28,6 +28,7 @@ public class GraphqlEndpointUriFactory extends org.apache.camel.support.componen
         props.add("jwtAuthorizationType");
         props.add("httpUri");
         props.add("query");
+        props.add("variablesHeader");
         props.add("operationName");
         props.add("accessToken");
         props.add("proxyHost");
diff --git a/components/camel-graphql/src/generated/resources/org/apache/camel/component/graphql/graphql.json b/components/camel-graphql/src/generated/resources/org/apache/camel/component/graphql/graphql.json
index d02a6fa..93bff64 100644
--- a/components/camel-graphql/src/generated/resources/org/apache/camel/component/graphql/graphql.json
+++ b/components/camel-graphql/src/generated/resources/org/apache/camel/component/graphql/graphql.json
@@ -33,6 +33,7 @@
     "query": { "kind": "parameter", "displayName": "Query", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The query text." },
     "queryFile": { "kind": "parameter", "displayName": "Query File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The query file name located in the classpath." },
     "variables": { "kind": "parameter", "displayName": "Variables", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.util.json.JsonObject", "deprecated": false, "autowired": false, "secret": false, "description": "The JsonObject instance containing the operation variables." },
+    "variablesHeader": { "kind": "parameter", "displayName": "Variables Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing a JsonObject instance containing the operation variables." },
     "accessToken": { "kind": "parameter", "displayName": "Access Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The access token sent in the Authorization header." },
     "jwtAuthorizationType": { "kind": "parameter", "displayName": "Jwt Authorization Type", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Bearer", "description": "The JWT Authorization type. Default is Bearer." },
     "password": { "kind": "parameter", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password for Basic authentication." },
diff --git a/components/camel-graphql/src/main/docs/graphql-component.adoc b/components/camel-graphql/src/main/docs/graphql-component.adoc
index 8a1e1a4..289f573 100644
--- a/components/camel-graphql/src/main/docs/graphql-component.adoc
+++ b/components/camel-graphql/src/main/docs/graphql-component.adoc
@@ -100,7 +100,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (10 parameters):
+=== Query Parameters (11 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -112,6 +112,7 @@ with the following path and query parameters:
 | *query* (producer) | The query text. |  | String
 | *queryFile* (producer) | The query file name located in the classpath. |  | String
 | *variables* (producer) | The JsonObject instance containing the operation variables. |  | JsonObject
+| *variablesHeader* (producer) | The name of a header containing a JsonObject instance containing the operation variables. |  | String
 | *accessToken* (security) | The access token sent in the Authorization header. |  | String
 | *jwtAuthorizationType* (security) | The JWT Authorization type. Default is Bearer. | Bearer | String
 | *password* (security) | The password for Basic authentication. |  | String
@@ -122,7 +123,7 @@ with the following path and query parameters:
 
 == Message Body
 
-Camel will store the GraphQL response from the external server on the OUT message body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.
+If the `variables` and `variablesHeader` parameters are not used and the IN body is a JsonObject instance, Camel will use it for the operation's variables. Camel will store the GraphQL response from the external server on the OUT message body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.
 
 == Examples
 
@@ -177,6 +178,19 @@ from("direct:start")
     .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variables=#bookByIdQueryVariables")
 ----
 
+A query that accesses variables via the variablesHeader parameter:
+
+[source,java]
+----
+from("direct:start")
+    .setHeader("myVariables", () -> {
+        JsonObject variables = new JsonObject();
+        variables.put("id", "book-1");
+        return variables;
+    })
+    .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variablesHeader=myVariables")
+----
+
 === Mutations
 
 Mutations are like queries with variables. They specify a query and a reference to a variables bean:
diff --git a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java
index 202baff..d4b79b9 100644
--- a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java
+++ b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java
@@ -74,6 +74,8 @@ public class GraphqlEndpoint extends DefaultEndpoint {
     private String operationName;
     @UriParam
     private JsonObject variables;
+    @UriParam
+    private String variablesHeader;
 
     private CloseableHttpClient httpClient;
 
@@ -244,4 +246,14 @@ public class GraphqlEndpoint extends DefaultEndpoint {
         this.variables = variables;
     }
 
+    public String getVariablesHeader() {
+        return variablesHeader;
+    }
+
+    /**
+     * The name of a header containing a JsonObject instance containing the operation variables.
+     */
+    public void setVariablesHeader(String variablesHeader) {
+        this.variablesHeader = variablesHeader;
+    }
 }
diff --git a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java
index a74e40b..4b38424 100644
--- a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java
+++ b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java
@@ -47,7 +47,7 @@ public class GraphqlProducer extends DefaultAsyncProducer {
             CloseableHttpClient httpClient = getEndpoint().getHttpclient();
             URI httpUri = getEndpoint().getHttpUri();
             String requestBody = buildRequestBody(getEndpoint().getQuery(), getEndpoint().getOperationName(),
-                    getEndpoint().getVariables());
+                    getVariables(exchange));
             HttpEntity requestEntity = new StringEntity(requestBody, ContentType.create("application/json", "UTF-8"));
 
             HttpPost httpPost = new HttpPost(httpUri);
@@ -74,4 +74,16 @@ public class GraphqlProducer extends DefaultAsyncProducer {
         jsonObject.put("variables", variables != null ? variables : new JsonObject());
         return jsonObject.toJson();
     }
+
+    private JsonObject getVariables(Exchange exchange) {
+        JsonObject variables = null;
+        if (getEndpoint().getVariables() != null) {
+            variables = getEndpoint().getVariables();
+        } else if (getEndpoint().getVariablesHeader() != null) {
+            variables = exchange.getIn().getHeader(getEndpoint().getVariablesHeader(), JsonObject.class);
+        } else if (exchange.getIn().getBody() instanceof JsonObject) {
+            variables = exchange.getIn().getBody(JsonObject.class);
+        }
+        return variables;
+    }
 }
diff --git a/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlComponentTest.java b/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlComponentTest.java
index 26b04f2..b2cd7b3 100644
--- a/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlComponentTest.java
+++ b/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlComponentTest.java
@@ -99,6 +99,10 @@ public class GraphqlComponentTest extends CamelTestSupport {
                         .to("graphql://http://localhost:" + server.getPort()
                             + "/graphql?queryFile=addBookMutation.graphql&variables=#addBookMutationVariables")
                         .to("mock:result");
+                from("direct:start5")
+                        .to("graphql://http://localhost:" + server.getPort()
+                            + "/graphql?query={books{id name}}&variablesHeader=bookByIdQueryVariables")
+                        .to("mock:result");
             }
         };
     }
@@ -143,4 +147,27 @@ public class GraphqlComponentTest extends CamelTestSupport {
         result.assertIsSatisfied();
     }
 
+    @Test
+    public void booksQueryWithVariablesHeader() throws Exception {
+        result.expectedMessageCount(1);
+        result.expectedBodiesReceived(booksQueryResult);
+
+        JsonObject variables = new JsonObject();
+        variables.put("id", "book-1");
+        template.sendBodyAndHeader("direct:start5", "", "bookByIdQueryVariables", variables);
+
+        result.assertIsSatisfied();
+    }
+
+    @Test
+    public void booksQueryWithVariablesBody() throws Exception {
+        result.expectedMessageCount(1);
+        result.expectedBodiesReceived(booksQueryResult);
+
+        JsonObject variables = new JsonObject();
+        variables.put("id", "book-1");
+        template.sendBody("direct:start1", variables);
+
+        result.assertIsSatisfied();
+    }
 }
diff --git a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/GraphqlEndpointBuilderFactory.java b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/GraphqlEndpointBuilderFactory.java
index e5c5900..ef65cac 100644
--- a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/GraphqlEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/GraphqlEndpointBuilderFactory.java
@@ -170,6 +170,21 @@ public interface GraphqlEndpointBuilderFactory {
             return this;
         }
         /**
+         * The name of a header containing a JsonObject instance containing the
+         * operation variables.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: producer
+         * 
+         * @param variablesHeader the value to set
+         * @return the dsl builder
+         */
+        default GraphqlEndpointBuilder variablesHeader(String variablesHeader) {
+            doSetProperty("variablesHeader", variablesHeader);
+            return this;
+        }
+        /**
          * The access token sent in the Authorization header.
          * 
          * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
diff --git a/docs/components/modules/ROOT/pages/graphql-component.adoc b/docs/components/modules/ROOT/pages/graphql-component.adoc
index d02cccb..d88fd05 100644
--- a/docs/components/modules/ROOT/pages/graphql-component.adoc
+++ b/docs/components/modules/ROOT/pages/graphql-component.adoc
@@ -102,7 +102,7 @@ with the following path and query parameters:
 |===
 
 
-=== Query Parameters (10 parameters):
+=== Query Parameters (11 parameters):
 
 
 [width="100%",cols="2,5,^1,2",options="header"]
@@ -114,6 +114,7 @@ with the following path and query parameters:
 | *query* (producer) | The query text. |  | String
 | *queryFile* (producer) | The query file name located in the classpath. |  | String
 | *variables* (producer) | The JsonObject instance containing the operation variables. |  | JsonObject
+| *variablesHeader* (producer) | The name of a header containing a JsonObject instance containing the operation variables. |  | String
 | *accessToken* (security) | The access token sent in the Authorization header. |  | String
 | *jwtAuthorizationType* (security) | The JWT Authorization type. Default is Bearer. | Bearer | String
 | *password* (security) | The password for Basic authentication. |  | String
@@ -124,7 +125,7 @@ with the following path and query parameters:
 
 == Message Body
 
-Camel will store the GraphQL response from the external server on the OUT message body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.
+If the `variables` and `variablesHeader` parameters are not used and the IN body is a JsonObject instance, Camel will use it for the operation's variables. Camel will store the GraphQL response from the external server on the OUT message body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.
 
 == Examples
 
@@ -179,6 +180,19 @@ from("direct:start")
     .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variables=#bookByIdQueryVariables")
 ----
 
+A query that accesses variables via the variablesHeader parameter:
+
+[source,java]
+----
+from("direct:start")
+    .setHeader("myVariables", () -> {
+        JsonObject variables = new JsonObject();
+        variables.put("id", "book-1");
+        return variables;
+    })
+    .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variablesHeader=myVariables")
+----
+
 === Mutations
 
 Mutations are like queries with variables. They specify a query and a reference to a variables bean: