[JAVA-8285] Split spring-mvc-basics into a new module

This commit is contained in:
Haroon Khan
2021-12-11 19:48:40 +00:00
parent 295e05c73a
commit 273eddf4c6
36 changed files with 606 additions and 31 deletions

View File

@@ -14,8 +14,4 @@ The "REST With Spring" Classes: https://bit.ly/restwithspring
- [Guide to Spring Handler Mappings](https://www.baeldung.com/spring-handler-mappings)
- [Spring MVC Content Negotiation](https://www.baeldung.com/spring-mvc-content-negotiation-json-xml)
- [Spring @RequestMapping New Shortcut Annotations](https://www.baeldung.com/spring-new-requestmapping-shortcuts)
- [Spring MVC Custom Validation](https://www.baeldung.com/spring-mvc-custom-validator)
- [Using Spring @ResponseStatus to Set HTTP Status Code](https://www.baeldung.com/spring-response-status)
- [Spring MVC and the @ModelAttribute Annotation](https://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation)
- [The HttpMediaTypeNotAcceptableException in Spring MVC](https://www.baeldung.com/spring-httpmediatypenotacceptable)
- More articles: [[more -->]](/spring-mvc-basics-2)
- More articles: [[more -->]](../spring-mvc-basics-2)

View File

@@ -20,10 +20,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>

View File

@@ -1,24 +0,0 @@
package com.baeldung.customvalidator;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Documented
@Constraint(validatedBy = ContactNumberValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ContactNumberConstraint {
String message() default "Invalid phone number";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@@ -1,17 +0,0 @@
package com.baeldung.customvalidator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class ContactNumberValidator implements ConstraintValidator<ContactNumberConstraint, String> {
@Override
public void initialize(ContactNumberConstraint contactNumber) {
}
@Override
public boolean isValid(String contactField, ConstraintValidatorContext cxt) {
return contactField != null && contactField.matches("[0-9]+") && (contactField.length() > 8) && (contactField.length() < 14);
}
}

View File

@@ -1,31 +0,0 @@
package com.baeldung.customvalidator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
@Constraint(validatedBy = FieldsValueMatchValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsValueMatch {
String message() default "Fields values don't match!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String field();
String fieldMatch();
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface List {
FieldsValueMatch[] value();
}
}

View File

@@ -1,31 +0,0 @@
package com.baeldung.customvalidator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.springframework.beans.BeanWrapperImpl;
public class FieldsValueMatchValidator implements ConstraintValidator<FieldsValueMatch, Object> {
private String field;
private String fieldMatch;
public void initialize(FieldsValueMatch constraintAnnotation) {
this.field = constraintAnnotation.field();
this.fieldMatch = constraintAnnotation.fieldMatch();
}
public boolean isValid(Object value, ConstraintValidatorContext context) {
Object fieldValue = new BeanWrapperImpl(value).getPropertyValue(field);
Object fieldMatchValue = new BeanWrapperImpl(value).getPropertyValue(fieldMatch);
if (fieldValue != null) {
return fieldValue.equals(fieldMatchValue);
} else {
return fieldMatchValue == null;
}
}
}

View File

@@ -1,29 +0,0 @@
package com.baeldung.exception;
import java.util.Collections;
import java.util.Map;
import org.springframework.http.MediaType;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@ControllerAdvice
public class HttpMediaTypeNotAcceptableExceptionExampleController {
@PostMapping(value = "/test", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Map<String, String> test() {
return Collections.singletonMap("key", "value");
}
@ResponseBody
@ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
public String handleHttpMediaTypeNotAcceptableException() {
return "acceptable MIME type:" + MediaType.APPLICATION_JSON_VALUE;
}
}

View File

@@ -1,55 +0,0 @@
package com.baeldung.model;
import com.baeldung.customvalidator.FieldsValueMatch;
@FieldsValueMatch.List({ @FieldsValueMatch(field = "password", fieldMatch = "verifyPassword", message = "Passwords do not match!"), @FieldsValueMatch(field = "email", fieldMatch = "verifyEmail", message = "Email addresses do not match!") })
public class NewUserForm {
private String email;
private String verifyEmail;
private String password;
private String verifyPassword;
public NewUserForm() {
}
public NewUserForm(String email, String verifyEmail, String password, String verifyPassword) {
super();
this.email = email;
this.verifyEmail = verifyEmail;
this.password = password;
this.verifyPassword = verifyPassword;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getVerifyEmail() {
return verifyEmail;
}
public void setVerifyEmail(String verifyEmail) {
this.verifyEmail = verifyEmail;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getVerifyPassword() {
return verifyPassword;
}
public void setVerifyPassword(String verifyPassword) {
this.verifyPassword = verifyPassword;
}
}

View File

@@ -1,22 +0,0 @@
package com.baeldung.model;
import com.baeldung.customvalidator.ContactNumberConstraint;
public class ValidatedPhone {
@ContactNumberConstraint
private String phone;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return phone;
}
}

View File

@@ -1,31 +0,0 @@
package com.baeldung.web.controller;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.baeldung.model.NewUserForm;
@Controller
public class NewUserController {
@GetMapping("/user")
public String loadFormPage(Model model) {
model.addAttribute("newUserForm", new NewUserForm());
return "userHome";
}
@PostMapping("/user")
public String submitForm(@Valid NewUserForm newUserForm, BindingResult result, Model model) {
if (result.hasErrors()) {
return "userHome";
}
model.addAttribute("message", "Valid form");
return "userHome";
}
}

View File

@@ -1,32 +0,0 @@
package com.baeldung.web.controller;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.baeldung.model.ValidatedPhone;
@Controller
public class ValidatedPhoneController {
@GetMapping("/validatePhone")
public String loadFormPage(Model m) {
m.addAttribute("validatedPhone", new ValidatedPhone());
return "phoneHome";
}
@PostMapping("/addValidatePhone")
public String submitForm(@Valid ValidatedPhone validatedPhone, BindingResult result, Model m) {
if (result.hasErrors()) {
return "phoneHome";
}
m.addAttribute("message", "Successfully saved phone: " + validatedPhone.toString());
return "phoneHome";
}
}

View File

@@ -1,30 +0,0 @@
package com.baeldung.exception;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import org.junit.Test;
import org.junit.runner.RunWith;
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.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import com.baeldung.Application;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
public class HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest {
@Autowired
MockMvc mockMvc;
@Test
public void whenHttpMediaTypeNotAcceptableExceptionTriggered_thenExceptionHandled() throws Exception {
mockMvc.perform(post("/test").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_PDF))
.andExpect(content().string("acceptable MIME type:application/json"));
}
}

View File

@@ -1,51 +0,0 @@
package com.baeldung.web.controller;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class ClassValidationMvcIntegrationTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new NewUserController())
.build();
}
@Test
public void givenMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/user")
.accept(MediaType.TEXT_HTML)
.param("email", "john@yahoo.com")
.param("verifyEmail", "john@yahoo.com")
.param("password", "pass")
.param("verifyPassword", "pass"))
.andExpect(model().attribute("message", "Valid form"))
.andExpect(view().name("userHome"))
.andExpect(status().isOk())
.andDo(print());
}
@Test
public void givenNotMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/user")
.accept(MediaType.TEXT_HTML)
.param("email", "john@yahoo.com")
.param("verifyEmail", "john@yahoo.commmm")
.param("password", "pass")
.param("verifyPassword", "passsss"))
.andExpect(model().errorCount(2))
.andExpect(view().name("userHome"))
.andExpect(status().isOk())
.andDo(print());
}
}

View File

@@ -1,43 +0,0 @@
package com.baeldung.web.controller;
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.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class CustomMVCValidatorIntegrationTest {
private MockMvc mockMvc;
@BeforeEach
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new ValidatedPhoneController())
.build();
}
@Test
public void givenPhonePageUri_whenMockMvc_thenReturnsPhonePage() throws Exception {
this.mockMvc.perform(get("/validatePhone"))
.andExpect(view().name("phoneHome"));
}
@Test
public void givenPhoneURIWithPostAndFormData_whenMockMVC_thenVerifyErrorResponse() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/addValidatePhone")
.accept(MediaType.TEXT_HTML)
.param("phoneInput", "123"))
.andExpect(model().attributeHasFieldErrorCode("validatedPhone", "phone", "ContactNumberConstraint"))
.andExpect(view().name("phoneHome"))
.andExpect(status().isOk())
.andDo(print());
}
}

View File

@@ -1,40 +0,0 @@
package com.baeldung.web.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import java.util.Arrays;
import java.util.Collection;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest
@AutoConfigureMockMvc
public class EmployeeControllerModelAttributeIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void givenUrlEncodedFormData_whenAddEmployeeEndpointCalled_thenModelContainsMsgAttribute() throws Exception {
Collection<NameValuePair> formData = Arrays.asList(new BasicNameValuePair("name", "employeeName"), new BasicNameValuePair("id", "99"), new BasicNameValuePair("contactNumber", "123456789"));
String urlEncodedFormData = EntityUtils.toString(new UrlEncodedFormEntity(formData));
mockMvc.perform(post("/addEmployee").contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(urlEncodedFormData))
.andExpect(status().isOk())
.andExpect(view().name("employeeView"))
.andExpect(model().attribute("msg", "Welcome to the Netherlands!"));
}
}