Spring boot validation CGLIB enhanced controller components not autowired

580 views Asked by At

I have created a spring boot application (user spring-boot-starter-parent V. 2.2.2.RELEASE) with Rest controllers, that work fine, now I have added a dependency to :

    <dependency> 
        <groupId>org.springframework.boot</groupId> 
        <artifactId>spring-boot-starter-validation</artifactId> 
    </dependency> 

And have added @Validated on my controller class so that all methods in it should be validated:

@RestController
@Validated 
public class UserController {
  @Autowired
  private UserService userService;

  @PostConstruct
  public void init() {
    System.out.println("test");
  }
}

Now the controller methods when called start throwing NullPointerExceptions because the userService is null; I did a @PostConstruct as a test. Apparently it is called on a normal unenhanced bean which has the fields autowired correctly. But when calling the controller through HTTP, this unenhanced bean is not called, but it is a bean of class UserController$$EnhancerBySpringCGLIB$$ and it has the userController not autowired. I don't really know why cause this is supposed to be really simple, there is not much to configure as far as I know. So I guess for some reason spring does not inject dependencies to CGLIB enhanced classes or just injects it into a wrong class. When I remove @Validated, everything is working fine again, but there is no validation of course.

2

There are 2 answers

1
maslan On

This was the most ridiculous error I had for ages. I mistakenly set controller methods in my original project as private. This caused the CGLIB to not enhance them and instead just have them with original code. Spring did not complain and is happy to run those methods

3
geekTechnique On

Taking your supplied code and making a dummy UserService class, HTTP requests work fine in other environments.

To help solve the issue you're having, you should create a new project, adding the lombok, starter-web, and starter-validation dependencies. Create the following classes.

@RestController
@Validated
public class UserController {
    @Autowired
    private UserService userService;

    @PostConstruct
    public void init() {
        System.out.println("test");
    }

    @GetMapping("/test")
    public int test(){
        return userService.getAge();
    }
}

@Data
@Service
public class UserService {
    private int age = 21;
}

Then test http://localhost:8080/test

If this doesn't work for you, then you should try invalidating your cache and restarting your IDE. Intellij has an option for that if you click on File > Invalidate Caches / Restart .... Alternatively, you can delete the artifacts (or the full local repo) from your .m2 folder. C:\Users\<username>\.m2\repository and rebuild with maven.

If this still doesn't solve your issue, please update your question with a more complete reproducible example of your problem along with a full console log of your error, and I will update my answer.