| = GraphQL Component | |
| :doctitle: GraphQL | |
| :shortname: graphql | |
| :artifactid: camel-graphql | |
| :description: Send GraphQL queries and mutations to external systems. | |
| :since: 3.0 | |
| :supportlevel: Stable | |
| :tabs-sync-option: | |
| :component-header: Only producer is supported | |
| *Since Camel {since}* | |
| *{component-header}* | |
| The GraphQL component is a GraphQL client that communicates over HTTP and supports queries and mutations, but not subscriptions. It uses the https://hc.apache.org/httpcomponents-client-4.5.x/index.html[Apache HttpClient] library. | |
| Maven users will need to add the following dependency to their `pom.xml` | |
| for this component: | |
| [source,xml] | |
| ---- | |
| <dependency> | |
| <groupId>org.apache.camel</groupId> | |
| <artifactId>camel-graphql</artifactId> | |
| <version>x.x.x</version> | |
| <!-- use the same version as your Camel core version --> | |
| </dependency> | |
| ---- | |
| // component options: START | |
| include::partial$component-configure-options.adoc[] | |
| include::partial$component-endpoint-options.adoc[] | |
| include::partial$component-endpoint-headers.adoc[] | |
| // component options: END | |
| == Message Body | |
| If the `variables` and `variablesHeader` parameters are not set and the IN body is a JsonObject instance, Camel will use it for the operation's variables. If the `query` and `queryFile` parameters are not set and the IN body is a String, Camel will use it as the query. 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 | |
| === Queries | |
| Simple queries can be defined directly in the URI: | |
| [tabs] | |
| ==== | |
| Java:: | |
| + | |
| [source,java] | |
| ---- | |
| from("direct:start") | |
| .to("graphql://http://example.com/graphql?query={books{id name}}"); | |
| ---- | |
| XML:: | |
| + | |
| [source,xml] | |
| ---- | |
| <route> | |
| <from uri="direct:start"/> | |
| <to uri="graphql://http://example.com/graphql?query={books{id name}}"/> | |
| </route> | |
| ---- | |
| YAML:: | |
| + | |
| [source,yaml] | |
| ---- | |
| - route: | |
| from: | |
| uri: direct:start | |
| steps: | |
| - to: | |
| uri: graphql://http://example.com/graphql | |
| parameters: | |
| query: "{books{id name}}" | |
| ---- | |
| ==== | |
| The body can also be used for the query: | |
| [tabs] | |
| ==== | |
| Java:: | |
| + | |
| [source,java] | |
| ---- | |
| from("direct:start") | |
| .setBody(constant("{books{id name}}")) | |
| .to("graphql://http://example.com/graphql"); | |
| ---- | |
| XML:: | |
| + | |
| [source,xml] | |
| ---- | |
| <route> | |
| <from uri="direct:start"/> | |
| <setBody> | |
| <constant>{books{id name}}</constant> | |
| </setBody> | |
| <to uri="graphql://http://example.com/graphql"/> | |
| </route> | |
| ---- | |
| YAML:: | |
| + | |
| [source,yaml] | |
| ---- | |
| - route: | |
| from: | |
| uri: direct:start | |
| steps: | |
| - setBody: | |
| constant: "{books{id name}}" | |
| - to: | |
| uri: graphql://http://example.com/graphql | |
| ---- | |
| ==== | |
| The query can come from a header also: | |
| [tabs] | |
| ==== | |
| Java:: | |
| + | |
| [source,java] | |
| ---- | |
| from("direct:start") | |
| .setHeader("myQuery", constant("{books{id name}}")) | |
| .to("graphql://http://example.com/graphql?queryHeader=myQuery"); | |
| ---- | |
| XML:: | |
| + | |
| [source,xml] | |
| ---- | |
| <route> | |
| <from uri="direct:start"/> | |
| <setHeader name="myQuery"> | |
| <constant>{books{id name}}</constant> | |
| </setHeader> | |
| <to uri="graphql://http://example.com/graphql?queryHeader=myQuery"/> | |
| </route> | |
| ---- | |
| YAML:: | |
| + | |
| [source,yaml] | |
| ---- | |
| - route: | |
| from: | |
| uri: direct:start | |
| steps: | |
| - setHeader: | |
| name: myQuery | |
| constant: "{books{id name}}" | |
| - to: | |
| uri: graphql://http://example.com/graphql | |
| parameters: | |
| queryHeader: myQuery | |
| ---- | |
| ==== | |
| More complex queries can be stored in a file and referenced in the URI: | |
| booksQuery.graphql file: | |
| ---- | |
| query Books { | |
| books { | |
| id | |
| name | |
| } | |
| } | |
| ---- | |
| [tabs] | |
| ==== | |
| Java:: | |
| + | |
| [source,java] | |
| ---- | |
| from("direct:start") | |
| .to("graphql://http://example.com/graphql?queryFile=booksQuery.graphql"); | |
| ---- | |
| XML:: | |
| + | |
| [source,xml] | |
| ---- | |
| <route> | |
| <from uri="direct:start"/> | |
| <to uri="graphql://http://example.com/graphql?queryFile=booksQuery.graphql"/> | |
| </route> | |
| ---- | |
| YAML:: | |
| + | |
| [source,yaml] | |
| ---- | |
| - route: | |
| from: | |
| uri: direct:start | |
| steps: | |
| - to: | |
| uri: graphql://http://example.com/graphql | |
| parameters: | |
| queryFile: booksQuery.graphql | |
| ---- | |
| ==== | |
| When the query file defines multiple operations, it's required to specify which one should be executed: | |
| [tabs] | |
| ==== | |
| Java:: | |
| + | |
| [source,java] | |
| ---- | |
| from("direct:start") | |
| .to("graphql://http://example.com/graphql?queryFile=multipleQueries.graphql&operationName=Books"); | |
| ---- | |
| XML:: | |
| + | |
| [source,xml] | |
| ---- | |
| <route> | |
| <from uri="direct:start"/> | |
| <to uri="graphql://http://example.com/graphql?queryFile=multipleQueries.graphql&operationName=Books"/> | |
| </route> | |
| ---- | |
| YAML:: | |
| + | |
| [source,yaml] | |
| ---- | |
| - route: | |
| from: | |
| uri: direct:start | |
| steps: | |
| - to: | |
| uri: graphql://http://example.com/graphql | |
| parameters: | |
| queryFile: multipleQueries.graphql | |
| operationName: Books | |
| ---- | |
| ==== | |
| Queries with variables need to reference a JsonObject instance from the registry: | |
| bookByIdQuery.graphql file: | |
| ---- | |
| query BookById($id: Int!) { | |
| bookById(id: $id) { | |
| id | |
| name | |
| author | |
| } | |
| } | |
| ---- | |
| ._Java-only: registering query variables and referencing them in the endpoint_ | |
| [source,java] | |
| ---- | |
| @BindToRegistry("bookByIdQueryVariables") | |
| public JsonObject bookByIdQueryVariables() { | |
| JsonObject variables = new JsonObject(); | |
| variables.put("id", "book-1"); | |
| return variables; | |
| } | |
| from("direct:start") | |
| .to("graphql://http://example.com/graphql?queryFile=bookByIdQuery.graphql&variables=#bookByIdQueryVariables") | |
| ---- | |
| A query that accesses variables via the variablesHeader parameter: | |
| ._Java-only: setting variables via a header with a lambda supplier_ | |
| [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: | |
| addBookMutation.graphql file: | |
| ---- | |
| mutation AddBook($bookInput: BookInput) { | |
| addBook(bookInput: $bookInput) { | |
| id | |
| name | |
| author { | |
| name | |
| } | |
| } | |
| } | |
| ---- | |
| ._Java-only: registering mutation variables and referencing them in the endpoint_ | |
| [source,java] | |
| ---- | |
| @BindToRegistry("addBookMutationVariables") | |
| public JsonObject addBookMutationVariables() { | |
| JsonObject bookInput = new JsonObject(); | |
| bookInput.put("name", "Typee"); | |
| bookInput.put("authorId", "author-2"); | |
| JsonObject variables = new JsonObject(); | |
| variables.put("bookInput", bookInput); | |
| return variables; | |
| } | |
| from("direct:start") | |
| .to("graphql://http://example.com/graphql?queryFile=addBookMutation.graphql&variables=#addBookMutationVariables") | |
| ---- |