From c5081d8c281cbeb02306a6d35789351c627f890d Mon Sep 17 00:00:00 2001 From: DOHA Date: Tue, 17 Feb 2015 20:01:50 +0200 Subject: [PATCH 1/2] minor modifications --- .../src/main/java/org/baeldung/spring/MvcConfig.java | 1 - .../org/baeldung/web/controller/RegistrationController.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java index d4ecf3e246..5229893298 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java @@ -39,7 +39,6 @@ public class MvcConfig extends WebMvcConfigurerAdapter { registry.addViewController("/logout.html"); registry.addViewController("/homepage.html"); registry.addViewController("/expiredAccount.html"); - registry.addViewController("/regitrationConfirm.html"); registry.addViewController("/badUser.html"); registry.addViewController("/emailError.html"); registry.addViewController("/home.html"); diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java b/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java index 1bbd4f6938..ee35f91b56 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/web/controller/RegistrationController.java @@ -129,7 +129,7 @@ public class RegistrationController { final VerificationToken newToken = userService.generateNewVerificationToken(existingToken); final User user = userService.getUser(newToken.getToken()); final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); - final SimpleMailMessage email = constructResetVerificationTokenEmail(appUrl, request.getLocale(), newToken, user); + final SimpleMailMessage email = constructResendVerificationTokenEmail(appUrl, request.getLocale(), newToken, user); mailSender.send(email); return new GenericResponse(messages.getMessage("message.resendToken", null, request.getLocale())); @@ -187,7 +187,7 @@ public class RegistrationController { // NON-API - private final SimpleMailMessage constructResetVerificationTokenEmail(final String contextPath, final Locale locale, final VerificationToken newToken, final User user) { + private final SimpleMailMessage constructResendVerificationTokenEmail(final String contextPath, final Locale locale, final VerificationToken newToken, final User user) { final String confirmationUrl = contextPath + "/regitrationConfirm.html?token=" + newToken.getToken(); final String message = messages.getMessage("message.resendToken", null, locale); final SimpleMailMessage email = new SimpleMailMessage(); From c16add062a7fde9de8fdfa3d24fd0e680fc92ad5 Mon Sep 17 00:00:00 2001 From: DOHA Date: Tue, 17 Feb 2015 20:02:30 +0200 Subject: [PATCH 2/2] JPA specifications more operations --- .../persistence/dao/UserSpecification.java | 36 ++++++---- .../dao/UserSpecificationsBuilder.java | 29 ++++++-- .../web/controller/UserController.java | 7 +- .../baeldung/web/util/SearchOperation.java | 24 +++++++ .../baeldung/web/util/SpecSearchCriteria.java | 44 ++++++++++++ ...onsTest.java => JPASpecificationTest.java} | 68 ++++++++++++------- 6 files changed, 161 insertions(+), 47 deletions(-) create mode 100644 spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java create mode 100644 spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java rename spring-security-rest-full/src/test/java/org/baeldung/persistence/query/{JPASpecificationsTest.java => JPASpecificationTest.java} (64%) diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java index 7d37874fd2..35884290f3 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java @@ -6,36 +6,44 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.baeldung.persistence.model.User; -import org.baeldung.web.util.SearchCriteria; +import org.baeldung.web.util.SpecSearchCriteria; import org.springframework.data.jpa.domain.Specification; public class UserSpecification implements Specification { - private final SearchCriteria criteria; + private SpecSearchCriteria criteria; - public UserSpecification(final SearchCriteria criteria) { + public UserSpecification(final SpecSearchCriteria criteria) { super(); this.criteria = criteria; } - public SearchCriteria getCriteria() { + public SpecSearchCriteria getCriteria() { return criteria; } @Override public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder builder) { - if (criteria.getOperation().equalsIgnoreCase(">")) { - return builder.greaterThanOrEqualTo(root. get(criteria.getKey()), criteria.getValue().toString()); - } else if (criteria.getOperation().equalsIgnoreCase("<")) { + switch (criteria.getOperation()) { + case EQUALITY: + return builder.equal(root.get(criteria.getKey()), criteria.getValue()); + case NEGATION: + return builder.notEqual(root.get(criteria.getKey()), criteria.getValue()); + case GREATER_THAN: + return builder.greaterThan(root. get(criteria.getKey()), criteria.getValue().toString()); + case LESS_THAN: return builder.lessThanOrEqualTo(root. get(criteria.getKey()), criteria.getValue().toString()); - } else if (criteria.getOperation().equalsIgnoreCase(":")) { - if (root.get(criteria.getKey()).getJavaType() == String.class) { - return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue() + "%"); - } else { - return builder.equal(root.get(criteria.getKey()), criteria.getValue()); - } + case LIKE: + return builder.like(root. get(criteria.getKey()), criteria.getValue().toString()); + case STARTS_WITH: + return builder.like(root. get(criteria.getKey()), criteria.getValue() + "%"); + case ENDS_WITH: + return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue()); + case CONTAINS: + return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue() + "%"); + default: + return null; } - return null; } } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java index a3d7dc849d..3db4267ae0 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java @@ -4,22 +4,39 @@ import java.util.ArrayList; import java.util.List; import org.baeldung.persistence.model.User; -import org.baeldung.web.util.SearchCriteria; +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specifications; public final class UserSpecificationsBuilder { - private final List params; + private final List params; public UserSpecificationsBuilder() { - params = new ArrayList(); + params = new ArrayList(); } // API - public final UserSpecificationsBuilder with(final String key, final String operation, final Object value) { - params.add(new SearchCriteria(key, operation, value)); + public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) // the operation may be complex operation + { + final boolean startWithAsterisk = prefix.contains("*"); + final boolean endWithAsterisk = suffix.contains("*"); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(key, op, value)); + } return this; } @@ -29,7 +46,7 @@ public final class UserSpecificationsBuilder { } final List> specs = new ArrayList>(); - for (final SearchCriteria param : params) { + for (final SpecSearchCriteria param : params) { specs.add(new UserSpecification(param)); } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java index e54dc660a7..e3674f3e03 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java @@ -13,6 +13,7 @@ import org.baeldung.persistence.dao.UserSpecificationsBuilder; import org.baeldung.persistence.model.MyUser; import org.baeldung.persistence.model.User; import org.baeldung.web.util.SearchCriteria; +import org.baeldung.web.util.SearchOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.Specification; import org.springframework.http.HttpStatus; @@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.mysema.query.types.expr.BooleanExpression; @@ -63,10 +65,11 @@ public class UserController { @ResponseBody public List findAllBySpecification(@RequestParam(value = "search") final String search) { final UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); - final Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),"); + final String operationSetExper = Joiner.on("|").join(SearchOperation.SIMPLE_OPERATION_SET); + final Pattern pattern = Pattern.compile("(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); final Matcher matcher = pattern.matcher(search + ","); while (matcher.find()) { - builder.with(matcher.group(1), matcher.group(2), matcher.group(3)); + builder.with(matcher.group(1), matcher.group(2), matcher.group(4), matcher.group(3), matcher.group(5)); } final Specification spec = builder.build(); diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java new file mode 100644 index 0000000000..703f9b93f6 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java @@ -0,0 +1,24 @@ +package org.baeldung.web.util; + +public enum SearchOperation { + EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; + + public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; + + public static SearchOperation getSimpleOperation(final char input) { + switch (input) { + case ':': + return EQUALITY; + case '!': + return NEGATION; + case '>': + return GREATER_THAN; + case '<': + return LESS_THAN; + case '~': + return LIKE; + default: + return null; + } + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java new file mode 100644 index 0000000000..4a04d395fa --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java @@ -0,0 +1,44 @@ +package org.baeldung.web.util; + +public class SpecSearchCriteria { + + private String key; + private SearchOperation operation; + private Object value; + + public SpecSearchCriteria() { + + } + + public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { + super(); + this.key = key; + this.operation = operation; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public SearchOperation getOperation() { + return operation; + } + + public void setOperation(final SearchOperation operation) { + this.operation = operation; + } + + public Object getValue() { + return value; + } + + public void setValue(final Object value) { + this.value = value; + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationsTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java similarity index 64% rename from spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationsTest.java rename to spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java index 7cd279d6d0..0b8daa5a12 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationsTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationTest.java @@ -10,7 +10,8 @@ import org.baeldung.persistence.dao.UserRepository; import org.baeldung.persistence.dao.UserSpecification; import org.baeldung.persistence.model.User; import org.baeldung.spring.PersistenceConfig; -import org.baeldung.web.util.SearchCriteria; +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -25,7 +26,7 @@ import org.springframework.transaction.annotation.Transactional; @ContextConfiguration(classes = { PersistenceConfig.class }) @Transactional @TransactionConfiguration -public class JPASpecificationsTest { +public class JPASpecificationTest { @Autowired private UserRepository repository; @@ -51,19 +52,10 @@ public class JPASpecificationsTest { repository.save(userTom); } - @Test - public void givenLast_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SearchCriteria("lastName", ":", "doe")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, isIn(results)); - } - @Test public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SearchCriteria("firstName", ":", "john")); - final UserSpecification spec1 = new UserSpecification(new SearchCriteria("lastName", ":", "doe")); + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); final List results = repository.findAll(Specifications.where(spec).and(spec1)); assertThat(userJohn, isIn(results)); @@ -71,31 +63,57 @@ public class JPASpecificationsTest { } @Test - public void givenLastAndAge_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SearchCriteria("age", ">", "25")); - final UserSpecification spec1 = new UserSpecification(new SearchCriteria("lastName", ":", "doe")); - final List results = repository.findAll(Specifications.where(spec).and(spec1)); + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); + final List results = repository.findAll(Specifications.where(spec)); assertThat(userTom, isIn(results)); assertThat(userJohn, not(isIn(results))); } @Test - public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SearchCriteria("firstName", ":", "Adam")); - final UserSpecification spec1 = new UserSpecification(new SearchCriteria("lastName", ":", "Fox")); - final List results = repository.findAll(Specifications.where(spec).and(spec1)); + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); + final List results = repository.findAll(Specifications.where(spec)); + assertThat(userTom, isIn(results)); assertThat(userJohn, not(isIn(results))); - assertThat(userTom, not(isIn(results))); } @Test - public void givenPartialFirst_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SearchCriteria("firstName", ":", "jo")); + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); final List results = repository.findAll(spec); assertThat(userJohn, isIn(results)); assertThat(userTom, not(isIn(results))); } -} \ No newline at end of file + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); + final List results = repository.findAll(Specifications.where(spec).and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } +}