{"id":331138,"date":"2022-03-28T09:00:19","date_gmt":"2022-03-28T09:00:19","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=331138"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=331138","title":{"rendered":"<span>\u0415\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e GraphQL \u0438 \u0437\u0430\u0447\u0435\u043c \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0420\u0443\u0441\u0442\u0430\u043c, \u0438 \u044f \u0442\u0435\u0445\u043b\u0438\u0434 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Distillery. \u041c\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0425\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u044b \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 GraphQL<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 GraphQL. \u042d\u0442\u043e \u044f\u0437\u044b\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432 Facebook \u0432 2012 \u0433\u043e\u0434\u0443. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0438 \u043d\u0443\u0436\u0434\u0430\u044e\u0442\u0441\u044f. GraphQL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0438 \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439.\u00a0<\/p>\n<p>\u042d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0437\u043d\u044b\u043c \u0442\u0438\u043f\u0430\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438 \u0441\u0430\u0439\u0442\u0443) \u043d\u0443\u0436\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043d\u0430\u0431\u043e\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u0421 GraphQL \u043c\u044b \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0441\u0445\u0435\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043e\u0442\u0432\u0435\u0442\u0430, \u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0441\u0430\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b.\u00a0<\/p>\n<p>GraphQL \u0430\u043a\u0442\u0443\u0430\u043b\u0435\u043d \u0434\u043b\u044f \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u2014 \u043a\u0430\u043a \u0442\u043e\u0442 \u0436\u0435 Facebook. \u041f\u0440\u0438 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u0430\u0436\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443\u044e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c. \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0441 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439, \u0433\u0434\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b GraphQL \u0441\u0430\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c, \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043b \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u0442\u0440\u043e\u0438\u043b \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u0435\u0439. \u0422\u0430\u043a \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c \u0443 GraphQL \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e REST \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432: \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0443 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b).<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0432\u043e\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 \u044f \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043b \u043d\u0430 \u0434\u0432\u0443\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 Java c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Spring Boot \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u0434\u044b \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"https:\/\/gitlab.com\/distillery-playground\/graphql-in-action.git\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/gitlab.com\/distillery-playground\/graphql-in-action.git<\/u><\/a>.<\/p>\n<p>\u0414\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0440\u0435\u0441\u0443\u0440\u0441 <a href=\"https:\/\/random-data-api.com\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/random-data-api.com<\/u><\/a>.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 (graphql-user) \u0441\u043b\u0443\u0436\u0438\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438, \u0432\u0442\u043e\u0440\u043e\u0439 (graphql-company) \u2014 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\u043c\u0438. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0411\u0414 PostgreSQL. \u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code class=\"xml\">@Data @EqualsAndHashCode(of = { \"id\" }) @Entity(name = \"_user\") @EntityListeners(AuditingEntityListener.class) public class User {   @Id   @GeneratedValue(strategy = GenerationType.IDENTITY)   private Long id;     private String uid;   private String password;   private String firstName;   private String lastName;   private String username;   private String email;   private String gender;   private String phoneNumber;   private String socialInsuranceNumber;   private LocalDate birthday;   private String country;     private String city;   private String streetName;   private String streetAddress;   private String zipCode;   private String cardNumber;     private Long companyId;   @CreatedDate   private Instant createdAt;   @LastModifiedDate   private Instant updatedAt; }  @Data @EqualsAndHashCode(of = { \"id\" }) @Entity(name = \"company\") @EntityListeners(AuditingEntityListener.class) public class Company {   @Id   @GeneratedValue(strategy = GenerationType.IDENTITY)   private Long id;   private String uid;   private String businessName;   private String suffix;   private String industry;   private String catchPhrase;     private String buzzword;   private String bsCompanyStatement;   private String employeeIdentificationNumber;   private String dunsNumber;   private String logo;   private String type;   private String phoneNumber;   private String fullAddress;   private Float latitude;   private Float longitude;   @CreatedDate   private Instant createdAt;   @LastModifiedDate   private Instant updatedAt; }<\/code><\/pre>\n<p>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 graphql-company \u0434\u043b\u044f \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438. \u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u044b:<\/p>\n<pre><code>@Component @RequiredArgsConstructor public class GraphqlCompanyClientImpl implements GraphqlCompanyClient {    private final RestTemplate graphqlCompanyRestTemplate;   private final GraphqlCompanyProperties properties;    @Override   @Retryable(interceptor = \"graphqlCompanyRetryInterceptor\")   public CompanyDto getCompany(Long id) {     try {       var builder = UriComponentsBuilder.fromPath(properties.getCompanyUrl()).queryParam(\"id\", id);       return graphqlCompanyRestTemplate           .exchange(builder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference&lt;CompanyDto>() {           }).getBody();     } catch (ResourceAccessException e) {       throw new DownstreamException(Downstream.GRAPHQL_COMPANY, e);     }   } }<\/code><\/pre>\n<p>C\u0435\u0440\u0432\u0435\u0440 GraphQL \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442 \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><strong>graphql-spring-boot-starter<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u043b\u0435\u0442\u0430 GraphQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e \u043f\u0443\u0442\u0438 \/graphql. \u041e\u043d \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 GraphQLSchema \u0431\u0438\u043d.<\/p>\n<\/li>\n<li>\n<p><strong>graphql-java<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 GraphQL.<\/p>\n<\/li>\n<\/ul>\n<p><strong>graphiql-spring-boot-starter<\/strong> \u2013 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 GraphQL \u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<pre><code>&lt;!-- GraphQL dependencies --> &lt;dependency>     &lt;groupId>com.graphql-java&lt;\/groupId>     &lt;artifactId>graphql-spring-boot-starter&lt;\/artifactId>     &lt;version>5.0.2&lt;\/version> &lt;\/dependency>     &lt;dependency>     &lt;groupId>com.graphql-java&lt;\/groupId>     &lt;artifactId>graphql-java-tools&lt;\/artifactId>     &lt;version>5.2.4&lt;\/version> &lt;\/dependency>     &lt;dependency>     &lt;groupId>com.graphql-java&lt;\/groupId>     &lt;artifactId>graphiql-spring-boot-starter&lt;\/artifactId>     &lt;version>5.0.2&lt;\/version> &lt;\/dependency><\/code><\/pre>\n<p>GraphQL API \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0430 \u0434\u0432\u0443\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u0445: \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 (queries) \u0438 \u0441\u0445\u0435\u043c\u0435 (schema).<\/p>\n<p>GraphQL \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f Schema Definition Language. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0432\u0441\u0435\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 API, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435. \u0421\u0445\u0435\u043c\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u043d\u0430\u0448\u0438\u043c GraphQL \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>scalar Date  type User { id: ID!, uid: String, password: String, firstName: String, lastName: String, username: String, email: String, gender: String, phoneNumber: String, socialInsuranceNumber: String, birthday: Date, country: String, city: String, streetName: String, streetAddress: String, zipCode: String, cardNumber: String, company: Company }  type Company { id: ID!, uid: String, businessName: String, suffix: String, industry: String, catchPhrase: String, buzzword: String, bsCompanyStatement: String, employeeIdentificationNumber: String, dunsNumber: String, logo: String, type: String, phoneNumber: String, fullAddress: String, latitude: Float!, longitude: Float! }  type Query { getUsers(isAddCompany: Boolean!):[User] getUser(id: ID!, isAddCompany: Boolean!):User }  type Mutation { createUser(uid: String, password: String, firstName: String, lastName: String, username: String, email: String, gender: String, phoneNumber: String, socialInsuranceNumber: String, birthday: Date!, country: String, city: String, streetName: String, streetAddress: String, zipCode: String, cardNumber: String, companyId: ID!):User updateUser(id: ID!, uid: String, password: String, firstName: String, lastName: String, username: String, email: String, gender: String, phoneNumber: String, socialInsuranceNumber: String, birthday: Date!, country: String, city: String, streetName: String, streetAddress: String, zipCode: String, cardNumber: String, companyId: ID!):User }<\/code><\/pre>\n<p>\u0412 \u043d\u0435\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0442\u0438\u043f\u044b \u2014 User \u0438 Company, \u043c\u0435\u0442\u043e\u0434\u044b \u2014 getUser, getUsers, createUser \u0438 updateUser, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u0441\u043a\u0430\u043b\u044f\u0440\u043d\u044b\u0439 \u0442\u0438\u043f Date, \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<pre><code>@Component public class DateScalarType extends GraphQLScalarType {      private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(\"dd-MM-yyyy\");    public DateScalarType() {     super(\"Date\", \"Date\", new Coercing&lt;Object, Object>() {       @Override       public Object serialize(Object o) throws CoercingSerializeException {         return ((LocalDate) o).format(formatter);       }        @Override       public Object parseValue(Object o) throws CoercingParseValueException {         return o;       }        @Override       public Object parseLiteral(Object o) throws CoercingParseLiteralException {         if (o == null) {           return null;         }         return LocalDate.parse(((StringValue) o).getValue(), formatter);       }     });   } }<\/code><\/pre>\n<p>\u0421\u0445\u0435\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445 \u0432 \u043f\u0430\u043f\u043a\u0435 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00abgraphql\u00bb. \u0424\u0430\u0439\u043b \u0441\u0445\u0435\u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u00abgraphqls\u00bb. \u0412\u0441\u0435 \u043f\u043e\u043b\u044f, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0442\u0438\u043f\u0430\u0445, \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<p>\u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 GraphQLMutationResolver \u0438 GraphQLQueryResolver. \u0412 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e GraphQLMutationResolver \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0430 \u0432 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e GraphQLQueryResolver \u2013 \u043c\u0435\u0442\u043e\u0434\u044b \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code>@Component @RequiredArgsConstructor public class UserMutation implements GraphQLMutationResolver {      private final UserService userService;      public UserDto createUser(String uid, String password, String firstName, String lastName, String username,       String email, String gender, String phoneNumber, String socialInsuranceNumber, LocalDate birthday, String country,       String city, String streetName, String streetAddress, String zipCode, String cardNumber, Long companyId) {     return userService.createUser(uid, password, firstName, lastName, username,         email, gender, phoneNumber, socialInsuranceNumber, birthday, country, city, streetName, streetAddress, zipCode,         cardNumber, companyId);   }      public UserDto updateUser(Long id, String uid, String password, String firstName, String lastName, String username,       String email, String gender, String phoneNumber, String socialInsuranceNumber, LocalDate birthday, String country,       String city, String streetName, String streetAddress, String zipCode, String cardNumber, Long companyId) {     return userService.updateUser(id, uid, password, firstName, lastName, username,         email, gender, phoneNumber, socialInsuranceNumber, birthday, country, city, streetName, streetAddress, zipCode,         cardNumber, companyId);   } } @Component @RequiredArgsConstructor public class UserQuery implements GraphQLQueryResolver {    private final UserService userService;    public List&lt;UserDto> getUsers(boolean isAddCompany) {     return userService.getUsers(isAddCompany);   }    public Optional&lt;UserDto> getUser(Long id, boolean isAddCompany) {     return userService.getUser(id, isAddCompany);   } }<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.<\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c GraphiQL. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"http:\/\/localhost:8080\/graphiql\" rel=\"noopener noreferrer nofollow\"><u>http:\/\/localhost:8080\/graphiql<\/u><\/a>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/b29\/49d\/9d1\/b2949d9d122c270004b53d3f87d7a5e6.jpg\" width=\"1551\" height=\"713\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b29\/49d\/9d1\/b2949d9d122c270004b53d3f87d7a5e6.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u00a0\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 GraphQL (query) \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u0417\u0430\u0442\u0435\u043c \u043e\u043d\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0432\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON. \u041d\u0435\u0432\u0430\u0436\u043d\u043e, \u043e\u0442\u043a\u0443\u0434\u0430 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439.<\/p>\n<p>\u041f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 Postman:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/5ea\/084\/164\/5ea084164603d8bb2b52aa20e6396bc0.jpg\" width=\"1448\" height=\"623\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5ea\/084\/164\/5ea084164603d8bb2b52aa20e6396bc0.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<pre><code>curl --location --request POST 'http:\/\/localhost:8080\/graphql' \\ --header 'Content-Type: application\/json' \\ --data-raw '{\"query\":\"query {\\r\\n    getUsers(isAddCompany: true) {\\r\\n        id,\\r\\n        uid,\\r\\n        password,\\r\\n        firstName,\\r\\n        lastName,\\r\\n        username,\\r\\n        birthday,\\r\\n        company {\\r\\n            id,\\r\\n            uid,\\r\\n            businessName,\\r\\n            phoneNumber,\\r\\n            fullAddress\\r\\n        }\\r\\n    }\\r\\n}\",\"variables\":{}}'<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432 GraphiQL:<\/p>\n<p>1. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<pre><code>mutation {   createUser(     uid: \"8aa68c80-4635-461f-8707-0bf5b7691119\",     password: \"qwerty\",     firstName: \"James\",   lastName: \"Bond\",     username: \"bond007\",     email: \"james.bond@distillery.com\",     gender: \"Male\",     phoneNumber: \"+77777777777\",     socialInsuranceNumber: null,  birthday: \"11-11-1991\",     country: \"Russia\",     city: \"Moscow\",     streetName: \"1 May\",     streetAddress: \"777\",     zipCode: null,     cardNumber: null,   companyId: 10)   {id} }<\/code><\/pre>\n<p>2. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<pre><code>mutation {   updateUser(     id: 8,     uid: \"8aa68c80-4635-461f-8707-0bf5b7691119\",     password: \"123\",     firstName: \"James\",   lastName: \"Bond\",     username: \"bond007\",     email: \"james.bond@distillery.com\",     gender: \"Male\",     phoneNumber: \"+77777777777\",     socialInsuranceNumber: null,  birthday: \"11-11-1991\",     country: \"Russia\",     city: \"Moscow\",     streetName: \"1 May\",     streetAddress: \"777\",     zipCode: null,     cardNumber: null,   companyId: 10)   {     id,     uid,     password,     firstName,   lastName,     username,     email,     gender,     phoneNumber,     socialInsuranceNumber,  birthday,     country,     city,     streetName,     streetAddress,     zipCode,     cardNumber,   company {       id,       uid,       businessName,       phoneNumber,       fullAddress     }   } }<\/code><\/pre>\n<p>3. \u0417\u0430\u043f\u0440\u043e\u0441 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c id.<\/p>\n<pre><code>query {   getUser(id: 3876, isAddCompany: true) {     id,     uid,     password,     firstName,     lastName,     username,     birthday,     company {       id,       uid,       businessName,       phoneNumber,       fullAddress     }   } }<\/code><\/pre>\n<p>GraphQL \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0441 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u2014 REST \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f BFF (Backend-for-Frontend), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u043e\u043c \u0441\u043b\u043e\u0435 \u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \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\/657739\/\"> https:\/\/habr.com\/ru\/post\/657739\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0420\u0443\u0441\u0442\u0430\u043c, \u0438 \u044f \u0442\u0435\u0445\u043b\u0438\u0434 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Distillery. \u041c\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0425\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u044b \u0441 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0435\u0439 GraphQL<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 GraphQL. \u042d\u0442\u043e \u044f\u0437\u044b\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432 Facebook \u0432 2012 \u0433\u043e\u0434\u0443. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043d\u0438 \u043d\u0443\u0436\u0434\u0430\u044e\u0442\u0441\u044f. GraphQL \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0438 \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439.\u00a0<\/p>\n<p>\u042d\u0442\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0437\u043d\u044b\u043c \u0442\u0438\u043f\u0430\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438 \u0441\u0430\u0439\u0442\u0443) \u043d\u0443\u0436\u043d\u044b \u0440\u0430\u0437\u043d\u044b\u0435 \u043d\u0430\u0431\u043e\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u0421 GraphQL \u043c\u044b \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0441\u0445\u0435\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043e\u0442\u0432\u0435\u0442\u0430, \u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0441\u0430\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b.\u00a0<\/p>\n<p>GraphQL \u0430\u043a\u0442\u0443\u0430\u043b\u0435\u043d \u0434\u043b\u044f \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u2014 \u043a\u0430\u043a \u0442\u043e\u0442 \u0436\u0435 Facebook. \u041f\u0440\u0438 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u0430\u0436\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0430\u0444\u0438\u043a\u0430 \u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0443\u044e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c. \u0412 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0441 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439, \u0433\u0434\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b GraphQL \u0441\u0430\u043c \u043e\u0431\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c, \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043b \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u0442\u0440\u043e\u0438\u043b \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u0435\u0439. \u0422\u0430\u043a \u043e\u0442\u0441\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c \u0443 GraphQL \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e REST \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432: \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0432\u043b\u0435\u0447\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u0432\u0435\u0441\u0442\u0438 \u043e\u0434\u0438\u043d \u0437\u0430\u043f\u0440\u043e\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0443 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b).<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0432\u043e\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 \u044f \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043b \u043d\u0430 \u0434\u0432\u0443\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 Java c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Spring Boot \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u0434\u044b \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"https:\/\/gitlab.com\/distillery-playground\/graphql-in-action.git\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/gitlab.com\/distillery-playground\/graphql-in-action.git<\/u><\/a>.<\/p>\n<p>\u0414\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0440\u0435\u0441\u0443\u0440\u0441 <a href=\"https:\/\/random-data-api.com\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/random-data-api.com<\/u><\/a>.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 (graphql-user) \u0441\u043b\u0443\u0436\u0438\u0442 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438, \u0432\u0442\u043e\u0440\u043e\u0439 (graphql-company) \u2014 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\u043c\u0438. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0411\u0414 PostgreSQL. \u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438\u043c\u0435\u044e\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code class=\"xml\">@Data @EqualsAndHashCode(of = { \"id\" }) @Entity(name = \"_user\") @EntityListeners(AuditingEntityListener.class) public class User {   @Id   @GeneratedValue(strategy = GenerationType.IDENTITY)   private Long id;     private String uid;   private String password;   private String firstName;   private String lastName;   private String username;   private String email;   private String gender;   private String phoneNumber;   private String socialInsuranceNumber;   private LocalDate birthday;   private String country;     private String city;   private String streetName;   private String streetAddress;   private String zipCode;   private String cardNumber;     private Long companyId;   @CreatedDate   private Instant createdAt;   @LastModifiedDate   private Instant updatedAt; }  @Data @EqualsAndHashCode(of = { \"id\" }) @Entity(name = \"company\") @EntityListeners(AuditingEntityListener.class) public class Company {   @Id   @GeneratedValue(strategy = GenerationType.IDENTITY)   private Long id;   private String uid;   private String businessName;   private String suffix;   private String industry;   private String catchPhrase;     private String buzzword;   private String bsCompanyStatement;   private String employeeIdentificationNumber;   private String dunsNumber;   private String logo;   private String type;   private String phoneNumber;   private String fullAddress;   private Float latitude;   private Float longitude;   @CreatedDate   private Instant createdAt;   @LastModifiedDate   private Instant updatedAt; }<\/code><\/pre>\n<p>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 graphql-company \u0434\u043b\u044f \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438. \u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437 HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u044b:<\/p>\n<pre><code>@Component @RequiredArgsConstructor public class GraphqlCompanyClientImpl implements GraphqlCompanyClient {    private final RestTemplate graphqlCompanyRestTemplate;   private final GraphqlCompanyProperties properties;    @Override   @Retryable(interceptor = \"graphqlCompanyRetryInterceptor\")   public CompanyDto getCompany(Long id) {     try {       var builder = UriComponentsBuilder.fromPath(properties.getCompanyUrl()).queryParam(\"id\", id);       return graphqlCompanyRestTemplate           .exchange(builder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference&lt;CompanyDto>() {           }).getBody();     } catch (ResourceAccessException e) {       throw new DownstreamException(Downstream.GRAPHQL_COMPANY, e);     }   } }<\/code><\/pre>\n<p>C\u0435\u0440\u0432\u0435\u0440 GraphQL \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442 \u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439:<\/p>\n<ul>\n<li>\n<p><strong>graphql-spring-boot-starter<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u043b\u0435\u0442\u0430 GraphQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e \u043f\u0443\u0442\u0438 \/graphql. \u041e\u043d \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 GraphQLSchema \u0431\u0438\u043d.<\/p>\n<\/li>\n<li>\n<p><strong>graphql-java<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 GraphQL.<\/p>\n<\/li>\n<\/ul>\n<p><strong>graphiql-spring-boot-starter<\/strong> \u2013 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430 GraphQL \u0438 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<pre><code>&lt;!-- GraphQL dependencies --> &lt;dependency>     &lt;groupId>com.graphql-java&lt;\/groupId>     &lt;artifactId>graphql-spring-boot-starter&lt;\/artifactId>     &lt;version>5.0.2&lt;\/version> &lt;\/dependency>     &lt;dependency>     &lt;groupId>com.graphql-java&lt;\/groupId>     &lt;artifactId>graphql-java-tools&lt;\/artifactId>     &lt;version>5.2.4&lt;\/version> &lt;\/dependency>     &lt;dependency>     &lt;groupId>com.graphql-java&lt;\/groupId>     &lt;artifactId>graphiql-spring-boot-starter&lt;\/artifactId>     &lt;version>5.0.2&lt;\/version> &lt;\/dependency><\/code><\/pre>\n<p>GraphQL API \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0430 \u0434\u0432\u0443\u0445 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u0445: \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 (queries) \u0438 \u0441\u0445\u0435\u043c\u0435 (schema).<\/p>\n<p>GraphQL \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0445\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f Schema Definition Language. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0432\u0441\u0435\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 API, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435. \u0421\u0445\u0435\u043c\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u043d\u0430\u0448\u0438\u043c GraphQL \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>scalar Date  type User { id: ID!, uid: String, password: String, firstName: String, lastName: String, username: String, email: String, gender: String, phoneNumber: String, socialInsuranceNumber: String, birthday: Date, country: String, city: String, streetName: String, streetAddress: String, zipCode: String, cardNumber: String, company: Company }  type Company { id: ID!, uid: String, businessName: String, suffix: String, industry: String, catchPhrase: String, buzzword: String, bsCompanyStatement: String, employeeIdentificationNumber: String, dunsNumber: String, logo: String, type: String, phoneNumber: String, fullAddress: String, latitude: Float!, longitude: Float! }  type Query { getUsers(isAddCompany: Boolean!):[User] getUser(id: ID!, isAddCompany: Boolean!):User }  type Mutation { createUser(uid: String, password: String, firstName: String, lastName: String, username: String, email: String, gender: String, phoneNumber: String, socialInsuranceNumber: String, birthday: Date!, country: String, city: String, streetName: String, streetAddress: String, zipCode: String, cardNumber: String, companyId: ID!):User updateUser(id: ID!, uid: String, password: String, firstName: String, lastName: String, username: String, email: String, gender: String, phoneNumber: String, socialInsuranceNumber: String, birthday: Date!, country: String, city: String, streetName: String, streetAddress: String, zipCode: String, cardNumber: String, companyId: ID!):User }<\/code><\/pre>\n<p>\u0412 \u043d\u0435\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0442\u0438\u043f\u044b \u2014 User \u0438 Company, \u043c\u0435\u0442\u043e\u0434\u044b \u2014 getUser, getUsers, createUser \u0438 updateUser, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u0441\u043a\u0430\u043b\u044f\u0440\u043d\u044b\u0439 \u0442\u0438\u043f Date, \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<pre><code>@Component public class DateScalarType extends GraphQLScalarType {      private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(\"dd-MM-yyyy\");    public DateScalarType() {     super(\"Date\", \"Date\", new Coercing&lt;Object, Object>() {       @Override       public Object serialize(Object o) throws CoercingSerializeException {         return ((LocalDate) o).format(formatter);       }        @Override       public Object parseValue(Object o) throws CoercingParseValueException {         return o;       }        @Override       public Object parseLiteral(Object o) throws CoercingParseLiteralException {         if (o == null) {           return null;         }         return LocalDate.parse(((StringValue) o).getValue(), formatter);       }     });   } }<\/code><\/pre>\n<p>\u0421\u0445\u0435\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u0445 \u0432 \u043f\u0430\u043f\u043a\u0435 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00abgraphql\u00bb. \u0424\u0430\u0439\u043b \u0441\u0445\u0435\u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u00abgraphqls\u00bb. \u0412\u0441\u0435 \u043f\u043e\u043b\u044f, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0442\u0438\u043f\u0430\u0445, \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<p>\u0414\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 GraphQLMutationResolver \u0438 GraphQLQueryResolver. \u0412 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e GraphQLMutationResolver \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0430 \u0432 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e GraphQLQueryResolver \u2013 \u043c\u0435\u0442\u043e\u0434\u044b \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code>@Component @RequiredArgsConstructor public class UserMutation implements GraphQLMutationResolver {      private final UserService userService;      public UserDto createUser(String uid, String password, String firstName, String lastName, String username,       String email, String gender, String phoneNumber, String socialInsuranceNumber, LocalDate birthday, String country,       String city, String streetName, String streetAddress, String zipCode, String cardNumber, Long companyId) {     return userService.createUser(uid, password, firstName, lastName, username,         email, gender, phoneNumber, socialInsuranceNumber, birthday, country, city, streetName, streetAddress, zipCode,         cardNumber, companyId);   }      public UserDto updateUser(Long id, String uid, String password, String firstName, String lastName, String username,       String email, String gender, String phoneNumber, String socialInsuranceNumber,<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\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-331138","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/331138","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=331138"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/331138\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=331138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=331138"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=331138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}