user9398992
user9398992

Reputation:

How to make spring data jpa generated methods throw exception on null parameters

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?

Upvotes: 2

Views: 1122

Answers (2)

SKumar
SKumar

Reputation: 2030

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]

Upvotes: 2

Taleb Ibrahim
Taleb Ibrahim

Reputation: 82

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.

Upvotes: 0

Related Questions