PageSourceSearch

https://graphql-java.com/assets/js/f90ade85.57e531a4.js

js graphql-java.com collected 2026-10-02 07:25:07 UTC 9,211 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkwebsite=globalThis.webpackChunkwebsite||[]).push([[1829],{1221(e,t,n){n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>u});const s=JSON.parse('{"id":"subscriptions","title":"Subscriptions","description":"Graphql subscriptions allow you subscribe to a reactive source and as new data arrives a graphql query is applied over that data and the results are passed on.","source":"@site/versioned_docs/version-v25/subscriptions.md","sourceDirName":".","slug":"/subscriptions","permalink":"/documentation/subscriptions","draft":false,"unlisted":false,"editUrl":"https://github.com/graphql-java/graphql-java-page/edit/master/versioned_docs/version-v25/subscriptions.md","tags":[],"version":"v25","frontMatter":{"title":"Subscriptions","date":"2018-09-09T02:52:46.000Z","description":"Graphql subscriptions allow you subscribe to a reactive source and as new data arrives a graphql query is applied over that data and the results are passed on."},"sidebar":"tutorialSidebar","previous":{"title":"Schema","permalink":"/documentation/schema"},"next":{"title":"Upgrade notes","permalink":"/documentation/upgrade-notes"}}');var r=n(4848),i=n(8453);const a={title:"Subscriptions",date:new Date("2018-09-09T02:52:46.000Z"),description:"Graphql subscriptions allow you subscribe to a reactive source and as new data arrives a graphql query is applied over that data and the results are passed on."},o="Subscriptions",c={},u=[{value:"Subscription Queries",id:"subscription-queries",level:2},{value:"Subscription Data Fetchers",id:"subscription-data-fetchers",level:2}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"subscriptions",children:"Subscriptions"})}),"\n",(0,r.jsx)(t.h2,{id:"subscription-queries",children:"Subscription Queries"}),"\n",(0,r.jsx)(t.p,{children:"Graphql subscriptions allow you subscribe to a reactive source and as new data arrives\na graphql query is applied over that data and the results are passed on."}),"\n",(0,r.jsxs)(t.p,{children:["See ",(0,r.jsx)(t.a,{href:"http://graphql.org/blog/subscriptions-in-graphql-and-relay/",children:"http://graphql.org/blog/subscriptions-in-graphql-and-relay/"})," for more general details on\ngraphql subscriptions."]}),"\n",(0,r.jsx)(t.p,{children:"Imagine you have an stock market pricing service and you make a graphql subscription to it like this"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-graphql",children:'subscription StockCodeSubscription {\n  stockQuotes(stockCode:"IBM") {\n    dateTime\n    stockCode\n    stockPrice\n    stockPriceChange\n  }\n}\n'})}),"\n",(0,r.jsxs)(t.p,{children:["graphql subscriptions allow a stream of ",(0,r.jsx)(t.code,{children:"ExecutionResult"})," objects to be sent down each time the stock price\nchanges.  The field selection set will applied to the underlying data and are represented just like any other\ngraphql query."]}),"\n",(0,r.jsxs)(t.p,{children:["What is special is that the initial result of a subscription query is a reactive-streams ",(0,r.jsx)(t.code,{children:"Publisher"})," object which you\nneed to use to get the future values."]}),"\n",(0,r.jsxs)(t.p,{children:["You need to use ",(0,r.jsx)(t.code,{children:"SubscriptionExecutionStrategy"})," as your execution strategy as it has the support for the reactive-streams APIs."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:"GraphQL graphQL = GraphQL\n        .newGraphQL(schema)\n        .subscriptionExecutionStrategy(new SubscriptionExecutionStrategy())\n        .build();\n\nExecutionResult executionResult = graphQL.execute(query);\n\nPublisher<ExecutionResult> stockPriceStream = executionResult.getData();\n"})}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.code,{children:"Publisher<ExecutionResult>"})," here is the publisher of a stream of events.  You need to subscribe to this with your processing\ncode which will look something like the following"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'GraphQL graphQL = GraphQL\n        .newGraphQL(schema)\n        .subscriptionExecutionStrategy(new SubscriptionExecutionStrategy())\n        .build();\n\nString query = "" +\n        "    subscription StockCodeSubscription {\\n" +\n        "        stockQuotes(stockCode:\\"IBM\\") {\\n" +\n        "            dateTime\\n" +\n        "            stockCode\\n" +\n        "            stockPrice\\n" +\n        "            stockPriceChange\\n" +\n        "        }\\n" +\n        "    }\\n";\n\nExecutionResult executionResult = graphQL.execute(query);\n\nPublisher<ExecutionResult> stockPriceStream = executionResult.getData();
1\n\nAtomicReference<Subscription> subscriptionRef = new AtomicReference<>();\nstockPriceStream.subscribe(new Subscriber<ExecutionResult>() {\n\n    @Override\n    public void onSubscribe(Subscription s) {\n        subscriptionRef.set(s);\n        s.request(1);\n    }\n\n    @Override\n    public void onNext(ExecutionResult er) {\n        //\n        // process the next stock price\n        //\n        processStockPriceChange(er.getData());\n\n        //\n        // ask the publisher for one more item please\n        //\n        subscriptionRef.get().request(1);\n    }\n\n    @Override\n    public void onError(Throwable t) {\n        //\n        // The upstream publishing data source has encountered an error\n        // and the subscription is now terminated.  Real production code needs\n        // to decide on a error handling strategy.\n        //\n    }\n\n    @Override\n    public void onComplete() {\n        //\n        // the subscription has completed.  There is not more data\n        //\n    }\n});\n'})}),"\n",(0,r.jsxs)(t.p,{children:["You are now writing reactive-streams code to consume a series of ",(0,r.jsx)(t.code,{children:"ExecutionResults"}),".  You can see\nmore details on reactive-streams code here ",(0,r.jsx)(t.a,{href:"http://www.reactive-streams.org/",children:"http://www.reactive-streams.org/"})]}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.code,{children:"RxJava"})," is a popular implementation of reactive-streams.  Check out ",(0,r.jsx)(t.a,{href:"http://reactivex.io/intro.html",children:"http://reactivex.io/intro.html"})," to find out more\nabout creating Publishers of data and Subscriptions to that data."]}),"\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.code,{children:"Project Reactor"})," is another popular implementation of reactive-streams.  Check out ",(0,r.jsx)(t.a,{href:"https://projectreactor.io/",children:"https://projectreactor.io/"})," as well."]}),"\n",(0,r.jsx)(t.p,{children:"graphql-java only produces a stream of results.  It does not concern itself with sending these over the network on things\nlike web sockets and so on.  That is important but not a concern of the base graphql-java library."}),"\n",(0,r.jsx)(t.p,{children:"We have put together a basic example of using websockets (backed by Jetty) with a simulated stock price application that\nis built using RxJava."}),"\n",(0,r.jsxs)(t.p,{children:["See ",(0,r.jsx)(t.a,{href:"https://github.com/graphql-java/graphql-java-subscription-example",children:"https://github.com/graphql-java/graphql-java-subscription-example"})," for more detailed code on handling network concerns and\nthe like."]}),"\n",(0,r.jsx)(t.h2,{id:"subscription-data-fetchers",children:"Subscription Data Fetchers"}),"\n",(0,r.jsxs)(t.p,{children:["The ",(0,r.jsx)(t.code,{children:"DataFetcher"})," behind a subscription field is responsible for creating the ",(0,r.jsx)(t.code,{children:"Publisher"})," of data.  The objects\nreturn by this Publisher will be mapped over the graphql query as each arrives and then sent back out as an execution result."]}),"\n",(0,r.jsx)(t.p,{children:"You data fetcher is going to look something like this."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-java",children:'DataFetcher<Publisher<StockInfo>> publisherDataFetcher = new DataFetcher<Publisher<StockInfo>>() {\n    @Override\n    public Publisher<StockInfo> get(DataFetchingEnvironment environment) {\n        String stockCodeArg = environment.getArgument("stockCode");\n        return buildPublisherForStockCode(stockCodeArg);\n    }\n};\n'})}),"\n",(0,r.jsx)(t.p,{children:"Now the exact details of how you get that stream of events is up to you and you're reactive code.  graphql-java\ngives you a way to map the graphql query fields over that stream of objects just like a standard graphql query."})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(l,{...e})}):l(e)}},8453(e,t,n){n.d(t,{R:()=>a,x:()=>o});var s=n(6540);const r={},i=s.createContext(r);function a(e){const t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.