diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml index f7f28aa9f1..5ae694a04f 100644 --- a/spring-data-rest/pom.xml +++ b/spring-data-rest/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung @@ -15,7 +15,7 @@ org.springframework.boot spring-boot-starter-parent 1.3.3.RELEASE - + diff --git a/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java b/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java index 6e8e62f52c..94eddc5b3e 100644 --- a/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java +++ b/spring-data-rest/src/main/java/com/baeldung/SpringDataRestApplication.java @@ -5,7 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringDataRestApplication { - public static void main(String[] args) { - SpringApplication.run(SpringDataRestApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(SpringDataRestApplication.class, args); + } } diff --git a/spring-data-rest/src/main/java/com/baeldung/UserRepository.java b/spring-data-rest/src/main/java/com/baeldung/UserRepository.java deleted file mode 100644 index ebbf0d49ab..0000000000 --- a/spring-data-rest/src/main/java/com/baeldung/UserRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung; - -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.repository.query.Param; -import org.springframework.data.rest.core.annotation.RepositoryRestResource; - -import java.util.List; - -@RepositoryRestResource(collectionResourceRel = "users", path = "users") -public interface UserRepository extends PagingAndSortingRepository { - List findByName(@Param("name") String name); -} diff --git a/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java new file mode 100644 index 0000000000..89ab848e81 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/config/ValidatorEventRegister.java @@ -0,0 +1,30 @@ +package com.baeldung.config; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener; +import org.springframework.validation.Validator; + +@Configuration +public class ValidatorEventRegister implements InitializingBean { + + @Autowired + ValidatingRepositoryEventListener validatingRepositoryEventListener; + + @Autowired + private Map validators; + + @Override + public void afterPropertiesSet() throws Exception { + List events = Arrays.asList("beforeCreate", "afterCreate", "beforeSave", "afterSave", "beforeLinkSave", "afterLinkSave", "beforeDelete", "afterDelete"); + + for (Map.Entry entry : validators.entrySet()) { + events.stream().filter(p -> entry.getKey().startsWith(p)).findFirst().ifPresent(p -> validatingRepositoryEventListener.addValidator(p, entry.getValue())); + } + } +} diff --git a/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000000..ee84738e7a --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/exception/handlers/RestResponseEntityExceptionHandler.java @@ -0,0 +1,25 @@ +package com.baeldung.exception.handlers; + +import java.util.stream.Collectors; + +import org.springframework.data.rest.core.RepositoryConstraintViolationException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler({ RepositoryConstraintViolationException.class }) + public ResponseEntity handleAccessDeniedException(Exception ex, WebRequest request) { + RepositoryConstraintViolationException nevEx = (RepositoryConstraintViolationException) ex; + + String errors = nevEx.getErrors().getAllErrors().stream().map(p -> p.toString()).collect(Collectors.joining("\n")); + return new ResponseEntity(errors, new HttpHeaders(), HttpStatus.NOT_ACCEPTABLE); + } + +} \ No newline at end of file diff --git a/spring-data-rest/src/main/java/com/baeldung/WebsiteUser.java b/spring-data-rest/src/main/java/com/baeldung/models/WebsiteUser.java similarity index 96% rename from spring-data-rest/src/main/java/com/baeldung/WebsiteUser.java rename to spring-data-rest/src/main/java/com/baeldung/models/WebsiteUser.java index a7a35a2573..4eb9773e36 100644 --- a/spring-data-rest/src/main/java/com/baeldung/WebsiteUser.java +++ b/spring-data-rest/src/main/java/com/baeldung/models/WebsiteUser.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.models; import javax.persistence.Entity; import javax.persistence.GeneratedValue; diff --git a/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java b/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java new file mode 100644 index 0000000000..0b55ac89b6 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/repositories/UserRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.repositories; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import com.baeldung.models.WebsiteUser; + +@RepositoryRestResource(collectionResourceRel = "users", path = "users") +public interface UserRepository extends CrudRepository { + +} diff --git a/spring-data-rest/src/main/java/com/baeldung/validators/WebsiteUserValidator.java b/spring-data-rest/src/main/java/com/baeldung/validators/WebsiteUserValidator.java new file mode 100644 index 0000000000..0380332708 --- /dev/null +++ b/spring-data-rest/src/main/java/com/baeldung/validators/WebsiteUserValidator.java @@ -0,0 +1,33 @@ +package com.baeldung.validators; + +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import com.baeldung.models.WebsiteUser; + +@Component("beforeCreateWebsiteUserValidator") +public class WebsiteUserValidator implements Validator { + + @Override + public boolean supports(Class clazz) { + return WebsiteUser.class.equals(clazz); + } + + @Override + public void validate(Object obj, Errors errors) { + + WebsiteUser user = (WebsiteUser) obj; + if (checkInputString(user.getName())) { + errors.rejectValue("name", "name.empty"); + } + + if (checkInputString(user.getEmail())) { + errors.rejectValue("email", "email.empty"); + } + } + + private boolean checkInputString(String input) { + return (input == null || input.trim().length() == 0); + } +} diff --git a/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java b/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java new file mode 100644 index 0000000000..b185c6d5ab --- /dev/null +++ b/spring-data-rest/src/main/test/com/baeldung/validator/SpringDataRestValidatorTest.java @@ -0,0 +1,100 @@ +package com.baeldung.validator; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +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.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.ResultMatcher; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.SpringDataRestApplication; +import com.baeldung.models.WebsiteUser; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SpringDataRestApplication.class) +@WebAppConfiguration +public class SpringDataRestValidatorTest { + public static final String URL = "http://localhost"; + + private MockMvc mockMvc; + + @Autowired + protected WebApplicationContext wac; + + @Before + public void setup() { + mockMvc = webAppContextSetup(wac).build(); + } + + @Test + public void whenStartingApplication_thenCorrectStatusCode() throws Exception { + mockMvc.perform(get("/users")).andExpect(status().is2xxSuccessful()); + }; + + @Test + public void whenAddingNewCorrectUser_thenCorrectStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().is2xxSuccessful()) + .andExpect(redirectedUrl("http://localhost/users/1")); + } + + @Test + public void whenAddingNewUserWithoutName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyName_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setEmail("john.doe@john.com"); + user.setName(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithoutEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + + @Test + public void whenAddingNewUserWithEmptyEmail_thenErrorStatusCodeAndResponse() throws Exception { + WebsiteUser user = new WebsiteUser(); + user.setName("John Doe"); + user.setEmail(""); + mockMvc.perform(post("/users", user).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(user))) + .andExpect(status().isNotAcceptable()) + .andExpect(redirectedUrl(null)); + } + +}