Spring boot 2 @Transactional annotation makes Autowired fields null

I am trying to use the @Transactional annotation in my service method to lazily load a field. However, using @Transactional in my implementation class makes all fields auto- null .

Here is my implementation:

 @Service public class UserServiceImpl implements UserService { /** * DefaultMapper. */ @Autowired private DefaultMapper defaultMapper; /** * Resource service injection. */ @Autowired private ResourceService resourceService; /** * UserRepository. */ @Autowired private UserRepository userRepository; /** * Jwt Factory. */ @Autowired private JwtService jwtService; @Override @Transactional public final UserDto findByLogin(final String login) throws ResourceNotFoundException { // user repository is null here when using @Transactional User user = this.userRepository.findByLogin(login) .orElseThrow(() -> new ResourceNotFoundException( resourceService.getMessage(MessageBundle.EXCEPTION, "resource.notfound.user.login") )); UserDto userDto = defaultMapper.asUserDtoWithRoles(user); return userDto; } 

Thanks in advance.

+5
source share
1 answer

A transaction, in particular, is applied using AOP; the default AOP mechanism in Spring is to use a proxy. When using Spring Boot in proxy mode, class-based proxy classes are installed.

You can fix this in one of 2 ways.

  • Remove final from your method
  • Disable class-based proxies by adding spring.aop.proxy-target-class=false to your application.properties

Now that you have added @Transactional , this will lead to the creation of a proxy server for your UserServiceImpl , a class-based proxy, to be exact. It happens that a subclass is created for your UserServiceImpl , and all methods are overridden to apply a TransactionInterceptor . However, since your method is marked final , a dynamically created class cannot override this method. As a result, the method considers field instances in a dynamically created proxy class, which will always be null .

When removing final method can be overridden, the applicable behavior will be considered in the corresponding field instances (the actual UserServiceImpl instead of the proxy server).

When disabling class-based proxies, you get a dynamic JDK proxy, which is basically a thin shell that implements all the interfaces that your service has. It applies the added behavior (transactions) and calls the actual service. No extension of the actual class is required, and as such you can proxy the final methods (for now, this is part of your interface).

+5
source

Source: https://habr.com/ru/post/1269433/


All Articles