diff --git a/libraries-http-2/src/main/java/com/baeldung/okhttp/interceptors/ErrorResponseInterceptor.java b/libraries-http-2/src/main/java/com/baeldung/okhttp/interceptors/ErrorResponseInterceptor.java index f6c6673705..02f45e1282 100644 --- a/libraries-http-2/src/main/java/com/baeldung/okhttp/interceptors/ErrorResponseInterceptor.java +++ b/libraries-http-2/src/main/java/com/baeldung/okhttp/interceptors/ErrorResponseInterceptor.java @@ -21,7 +21,12 @@ public class ErrorResponseInterceptor implements Interceptor { Gson gson = new Gson(); String body = gson.toJson(new ErrorMessage(response.code(), "The response from the server was not OK")); ResponseBody responseBody = ResponseBody.create(body, APPLICATION_JSON); - + + ResponseBody originalBody = response.body(); + if (originalBody != null) { + originalBody.close(); + } + return response.newBuilder() .body(responseBody) .build(); diff --git a/mapstruct/src/main/java/com/baeldung/mapper/SimpleDestinationMapperUsingInjectedService.java b/mapstruct/src/main/java/com/baeldung/mapper/SimpleDestinationMapperUsingInjectedService.java new file mode 100644 index 0000000000..22e6499711 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/mapper/SimpleDestinationMapperUsingInjectedService.java @@ -0,0 +1,22 @@ +package com.baeldung.mapper; + +import com.baeldung.dto.SimpleSource; +import com.baeldung.entity.SimpleDestination; +import com.baeldung.service.SimpleService; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.springframework.beans.factory.annotation.Autowired; + +@Mapper(componentModel = "spring") +public abstract class SimpleDestinationMapperUsingInjectedService { + + @Autowired + protected SimpleService simpleService; + + @Mapping(target = "name", expression = "java(simpleService.enrichName(source.getName()))") + public abstract SimpleDestination sourceToDestination(SimpleSource source); + + public abstract SimpleSource destinationToSource(SimpleDestination destination); + + +} diff --git a/mapstruct/src/main/java/com/baeldung/service/SimpleService.java b/mapstruct/src/main/java/com/baeldung/service/SimpleService.java new file mode 100644 index 0000000000..14b6c09592 --- /dev/null +++ b/mapstruct/src/main/java/com/baeldung/service/SimpleService.java @@ -0,0 +1,11 @@ +package com.baeldung.service; + +import org.springframework.stereotype.Service; + +@Service +public class SimpleService { + + public String enrichName(String name) { + return "-:: " + name + " ::-"; + } +} diff --git a/mapstruct/src/test/java/com/baeldung/mapper/SimpleDestinationMapperUsingInjectedIntegrationTest.java b/mapstruct/src/test/java/com/baeldung/mapper/SimpleDestinationMapperUsingInjectedIntegrationTest.java new file mode 100644 index 0000000000..3bfbc60de6 --- /dev/null +++ b/mapstruct/src/test/java/com/baeldung/mapper/SimpleDestinationMapperUsingInjectedIntegrationTest.java @@ -0,0 +1,35 @@ +package com.baeldung.mapper; + +import com.baeldung.dto.SimpleSource; +import com.baeldung.entity.SimpleDestination; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:applicationContext.xml") +public class SimpleDestinationMapperUsingInjectedIntegrationTest { + + @Autowired + private SimpleDestinationMapperUsingInjectedService mapper; + + @Test + public void givenSourceToDestination_whenMaps_thenNameEnriched() { + // Given + SimpleSource source = new SimpleSource(); + source.setName("Bob"); + source.setDescription("The Builder"); + + // When + SimpleDestination destination = mapper.sourceToDestination(source); + + // Then + assertThat(destination).isNotNull(); + assertThat(destination.getName()).isEqualTo("-:: Bob ::-"); + assertThat(destination.getDescription()).isEqualTo("The Builder"); + } +} \ No newline at end of file diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 7c94d5b7d7..53af0de315 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -70,7 +70,6 @@ spring-boot-swagger-jwt spring-boot-testing spring-boot-vue - spring-boot-xml spring-boot-actuator spring-boot-data-2 spring-boot-react diff --git a/spring-boot-modules/spring-boot-basic-customization-2/README.md b/spring-boot-modules/spring-boot-basic-customization-2/README.md index bf7e4abb76..f041c1d38a 100644 --- a/spring-boot-modules/spring-boot-basic-customization-2/README.md +++ b/spring-boot-modules/spring-boot-basic-customization-2/README.md @@ -5,3 +5,4 @@ This module contains articles about Spring Boot customization 2 ### Relevant Articles: - [DispatcherServlet and web.xml in Spring Boot](https://www.baeldung.com/spring-boot-dispatcherservlet-web-xml) + - [XML Defined Beans in Spring Boot](https://www.baeldung.com/spring-boot-xml-beans) \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-basic-customization-2/pom.xml b/spring-boot-modules/spring-boot-basic-customization-2/pom.xml index d42a7fd3de..8c1bc22600 100644 --- a/spring-boot-modules/spring-boot-basic-customization-2/pom.xml +++ b/spring-boot-modules/spring-boot-basic-customization-2/pom.xml @@ -23,7 +23,10 @@ org.springframework.boot spring-boot-starter-test - test + + + junit + junit diff --git a/spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/Pojo.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/springbootxml/Pojo.java similarity index 100% rename from spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/Pojo.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/springbootxml/Pojo.java diff --git a/spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplication.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplication.java similarity index 100% rename from spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplication.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplication.java diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/application.properties index e69de29bb2..ab9de92c82 100644 --- a/spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/application.properties @@ -0,0 +1 @@ +sample=string loaded from properties! \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-xml/src/main/resources/beans.xml b/spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/beans.xml similarity index 100% rename from spring-boot-modules/spring-boot-xml/src/main/resources/beans.xml rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/beans.xml diff --git a/spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/test/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java similarity index 99% rename from spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/test/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java index 2c3993d0d8..f3060de82a 100644 --- a/spring-boot-modules/spring-boot-xml/src/main/java/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/test/com/baeldung/springbootxml/SpringBootXmlApplicationIntegrationTest.java @@ -1,5 +1,6 @@ package com.baeldung.springbootxml; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-boot-modules/spring-boot-xml/README.md b/spring-boot-modules/spring-boot-xml/README.md deleted file mode 100644 index 7a9a0bdc09..0000000000 --- a/spring-boot-modules/spring-boot-xml/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [XML Defined Beans in Spring Boot](https://www.baeldung.com/spring-boot-xml-beans) diff --git a/spring-boot-modules/spring-boot-xml/pom.xml b/spring-boot-modules/spring-boot-xml/pom.xml deleted file mode 100644 index b3fd343e4f..0000000000 --- a/spring-boot-modules/spring-boot-xml/pom.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - 4.0.0 - spring-boot-xml - - - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-test - - - junit - junit - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-xml/src/main/resources/application.properties b/spring-boot-modules/spring-boot-xml/src/main/resources/application.properties deleted file mode 100644 index ab9de92c82..0000000000 --- a/spring-boot-modules/spring-boot-xml/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -sample=string loaded from properties! \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml b/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml index fdd569d144..37bcee0b8d 100644 --- a/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml @@ -24,6 +24,11 @@ org.springframework.boot spring-boot-starter-thymeleaf + + org.projectlombok + lombok + + org.springframework.boot diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/Employee.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/Employee.java new file mode 100644 index 0000000000..0bc600dd6a --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/Employee.java @@ -0,0 +1,16 @@ +package com.baeldung.multipartupload; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.web.multipart.MultipartFile; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class Employee { + private String name; + private MultipartFile document; +} diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java new file mode 100644 index 0000000000..e02844233e --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeController.java @@ -0,0 +1,49 @@ +package com.baeldung.multipartupload; + +import lombok.AllArgsConstructor; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@Controller +@AllArgsConstructor +public class EmployeeController { + + private final EmployeeService employeeService; + + @GetMapping(value = "/employee") + public String showEmployeeForm(Model model) { + model.addAttribute("employee", new Employee()); + return "employee/createEmployeeForm"; + } + + @RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + public String saveEmployee(@ModelAttribute Employee employee) { + employeeService.save(employee); + return "employee/success"; + } + + @RequestMapping(path = "/requestpart/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + public ResponseEntity saveEmployee(@RequestPart Employee employee, @RequestPart MultipartFile document) { + employee.setDocument(document); + employeeService.save(employee); + return ResponseEntity.ok().build(); + } + + @RequestMapping(path = "/requestparam/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + public ResponseEntity saveEmployee(@RequestParam String name, @RequestPart MultipartFile document) { + Employee employee = new Employee(name, document); + employeeService.save(employee); + return ResponseEntity.ok().build(); + } + +} \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeRepository.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeRepository.java new file mode 100644 index 0000000000..d4182e100d --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.multipartupload; + +import org.springframework.stereotype.Repository; + +@Repository +public interface EmployeeRepository { + void saveEmployee(Employee employee); +} \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeService.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeService.java new file mode 100644 index 0000000000..f6906c8ba9 --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/EmployeeService.java @@ -0,0 +1,36 @@ +package com.baeldung.multipartupload; + +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; + +@Service +public class EmployeeService { + + public void save(Employee employee) { + saveFile(employee.getDocument()); + // save other employee data + } + + private void saveFile(MultipartFile multipartFile) { + try { + saveToFilesystem(multipartFile); + } catch (Exception e) { + throw new RuntimeException("Unable to save file", e); + } + } + + private static void saveToFilesystem(MultipartFile multipartFile) throws IOException { + String dir = Files.createTempDirectory("tmpDir").toFile().getAbsolutePath(); + File file = new File(dir + File.pathSeparator + multipartFile.getName()); + + try (OutputStream os = new FileOutputStream(file)) { + os.write(multipartFile.getBytes()); + } + } +} diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/MultipartUploadApplication.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/MultipartUploadApplication.java new file mode 100644 index 0000000000..299a5c2325 --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/multipartupload/MultipartUploadApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.multipartupload; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultipartUploadApplication { + + public static void main(String[] args) { + SpringApplication.run(MultipartUploadApplication.class, args); + } + +} diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/employee/createEmployeeForm.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/employee/createEmployeeForm.html new file mode 100644 index 0000000000..c88a8b9318 --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/employee/createEmployeeForm.html @@ -0,0 +1,16 @@ + + + + Getting Started: Handling Form Submission + + + +

Form

+
+

name:

+

document: + +

+
+ + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/employee/success.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/employee/success.html new file mode 100644 index 0000000000..2a49c01613 --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/employee/success.html @@ -0,0 +1,8 @@ + + + + + + Employee data submitted. + + \ No newline at end of file diff --git a/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java new file mode 100644 index 0000000000..73cf905a34 --- /dev/null +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/multipartupload/EmployeeControllerIntegrationTest.java @@ -0,0 +1,56 @@ +package com.baeldung.multipartupload; + +import org.junit.jupiter.api.Test; +import org.mockito.BDDMockito; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import static org.apache.http.entity.ContentType.DEFAULT_BINARY; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest +@EnableWebMvc +public class EmployeeControllerIntegrationTest { + + private static final MockMultipartFile A_FILE = new MockMultipartFile("document", null, DEFAULT_BINARY.toString(), "Employee Record".getBytes()); + + @Autowired + private MockMvc mockMvc; + + @MockBean + private EmployeeService employeeService; + + @Test + public void givenFormData_whenPost_thenReturns200OK() throws Exception { + + mockMvc.perform(multipart("/employee") + .file(A_FILE) + .param("name", "testname")) + .andExpect(status().isOk()); + } + + @Test + public void givenEmployeeJsonAndMultipartFile_whenPostWithRequestPart_thenReturnsOK() throws Exception { + MockMultipartFile employeeJson = new MockMultipartFile("employee", null, + "application/json", "{\"name\": \"Emp Name\"}".getBytes()); + + mockMvc.perform(multipart("/requestpart/employee") + .file(A_FILE) + .file(employeeJson)) + .andExpect(status().isOk()); + } + + @Test + public void givenRequestPartAndRequestParam_whenPost_thenReturns200OK() throws Exception { + mockMvc.perform(multipart("/requestparam/employee") + .file(A_FILE) + .param("name", "testname")) + .andExpect(status().isOk()); + } +} \ No newline at end of file