{"id":322812,"date":"2021-05-09T15:00:34","date_gmt":"2021-05-09T15:00:34","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=322812"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=322812","title":{"rendered":"\u0421\u043e\u0437\u0434\u0430\u0435\u043c GraphQL API \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Guice \u0438 Spark"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/817\/261\/f31\/817261f318ece574a0acb1247b598069.png\" width=\"780\" height=\"440\"><figcaption><\/figcaption><\/figure>\n<p><a href=\"https:\/\/github.com\/graphql\/graphql-spec\" rel=\"noopener noreferrer nofollow\">GraphQL<\/a> \u044d\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e API \u0434\u043b\u044f \u0446\u0435\u043b\u043e\u0433\u043e \u0432\u043e\u0440\u043e\u0445\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u043d\u043e \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f Java \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u0438\u0448\u044c \u043e\u0434\u0438\u043d \u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 <a href=\"https:\/\/spring.io\/projects\/spring-framework\" rel=\"noopener noreferrer nofollow\">Spring Framework<\/a>. \u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433 \u043d\u0430 \u0441\u0432\u044f\u0437\u043a\u0435 <a href=\"https:\/\/github.com\/google\/guice\" rel=\"noopener noreferrer nofollow\">Google Guice<\/a> \u0438 <a href=\"https:\/\/sparkjava.com\/\" rel=\"noopener noreferrer nofollow\">Spark<\/a>. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u043c <a href=\"https:\/\/www.graphql-java.com\/tutorials\/getting-started-with-spring-boot\/\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0430\u043b\u043e\u043c<\/a>, \u0442.\u043a. \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0443\u0433\u043b\u0443\u0431\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 <a href=\"https:\/\/github.com\/graphql-java\/graphql-java\" rel=\"noopener noreferrer nofollow\">GraphQL Java<\/a> <\/p>\n<h4>1. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Guice \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u0417\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c <a href=\"https:\/\/gradle.org\/\" rel=\"noopener noreferrer nofollow\">Gradle<\/a>. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443, \u0432 \u043d\u0435\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 <code>gradle init<\/code><\/p>\n<p>\u041d\u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>Select type of project to generate: application Select implementation language: Java Select build script DSL: Kotlin Select test framework: JUnit Jupiter Project name: guice-spark-graphql Source package: guice.spark.graphql<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0432\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 Java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>src\/main\/java\/guice\/spark\/graphql\/App.java<\/code><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043d\u0430\u0448\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>build.gradle.kts<\/code><\/p>\n<pre><code class=\"kotlin\">dependencies {     \/\/ This dependency is used by the application.     implementation(\"com.google.guava:guava:29.0-jre\")     \/\/Guice     implementation(\"com.google.inject:guice:5.0.1\") \/\/NEW      \/\/Spark     implementation(\"com.sparkjava:spark-core:2.9.3\") \/\/NEW     implementation(\"com.sparkjava:spark-template-velocity:2.7.1\") \/\/\/\/NEW spark template engine     implementation(\"org.slf4j:slf4j-simple:1.7.21\") \/\/NEW fix Spark SLF4J: Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".     implementation(\"com.fasterxml.jackson.core:jackson-databind:2.12.3\") \/\/NEW      \/\/graphql     implementation(\"com.graphql-java:graphql-java:16.2\") \/\/NEW      \/\/ Use JUnit Jupiter API for testing.     testImplementation(\"org.junit.jupiter:junit-jupiter-api:5.6.2\")      \/\/ Use JUnit Jupiter Engine for testing.     testRuntimeOnly(\"org.junit.jupiter:junit-jupiter-engine:5.6.2\") } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 Guice, GraphQL \u0438 Spark \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 <abbr title=\"\u0427\u0442\u043e\u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u043b\u043e\u0433 Spark\">Slf4j<\/abbr>, <abbr title=\"\u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Json\">Jackson<\/abbr> \u0438 <abbr title=\"\u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u0435\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f GraphQL Playground\">Velocity Template<\/abbr>. Guava \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b, \u043d\u043e \u0441 \u043d\u0438\u043c\u0438 \u0436\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043a\u0430\u043a-\u0442\u043e \u043f\u0440\u043e\u0449\u0435<\/p>\n<h4>2. \u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 GraphQL<\/h4>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f GraphQL \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c API. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b <code>schema.graphqls<\/code> \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>src\/main\/resources<\/code><\/p>\n<pre><code class=\"json\">type Query {   bookById(id: ID): Book  }  type Book {   id: ID   name: String   pageCount: Int   author: Author }  type Author {   id: ID   firstName: String   lastName: String }<\/code><\/pre>\n<h4>3. \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Guice <\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Guice DI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>src\/main\/java\/guice\/spark\/graphql\/App.java<\/code><\/p>\n<pre><code class=\"java\">public class App {     @Inject     private GraphQLService service;      public static void main(String[] args) {         App app = new App();          Injector injector = Guice.createInjector(new GraphQLModule());         injector.injectMembers(app);          app.service.initialize();     } } <\/code><\/pre>\n<p>Guice \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043d\u043e\u0432\u044b\u0439 Injector, \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 GraphQLModule \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>injector.injectMembers(app)<\/code>\u0432 \u043f\u043e\u043b\u0435 service \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0438\u0441 <code>GraphQLService<\/code>, \u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/p>\n<h4>4. GraphQLModule<\/h4>\n<p>\u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 Guice \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043c\u043e\u0434\u0443\u043b\u044f\u0445. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>src\/main\/java\/guice\/spark\/graphql\/GraphQLModule.java<\/code><\/p>\n<pre><code class=\"java\">public class GraphQLModule extends AbstractModule {     protected void configure() {         bind(GraphQLService.class).asEagerSingleton();         bind(GraphQL.class).toProvider(GraphQlProvider.class).asEagerSingleton();         bind(ObjectMapper.class).asEagerSingleton();     } }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>configure<\/code>\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code>GraphQLService<\/code> \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 Spark \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 c \u043f\u043e\u043c\u043e\u0449\u044c\u044e Spark, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u044f \u0438\u0445 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 GraphQL<\/p>\n<\/li>\n<li>\n<p><code>GraphQL<\/code>\u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>ObjectMapper<\/code>\u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432 JSON \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443<\/p>\n<\/li>\n<\/ul>\n<h4>5. GraphQlProvider<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0448 <code>GraphQL<\/code>\u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c <code>Provider<\/code> \u0432 Guice, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u0443\u0436\u0438\u0442 \u0444\u0430\u0431\u0440\u0438\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 <code>GraphQlProvider<\/code><\/p>\n<pre><code class=\"java\">public class GraphQlProvider implements Provider&lt;GraphQL&gt; {      private GraphQLDataFetchers graphQLDataFetchers;      @Inject     public GraphQlProvider(GraphQLDataFetchers graphQLDataFetchers) {         this.graphQLDataFetchers = graphQLDataFetchers;     }      @Override     public GraphQL get() {         URL url = Resources.getResource(\"schema.graphqls\");         String sdl = null;         try {             sdl = Resources.toString(url, Charsets.UTF_8);         } catch (IOException e) {             e.printStackTrace();         }         GraphQLSchema graphQLSchema = buildSchema(sdl);         return GraphQL.newGraphQL(graphQLSchema).build();      }      private GraphQLSchema buildSchema(String sdl) {         TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);         RuntimeWiring runtimeWiring = buildWiring();         SchemaGenerator schemaGenerator = new SchemaGenerator();         return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);     }      private RuntimeWiring buildWiring() {         return RuntimeWiring.newRuntimeWiring()                 .type(newTypeWiring(\"Query\")                         .dataFetcher(\"bookById\", graphQLDataFetchers.getBookByIdDataFetcher()))                 .type(newTypeWiring(\"Book\")                         .dataFetcher(\"author\", graphQLDataFetchers.getAuthorDataFetcher()))                 .build();     } } <\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 get() \u0432\u0435\u0440\u043d\u0435\u0442 \u043d\u0430\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439, \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 GraphQL \u0438\u043d\u0441\u0442\u0430\u043d\u0441. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u043b\u0438 \u0432\u044b\u0448\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/p>\n<h4>6. GraphQLDataFetchers<\/h4>\n<p><code>DataFetcher<\/code> \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 GraphQL Java. DataFetcher \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u044e \u0431\u0438\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>src\/main\/java\/guice\/spark\/graphql\/GraphQLDataFetchers.java<\/code><\/p>\n<pre><code class=\"java\">@Singleton public class GraphQLDataFetchers {     private static List&lt;Map&lt;String, String&gt;&gt; books = Arrays.asList(             ImmutableMap.of(\"id\", \"book-1\",                     \"name\", \"Harry Potter and the Philosopher's Stone\",                     \"pageCount\", \"223\",                     \"authorId\", \"author-1\"),             ImmutableMap.of(\"id\", \"book-2\",                     \"name\", \"Moby Dick\",                     \"pageCount\", \"635\",                     \"authorId\", \"author-2\"),             ImmutableMap.of(\"id\", \"book-3\",                     \"name\", \"Interview with the vampire\",                     \"pageCount\", \"371\",                     \"authorId\", \"author-3\")     );      private static List&lt;Map&lt;String, String&gt;&gt; authors = Arrays.asList(             ImmutableMap.of(\"id\", \"author-1\",                     \"firstName\", \"Joanne\",                     \"lastName\", \"Rowling\"),             ImmutableMap.of(\"id\", \"author-2\",                     \"firstName\", \"Herman\",                     \"lastName\", \"Melville\"),             ImmutableMap.of(\"id\", \"author-3\",                     \"firstName\", \"Anne\",                     \"lastName\", \"Rice\")     );      public DataFetcher getBookByIdDataFetcher() {         return dataFetchingEnvironment -&gt; {             String bookId = dataFetchingEnvironment.getArgument(\"id\");             return books                     .stream()                     .filter(book -&gt; book.get(\"id\").equals(bookId))                     .findFirst()                     .orElse(null);         };     }      public DataFetcher getAuthorDataFetcher() {         return dataFetchingEnvironment -&gt; {             Map&lt;String, String&gt; book = dataFetchingEnvironment.getSource();             String authorId = book.get(\"authorId\");             return authors                     .stream()                     .filter(author -&gt; author.get(\"id\").equals(authorId))                     .findFirst()                     .orElse(null);         };     } }<\/code><\/pre>\n<p>\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@Singleton<\/code>\u0441\u043e\u043e\u0431\u0449\u0438\u0442 Guice \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043a\u0442\u043e-\u0442\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 <abbr title=\"\u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435\">\u0441\u043e\u0437\u0434\u0430\u043d<\/abbr> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d. \u0412 \u0442\u0430\u043a\u0438\u0445 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0431\u043b\u043e\u043a\u0435 <code>configure<\/code>\u043c\u043e\u0434\u0443\u043b\u044f <code>GraphQLModule<\/code>\u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u0442\u0430\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 &#8212; \u044d\u0442\u043e \u043f\u043e\u0432\u044b\u0441\u0438\u0442 \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430<\/p>\n<h4>7. GraphQLService<\/h4>\n<p>\u041f\u043e\u0440\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 API \u043f\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c web \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041a\u0430\u043a \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435 \u0437\u0430 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>GraphQLService<\/code><\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0433\u043e <code>src\/main\/java\/guice\/spark\/graphql\/GraphQLService.java<\/code><\/p>\n<pre><code class=\"java\">public class GraphQLService {     private final GraphQL graphQL;     private final ObjectMapper mapper;      @Inject     public GraphQLService(GraphQL graphQL, ObjectMapper mapper) {         this.graphQL = graphQL;         this.mapper = mapper;     }      public void initialize() {         post(\"\/graphql\", (request, response) -&gt; {             GraphQLRequestBody body = mapper.readValue(request.body(), GraphQLRequestBody.class);              String query = body.getQuery();             if (query == null) {                 query = \"\";             }              ExecutionResult executionResult = graphQL.execute(                     ExecutionInput.newExecutionInput()                             .query(query)                             .operationName(body.getOperationName())                             .variables(body.getVariables())                             .build()             );              response.type(\"application\/json\");             return mapper.writeValueAsString(executionResult.toSpecification());         });                  get(\"\/playground\", (req, res) -&gt; new VelocityTemplateEngine().render(                 new ModelAndView(Collections.emptyMap(), \"playground.html\"))         );     } <\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u043a \u043c\u0435\u0442\u043e\u0434\u0443 <code>initialize<\/code>\u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d <a href=\"https:\/\/www.eclipse.org\/jetty\/\" rel=\"noopener noreferrer nofollow\">Jetty<\/a> web server \u043d\u0430 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443 <strong>4567<\/strong>. \u041c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0434\u0432\u0430 \u0435\u043d\u0434\u043f\u043e\u0439\u043d\u0442\u0430: <\/p>\n<p>\u041f\u0440\u0438 <strong>POST<\/strong> \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 \u0430\u0434\u0440\u0435\u0441 <a href=\"http:\/\/localhost:4567\/graphql\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:4567\/graphql<\/a> <code>ObjectMapper<\/code> \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0435\u0433\u043e \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 <code>GraphQLRequestBody<\/code> \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 GraphQL \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0443 \u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435. \u041e\u0442\u0432\u0435\u0442  \u0432\u0438\u0434\u0435 JSON \u0432\u0435\u0440\u043d\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p>\u041d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 <code>GraphQLRequestBody:<\/code><\/p>\n<pre><code>public class GraphQLRequestBody {     private String query;     private String operationName;     private Map&lt;String, Object&gt; variables;      public String getQuery() {         return query;     }      public void setQuery(String query) {         this.query = query;     }      public String getOperationName() {         return operationName;     }      public void setOperationName(String operationName) {         this.operationName = operationName;     }      public Map&lt;String, Object&gt; getVariables() {         return variables;     }      public void setVariables(Map&lt;String, Object&gt; variables) {         this.variables = variables;     } }<\/code><\/pre>\n<p>\u041f\u0440\u0438 <strong>GET <\/strong>\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0430 \u0430\u0434\u0440\u0435\u0441<a href=\"http:\/\/localhost:4567\/playground\" rel=\"noopener noreferrer nofollow\"> http:\/\/localhost:4567\/playground<\/a> \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0435\u043d playground.html \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u043f\u0430\u043f\u043a\u0443 <code>src\/main\/resources<\/code>. \u042d\u0442\u043e \u043d\u0430\u0448 \u0442\u0443\u043b \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 API \u043f\u0440\u044f\u043c\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435. \u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/github.com\/graphql\/graphql-playground\/blob\/main\/packages\/graphql-playground-html\/minimal.html%20\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a> <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0430\u0434\u0440\u0435\u0441 <a href=\"http:\/\/localhost:4567\/playground\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:4567\/playground<\/a> \u0438 \u0432\u0438\u0434\u0438\u043c \u043d\u0430\u0448\u0443 \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c65\/347\/b6d\/c65347b6d8d854edea3caf263e4640a0.png\" width=\"1176\" height=\"801\"><figcaption><\/figcaption><\/figure>\n<h4>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448 API<\/h4>\n<p>\u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code>query {   bookById(id: \"book-1\") {     name,     author {       firstName     }   } } <\/code><\/pre>\n<p>\u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 API:<\/p>\n<pre><code>{   \"data\": {     \"bookById\": {       \"name\": \"Harry Potter and the Philosopher's Stone\",       \"author\": {         \"firstName\": \"Joanne\"       }     }   } }<\/code><\/pre>\n<h4>\u041f\u043e\u043b\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f<\/h4>\n<ul>\n<li>\n<p>\u0412\u0441\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0437\u0434\u0435\u0441\u044c <a href=\"https:\/\/github.com\/fzn7\/guice-spark-graphql\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/fzn7\/guice-spark-graphql<\/a><\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e GraphQL \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 <a href=\"https:\/\/github.com\/graphql-java\/\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/graphql-java\/<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/556478\/\"> https:\/\/habr.com\/ru\/post\/556478\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p><a href=\"https:\/\/github.com\/graphql\/graphql-spec\" rel=\"noopener noreferrer nofollow\">GraphQL<\/a> \u044d\u0442\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043f\u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e API \u0434\u043b\u044f \u0446\u0435\u043b\u043e\u0433\u043e \u0432\u043e\u0440\u043e\u0445\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c, \u043d\u043e \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f Java \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u0438\u0448\u044c \u043e\u0434\u0438\u043d \u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0431\u0430\u0437\u0435 <a href=\"https:\/\/spring.io\/projects\/spring-framework\" rel=\"noopener noreferrer nofollow\">Spring Framework<\/a>. \u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0430\u043d\u0430\u043b\u043e\u0433 \u043d\u0430 \u0441\u0432\u044f\u0437\u043a\u0435 <a href=\"https:\/\/github.com\/google\/guice\" rel=\"noopener noreferrer nofollow\">Google Guice<\/a> \u0438 <a href=\"https:\/\/sparkjava.com\/\" rel=\"noopener noreferrer nofollow\">Spark<\/a>. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u043c <a href=\"https:\/\/www.graphql-java.com\/tutorials\/getting-started-with-spring-boot\/\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0430\u043b\u043e\u043c<\/a>, \u0442.\u043a. \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u0443\u0433\u043b\u0443\u0431\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 <a href=\"https:\/\/github.com\/graphql-java\/graphql-java\" rel=\"noopener noreferrer nofollow\">GraphQL Java<\/a> <\/p>\n<h4>1. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Guice \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u0417\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c <a href=\"https:\/\/gradle.org\/\" rel=\"noopener noreferrer nofollow\">Gradle<\/a>. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443, \u0432 \u043d\u0435\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 <code>gradle init<\/code><\/p>\n<p>\u041d\u0430 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>Select type of project to generate: application Select implementation language: Java Select build script DSL: Kotlin Select test framework: JUnit Jupiter Project name: guice-spark-graphql Source package: guice.spark.graphql<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0432\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 Java \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0442\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <code>src\/main\/java\/guice\/spark\/graphql\/App.java<\/code><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u043d\u0430\u0448\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>build.gradle.kts<\/code><\/p>\n<pre><code class=\"kotlin\">dependencies {     \/\/ This dependency is used by the application.     implementation(\"com.google.guava:guava:29.0-jre\")     \/\/Guice     implementation(\"com.google.inject:guice:5.0.1\") \/\/NEW      \/\/Spark     implementation(\"com.sparkjava:spark-core:2.9.3\") \/\/NEW     implementation(\"com.sparkjava:spark-template-velocity:2.7.1\") \/\/\/\/NEW spark template engine     implementation(\"org.slf4j:slf4j-simple:1.7.21\") \/\/NEW fix Spark SLF4J: Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".     implementation(\"com.fasterxml.jackson.core:jackson-databind:2.12.3\") \/\/NEW      \/\/graphql     implementation(\"com.graphql-java:graphql-java:16.2\") \/\/NEW      \/\/ Use JUnit Jupiter API for testing.     testImplementation(\"org.junit.jupiter:junit-jupiter-api:5.6.2\")      \/\/ Use JUnit Jupiter Engine for testing.     testRuntimeOnly(\"org.junit.jupiter:junit-jupiter-engine:5.6.2\") } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 Guice, GraphQL \u0438 Spark \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 <abbr title=\"\u0427\u0442\u043e\u0431\u044b \u0432\u0438\u0434\u0435\u0442\u044c \u043b\u043e\u0433 Spark\">\u043b\u043e\u0433 Spark&#187;>Slf4j<\/abbr>, <abbr title=\"\u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Json\"> \u0441 Json&#187;>Jackson<\/abbr> \u0438 <abbr title=\"\u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u0435\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f GraphQL Playground\">\u0435\u043d\u0438\u044f GraphQL Playground&#187;>Velocity Template<\/abbr>. Guava \u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b, \u043d\u043e \u0441 \u043d\u0438\u043c\u0438 \u0436\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043a\u0430\u043a-\u0442\u043e \u043f\u0440\u043e\u0449\u0435<\/p>\n<h4>2. \u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 GraphQL<\/h4>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f GraphQL \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c API. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0444\u0430\u0439\u043b <code>schema.graphqls<\/code> \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>src\/main\/resources<\/code><\/p>\n<pre><code class=\"json\">type Query {   bookById(id: ID): Book  }  type Book {   id: ID   name: String   pageCount: Int   author: Author }  type Author {   id: ID   firstName: String   lastName: String }<\/code><\/pre>\n<h4>3. \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Guice <\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Guice DI \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432 \u0444\u0430\u0439\u043b\u0435 <code>src\/main\/java\/guice\/spark\/graphql\/App.java<\/code><\/p>\n<pre><code class=\"java\">public class App {     @Inject     private GraphQLService service;      public static void main(String[] args) {         App app = new App();          Injector injector = Guice.createInjector(new GraphQLModule());         injector.injectMembers(app);          app.service.initialize();     } } <\/code><\/pre>\n<p>Guice \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043d\u043e\u0432\u044b\u0439 Injector, \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 GraphQLModule \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>injector.injectMembers(app)<\/code>\u0432 \u043f\u043e\u043b\u0435 service \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0438\u0441 <code>GraphQLService<\/code>, \u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/p>\n<h4>4. GraphQLModule<\/h4>\n<p>\u041e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 Guice \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043c\u043e\u0434\u0443\u043b\u044f\u0445. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>src\/main\/java\/guice\/spark\/graphql\/GraphQLModule.java<\/code><\/p>\n<pre><code class=\"java\">public class GraphQLModule extends AbstractModule {     protected void configure() {         bind(GraphQLService.class).asEagerSingleton();         bind(GraphQL.class).toProvider(GraphQlProvider.class).asEagerSingleton();         bind(ObjectMapper.class).asEagerSingleton();     } }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>configure<\/code>\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><code>GraphQLService<\/code> \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 Spark \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 c \u043f\u043e\u043c\u043e\u0449\u044c\u044e Spark, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u044f \u0438\u0445 \u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 GraphQL<\/p>\n<\/li>\n<li>\n<p><code>GraphQL<\/code>\u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>ObjectMapper<\/code>\u0431\u0443\u0434\u0435\u0442 \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432 JSON \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443<\/p>\n<\/li>\n<\/ul>\n<h4>5. GraphQlProvider<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0448 <code>GraphQL<\/code>\u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c <code>Provider<\/code> \u0432 Guice, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u0443\u0436\u0438\u0442 \u0444\u0430\u0431\u0440\u0438\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0441 <code>GraphQlProvider<\/code><\/p>\n<pre><code class=\"java\">public class GraphQlProvider implements Provider&lt;GraphQL&gt; {      private GraphQLDataFetchers graphQLDataFetchers;      @Inject     public GraphQlProvider(GraphQLDataFetchers graphQLDataFetchers) {         this.graphQLDataFetchers = graphQLDataFetchers;     }      @Override     public GraphQL get() {         URL url = Resources.getResource(\"schema.graphqls\");         String sdl = null;         try {             sdl = Resources.toString(url, Charsets.UTF_8);         } catch (IOException e) {             e.printStackTrace();         }         GraphQLSchema graphQLSchema = buildSchema(sdl);         return GraphQL.newGraphQL(graphQLSchema).build();      }      private GraphQLSchema buildSchema(String sdl) {         TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);         RuntimeWiring runtimeWiring = buildWiring();         SchemaGenerator schemaGenerator = new SchemaGenerator();         return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);     }      private RuntimeWiring buildWiring() {         return RuntimeWiring.newRuntimeWiring()                 .type(newTypeWiring(\"Query\")                         .dataFetcher(\"bookById\", graphQLDataFetchers.getBookByIdDataFetcher()))                 .type(newTypeWiring(\"Book\")                         .dataFetcher(\"author\", graphQLDataFetchers.getAuthorDataFetcher()))                 .build();     } } <\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 get() \u0432\u0435\u0440\u043d\u0435\u0442 \u043d\u0430\u043c \u0433\u043e\u0442\u043e\u0432\u044b\u0439, \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 GraphQL \u0438\u043d\u0441\u0442\u0430\u043d\u0441. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u043b\u0438 \u0432\u044b\u0448\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/p>\n<h4>6. GraphQLDataFetchers<\/h4>\n<p><code>DataFetcher<\/code> \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 GraphQL Java. DataFetcher \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0441\u044e \u0431\u0438\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b <code>src\/main\/java\/guice\/spark\/graphql\/GraphQLDataFetchers.java<\/code><\/p>\n<pre><code class=\"java\">@Singleton public class GraphQLDataFetchers {     private static List&lt;Map&lt;String, String&gt;&gt; books = Arrays.asList(             ImmutableMap.of(\"id\", \"book-1\",                     \"name\", \"Harry Potter and the Philosopher's Stone\",                     \"pageCount\", \"223\",                     \"authorId\", \"author-1\"),             ImmutableMap.of(\"id\", \"book-2\",                     \"name\", \"Moby Dick\",                     \"pageCount\", \"635\",                     \"authorId\", \"author-2\"),             ImmutableMap.of(\"id\", \"book-3\",                     \"name\", \"Interview with the vampire\",                     \"pageCount\", \"371\",                     \"authorId\", \"author-3\")     );      private static List&lt;Map&lt;String, String&gt;&gt; authors = Arrays.asList(             ImmutableMap.of(\"id\", \"author-1\",                     \"firstName\", \"Joanne\",                     \"lastName\", \"Rowling\"),             ImmutableMap.of(\"id\", \"author-2\",                     \"firstName\", \"Herman\",                     \"lastName\", \"Melville\"),             ImmutableMap.of(\"id\", \"author-3\",                     \"firstName\", \"Anne\",                     \"lastName\", \"Rice\")     );      public DataFetcher getBookByIdDataFetcher() {         return dataFetchingEnvironment -&gt; {             String bookId = dataFetchingEnvironment.getArgument(\"id\");             return books                     .stream()                     .filter(book -&gt; book.get(\"id\").equals(bookId))                     .findFirst()                     .orElse(null);         };     }      public DataFetcher getAuthorDataFetcher() {         return dataFetchingEnvironment -&gt; {             Map&lt;String, String&gt; book = dataFetchingEnvironment.getSource();             String authorId = book.get(\"authorId\");             return authors                     .stream()                     .filter(author -&gt; author.get(\"id\").equals(authorId))                     .findFirst()                     .orElse(null);         };     } }<\/code><\/pre>\n<p>\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f <code>@Singleton<\/code>\u0441\u043e\u043e\u0431\u0449\u0438\u0442 Guice \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043a\u0442\u043e-\u0442\u043e \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 <abbr title=\"\u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435\"> \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435&#187;>\u0441\u043e\u0437\u0434\u0430\u043d<\/abbr> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d. \u0412 \u0442\u0430\u043a\u0438\u0445 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0431\u043b\u043e\u043a\u0435 <code>configure<\/code>\u043c\u043e\u0434\u0443\u043b\u044f <code>GraphQLModule<\/code>\u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0435\u0433\u043e \u0442\u0430\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 &#8212; \u044d\u0442\u043e \u043f\u043e\u0432\u044b\u0441\u0438\u0442 \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430<\/p>\n<h4>7. GraphQLService<\/h4>\n<p>\u041f\u043e\u0440\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 API \u043f\u043e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c web \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041a\u0430\u043a \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435 \u0437\u0430 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>GraphQLService<\/code><\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0433\u043e <code>src\/main\/java\/guice\/spark\/graphql\/GraphQLService.java<\/code><\/p>\n<pre><code class=\"java\">public class GraphQLService {     private final GraphQL graphQL;     private final ObjectMapper mapper;      @Inject     public GraphQLService(GraphQL graphQL, ObjectMapper mapper) {         this.graphQL = graphQL;         this.mapper = mapper;     }      public void initialize() {         post(\"\/graphql\", (request, response) -&gt; {             GraphQLRequestBody body = mapper.readValue(request.body(), GraphQLRequestBody.class);              String query = body.getQuery();             if (query == null) {                 query = \"\";             }              ExecutionResult executionResult = graphQL.execute(                     ExecutionInput.newExecutionInput()                             .query(query)                             .operationName(body.getOperationName())                             .variables(body.getVariables())                             .build()             );              response.type(\"application\/json\");             return mapper.writeValueAsString(executionResult.toSpecification());         });                  get(\"\/playground\", (req, res) -&gt; new VelocityTemplateEngine().render(                 new ModelAndView(Collections.emptyMap(), \"playground.html\"))         );     } <\/code><\/pre>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u043a \u043c\u0435\u0442\u043e\u0434\u0443 <code>ini<\/code><\/p>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-322812","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/322812","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=322812"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/322812\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=322812"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=322812"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=322812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}