From b61c2af4ac2b09312ee7ea1290dffa34c17cb986 Mon Sep 17 00:00:00 2001 From: uzma Date: Sun, 2 Jul 2023 17:45:59 +0100 Subject: [PATCH] [BAEL-6318] code for consuming Page using rest template --- .../pageentityresponse/CustomPageImpl.java | 36 ++++++++++ .../pageentityresponse/EmployeeClient.java | 32 +++++++++ .../EmployeeController.java | 56 ++++++++++++++++ .../pageentityresponse/EmployeeDto.java | 48 ++++++++++++++ .../pageentityresponse/EmployeeService.java | 18 +++++ .../PageEntityResponseApp.java | 12 ++++ .../RestTemplateConfig.java | 15 +++++ .../EmployeeClientUnitTest.java | 65 +++++++++++++++++++ .../EmployeeControllerIntegrationTest.java | 64 ++++++++++++++++++ 9 files changed, 346 insertions(+) create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/CustomPageImpl.java create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeClient.java create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeController.java create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeDto.java create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeService.java create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/PageEntityResponseApp.java create mode 100644 persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/RestTemplateConfig.java create mode 100644 persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeClientUnitTest.java create mode 100644 persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeControllerIntegrationTest.java diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/CustomPageImpl.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/CustomPageImpl.java new file mode 100644 index 0000000000..4531446da7 --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/CustomPageImpl.java @@ -0,0 +1,36 @@ +package com.baeldung.pageentityresponse; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CustomPageImpl extends PageImpl { + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public CustomPageImpl(@JsonProperty("content") List content, @JsonProperty("number") int number, @JsonProperty("size") int size, @JsonProperty("totalElements") Long totalElements, @JsonProperty("pageable") JsonNode pageable, + @JsonProperty("last") boolean last, @JsonProperty("totalPages") int totalPages, @JsonProperty("sort") JsonNode sort, @JsonProperty("numberOfElements") int numberOfElements) { + super(content, PageRequest.of(number, 1), 10); + + } + + public CustomPageImpl(List content, Pageable pageable, long total) { + super(content, pageable, total); + } + + public CustomPageImpl(List content) { + super(content); + } + + public CustomPageImpl() { + super(new ArrayList<>()); + } +} diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeClient.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeClient.java new file mode 100644 index 0000000000..732b4afd9e --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeClient.java @@ -0,0 +1,32 @@ +package com.baeldung.pageentityresponse; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +@Component +public class EmployeeClient { + private final RestTemplate restTemplate; + + public EmployeeClient(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + public Page getEmployeeDataFromExternalAPI(Pageable pageable) { + String url = "http://localhost:8080/external-service/employee"; + + UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString(url) + .queryParam("page", pageable.getPageNumber()) + .queryParam("size", pageable.getPageSize()); + + ResponseEntity> responseEntity = restTemplate.exchange(uriBuilder.toUriString(), HttpMethod.GET, null, new ParameterizedTypeReference>() { + }); + + return responseEntity.getBody(); + } +} diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeController.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeController.java new file mode 100644 index 0000000000..1bbb763491 --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeController.java @@ -0,0 +1,56 @@ +package com.baeldung.pageentityresponse; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/organisation") +public class EmployeeController { + + private final EmployeeService organisationService; + + public EmployeeController(EmployeeService organisationService) { + this.organisationService = organisationService; + } + + @GetMapping("/employee") + public ResponseEntity> getEmployeeData(Pageable pageable) { + Page employeeData = organisationService.getEmployeeData(pageable); + return ResponseEntity.ok(employeeData); + } + + @GetMapping("/data") + public ResponseEntity> getData(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) { + List empList = listImplementation(); + + int totalSize = empList.size(); + int startIndex = page * size; + int endIndex = Math.min(startIndex + size, totalSize); + + List pageContent = empList.subList(startIndex, endIndex); + + Page employeeDtos = new PageImpl<>(pageContent, PageRequest.of(page, size), totalSize); + + return ResponseEntity.ok() + .body(employeeDtos); + } + + private static List listImplementation() { + List empList = new ArrayList<>(); + empList.add(new EmployeeDto("Jane", "Finance", 50000)); + empList.add(new EmployeeDto("Sarah", "IT", 70000)); + empList.add(new EmployeeDto("John", "IT", 90000)); + return empList; + } + +} diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeDto.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeDto.java new file mode 100644 index 0000000000..1ea22ed671 --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeDto.java @@ -0,0 +1,48 @@ +package com.baeldung.pageentityresponse; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class EmployeeDto { + @JsonProperty("name") + private String name; + + @JsonProperty("dept") + private String dept; + + @JsonProperty("salary") + private long salary; + + public EmployeeDto() { + } + + public EmployeeDto(String name, String dept, long salary) { + this.name = name; + this.dept = dept; + this.salary = salary; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDept() { + return dept; + } + + public void setDept(String dept) { + this.dept = dept; + } + + public long getSalary() { + return salary; + } + + public void setSalary(long salary) { + this.salary = salary; + } +} + diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeService.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeService.java new file mode 100644 index 0000000000..e6e13d986f --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/EmployeeService.java @@ -0,0 +1,18 @@ +package com.baeldung.pageentityresponse; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +public class EmployeeService { + private final EmployeeClient employeeClient; + + public EmployeeService(EmployeeClient employeeClient) { + this.employeeClient = employeeClient; + } + + public Page getEmployeeData(Pageable pageable) { + return employeeClient.getEmployeeDataFromExternalAPI(pageable); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/PageEntityResponseApp.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/PageEntityResponseApp.java new file mode 100644 index 0000000000..fe5fc95268 --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/PageEntityResponseApp.java @@ -0,0 +1,12 @@ +package com.baeldung.pageentityresponse; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class PageEntityResponseApp { + public static void main(String[] args) { + SpringApplication.run(PageEntityResponseApp.class, args); + } + +} diff --git a/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/RestTemplateConfig.java b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/RestTemplateConfig.java new file mode 100644 index 0000000000..a0f9a5c4bb --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/main/java/com/baeldung/pageentityresponse/RestTemplateConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.pageentityresponse; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} + diff --git a/persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeClientUnitTest.java b/persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeClientUnitTest.java new file mode 100644 index 0000000000..e6f797c8f7 --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeClientUnitTest.java @@ -0,0 +1,65 @@ +package com.baeldung.pageentityresponse; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.util.Arrays; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +public class EmployeeClientUnitTest { + + @Test + void givenRestTemplate_whenGetEmployeeDataFromExternalAPI_thenGetPageDataWithContents() { + CustomPageImpl mockedResponse = new CustomPageImpl<>(Arrays.asList( + new EmployeeDto("Jane", "Finance", 50000), + new EmployeeDto("Sarah", "IT", 70000), + new EmployeeDto("John", "IT", 90000) + )); + + RestTemplate restTemplate = mock(RestTemplate.class); + ResponseEntity> responseEntity = new ResponseEntity<>(mockedResponse, + HttpStatus.OK); + + String url = "http://localhost:8080/employee"; + int pageNumber = 0; + int pageSize = 10; + String expectedUrl = url + "?page=" + pageNumber + "&size=" + pageSize; + + HttpMethod expectedMethod = HttpMethod.GET; + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { + }; + + Mockito.when(restTemplate.exchange( + expectedUrl, + expectedMethod, + null, + responseType + )).thenReturn(responseEntity); + + EmployeeClient employeeClient = new EmployeeClient(restTemplate); + + Page result = employeeClient.getEmployeeDataFromExternalAPI( + PageRequest.of(pageNumber, pageSize) + ); + + verify(restTemplate).exchange( + eq(expectedUrl), + eq(expectedMethod), + isNull(), + eq(responseType) + ); + assertEquals(1, result.getNumberOfElements()); + assertEquals(mockedResponse, result.getContent().get(0)); + } +} diff --git a/persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeControllerIntegrationTest.java b/persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeControllerIntegrationTest.java new file mode 100644 index 0000000000..b2d5b23889 --- /dev/null +++ b/persistence-modules/spring-data-rest-2/src/test/java/com/baeldung/pageentityresponse/EmployeeControllerIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.pageentityresponse; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; +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.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.data.domain.PageImpl; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest(classes = PageEntityResponseApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class EmployeeControllerIntegrationTest { + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + +@Test +void givenGetData_whenRestTemplateExchange_thenReturnsPageOfEmployee() { + ResponseEntity> responseEntity = restTemplate.exchange( + "http://localhost:" + port + "/organisation/data", + HttpMethod.GET, + null, + new ParameterizedTypeReference>() {} + ); + + assertEquals(200, responseEntity.getStatusCodeValue()); + PageImpl restPage = responseEntity.getBody(); + assertNotNull(restPage); + + assertEquals(10, restPage.getTotalElements()); + + List content = restPage.getContent(); + assertNotNull(content); + assertEquals(3, content.size()); + + EmployeeDto employee1 = content.get(0); + assertEquals("Jane", employee1.getName()); + assertEquals("Finance", employee1.getDept()); + assertEquals(50000, employee1.getSalary()); + + EmployeeDto employee2 = content.get(1); + assertEquals("Sarah", employee2.getName()); + assertEquals("IT", employee2.getDept()); + assertEquals(70000, employee2.getSalary()); + + EmployeeDto employee3 = content.get(2); + assertEquals("John", employee3.getName()); + assertEquals("IT", employee3.getDept()); + assertEquals(90000, employee3.getSalary()); +} + +}