{"id":6833,"date":"2019-03-17T18:59:59","date_gmt":"2019-03-17T18:59:59","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=6833"},"modified":"2019-03-17T19:04:09","modified_gmt":"2019-03-17T19:04:09","slug":"spring-boot-and-graphql","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/spring-boot-and-graphql\/","title":{"rendered":"Spring boot and GraphQL"},"content":{"rendered":"<p>A previous post <a href=\"http:\/\/putridparrot.com\/blog\/writing-a-graphql-service-using-graphql-dotnet-and-asp-net-core\/\" rel=\"noopener noreferrer\" target=\"_blank\">Writing a GraphQL service using graphql-dotnet and ASP.NET core<\/a> covered implementing an ASP.NET application with a GraphQL service.<\/p>\n<p>As GraphQL is language\/platform agnostic I wanted to see how to implement a similar little service using Java frameworks.<\/p>\n<p>I&#8217;m using JetBrains&#8217; IntelliJ (I think you need the ultimate edition for this) to create a project, so I&#8217;ll list a few steps regarding this process. In IntelliJ<\/p>\n<ul>\n<li>Create a new Project<\/li>\n<li>Select Spring Initializr<\/li>\n<li>Leave the defaults as https:\/\/start.spring.io and just press the Next button<\/li>\n<li>Supply a name for your project then press the Next button<\/li>\n<li>At the next page you can select dependencies, just press the Next button<\/li>\n<li>Finally give your project a name then press the Finish button<\/li>\n<\/ul>\n<p>Now let&#8217;s update the pom.xml with the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;!-- Add the following for GraphQL --&gt;\r\n&lt;dependency&gt;\r\n   &lt;groupId&gt;com.graphql-java&lt;\/groupId&gt;\r\n   &lt;artifactId&gt;graphql-spring-boot-starter&lt;\/artifactId&gt;\r\n   &lt;version&gt;5.0.2&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n&lt;dependency&gt;\r\n   &lt;groupId&gt;com.graphql-java&lt;\/groupId&gt;\r\n   &lt;artifactId&gt;graphql-java-tools&lt;\/artifactId&gt;\r\n   &lt;version&gt;5.2.4&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;!-- Add this for the GraphQL interactive tool --&gt;\r\n&lt;dependency&gt;\r\n   &lt;groupId&gt;com.graphql-java&lt;\/groupId&gt;\r\n   &lt;artifactId&gt;graphiql-spring-boot-starter&lt;\/artifactId&gt;\r\n   &lt;version&gt;4.0.0&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n<\/pre>\n<p>As shown with the comments, the last dependency will allow us to include the GraphQL interactive web application graphiql, obviously remove this if you do not need it. <\/p>\n<p>Now let&#8217;s write some code&#8230;<\/p>\n<p><strong>Schema and Queries<\/strong><\/p>\n<p>Unlike the previous C# example, we&#8217;re going to use the GraphQL schema definition language to declare our schema (in C# we used code to implement this). <\/p>\n<p>In your package folder add Person.java with the following code<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class Person {\r\n    private String name;\r\n\r\n    public Person() {\r\n    }\r\n\r\n    public Person(String name) {\r\n        this.name = name;\r\n    }\r\n\r\n    public String getName() {\r\n        return name;\r\n    }\r\n\r\n    public void setName(String name) {\r\n        this.name = name;\r\n    }\r\n}\r\n<\/pre>\n<p>It&#8217;s basic but this is our starting point (and matches what we did in the C# example).<\/p>\n<p>We now need to create a QueryResolver, so add a file named Query.java to the package with the following code<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport com.coxautodev.graphql.tools.GraphQLQueryResolver;\r\nimport org.springframework.stereotype.Component;\r\n\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\n@Component\r\npublic class Query implements GraphQLQueryResolver {\r\n    List&lt;Person&gt; people = new ArrayList&lt;&gt;();\r\n\r\n    public Query() {\r\n        people.add(new Person(&quot;Scooby&quot;));\r\n        people.add(new Person(&quot;Shaggy&quot;));\r\n        people.add(new Person(&quot;Daphne&quot;));\r\n        people.add(new Person(&quot;Thelma&quot;));\r\n        people.add(new Person(&quot;Fred&quot;));\r\n    }\r\n\r\n    public List&lt;Person&gt; people() {\r\n        return people;\r\n    }\r\n}\r\n<\/pre>\n<p>That&#8217;s it for the Java code for now &#8211; Spring Boot&#8217;s dark magic will wire everything up for us, but before then we need to add a .graphqls file. Within the resources folder lets add a schema file named schema.graphqls (IntelliJ comes with a plugin for recognising this file type).<\/p>\n<p><em>Note: the name of the file need not be schema, any name will suffice for this example.<\/em><\/p>\n<p>Within the schema.graphqls file we have the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ntype Query {\r\n    people : &#x5B;Person]\r\n}\r\n\r\ntype Person {\r\n    name: String!\r\n}\r\n<\/pre>\n<p>That&#8217;s it! <\/p>\n<p>Running the application will result in a Tomcat embedded server running on http:\/\/localhost:8080\/graphiql (assuming you include graphiql in the Maven file). If we now execute the following query within graphiql<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n{\r\n  people {\r\n    name\r\n  } \r\n}\r\n<\/pre>\n<p>we should see the result <\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;data&quot;: {\r\n    &quot;people&quot;: &#x5B;\r\n      {\r\n        &quot;name&quot;: &quot;Scooby&quot;\r\n      },\r\n      {\r\n        &quot;name&quot;: &quot;Shaggy&quot;\r\n      },\r\n      {\r\n        &quot;name&quot;: &quot;Daphne&quot;\r\n      },\r\n      {\r\n        &quot;name&quot;: &quot;Thelma&quot;\r\n      },\r\n      {\r\n        &quot;name&quot;: &quot;Fred&quot;\r\n      }\r\n    ]\r\n  }\r\n}\r\n<\/pre>\n<p>Let&#8217;s now add an operation <em>find<\/em> to allow us to locate a Person by their name. In the Query class, add the following<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic Person find(String input) {\r\n   return people.stream()\r\n      .filter(p -&gt; p.getName().equalsIgnoreCase(input))\r\n      .findFirst()\r\n      .orElse(null);\r\n}\r\n<\/pre>\n<p>This code acts a little like a Linq query in C#, returning an Optional, we&#8217;ll basically return a null if no item was found hence unwrapping our return from the Optional.<\/p>\n<p>We need to add this operation to the schema.graphql Query type, so it now looks like this<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ntype Query {\r\n    people: &#x5B;Person]\r\n    find(input: String!) : Person\r\n}\r\n<\/pre>\n<p>Running the application we can now write the following in graphiql<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n{\r\n   find(input : &quot;Scooby&quot;) {\r\n      name\r\n  }\r\n}\r\n<\/pre>\n<p><strong>Mutations<\/strong><\/p>\n<p>Next up, let&#8217;s write a mutation to add a person. We&#8217;re not going to add a Person to the list of people as this would require some refactoring of the query data, but it simply demonstrates the changes required to our project to implement mutations.<\/p>\n<p>Let&#8217;s jump into the schema file and add mutation to the schema definition, so it looks like this<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nschema {\r\n    query: Query\r\n    mutation: Mutation\r\n}\r\n<\/pre>\n<p>and now add the mutation type into the file, which should look like this<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ntype Mutation {\r\n    addPerson(input: String) : Person\r\n}\r\n<\/pre>\n<p>Now we&#8217;ll create the code. Add a file (mine&#8217;s called Mutation.java) for our mutation code, here&#8217;s a the very simple example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport com.coxautodev.graphql.tools.GraphQLMutationResolver;\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class Mutation implements GraphQLMutationResolver {\r\n    public Person addPerson(String input) {\r\n        return new Person(input);\r\n    }\r\n}\r\n<\/pre>\n<p>That&#8217;s all there is to it, run the application and using grapiql, write the following in your query window<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nmutation addPerson($input : String) {\r\n   addPerson(input : $input)\r\n   {\r\n      name\r\n   }\r\n}\r\n<\/pre>\n<p>and in the Query variables window add the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;input&quot; : &quot;Scooby Doo&quot;\r\n}\r\n<\/pre>\n<p><strong>Subscriptions<\/strong><\/p>\n<p>Finally let&#8217;s write some subscription code. Change the schema.graphqls schema to look like this<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nschema {\r\n    query: Query\r\n    mutation: Mutation\r\n    subscription : Subscription\r\n}\r\n<\/pre>\n<p>and add the following type<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ntype Subscription {\r\n    personAdded : Person\r\n}\r\n<\/pre>\n<p>The Subscription.java file will look like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport com.coxautodev.graphql.tools.GraphQLSubscriptionResolver;\r\nimport org.reactivestreams.Publisher;\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class Subscription implements GraphQLSubscriptionResolver {\r\n\r\n    private PersonPublisher publisher;\r\n\r\n    public Subscription(PersonPublisher publisher) {\r\n        this.publisher = publisher;\r\n    }\r\n\r\n    public Publisher&lt;Person&gt; personAdded() {\r\n        return publisher.getPublisher();\r\n    }\r\n}\r\n<\/pre>\n<p>This implements our Subscription resolver, but we&#8217;ll separate out the publisher code to look like this. Here&#8217;s my PersonPublisher.java file<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport io.reactivex.BackpressureStrategy;\r\nimport io.reactivex.Flowable;\r\nimport io.reactivex.Observable;\r\nimport io.reactivex.observables.ConnectableObservable;\r\nimport org.springframework.stereotype.Component;\r\nimport java.util.concurrent.TimeUnit;\r\n\r\n@Component\r\npublic class PersonPublisher {\r\n\r\n    private final Flowable&lt;Person&gt; publisher;\r\n\r\n    public PersonPublisher() {\r\n        Observable&lt;Person&gt; o = Observable.interval(1, 1, TimeUnit.SECONDS)\r\n                .map(l -&gt; new Person(l.toString()));\r\n        ConnectableObservable&lt;Person&gt; co = o.share().publish();\r\n\r\n        publisher = co.toFlowable(BackpressureStrategy.BUFFER);\r\n    }\r\n\r\n    public Flowable&lt;Person&gt; getPublisher() {\r\n        return publisher;\r\n    }\r\n}\r\n<\/pre>\n<p><em>Note: I&#8217;ve based the code for the Subcription and PersonPublisher on the <a href=\"https:\/\/github.com\/graphql-java-kickstart\/graphql-spring-boot\/blob\/0184c4e779a33d17ed64b4d14b03238ceb0518f8\/example-graphql-subscription\/src\/main\/java\/com\/oembedler\/moon\/graphql\/boot\/publishers\/StockTickerPublisher.java\" rel=\"noopener noreferrer\" target=\"_blank\">Subscription.java<\/a> and the <a href=\"https:\/\/github.com\/graphql-java-kickstart\/graphql-spring-boot\/blob\/0184c4e779a33d17ed64b4d14b03238ceb0518f8\/example-graphql-subscription\/src\/main\/java\/com\/oembedler\/moon\/graphql\/boot\/publishers\/StockTickerPublisher.java\" rel=\"noopener noreferrer\" target=\"_blank\">StockTickerPublisher.java<\/a> sample code.<\/em><\/p>\n<p><strong>Code<\/strong><\/p>\n<p>Code is available on <a href=\"https:\/\/github.com\/putridparrot\/blog-projects\/tree\/master\/GraphQLJava\" rel=\"noopener noreferrer\" target=\"_blank\">GitHub<\/a>.<\/p>\n<p><strong>Disclaimer<\/strong><\/p>\n<p>graphiql does not display subscription events at this time. So I&#8217;ve not tested this subscription code. Hence beware, it may or may not work. I&#8217;ll try to update when I get chance to test it fully.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A previous post Writing a GraphQL service using graphql-dotnet and ASP.NET core covered implementing an ASP.NET application with a GraphQL service. As GraphQL is language\/platform agnostic I wanted to see how to implement a similar little service using Java frameworks. I&#8217;m using JetBrains&#8217; IntelliJ (I think you need the ultimate edition for this) to create [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[189,238],"tags":[],"class_list":["post-6833","post","type-post","status-publish","format-standard","hentry","category-graphql","category-spring-boot"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6833","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=6833"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6833\/revisions"}],"predecessor-version":[{"id":6843,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6833\/revisions\/6843"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=6833"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=6833"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=6833"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}