The below code outputs "Inside Method" even though I'm passing null to the function. It should throw an exception instead. What's wrong with the below code? Why isn't it throwing an exception when a null parameter is being passed.
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
@Validated
class MyClass {
public static void main(String[] args) {
MyClass m = new MyClass();
m.wontTakeNull(null);
}
public void wontTakeNull(@NotNull String param) {
System.out.println("Inside Method");
}
}
If you want MyClass
to be validated, it needs to be a Spring-managed bean. At the moment you're creating it yourself and then calling a method on it:
MyClass m = new MyClass();
m.wontTakeNull(null);
This means that Spring doesn't know anything about m
and that it isn't a Spring-managed bean. As a result, Spring can't perform validation when you call wontTakeNull
with null
.
To make m
a Spring-managed bean, you need to annotate it with @Component
and use component-scanning or return an instance of it from a @Bean
method in a configuration class. You then need to have Spring inject an instance of MyClass
rather than creating it yourself. Here's a complete example that shows the @Component
-based approach:
package com.example.demo;
import javax.validation.constraints.NotNull;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
@SpringBootApplication
public class ValidationExampleApplication {
public ValidationExampleApplication(MyClass myClass) {
myClass.wontTakeNull(null);
}
public static void main(String[] args) {
SpringApplication.run(ValidationExampleApplication.class, args);
}
@Component
@Validated
static class MyClass {
public void wontTakeNull(@NotNull String param) {
System.out.println("Inside Method");
}
}
}
This application will fail to start with the following root cause:
Caused by: javax.validation.ConstraintViolationException: wontTakeNull.param: must not be null
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:120) ~[spring-context-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.9.jar:5.3.9]
at com.example.demo.ValidationExampleApplication$MyClass$$EnhancerBySpringCGLIB$$82020c75.wontTakeNull(<generated>) ~[main/:na]
at com.example.demo.ValidationExampleApplication.<init>(ValidationExampleApplication.java:14) ~[main/:na]
at com.example.demo.ValidationExampleApplication$$EnhancerBySpringCGLIB$$4c0df4b8.<init>(<generated>) ~[main/:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[na:na]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:208) ~[spring-beans-5.3.9.jar:5.3.9]
... 20 common frames omitted