Feature/bael 5756 choose api (#13055)
* BAEL-5756: Rest controller * BAEL-5756: GraphQL controller (without tests) * BAEL-5756: Fix GraphQL test * BAEL-5756: Fix GraphQL test 2 * BAEL-5756: GRPC working * BAEL-5756: GRPC with Spring Boot * BAEL-5756: Books proto service * BAEL-5756: Fix grpc integration test * BAEL-5756: Refactor * BAEL-5756: Revert some changes
This commit is contained in:
parent
5f939afaf0
commit
0f3c81c248
|
@ -13,6 +13,47 @@
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<extensions>
|
||||||
|
<extension>
|
||||||
|
<groupId>kr.motd.maven</groupId>
|
||||||
|
<artifactId>os-maven-plugin</artifactId>
|
||||||
|
<version>1.7.0</version>
|
||||||
|
</extension>
|
||||||
|
</extensions>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.xolstice.maven.plugins</groupId>
|
||||||
|
<artifactId>protobuf-maven-plugin</artifactId>
|
||||||
|
<version>${protobuf-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
|
||||||
|
<pluginId>grpc-java</pluginId>
|
||||||
|
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
<goal>compile-custom</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<protobuf.version>3.19.2</protobuf.version>
|
||||||
|
<protobuf-plugin.version>0.6.1</protobuf-plugin.version>
|
||||||
|
<grpc.version>1.43.2</grpc.version>
|
||||||
|
<grpc.spring.version>2.13.1.RELEASE</grpc.spring.version>
|
||||||
|
<jsonassert.version>1.5.1</jsonassert.version>
|
||||||
|
<jakarta.annotation.version>1.3.5</jakarta.annotation.version>
|
||||||
|
<os-maven-plugin.version>1.6.2</os-maven-plugin.version>
|
||||||
|
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -34,6 +75,27 @@
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.grpc</groupId>
|
||||||
|
<artifactId>grpc-stub</artifactId>
|
||||||
|
<version>${grpc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.grpc</groupId>
|
||||||
|
<artifactId>grpc-protobuf</artifactId>
|
||||||
|
<version>${grpc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.annotation</groupId>
|
||||||
|
<artifactId>jakarta.annotation-api</artifactId>
|
||||||
|
<version>${jakarta.annotation.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.devh</groupId>
|
||||||
|
<artifactId>grpc-spring-boot-starter</artifactId>
|
||||||
|
<version>${grpc.spring.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
@ -49,6 +111,12 @@
|
||||||
<artifactId>spring-graphql-test</artifactId>
|
<artifactId>spring-graphql-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.skyscreamer</groupId>
|
||||||
|
<artifactId>jsonassert</artifactId>
|
||||||
|
<version>${jsonassert.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.chooseapi;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class ChooseApiApp {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.setProperty("spring.profiles.default", "chooseapi");
|
||||||
|
SpringApplication.run(ChooseApiApp.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.chooseapi.controllers;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.dtos.Book;
|
||||||
|
import com.baeldung.chooseapi.services.BooksService;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class BooksControllerGraphQL {
|
||||||
|
|
||||||
|
private final BooksService booksService;
|
||||||
|
|
||||||
|
public BooksControllerGraphQL(BooksService booksService) {
|
||||||
|
this.booksService = booksService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@QueryMapping
|
||||||
|
public List<Book> books() {
|
||||||
|
return booksService.getBooks();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.baeldung.chooseapi.controllers;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.dtos.Book;
|
||||||
|
import com.baeldung.chooseapi.services.BooksService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class BooksControllerRest {
|
||||||
|
|
||||||
|
private final BooksService booksService;
|
||||||
|
|
||||||
|
public BooksControllerRest(BooksService booksService) {
|
||||||
|
this.booksService = booksService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/rest/books")
|
||||||
|
public List<Book> books() {
|
||||||
|
return booksService.getBooks();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.chooseapi.dtos;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Author {
|
||||||
|
|
||||||
|
private final String firstName;
|
||||||
|
private final String lastName;
|
||||||
|
|
||||||
|
public Author(String firstName, String lastName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Author author = (Author) o;
|
||||||
|
return firstName.equals(author.firstName) && lastName.equals(author.lastName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(firstName, lastName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.baeldung.chooseapi.dtos;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Book {
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
private final Author author;
|
||||||
|
private final int year;
|
||||||
|
|
||||||
|
public Book(String title, Author author, int year) {
|
||||||
|
this.title = title;
|
||||||
|
this.author = author;
|
||||||
|
this.year = year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Author getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Book book = (Book) o;
|
||||||
|
return year == book.year && title.equals(book.title) && author.equals(book.author);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(title, author, year);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.chooseapi.grpc;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.BooksServiceGrpc.BooksServiceImplBase;
|
||||||
|
import com.baeldung.chooseapi.BooksServiceOuterClass.BooksRequest;
|
||||||
|
import com.baeldung.chooseapi.BooksServiceOuterClass.BooksResponse;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.dtos.Book;
|
||||||
|
import com.baeldung.chooseapi.services.BooksService;
|
||||||
|
import io.grpc.stub.StreamObserver;
|
||||||
|
import net.devh.boot.grpc.server.service.GrpcService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@GrpcService
|
||||||
|
public class BooksServiceGrpc extends BooksServiceImplBase {
|
||||||
|
|
||||||
|
private final BooksService booksService;
|
||||||
|
|
||||||
|
public BooksServiceGrpc(BooksService booksService) {
|
||||||
|
this.booksService = booksService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void books(BooksRequest request, StreamObserver<BooksResponse> responseObserver) {
|
||||||
|
List<Book> books = booksService.getBooks();
|
||||||
|
BooksResponse.Builder responseBuilder = BooksResponse.newBuilder();
|
||||||
|
books.forEach(book -> responseBuilder.addBook(GrpcBooksMapper.mapBookToProto(book)));
|
||||||
|
responseObserver.onNext(responseBuilder.build());
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.chooseapi.grpc;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.BooksServiceOuterClass;
|
||||||
|
import com.baeldung.chooseapi.dtos.Author;
|
||||||
|
import com.baeldung.chooseapi.dtos.Book;
|
||||||
|
|
||||||
|
public class GrpcBooksMapper {
|
||||||
|
|
||||||
|
public static BooksServiceOuterClass.BookProto mapBookToProto(Book book) {
|
||||||
|
return BooksServiceOuterClass.BookProto.newBuilder()
|
||||||
|
.setTitle(book.getTitle())
|
||||||
|
.setAuthor(BooksServiceOuterClass.AuthorProto.newBuilder()
|
||||||
|
.setFirstName(book.getAuthor().getFirstName())
|
||||||
|
.setLastName(book.getAuthor().getLastName())
|
||||||
|
.build())
|
||||||
|
.setYear(book.getYear())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Book mapProtoToBook(BooksServiceOuterClass.BookProto bookProto) {
|
||||||
|
return new Book(bookProto.getTitle(),
|
||||||
|
new Author(bookProto.getAuthor().getFirstName(), bookProto.getAuthor().getLastName()),
|
||||||
|
bookProto.getYear());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.chooseapi.services;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.dtos.Author;
|
||||||
|
import com.baeldung.chooseapi.dtos.Book;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class BooksService {
|
||||||
|
|
||||||
|
private static final Author AUTHOR = new Author("Joanne", "Rowling");
|
||||||
|
|
||||||
|
private static final List<Book> BOOKS = new ArrayList<>(Arrays.asList(
|
||||||
|
new Book("Philosopher's Stone", AUTHOR, 1997),
|
||||||
|
new Book("Goblet of Fire", AUTHOR, 2000),
|
||||||
|
new Book("Deathly Hallows", AUTHOR, 2007)
|
||||||
|
));
|
||||||
|
|
||||||
|
public List<Book> getBooks() {
|
||||||
|
return BOOKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
package com.baeldung.chooseapi;
|
||||||
|
|
||||||
|
message BooksRequest {}
|
||||||
|
|
||||||
|
message AuthorProto {
|
||||||
|
string firstName = 1;
|
||||||
|
string lastName = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BookProto {
|
||||||
|
string title = 1;
|
||||||
|
AuthorProto author = 2;
|
||||||
|
int32 year = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BooksResponse {
|
||||||
|
repeated BookProto book = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service BooksService {
|
||||||
|
rpc books(BooksRequest) returns (BooksResponse);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
server:
|
||||||
|
port: 8082
|
||||||
|
|
||||||
|
spring:
|
||||||
|
graphql:
|
||||||
|
graphiql:
|
||||||
|
enabled: true
|
||||||
|
schema:
|
||||||
|
locations: classpath:chooseapi/
|
|
@ -0,0 +1,14 @@
|
||||||
|
type Author {
|
||||||
|
firstName: String!
|
||||||
|
lastName: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Book {
|
||||||
|
title: String!
|
||||||
|
year: Int!
|
||||||
|
author: Author!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
books: [Book]
|
||||||
|
}
|
|
@ -43,7 +43,6 @@ input ProductUpdateModel {
|
||||||
stock: Int
|
stock: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# The Root Query for the application
|
# The Root Query for the application
|
||||||
type Query {
|
type Query {
|
||||||
products(size: Int, page: Int): [Product]!
|
products(size: Int, page: Int): [Product]!
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.chooseapi.controllers;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.ChooseApiApp;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.graphql.test.tester.HttpGraphQlTester;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ChooseApiApp.class)
|
||||||
|
@ActiveProfiles("chooseapi")
|
||||||
|
class BooksControllerGraphQLIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HttpGraphQlTester graphQlTester;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenBooksServiceThatReturnThreeBooks_whenCallingGraphQLEndpoint_thenThreeBooksAreReturned() throws Exception {
|
||||||
|
String document = "query { books { title year author { firstName lastName }}}";
|
||||||
|
Path expectedResponse = Paths.get("src/test/resources/graphql-test/books_expected_response.json");
|
||||||
|
String expectedJson = new String(Files.readAllBytes(expectedResponse));
|
||||||
|
|
||||||
|
this.graphQlTester.document(document)
|
||||||
|
.execute()
|
||||||
|
.path("books")
|
||||||
|
.matchesJson(expectedJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.chooseapi.controllers;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
class BooksControllerRestIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenBooksServiceThatReturnThreeBooks_whenCallingRestEndpoint_thenThreeBooksAreReturned() throws Exception {
|
||||||
|
Path expectedResponse = Paths.get("src/test/resources/graphql-test/books_expected_response.json");
|
||||||
|
String expectedJson = new String(Files.readAllBytes(expectedResponse));
|
||||||
|
|
||||||
|
this.mockMvc.perform(get("/rest/books"))
|
||||||
|
.andDo(print())
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(content().json(expectedJson));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.baeldung.chooseapi.grpc;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.dtos.Book;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import net.devh.boot.grpc.client.inject.GrpcClient;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.skyscreamer.jsonassert.JSONAssert;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.BooksServiceOuterClass.BooksRequest;
|
||||||
|
import com.baeldung.chooseapi.BooksServiceOuterClass.BooksResponse;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.BooksServiceGrpc.BooksServiceBlockingStub;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@SpringBootTest(properties = {
|
||||||
|
"grpc.server.inProcessName=test", // Enable inProcess server
|
||||||
|
"grpc.server.port=-1", // Disable external server
|
||||||
|
"grpc.client.inProcess.address=in-process:test" // Configure the client to connect to the inProcess server
|
||||||
|
})
|
||||||
|
@SpringJUnitConfig(GrpcIntegrationTestConfig.class)
|
||||||
|
@DirtiesContext // Ensures that the grpc-server is properly shutdown after each test
|
||||||
|
class BooksServiceGrpcIntegrationTest {
|
||||||
|
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
@GrpcClient("inProcess")
|
||||||
|
private BooksServiceBlockingStub booksServiceGrpc;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DirtiesContext
|
||||||
|
void givenBooksServiceThatReturnThreeBooks_whenCallingGrpcEndpoint_thenThreeBooksAreReturned() throws IOException, JSONException {
|
||||||
|
Path expectedResponse = Paths.get("src/test/resources/graphql-test/books_expected_response.json");
|
||||||
|
String expectedJson = new String(Files.readAllBytes(expectedResponse));
|
||||||
|
|
||||||
|
BooksRequest request = BooksRequest.newBuilder().build();
|
||||||
|
BooksResponse response = booksServiceGrpc.books(request);
|
||||||
|
|
||||||
|
List<Book> books = response.getBookList().stream()
|
||||||
|
.map(GrpcBooksMapper::mapProtoToBook)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
JSONAssert.assertEquals(objectMapper.writeValueAsString(books), expectedJson, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.chooseapi.grpc;
|
||||||
|
|
||||||
|
import com.baeldung.chooseapi.services.BooksService;
|
||||||
|
import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
|
||||||
|
import net.devh.boot.grpc.server.autoconfigure.GrpcServerAutoConfiguration;
|
||||||
|
import net.devh.boot.grpc.server.autoconfigure.GrpcServerFactoryAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ImportAutoConfiguration({
|
||||||
|
GrpcServerAutoConfiguration.class, // Create required server beans
|
||||||
|
GrpcServerFactoryAutoConfiguration.class, // Select server implementation
|
||||||
|
GrpcClientAutoConfiguration.class}) // Support @GrpcClient annotation
|
||||||
|
class GrpcIntegrationTestConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
BooksService booksService() {
|
||||||
|
return new BooksService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
BooksServiceGrpc booksServiceGrpc() {
|
||||||
|
return new BooksServiceGrpc(booksService());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Philosopher's Stone",
|
||||||
|
"year": 1997,
|
||||||
|
"author": {
|
||||||
|
"firstName": "Joanne",
|
||||||
|
"lastName": "Rowling"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Goblet of Fire",
|
||||||
|
"year": 2000,
|
||||||
|
"author": {
|
||||||
|
"firstName": "Joanne",
|
||||||
|
"lastName": "Rowling"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Deathly Hallows",
|
||||||
|
"year": 2007,
|
||||||
|
"author": {
|
||||||
|
"firstName": "Joanne",
|
||||||
|
"lastName": "Rowling"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in New Issue