2

I have this service method which calls a repo method which is in turn generated by spring:

Service method:

 public User findUserByEmail(String email) {
        try {
            Assert.notNull(email,"email is null!");
            Optional<User> userOptional = userRepo.findUserDAOByEmail(email);
            return userOptional.orElseThrow();
        } 
        catch (...){
            ...
        }
    }

Repo:

public interface UserRepo extends JpaRepository<User, Long> {
    Optional<User> findUserByEmail(String email);
}

I wanted the repo method to throw IllegalArgumentException as its friends (the methods that come out of the box with Jparepository do), but instead it accepted the null parameter "email" and searched for it in the database and returned a result that no such user exist (p.s.: email is constrained to be not null in my schema)

So I did Assert.notNull(email,"email is null!");

But I wonder if there is a better way to validate that "email" is not null?

2 Answers 2

2

A constraint can be put on the parameter as well like this -

@Validated
@Repository
public interface UserRepo extends JpaRepository<User, Long> {
    Optional<User> findUserByEmail(@NotNull String email);
}

@Validated enables Spring to invoke various Validation Constraints.

Working Example


gradle dependency

    compile 'org.springframework.boot:spring-boot-starter'
    compile 'org.springframework.boot:spring-boot-starter-web'
    compile 'org.springframework.boot:spring-boot-starter-validation'
    compile 'org.springframework.boot:spring-boot-starter-data-jpa'
    compile("mysql:mysql-connector-java:8.0.16")

UserRepository.java

@Validated
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
    Optional<User> findUserByName(@NotEmpty String name);
}

Console Output

javax.validation.ConstraintViolationException: findUserByName.name: must not be empty
    at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:117) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at com.sun.proxy.$Proxy88.findUserByName(Unknown Source) ~[na:na]
    at com.test.validation.controller.UserController.get(UserController.java:18) ~[main/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Sign up to request clarification or add additional context in comments.

2 Comments

@User0123 do you have spring-boot-starter-validation dependency ?
@User0123 It worked for me. Do you have following dependency ? mvnrepository.com/artifact/javax.validation/validation-api/….
0

the repositories has no way to access it directly out of services classes so you need to create a service class annotated with @Service then implement your own method to find the user using the UserRepo repository interface then you can inject the service class into the testing unit and make your own tests.

6 Comments

I don't think you understand my question, To be clear, whatI want is: If I call findUserByEmail(null) I want the repository method to throw an IllegalArgumentException
you can't throw IllegalArgumentException directly from Repo, read more about DataAccessException : docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
So there is no better way to validate that the parameter is not empty unless the one mentioned above? From the service layer using Assert?
as a parameter, you can use @NotNull annotation to make sure that the passed parameter annotated with it will not be null in a such situation
add this snippet before return statement " if (email == null) { throw new IllegalArgumentException("No such email found "); } "
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.