I have a problem with lazy initialization in my Spring Boot application. I have an entity with lazy field Role, and I they have LazyInitializationException in My Spring Security (UserDetailsService) method, but in controller it's ok.
Can you explaine to me how Spring Boot works with fetch = FetchType.LAZY ? Why it does not work Spring Security UserDetailsService and work in controller methods?
I did not find any guide about this. Thanks!
Spring Boot :
@SpringBootApplication
public class App {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(App.class, args);
    }
}
An Entity:
@Entity
@Table(name = "users")
@Getter
@Setter
@NoArgsConstructor
public class Users {
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "Users_Role", joinColumns = @JoinColumn(name = "User_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
    private Set<Role> roles = new HashSet<Role>();
}
My Service:
@Transactional(readOnly = true)//does not matter
 public Users getUserByLogin(String login) {
        return usersRepository.findOneByLogin(login);
    }
    @Transactional(readOnly = true)
    public Users getUserByLoginWithRoles(String login) {
        Users oneByLogin = usersRepository.findOneByLogin(login);
        logger.debug("User was initialize with Roles: " + oneByLogin.getRoles().size()); // force initialize of roles and it works!
        return oneByLogin;
    }
   @Transactional(readOnly = true)//does not matter
    public Users testGetUser() {
        Users oneByLogin = usersRepository.getOne(1L);
        return oneByLogin;
    }
    @Transactional(readOnly = true)//does not matter
    public Users testFindUser() {
        Users oneByLogin = usersRepository.findOne(1L);
        return oneByLogin;
    }
And I have Spring Security UserDetailsService:
@Service
    public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private Services services;
    @Override
    public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
        Users user;
        Users userFetchedViaGet = services.testGetUser();
        Users userFetchedViaCustomMethod = services.getUserByLogin(login);
        Users userFetchedViaFind = services.testFindUser();
        Users userFetchedWithRoles = services.getUserByLoginWithRoles(login);
        try {
            userFetchedViaGet.getRoles().add(new Role("test"));
        } catch (Exception e) {
            e.printStackTrace();//LazyInitializationException: failed to lazily initialize a collection of role: , could not initialize proxy - no Session
        }
        try {
            userFetchedViaCustomMethod.getRoles().add(new Role("test"));
        } catch (Exception e) {
            e.printStackTrace();//LazyInitializationException: failed to lazily initialize a collection of role: , could not initialize proxy - no Session
        }
        try {
            userFetchedViaFind.getRoles().add(new Role("test")); //LazyInitializationException: failed to lazily initialize a collection of role: , could not initialize proxy - no Session
        } catch (Exception e) {
            e.printStackTrace();
        }
        //some code
        }
    }
And My Controller (All methods works! But there is have to excpetion happen, because there is no session and Lazy fetch type):
@RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test() {      
        Users userFetchedViaGet = services.testGetUser();
        Users userFetchedViaCustomMethod = services.getUserByLogin("ADMIN");
        Users userFetchedViaFind = services.testFindUser();
        Users userFetchedWithRoles = services.getUserByLoginWithRoles("ADMIN");
        try {
            userFetchedViaGet.getRoles().add(new Role("test"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            userFetchedViaCustomMethod.getRoles().add(new Role("test"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            userFetchedViaFind.getRoles().add(new Role("test"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        //some code
    }
 
    