diff --git a/spring-web-modules/spring-resttemplate-3/.gitignore b/spring-web-modules/spring-resttemplate-3/.gitignore new file mode 100644 index 0000000000..8f98975dc9 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/.gitignore @@ -0,0 +1,12 @@ +*.class + +#folders# +/target +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/README.md b/spring-web-modules/spring-resttemplate-3/README.md new file mode 100644 index 0000000000..6a00d226db --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/README.md @@ -0,0 +1,11 @@ +## Spring RestTemplate + +This module contains articles about Spring RestTemplate + +### The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: +- [Uploading MultipartFile with Spring RestTemplate](https://www.baeldung.com/spring-rest-template-multipart-upload) +- [Get and Post Lists of Objects with RestTemplate](https://www.baeldung.com/spring-rest-template-list) +- [Download a Large File Through a Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-download-large-file) \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/pom.xml b/spring-web-modules/spring-resttemplate-3/pom.xml new file mode 100644 index 0000000000..b1c26e002f --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + spring-resttemplate-3 + 0.1-SNAPSHOT + spring-resttemplate-3 + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + + diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java new file mode 100644 index 0000000000..1967d4f2aa --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.resttemplate.lists; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Sample application used to demonstrate working with Lists and RestTemplate. + */ +@SpringBootApplication +public class EmployeeApplication +{ + public static void main(String[] args) + { + SpringApplication.run(EmployeeApplication.class, args); + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java new file mode 100644 index 0000000000..49e375f9cc --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java @@ -0,0 +1,120 @@ +package com.baeldung.resttemplate.lists.client; + +import com.baeldung.resttemplate.lists.dto.Employee; +import com.baeldung.resttemplate.lists.dto.EmployeeList; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; + +/** + * Application that shows how to use Lists with RestTemplate. + */ +public class EmployeeClient { + public static void main(String[] args) { + EmployeeClient employeeClient = new EmployeeClient(); + + System.out.println("Calling GET for entity using arrays"); + employeeClient.getForEntityEmployeesAsArray(); + + System.out.println("Calling GET using ParameterizedTypeReference"); + employeeClient.getAllEmployeesUsingParameterizedTypeReference(); + + System.out.println("Calling GET using wrapper class"); + employeeClient.getAllEmployeesUsingWrapperClass(); + + System.out.println("Calling POST using normal lists"); + employeeClient.createEmployeesUsingLists(); + + System.out.println("Calling POST using wrapper class"); + employeeClient.createEmployeesUsingWrapperClass(); + } + + public EmployeeClient() { + + } + + public Employee[] getForEntityEmployeesAsArray() { + + RestTemplate restTemplate = new RestTemplate(); + + ResponseEntity response = + restTemplate.getForEntity( + "http://localhost:8082/spring-rest/employees/", + Employee[].class); + + Employee[] employees = response.getBody(); + + assert employees != null; + asList(employees).forEach(System.out::println); + + return employees; + + } + + + public List getAllEmployeesUsingParameterizedTypeReference() { + RestTemplate restTemplate = new RestTemplate(); + + ResponseEntity> response = + restTemplate.exchange( + "http://localhost:8082/spring-rest/employees/", + HttpMethod.GET, + null, + new ParameterizedTypeReference>() { + }); + + List employees = response.getBody(); + + assert employees != null; + employees.forEach(System.out::println); + + return employees; + } + + public List getAllEmployeesUsingWrapperClass() { + RestTemplate restTemplate = new RestTemplate(); + + EmployeeList response = + restTemplate.getForObject( + "http://localhost:8082/spring-rest/employees/v2", + EmployeeList.class); + + List employees = response.getEmployees(); + + employees.forEach(System.out::println); + + return employees; + } + + public void createEmployeesUsingLists() { + RestTemplate restTemplate = new RestTemplate(); + + List newEmployees = new ArrayList<>(); + newEmployees.add(new Employee(3, "Intern")); + newEmployees.add(new Employee(4, "CEO")); + + restTemplate.postForObject( + "http://localhost:8082/spring-rest/employees/", + newEmployees, + ResponseEntity.class); + } + + public void createEmployeesUsingWrapperClass() { + RestTemplate restTemplate = new RestTemplate(); + + List newEmployees = new ArrayList<>(); + newEmployees.add(new Employee(3, "Intern")); + newEmployees.add(new Employee(4, "CEO")); + + restTemplate.postForObject( + "http://localhost:8082/spring-rest/employees/v2/", + new EmployeeList(newEmployees), + ResponseEntity.class); + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java new file mode 100644 index 0000000000..8a4d510f63 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java @@ -0,0 +1,46 @@ +package com.baeldung.resttemplate.lists.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.resttemplate.lists.dto.Employee; +import com.baeldung.resttemplate.lists.dto.EmployeeList; +import com.baeldung.resttemplate.lists.service.EmployeeService; + +import java.util.List; + +@RestController +@RequestMapping("/employees") +public class EmployeeResource +{ + @Autowired + private EmployeeService employeeService; + + @RequestMapping(method = RequestMethod.GET, path = "/") + public List getEmployees() + { + return employeeService.getAllEmployees(); + } + + @RequestMapping(method = RequestMethod.GET, path = "/v2") + public EmployeeList getEmployeesUsingWrapperClass() + { + List employees = employeeService.getAllEmployees(); + return new EmployeeList(employees); + } + + @RequestMapping(method = RequestMethod.POST, path = "/") + public void addEmployees(@RequestBody List employees) + { + employeeService.addEmployees(employees); + } + + @RequestMapping(method = RequestMethod.POST, path = "/v2") + public void addEmployeesUsingWrapperClass(@RequestBody EmployeeList employeeWrapper) + { + employeeService.addEmployees(employeeWrapper.getEmployees()); + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java new file mode 100644 index 0000000000..0754c13c5b --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java @@ -0,0 +1,40 @@ +package com.baeldung.resttemplate.lists.dto; + +public class Employee { + + public long id; + public String title; + + public Employee() + { + + } + + public Employee(long id, String title) + { + this.id = id; + this.title = title; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + public String toString() + { + return "Employee #" + id + "[" + title + "]"; + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java new file mode 100644 index 0000000000..eeabbfe450 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java @@ -0,0 +1,29 @@ +package com.baeldung.resttemplate.lists.dto; + +import java.util.ArrayList; +import java.util.List; + +public class EmployeeList +{ + public List employees; + + public EmployeeList() + { + employees = new ArrayList<>(); + } + + public EmployeeList(List employees) + { + this.employees = employees; + } + + public void setEmployees(List employees) + { + this.employees = employees; + } + + public List getEmployees() + { + return employees; + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java new file mode 100644 index 0000000000..8a1773483a --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java @@ -0,0 +1,25 @@ +package com.baeldung.resttemplate.lists.service; + +import org.springframework.stereotype.Service; + +import com.baeldung.resttemplate.lists.dto.Employee; + +import java.util.ArrayList; +import java.util.List; + +@Service("EmployeeListService") +public class EmployeeService +{ + public List getAllEmployees() + { + List employees = new ArrayList<>(); + employees.add(new Employee(1, "Manager")); + employees.add(new Employee(2, "Java Developer")); + return employees; + } + + public void addEmployees(List employees) + { + employees.forEach(e -> System.out.println("Adding new employee " + e)); + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/app/UploadApplication.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/app/UploadApplication.java new file mode 100644 index 0000000000..f3b1c0dc6f --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/app/UploadApplication.java @@ -0,0 +1,17 @@ +package com.baeldung.web.upload.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; + +@EnableAutoConfiguration +@ComponentScan("com.baeldung.web.upload") +@SpringBootApplication +public class UploadApplication extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(UploadApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java new file mode 100644 index 0000000000..547aec17a0 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java @@ -0,0 +1,61 @@ +package com.baeldung.web.upload.client; + +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class MultipartFileUploadClient { + + public static void main(String[] args) throws IOException { + uploadSingleFile(); + uploadMultipleFile(); + } + + private static void uploadSingleFile() throws IOException { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("file", getTestFile()); + + + HttpEntity> requestEntity = new HttpEntity<>(body, headers); + String serverUrl = "http://localhost:8082/spring-rest/fileserver/singlefileupload/"; + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.postForEntity(serverUrl, requestEntity, String.class); + System.out.println("Response code: " + response.getStatusCode()); + } + + private static void uploadMultipleFile() throws IOException { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("files", getTestFile()); + body.add("files", getTestFile()); + body.add("files", getTestFile()); + + HttpEntity> requestEntity = new HttpEntity<>(body, headers); + String serverUrl = "http://localhost:8082/spring-rest/fileserver/multiplefileupload/"; + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.postForEntity(serverUrl, requestEntity, String.class); + System.out.println("Response code: " + response.getStatusCode()); + } + + public static Resource getTestFile() throws IOException { + Path testFile = Files.createTempFile("test-file", ".txt"); + System.out.println("Creating and Uploading Test File: " + testFile); + Files.write(testFile, "Hello World !!, This is a test file.".getBytes()); + return new FileSystemResource(testFile.toFile()); + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java new file mode 100644 index 0000000000..3863a8f20d --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java @@ -0,0 +1,43 @@ +package com.baeldung.web.upload.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +@RestController +@RequestMapping("/fileserver") +public class FileServerResource { + + @RequestMapping(path = "/singlefileupload/", method = RequestMethod.POST) + public ResponseEntity processFile(@RequestParam("file") MultipartFile file) throws IOException { + + byte[] bytes = file.getBytes(); + + System.out.println("File Name: " + file.getOriginalFilename()); + System.out.println("File Content Type: " + file.getContentType()); + System.out.println("File Content:\n" + new String(bytes)); + + return (new ResponseEntity<>("Successful", null, HttpStatus.OK)); + } + + @RequestMapping(path = "/multiplefileupload/", method = RequestMethod.POST) + public ResponseEntity processFile(@RequestParam("files") List files) throws IOException { + + for (MultipartFile file : files) { + byte[] bytes = file.getBytes(); + + System.out.println("File Name: " + file.getOriginalFilename()); + System.out.println("File Content Type: " + file.getContentType()); + System.out.println("File Content:\n" + new String(bytes)); + } + + return (new ResponseEntity<>("Successful", null, HttpStatus.OK)); + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/src/main/resources/application.properties b/spring-web-modules/spring-resttemplate-3/src/main/resources/application.properties new file mode 100644 index 0000000000..1a26e3ad99 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8082 +server.servlet.context-path=/spring-rest \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/src/main/resources/logback.xml b/spring-web-modules/spring-resttemplate-3/src/main/resources/logback.xml new file mode 100644 index 0000000000..9f48d36486 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/main/resources/logback.xml @@ -0,0 +1,23 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/SpringContextTest.java new file mode 100644 index 0000000000..26972a0aca --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/SpringContextTest.java @@ -0,0 +1,15 @@ +package com.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { com.baeldung.web.upload.app.UploadApplication.class, }) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/largefile/LargeFileDownloadIntegrationTest.java b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/largefile/LargeFileDownloadIntegrationTest.java new file mode 100644 index 0000000000..d8fc58319f --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/largefile/LargeFileDownloadIntegrationTest.java @@ -0,0 +1,105 @@ +package com.baeldung.largefile; + +import java.io.File; +import java.io.FileOutputStream; + +import org.assertj.core.api.Assertions; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.RestTemplate; + +public class LargeFileDownloadIntegrationTest { + + static String FILE_URL = "http://ovh.net/files/1Mio.dat"; + + RestTemplate restTemplate; + + @Before + public void setUp() { + restTemplate = new RestTemplate(); + } + + @Test + public void givenResumableUrl_whenUrlCalledByHeadOption_thenExpectHeadersAvailable() { + HttpHeaders headers = restTemplate.headForHeaders(FILE_URL); + Assertions + .assertThat(headers.get("Accept-Ranges")) + .contains("bytes"); + Assertions + .assertThat(headers.getContentLength()) + .isGreaterThan(0); + } + + @Test + public void givenResumableUrl_whenDownloadCompletely_thenExpectCorrectFileSize() { + HttpHeaders headers = restTemplate.headForHeaders(FILE_URL); + long contentLength = headers.getContentLength(); + File file = restTemplate.execute(FILE_URL, HttpMethod.GET, null, clientHttpResponse -> { + File ret = File.createTempFile("download", "tmp"); + StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(ret)); + return ret; + }); + + Assert.assertNotNull(file); + Assertions + .assertThat(file.length()) + .isEqualTo(contentLength); + } + + @Test + public void givenResumableUrl_whenDownloadRange_thenExpectFileSizeEqualOrLessThanRange() { + int range = 10; + File file = restTemplate.execute(FILE_URL, HttpMethod.GET, clientHttpRequest -> clientHttpRequest + .getHeaders() + .set("Range", String.format("bytes=0-%d", range - 1)), clientHttpResponse -> { + File ret = File.createTempFile("download", "tmp"); + StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(ret)); + return ret; + }); + + Assert.assertNotNull(file); + Assertions + .assertThat(file.length()) + .isLessThanOrEqualTo(range); + } + + @Test + public void givenResumableUrl_whenPauseDownloadAndResume_thenExpectCorrectFileSize() { + + int range = 10; + + HttpHeaders headers = restTemplate.headForHeaders(FILE_URL); + long contentLength = headers.getContentLength(); + + File file = restTemplate.execute(FILE_URL, HttpMethod.GET, clientHttpRequest -> clientHttpRequest + .getHeaders() + .set("Range", String.format("bytes=0-%d", range - 1)), clientHttpResponse -> { + File ret = File.createTempFile("download", "tmp"); + StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(ret)); + return ret; + }); + + Assert.assertNotNull(file); + + Assertions + .assertThat(file.length()) + .isLessThanOrEqualTo(range); + + restTemplate.execute(FILE_URL, HttpMethod.GET, clientHttpRequest -> clientHttpRequest + .getHeaders() + .set("Range", String.format("bytes=%d-%d", file.length(), contentLength)), clientHttpResponse -> { + StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(file, true)); + return file; + }); + + Assertions + .assertThat(file.length()) + .isEqualTo(contentLength); + + } + +} diff --git a/spring-web-modules/spring-resttemplate-3/src/test/resources/.gitignore b/spring-web-modules/spring-resttemplate-3/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/src/test/resources/logback-test.xml b/spring-web-modules/spring-resttemplate-3/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..9f48d36486 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/src/test/resources/logback-test.xml @@ -0,0 +1,23 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file