{"id":357364,"date":"2024-05-20T23:49:17","date_gmt":"2024-05-20T23:49:17","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=357364"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=357364","title":{"rendered":"<span>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 gRPC \u0441\u0435\u0440\u0432\u0438\u0441\u0430 (Spring Boot \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435)<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u043e\u043f\u044b\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <em>gRPC<\/em> \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <em>gRPC<\/em>-\u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 <em>Spring Boot<\/em>. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u044d\u0442\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e <em>gRPC<\/em> \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 <em>gRPC<\/em> \u0438 \u0438\u0449\u0435\u0442 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f <em>proto<\/em>-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e <em>interface-grpc<\/em>. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 pom.xml \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <em>gRPC<\/em>:<\/p>\n<pre><code class=\"xml\">&lt;dependencies>     &lt;dependency>         &lt;groupId>io.grpc&lt;\/groupId>         &lt;artifactId>grpc-stub&lt;\/artifactId>     &lt;\/dependency>     &lt;dependency>         &lt;groupId>io.grpc&lt;\/groupId>         &lt;artifactId>grpc-protobuf&lt;\/artifactId>     &lt;\/dependency>     &lt;dependency>         &lt;groupId>jakarta.annotation&lt;\/groupId>         &lt;artifactId>jakarta.annotation-api&lt;\/artifactId>         &lt;optional>true&lt;\/optional>     &lt;\/dependency>     &lt;dependency>         &lt;groupId>com.google.protobuf&lt;\/groupId>         &lt;artifactId>protobuf-java&lt;\/artifactId>         &lt;scope>compile&lt;\/scope>     &lt;\/dependency> &lt;\/dependencies><\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <em>build<\/em> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0437 <em>proto<\/em>-\u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"xml\">&lt;build>     &lt;extensions>         &lt;extension>             &lt;groupId>kr.motd.maven&lt;\/groupId>             &lt;artifactId>os-maven-plugin&lt;\/artifactId>         &lt;\/extension>     &lt;\/extensions>      &lt;plugins>         &lt;plugin>             &lt;groupId>org.xolstice.maven.plugins&lt;\/groupId>             &lt;artifactId>protobuf-maven-plugin&lt;\/artifactId>             &lt;configuration>                 &lt;protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}&lt;\/protocArtifact>                 &lt;pluginId>grpc-java&lt;\/pluginId>                 &lt;pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}&lt;\/pluginArtifact>             &lt;\/configuration>             &lt;executions>                 &lt;execution>                     &lt;goals>                         &lt;goal>compile&lt;\/goal>                         &lt;goal>compile-custom&lt;\/goal>                     &lt;\/goals>                 &lt;\/execution>             &lt;\/executions>         &lt;\/plugin>     &lt;\/plugins> &lt;\/build> <\/code><\/pre>\n<h3>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 gRPC \u0421\u0435\u0440\u0432\u0438\u0441\u0430<\/h3>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f \u0432\u0435\u0442\u0435\u0440\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0438\u043d\u0438\u043a\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c <em>proto<\/em>-\u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 &#171;\u043f\u0438\u0442\u043e\u043c\u0435\u0446&#187;:<\/p>\n<pre><code class=\"go\">syntax = \"proto3\";  package grpc.server.grpc_server.pet;  message CreatePetRequest {   Pet pet = 1;    message Pet {     string pet_name = 2;     string pet_type = 3;     string pet_birth_date = 4;   } }  message CreatePetResponse{   int32 pet_id = 1; }  message FindByIdPetRequest {   int32 pet_id = 1; }  message FindByIdPetResponse {   Pet pet = 1;    message Pet {     string pet_name = 2;     string pet_type = 3;   } }  message ErrorResponse {   string error_name = 1; }  service PetService {   rpc CreatePet (CreatePetRequest) returns (CreatePetResponse);   rpc FindByIDPet (FindByIdPetRequest) returns (FindByIdPetResponse); }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <em>proto<\/em>-\u0444\u0430\u0439\u043b\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e97\/4e9\/432\/e974e943214a232ffd1c2ae18e701e3d.png\" width=\"844\" height=\"488\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e97\/4e9\/432\/e974e943214a232ffd1c2ae18e701e3d.png\"\/><\/figure>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f gRPC \u0421\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 Spring Boot<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u043c\u043e\u0434\u0443\u043b\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u2013 <em>clinic-grpc-service. Pom<\/em>-\u0444\u0430\u0439\u043b \u0443 \u043c\u0435\u043d\u044f \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 class=\"xml\">    &lt;dependencies>         &lt;dependency>             &lt;groupId>net.devh&lt;\/groupId>             &lt;artifactId>grpc-server-spring-boot-autoconfigure&lt;\/artifactId>         &lt;\/dependency>       &lt;!--test -->         &lt;dependency>             &lt;groupId>net.devh&lt;\/groupId>             &lt;artifactId>grpc-client-spring-boot-autoconfigure&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-test&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.junit.jupiter&lt;\/groupId>             &lt;artifactId>junit-jupiter-api&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.testcontainers&lt;\/groupId>             &lt;artifactId>junit-jupiter&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.junit.jupiter&lt;\/groupId>             &lt;artifactId>junit-jupiter-engine&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency><\/code><\/pre>\n<p>\u041e\u043f\u0438\u0448\u0435\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 Pet \u0438 PetType, \u0430 \u0442\u0430\u043a\u0436\u0435 DTO \u043a\u043b\u0430\u0441\u0441\u044b. \u0417\u0430\u0442\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 PetService \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0438\u0442\u043e\u043c\u0446\u0430.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <em>PetRequestDTO<\/em> \u0438 <em>PetResponseDTO<\/em>.<\/p>\n<pre><code class=\"java\">@Builder public record PetRequestDTO(         @JsonProperty(\"pet_name\") String petName,         @JsonProperty(\"pet_type\") String petType,         @JsonProperty(\"pet_birth_date\") String petBirthDate ){}  @Builder public record PetResponseDTO(         @JsonProperty(\"pet_name\") String petName,         @JsonProperty(\"pet_type\") String petType ){}<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <em>PetService<\/em> c \u0434\u0432\u0443\u043c\u044f \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438: \u043d\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"java\">public interface PetService {      int createPet(PetRequestDTO pet);      PetResponseDTO findByIDPet(int id); }<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a\u00a0\u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 \u2013 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <em>gRPC<\/em> <em>service<\/em> <em>GrpcPetServiceImpl<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <em>PetServiceGrpc<\/em>.<em>PetServiceImplBase<\/em>. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b <em>createPet <\/em>\u0438<em> findByIDPet<\/em>.<br \/>\u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u0447\u0442\u043e\u00a0\u043c\u0435\u0442\u043e\u0434 \u043d\u0435\u00a0\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u044f\u0432\u043d\u043e. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u00a0\u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u00a0\u0432\u0442\u043e\u0440\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u0430. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c <em>gRPC<\/em> \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e\u00a0\u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043d\u0435\u00a0\u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442, \u0430\u00a0\u0441\u0442\u0440\u0438\u043c\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (<em>response)<\/em> \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 <em>StreamObserver<\/em>. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u0441\u043e\u0431\u0435\u0440\u0435\u043c <em>response<\/em> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <em>newBuilder(),<\/em> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u0441\u044b\u043b\u0430\u0442\u044c \u043d\u0430\u0448 \u043e\u0442\u0432\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b  <em>onNext()<\/em>. \u0417\u0430\u0432\u0435\u0440\u0448\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 <em>onCompleted()<\/em>.<\/p>\n<pre><code class=\"java\">@GrpcService @RequiredArgsConstructor public class GrpcPetServiceImpl extends PetServiceGrpc.PetServiceImplBase {     private final PetService petService;      @Override     public void createPet(PetOuterClass.CreatePetRequest request,                           StreamObserver&lt;PetOuterClass.CreatePetResponse> responseObserver) {          PetRequestDTO petRequestDTO = PetRequestDTO.builder()                 .petName(request.getPet().getPetName())                 .petType(request.getPet().getPetType())                 .petBirthDate(request.getPet().getPetBirthDate())                 .build();          PetOuterClass.CreatePetResponse response = PetOuterClass.CreatePetResponse                 .newBuilder()                 .setPetId(petService.createPet(petRequestDTO))                 .build();          responseObserver.onNext(response);         responseObserver.onCompleted();     }      @Override     public void findByIDPet(PetOuterClass.FindByIdPetRequest request,                             StreamObserver&lt;PetOuterClass.FindByIdPetResponse> responseObserver) {          PetResponseDTO pet = petService.findByIDPet(request.getPetId());          if (pet == null) {             Metadata.Key&lt;PetOuterClass.ErrorResponse> errorResponseKey =                     ProtoUtils.keyForProto(PetOuterClass.ErrorResponse.getDefaultInstance());             PetOuterClass.ErrorResponse errorResponse = PetOuterClass.ErrorResponse.newBuilder()                     .setErrorName(\"This pet with id = \" + request.getPetId() + \" is not in the database\")                     .build();             Metadata metadata = new Metadata();             metadata.put(errorResponseKey, errorResponse);             responseObserver.onError(                     NOT_FOUND.withDescription(\"This pet with id = \" + request.getPetId() + \" is not found\")                             .asRuntimeException(metadata)             );             return;         }         PetOuterClass.FindByIdPetResponse response = PetOuterClass.FindByIdPetResponse                 .newBuilder()                 .setPet(PetOuterClass.FindByIdPetResponse.Pet                         .newBuilder()                         .setPetName(pet.petName())                         .setPetType(pet.petType())                         .build())                 .build();          responseObserver.onNext(response);         responseObserver.onCompleted();     } }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 <em>\u043a\u043e\u043d\u0441\u043e\u043b\u044c<\/em>. \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0438\u0442\u043e\u043c\u0446\u0430 \u0438 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0435\u0433\u043e.<\/p>\n<pre><code class=\"bash\">VetClinicApp % grpcurl -plaintext -d '{\"pet\":{\"pet_name\":\"Joo\",\"pet_type\":\"dog\",\"pet_birth_date\":\"2023-09-01\"}}' localhost:9090 ru.vyrostkov.grpc.server.grpc_server.pet.PetService\/CreatePet    {   \"pet_id\": 1 } <\/code><\/pre>\n<pre><code class=\"bash\">VetClinicApp % grpcurl -plaintext -d '{\"pet_id\":1}' localhost:9090 ru.vyrostkov.grpc.server.grpc_server.pet.PetService\/FindByIDPet  {   \"pet\": {     \"pet_name\": \"Joo\",     \"pet_type\": \"dog\"   } } <\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 gRPC<\/h3>\n<p>\u0412\u0441\u0451 \u043e\u0442\u043b\u0438\u0447\u043d\u043e, \u0441\u0435\u0440\u0432\u0438\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043c \u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0432 \u0431\u0430\u0437\u0435? \u0421\u0435\u0440\u0432\u0438\u0441 \u0443\u043f\u0430\u0434\u0451\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 <strong><em>java.lang.NullPointerException: Cannot invoke &#171;ru.vyrostkov.grpc.dto.PetResponseDTO.getPetName()&#187; because &#171;pet&#187; is null<\/em><\/strong><em>.<\/em><\/p>\n<p>\u0427\u0442\u043e \u0431\u044b \u0442\u0430\u043a\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0448\u0438\u0431\u043e\u043a. \u0412 <em>proto<\/em>-\u0444\u0430\u0439\u043b\u0435 \u043e\u043f\u0438\u0441\u0430\u043b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 <em>message<\/em> <em>ErrorResponse<\/em>. \u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<pre><code class=\"go\">message ErrorResponse {   string error_name = 1; }<\/code><\/pre>\n<p><em>\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435<\/em> \u2013 \u044d\u0442\u043e \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0443\u044e \u0441 <em>RPC<\/em>.<\/p>\n<p>\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 <em>gRPC<\/em> \u2013 \u044d\u0442\u043e \u043f\u0430\u0440\u0430 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0438\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u0430\u043c\u0438 gRPC.<\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u0440\u044b \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043b\u044e\u0447 <em>Metadata.Key&lt;PetOuterClass.ErrorResponse><\/em>, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f <em>ErrorResponse<\/em>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043f\u0430\u0440\u044b \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u044b\u0437\u044b\u0432\u0430\u044f <em>metadata.put(Key,Value)<\/em>. \u0418 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c <em>responseObserver<\/em>, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0432 \u043d\u0435\u0433\u043e <em>StatusRuntimeException<\/em>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u0440\u043e\u043a\u0438\u043d\u0435\u043c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 <em>Status<\/em>.<\/p>\n<pre><code class=\"java\">Metadata.Key&lt;PetOuterClass.ErrorResponse> errorResponseKey =                     ProtoUtils.keyForProto(PetOuterClass.ErrorResponse.getDefaultInstance());             PetOuterClass.ErrorResponse errorResponse = PetOuterClass.ErrorResponse.newBuilder()                     .setErrorName(\"\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0432\u0435\u0440\u043d\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445\")                     .build();              Metadata metadata = new Metadata();             metadata.put(errorResponseKey, errorResponse);              responseObserver.onError(                     NOT_FOUND.withDescription(\"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438\")                             .asRuntimeException(metadata)             );<\/code><\/pre>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <em>io.grpc.Status<\/em> \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043e\u0448\u0438\u0431\u043a\u0438. \u0424\u0443\u043d\u043a\u0446\u0438\u044f <em>responseObserver::onError<\/em> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 <em>Throwable<\/em>-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 <em>asRuntimeException<\/em> (\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435) \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f <em>Status<\/em> \u0432 <em>Throwable<\/em>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u2013 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u0435\u0440\u043d\u0451\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0430 \u043d\u0435 \u0443\u043f\u0430\u0434\u0451\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<pre><code class=\"bash\">m.vyrostkov@macbook-KL920DXTK4 VetClinicApp % grpcurl -plaintext -d '{\"pet_id\":2}' localhost:9090 ru.vyrostkov.grpc.server.grpc_server.pet.PetService\/FindByIDPet  ERROR:   Code: NotFound   Message: This pet with id = 2 is not found <\/code><\/pre>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043a\u0440\u043e\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 <em>mockito<\/em> \u0438 <em>spring-boot-test<\/em>. \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 <a class=\"mention\" href=\"\/users\/GrpcClient\">@GrpcClient<\/a>, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432\u044b\u0437\u043e\u0432 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430\u0448\u0435\u0433\u043e <em>gRPC<\/em> \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0443 \u0434\u043b\u044f <em>petService<\/em>. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438  \u0442\u0435\u0441\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"java\">@SpringBootTest(properties = {         \"grpc.server.inProcessName=test\",         \"grpc.server.port=9091\",         \"grpc.client.petService.address=in-process:test\" }) @SpringJUnitConfig(classes = {GrpcApplication.class}) @Log4j2 public class GrpcPetServiceImplTest {      @MockBean     PetService petService;     @GrpcClient(\"petService\")     private PetServiceGrpc.PetServiceBlockingStub petServiceBlockingStub;        final int petId = 1;        Pet pet;     PetRequestDTO petRequestDTO;     PetResponseDTO petResponseDTO;      @BeforeEach     void setUp() {         pet = Pet                 .builder()                 .name(\"Bob\")                 .petType(PetType.builder().name(\"dog\").build())                 .birthDate(LocalDate.parse(\"2020-12-11\"))                 .build();          petRequestDTO = PetRequestDTO                 .builder()                 .petName(\"Bob\")                 .petType(\"dog\")                 .petBirthDate(\"2020-12-11\")                 .build();          petResponseDTO = PetResponseDTO                 .builder()                 .petName(\"Bob\")                 .petType(\"dog\")                 .build();     }      @Test     @DisplayName(\"JUnit grpc test for find pet by id\")     public void findByIDPetTest() {          doReturn(petResponseDTO)                 .when(petService)                 .findByIDPet(anyInt());          PetOuterClass.FindByIdPetRequest request =                 PetOuterClass.FindByIdPetRequest                         .newBuilder()                         .setPetId(petId)                         .build();          PetOuterClass.FindByIdPetResponse response =                 petServiceBlockingStub.findByIDPet(request);          assertThat(response).isNotNull();         assertThat(response.getPet().getPetName()).isEqualTo(pet.getName());         verify(petService).findByIDPet(petId);     }      @Test     @DisplayName(\"JUnit grpc test for find pet by id when pet not found\")     public void PetNotFoundWhenFindByIDTest() throws Exception {          doReturn(null)                 .when(petService)                 .findByIDPet(anyInt());          PetOuterClass.FindByIdPetRequest request =                 PetOuterClass.FindByIdPetRequest                         .newBuilder()                         .setPetId(petId)                         .build();          StatusRuntimeException thrown =                 Assertions.assertThrows(StatusRuntimeException.class, () ->                         petServiceBlockingStub.findByIDPet(request));          assertThat(thrown.getStatus().getCode().toString())                 .isEqualTo(\"NOT_FOUND\");         assertThat(thrown.getMessage())                 .isEqualTo(\"NOT_FOUND: This pet with id = 1 is not found\");         Metadata metadata = Status.trailersFromThrowable(thrown);         PetOuterClass.ErrorResponse errorResponse =                 metadata.get(ProtoUtils.keyForProto(                                 PetOuterClass.ErrorResponse.getDefaultInstance()                         )                 );         assertThat(errorResponse.getErrorName())                 .isEqualTo(\"This pet with id = 1 is not in the database\");          verify(petService).findByIDPet(petId);     } }<\/code><\/pre>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041c\u044b \u043f\u043e\u043a\u0440\u044b\u043b\u0438 \u043d\u0430\u0448 <em>gRPC<\/em> \u0441\u0435\u0440\u0432\u0438\u0441 \u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u043e\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0438 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 gRPC \u0432 Spring Boot \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0438\u0445 \u043d\u0430\u0434\u0435\u0436\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0432 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0438 gRPC \u0438 \u0443\u043b\u0443\u0447\u0448\u0438\u0442 \u0432\u0430\u0448\u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 Spring Boot.<\/p>\n<p>GitHub \u043f\u0440\u043e\u0435\u043a\u0442\u0430 : <a href=\"https:\/\/github.com\/mikhail-vyrostkov\/VetClinicApp\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/mikhail-vyrostkov\/VetClinicApp<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/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\/articles\/767130\/\"> https:\/\/habr.com\/ru\/articles\/767130\/<\/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 article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u043e\u043f\u044b\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <em>gRPC<\/em> \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <em>gRPC<\/em>-\u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 <em>Spring Boot<\/em>. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u2014 \u044d\u0442\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043f\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u043c\u0443 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e <em>gRPC<\/em> \u0441\u0435\u0440\u0432\u0438\u0441\u0430. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 <em>gRPC<\/em> \u0438 \u0438\u0449\u0435\u0442 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h3>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f <em>proto<\/em>-\u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e <em>interface-grpc<\/em>. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 pom.xml \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <em>gRPC<\/em>:<\/p>\n<pre><code class=\"xml\">&lt;dependencies>     &lt;dependency>         &lt;groupId>io.grpc&lt;\/groupId>         &lt;artifactId>grpc-stub&lt;\/artifactId>     &lt;\/dependency>     &lt;dependency>         &lt;groupId>io.grpc&lt;\/groupId>         &lt;artifactId>grpc-protobuf&lt;\/artifactId>     &lt;\/dependency>     &lt;dependency>         &lt;groupId>jakarta.annotation&lt;\/groupId>         &lt;artifactId>jakarta.annotation-api&lt;\/artifactId>         &lt;optional>true&lt;\/optional>     &lt;\/dependency>     &lt;dependency>         &lt;groupId>com.google.protobuf&lt;\/groupId>         &lt;artifactId>protobuf-java&lt;\/artifactId>         &lt;scope>compile&lt;\/scope>     &lt;\/dependency> &lt;\/dependencies><\/code><\/pre>\n<p>\u0412 \u0431\u043b\u043e\u043a\u0435 <em>build<\/em> \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043b\u0430\u0433\u0438\u043d \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0437 <em>proto<\/em>-\u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"xml\">&lt;build>     &lt;extensions>         &lt;extension>             &lt;groupId>kr.motd.maven&lt;\/groupId>             &lt;artifactId>os-maven-plugin&lt;\/artifactId>         &lt;\/extension>     &lt;\/extensions>      &lt;plugins>         &lt;plugin>             &lt;groupId>org.xolstice.maven.plugins&lt;\/groupId>             &lt;artifactId>protobuf-maven-plugin&lt;\/artifactId>             &lt;configuration>                 &lt;protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}&lt;\/protocArtifact>                 &lt;pluginId>grpc-java&lt;\/pluginId>                 &lt;pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}&lt;\/pluginArtifact>             &lt;\/configuration>             &lt;executions>                 &lt;execution>                     &lt;goals>                         &lt;goal>compile&lt;\/goal>                         &lt;goal>compile-custom&lt;\/goal>                     &lt;\/goals>                 &lt;\/execution>             &lt;\/executions>         &lt;\/plugin>     &lt;\/plugins> &lt;\/build> <\/code><\/pre>\n<h3>\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 gRPC \u0421\u0435\u0440\u0432\u0438\u0441\u0430<\/h3>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043b\u044f \u0432\u0435\u0442\u0435\u0440\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u043a\u043b\u0438\u043d\u0438\u043a\u0438. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c <em>proto<\/em>-\u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 &#171;\u043f\u0438\u0442\u043e\u043c\u0435\u0446&#187;:<\/p>\n<pre><code class=\"go\">syntax = \"proto3\";  package grpc.server.grpc_server.pet;  message CreatePetRequest {   Pet pet = 1;    message Pet {     string pet_name = 2;     string pet_type = 3;     string pet_birth_date = 4;   } }  message CreatePetResponse{   int32 pet_id = 1; }  message FindByIdPetRequest {   int32 pet_id = 1; }  message FindByIdPetResponse {   Pet pet = 1;    message Pet {     string pet_name = 2;     string pet_type = 3;   } }  message ErrorResponse {   string error_name = 1; }  service PetService {   rpc CreatePet (CreatePetRequest) returns (CreatePetResponse);   rpc FindByIDPet (FindByIdPetRequest) returns (FindByIdPetResponse); }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f <em>proto<\/em>-\u0444\u0430\u0439\u043b\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f gRPC \u0421\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 Spring Boot<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0435\u0449\u0451 \u043e\u0434\u0438\u043d \u043c\u043e\u0434\u0443\u043b\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u2013 <em>clinic-grpc-service. Pom<\/em>-\u0444\u0430\u0439\u043b \u0443 \u043c\u0435\u043d\u044f \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 class=\"xml\">    &lt;dependencies>         &lt;dependency>             &lt;groupId>net.devh&lt;\/groupId>             &lt;artifactId>grpc-server-spring-boot-autoconfigure&lt;\/artifactId>         &lt;\/dependency>       &lt;!--test -->         &lt;dependency>             &lt;groupId>net.devh&lt;\/groupId>             &lt;artifactId>grpc-client-spring-boot-autoconfigure&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.springframework.boot&lt;\/groupId>             &lt;artifactId>spring-boot-test&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.junit.jupiter&lt;\/groupId>             &lt;artifactId>junit-jupiter-api&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.testcontainers&lt;\/groupId>             &lt;artifactId>junit-jupiter&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency>         &lt;dependency>             &lt;groupId>org.junit.jupiter&lt;\/groupId>             &lt;artifactId>junit-jupiter-engine&lt;\/artifactId>             &lt;scope>test&lt;\/scope>         &lt;\/dependency><\/code><\/pre>\n<p>\u041e\u043f\u0438\u0448\u0435\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 Pet \u0438 PetType, \u0430 \u0442\u0430\u043a\u0436\u0435 DTO \u043a\u043b\u0430\u0441\u0441\u044b. \u0417\u0430\u0442\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 PetService \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0438\u0442\u043e\u043c\u0446\u0430.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <em>PetRequestDTO<\/em> \u0438 <em>PetResponseDTO<\/em>.<\/p>\n<pre><code class=\"java\">@Builder public record PetRequestDTO(         @JsonProperty(\"pet_name\") String petName,         @JsonProperty(\"pet_type\") String petType,         @JsonProperty(\"pet_birth_date\") String petBirthDate ){}  @Builder public record PetResponseDTO(         @JsonProperty(\"pet_name\") String petName,         @JsonProperty(\"pet_type\") String petType ){}<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <em>PetService<\/em> c \u0434\u0432\u0443\u043c\u044f \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438: \u043d\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"java\">public interface PetService {      int createPet(PetRequestDTO pet);      PetResponseDTO findByIDPet(int id); }<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043c\u044b \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a\u00a0\u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 \u2013 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <em>gRPC<\/em> <em>service<\/em> <em>GrpcPetServiceImpl<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <em>PetServiceGrpc<\/em>.<em>PetServiceImplBase<\/em>. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b <em>createPet <\/em>\u0438<em> findByIDPet<\/em>.<br \/>\u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u0447\u0442\u043e\u00a0\u043c\u0435\u0442\u043e\u0434 \u043d\u0435\u00a0\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u044f\u0432\u043d\u043e. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u00a0\u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u043e\u00a0\u0432\u0442\u043e\u0440\u043e\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0435 \u043c\u0435\u0442\u043e\u0434\u0430. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c <em>gRPC<\/em> \u0432\u00a0\u0442\u043e\u043c, \u0447\u0442\u043e\u00a0\u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043d\u0435\u00a0\u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442, \u0430\u00a0\u0441\u0442\u0440\u0438\u043c\u0438\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (<em>response)<\/em> \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 <em>StreamObserver<\/em>. \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u0441\u043e\u0431\u0435\u0440\u0435\u043c <em>response<\/em> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <em>newBuilder(),<\/em> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u0441\u044b\u043b\u0430\u0442\u044c \u043d\u0430\u0448 \u043e\u0442\u0432\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u044b  <em>onNext()<\/em>. \u0417\u0430\u0432\u0435\u0440\u0448\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u043f\u043e\u0442\u043e\u043a \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 <em>onCompleted()<\/em>.<\/p>\n<pre><code class=\"java\">@GrpcService @RequiredArgsConstructor public class GrpcPetServiceImpl extends PetServiceGrpc.PetServiceImplBase {     private final PetService petService;      @Override     public void createPet(PetOuterClass.CreatePetRequest request,                           StreamObserver&lt;PetOuterClass.CreatePetResponse> responseObserver) {          PetRequestDTO petRequestDTO = PetRequestDTO.builder()                 .petName(request.getPet().getPetName())                 .petType(request.getPet().getPetType())                 .petBirthDate(request.getPet().getPetBirthDate())                 .build();          PetOuterClass.CreatePetResponse response = PetOuterClass.CreatePetResponse                 .newBuilder()                 .setPetId(petService.createPet(petRequestDTO))                 .build();          responseObserver.onNext(response);         responseObserver.onCompleted();     }      @Override     public void findByIDPet(PetOuterClass.FindByIdPetRequest request,                             StreamObserver&lt;PetOuterClass.FindByIdPetResponse> responseObserver) {          PetResponseDTO pet = petService.findByIDPet(request.getPetId());          if (pet == null) {             Metadata.Key&lt;PetOuterClass.ErrorResponse> errorResponseKey =                     ProtoUtils.keyForProto(PetOuterClass.ErrorResponse.getDefaultInstance());             PetOuterClass.ErrorResponse errorResponse = PetOuterClass.ErrorResponse.newBuilder()                     .setErrorName(\"This pet with id = \" + request.getPetId() + \" is not in the database\")                     .build();             Metadata metadata = new Metadata();             metadata.put(errorResponseKey, errorResponse);             responseObserver.onError(                     NOT_FOUND.withDescription(\"This pet with id = \" + request.getPetId() + \" is not found\")                             .asRuntimeException(metadata)             );             return;         }         PetOuterClass.FindByIdPetResponse response = PetOuterClass.FindByIdPetResponse                 .newBuilder()                 .setPet(PetOuterClass.FindByIdPetResponse.Pet                         .newBuilder()                         .setPetName(pet.petName())                         .setPetType(pet.petType())                         .build())                 .build();          responseObserver.onNext(response);         responseObserver.onCompleted();     } }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 <em>\u043a\u043e\u043d\u0441\u043e\u043b\u044c<\/em>. \u0421\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0438\u0442\u043e\u043c\u0446\u0430 \u0438 \u043f\u043e\u0442\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0435\u0433\u043e.<\/p>\n<pre><code class=\"bash\">VetClinicApp % grpcurl -plaintext -d '{\"pet\":{\"pet_name\":\"Joo\",\"pet_type\":\"dog\",\"pet_birth_date\":\"2023-09-01\"}}' localhost:9090 ru.vyrostkov.grpc.server.grpc_server.pet.PetService\/CreatePet    {   \"pet_id\": 1 } <\/code><\/pre>\n<pre><code class=\"bash\">VetClinicApp % grpcurl -plaintext -d '{\"pet_id\":1}' localhost:9090 ru.vyrostkov.grpc.server.grpc_server.pet.PetService\/FindByIDPet  {   \"pet\": {     \"pet_name\": \"Joo\",     \"pet_type\": \"dog\"   } } <\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 gRPC<\/h3>\n<p>\u0412\u0441\u0451 \u043e\u0442\u043b\u0438\u0447\u043d\u043e, \u0441\u0435\u0440\u0432\u0438\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u0427\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442, \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u043c \u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0432 \u0431\u0430\u0437\u0435? \u0421\u0435\u0440\u0432\u0438\u0441 \u0443\u043f\u0430\u0434\u0451\u0442 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439 <strong><em>java.lang.NullPointerException: Cannot invoke &#171;ru.vyrostkov.grpc.dto.PetResponseDTO.getPetName()&#187; because &#171;pet&#187; is null<\/em><\/strong><em>.<\/em><\/p>\n<p>\u0427\u0442\u043e \u0431\u044b \u0442\u0430\u043a\u043e\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0448\u0438\u0431\u043e\u043a. \u0412 <em>proto<\/em>-\u0444\u0430\u0439\u043b\u0435 \u043e\u043f\u0438\u0441\u0430\u043b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 <em>message<\/em> <em>ErrorResponse<\/em>. \u042d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0432\u0438\u0434\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<pre><code class=\"go\">message ErrorResponse {   string error_name = 1; }<\/code><\/pre>\n<p><em>\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435<\/em> \u2013 \u044d\u0442\u043e \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0443\u044e \u0441 <em>RPC<\/em>.<\/p>\n<p>\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 <em>gRPC<\/em> \u2013 \u044d\u0442\u043e \u043f\u0430\u0440\u0430 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0438\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u0430\u043c\u0438 gRPC.<\/p>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0430\u0440\u044b \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043b\u044e\u0447 <em>Metadata.Key&lt;PetOuterClass.ErrorResponse><\/em>, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f <em>ErrorResponse<\/em>. \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043f\u0430\u0440\u044b \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u044b\u0437\u044b\u0432\u0430\u044f <em>metadata.put(Key,Value)<\/em>. \u0418 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c <em>responseObserver<\/em>, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0432 \u043d\u0435\u0433\u043e <em>StatusRuntimeException<\/em>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043f\u0440\u043e\u043a\u0438\u043d\u0435\u043c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 <em>Status<\/em>.<\/p>\n<pre><code class=\"java\">Metadata.Key&lt;PetOuterClass.ErrorResponse> errorResponseKey =<\/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-357364","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/357364","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=357364"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/357364\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=357364"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=357364"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=357364"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}