Почему вылетает StackOverflowError в моём приложении на Spring?

144
13 марта 2018, 02:39

Сама ошибка:

Type Exception Report
Message Filter execution threw an exception
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
javax.servlet.ServletException: Filter execution threw an exception
Root Cause
java.lang.StackOverflowError
    org.apache.commons.logging.impl.Log4JLogger.isDebugEnabled(Log4JLogger.java:273)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:161)
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:494)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:494)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:494)
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)

Конфиг классы:

@Configuration
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
@ComponentScan(value = {"my.example.service", "my.example.dao"})
public class SpringConfig {
    @Autowired
    private Environment environment;
    @Bean
    public DataSource getDataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/mydbtest");
        dataSource.setUsername("root");
        dataSource.setPassword("1234");
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        return dataSource;
    }
    @Bean
    public LocalSessionFactoryBean getSessionFactory() {
        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setDataSource(getDataSource());
        Properties props = new Properties();
        props.put("hibernate.show_sql", environment.getProperty("hibernate.show_sql"));
        props.put("hibernate.hbm2ddl.auto", environment.getProperty("hibernate.hbm2ddl.auto"));
        factoryBean.setHibernateProperties(props);
        factoryBean.setAnnotatedClasses(User.class, Role.class);
        return factoryBean;
    }
    @Bean
    public HibernateTransactionManager getTransactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(getSessionFactory().getObject());
        return transactionManager;
    }
}
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").access("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
                .antMatchers("/welcome").access("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
                .antMatchers("/admin").access("hasRole('ROLE_ADMIN')").and()
                .formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password")
                .successForwardUrl("/welcome").failureForwardUrl("/login?error").and().logout().logoutSuccessUrl("/login?logout");
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManagerBean();
    }
}
public class WebAppInit extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{WebConfig.class, SpringConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "my.example.controller")
@Import(SpringSecurityConfig.class)
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/WEB-INF/resources/**").addResourceLocations("/resources/");
    }
    @Bean
    public InternalResourceViewResolver setupViewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }
}

Контроллер:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private SecurityService securityService;
    @Autowired
    private Validator userValidator;
    @GetMapping("/registration")
    public String registration(Model model){
        model.addAttribute("userForm", new User());
        return "registration";
    }
    @PostMapping("/registration")
    public String registration(@ModelAttribute("userForm") User user, BindingResult result, Model model){
        userValidator.validate(user, result);
        if (result.hasErrors())
            return "registration";
        userService.save(user);
        securityService.autoLogin(user.getUsername(), user.getConfirmPassword());
        return "redirect:/welcome";
    }
    @GetMapping("/login")
    public String login(Model model, String error, String logout){
        if (error != null)
            model.addAttribute("error", "Username or password is incorrect");
        if (logout != null)
            model.addAttribute("message", "Logged out successfully");
        return "login";
    }
    @RequestMapping({"/", "/welcome"})
    public String welcome(){
        return "welcome";
    }
    @GetMapping("/admin")
    public String admin(){
        return "admin";
    }
}

Сущности:

@Entity
@Table(name = "ROLES")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "NAME")
    private String name;
    @ManyToMany(mappedBy = "roles")
    private Set<User> users;
    getter and setter
@Entity
@Table(name = "USERS")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "USERNAME")
    private String username;
    @Column(name = "PASSWORD")
    private String password;
    @Transient
    private String confirmPassword;
    @ManyToMany
    @JoinTable(name = "USER_ROLES", joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "roles_id"))
    private Set<Role> roles;
getter and setter

DAO:

@Repository
public class RoleDaoImpl implements RoleDao {
    private final static Logger logger = Logger.getLogger(RoleDaoImpl.class);
    @Autowired
    private SessionFactory sessionFactory;
    @Override
    @Transactional
    public Role findById(Long id) {
        Session session = sessionFactory.getCurrentSession();
        Role role = session.load(Role.class, id);
        logger.info("Class load: " + role);
        return role;
    }
}
@Repository
public class UserDaoImpl implements UserDao {
    private static final Logger logger = Logger.getLogger(UserDaoImpl.class);
    @Autowired
    private SessionFactory sessionFactory;
    @Override
    @Transactional
    public User findByUsername(String username) {
        List<User> list = getUserList();
        for (User u : list){
            if (u.getUsername().equals(username))
                return u;
        }
        return null;
    }
    @Override
    @Transactional
    public void add(User user) {
        sessionFactory.getCurrentSession().save(user);
    }
    @Override
    @Transactional
    @SuppressWarnings("unchecked")
    public List<User> getUserList(){
        return (List<User>) sessionFactory.getCurrentSession().createQuery("from User").list();
    }
}

Сервисы:

@Service
public class SecurityServiceImple implements SecurityService {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    public String findLoggedInUsername() {
        Object userDetails = SecurityContextHolder.getContext().getAuthentication().getDetails();
        if (userDetails instanceof UserDetails)
            return ((UserDetails)userDetails).getUsername();
        return null;
    }
    @Override
    public void autoLogin(String username, String password) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
        authenticationManager.authenticate(authenticationToken);
        if (authenticationToken.isAuthenticated())
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    }
}
@Service
public class UserDetailsImpl implements UserDetailsService {
    @Autowired
    private UserDao userDao;
    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userDao.findByUsername(s);
        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
        for (Role role : user.getRoles()){
            grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities);
    }
}
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private RoleDao roleDao;
    @Override
    public void save(User user) {
        user.setPassword(user.getPassword());
        Set<Role> roles = new HashSet<>();
        roles.add(roleDao.findById(1L));
        user.setRoles(roles);
        userDao.add(user);
    }
    @Override
    public User findByUsername(String name) {
        return userDao.findByUsername(name);
    }
}

При запуске приложения запускается форма с просьбой залогиниться или создать новый аккуаунт. После попытки залогиниться или зарегистрировать нового пользователя вылет ошибка 500, но новый зарегистрированный пользователь добавляется в БД.

READ ALSO
Как правильно передать данные из Fragment во ViewModel?

Как правильно передать данные из Fragment во ViewModel?

ЗдравствуйтеЕсть фрагмент, внутри которого RecyclerView, EditText и Button

129
NullPointerException и EditText

NullPointerException и EditText

Великая java требует от меня, что бы переменные name, number, data были final, но если их сделать final, то текст с edittext еще не будет получен и я схвачу NullPointerException,...

146