-2

У меня возникли проблемы с разработкой очень простого веб-приложения с использованием Spring-MVC (4.2.5), Spring-Security (4.0.3) и MongoDB.Исходное исключение из нулевого указателя Spring

Я пытаюсь реализовать собственный поставщик аутентификации для входа пользователя через базу данных с использованием шаблона DAO. Хотя он, похоже, правильно инициализировал контекст приложения, у меня есть исключение Null Pointer Exception для переменных Autwired (CustomerDao и CustomUserDetailsService).

web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
    id="WebApp_ID" version="3.1"> 
    <display-name>AcmeSpring</display-name> 
    <servlet> 
     <servlet-name>SpringController</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <init-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>/WEB-INF/spring-mvc.xml</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>SpringController</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/spring-security.xml 
     </param-value> 
    </context-param> 
    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
</web-app> 

пружинно-mvc.xml

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mongo="http://www.springframework.org/schema/data/mongo" 
    xsi:schemaLocation="http://www.springframework.org/schema/mvc 
     http://www.springframework.org/schema/mvc/spring-mvc.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd 
     http://www.springframework.org/schema/data/mongo 
     http://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd"> 

    <mvc:annotation-driven /> 
    <context:component-scan base-package="controller" /> 
    <context:component-scan base-package="model" /> 
    <context:component-scan base-package="dao" /> 
    <context:component-scan base-package="service" /> 

    <mvc:resources mapping="/resources/**" location="/resources/" /> 

    <bean id="templateResolver" 
     class="org.thymeleaf.templateresolver.ServletContextTemplateResolver"> 
     <property name="prefix" value="/WEB-INF/html/" /> 
     <property name="suffix" value=".html" /> 
     <property name="templateMode" value="HTML5" /> 
    </bean> 

    <bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine"> 
     <property name="templateResolver" ref="templateResolver" /> 
    </bean> 

    <bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver"> 
     <property name="templateEngine" ref="templateEngine" /> 
     <property name="order" value="1" /> 
    </bean> 

    <mongo:db-factory id="mongoDbFactory" host="localhost" 
     port="27017" dbname="AcmeSpring" /> 

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
     <constructor-arg ref="mongoDbFactory" /> 
    </bean> 

    <bean id="customerDao" class="dao.CustomerDaoImpl"> 
    </bean> 
</beans> 

пружинно-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-4.0.xsd"> 

    <http pattern="/resources/**" security="none" /> 

    <http auto-config="true"> 
     <intercept-url pattern="/user/**" access="hasRole('USER')" /> 
     <form-login authentication-failure-url="/login" login-page="/login" 
      login-processing-url="/login" default-target-url="/user" /> 
     <logout invalidate-session="true" success-handler-ref="logoutSuccessHandler" /> 
    </http> 

    <authentication-manager> 
     <authentication-provider ref="customAuthenticationProvider" /> 
    </authentication-manager> 

    <beans:bean id="customUserDetailsService" class="service.CustomUserDetailsService"> 
    </beans:bean> 

    <beans:bean id="customAuthenticationProvider" class="service.CustomAuthenticationProvider"> 
    </beans:bean> 

    <beans:bean id="logoutSuccessHandler" class="service.CustomLogoutSuccessHandler"> 
    </beans:bean> 
</beans:beans> 

CustomAuthenticationProvider

@Component 
public class CustomAuthenticationProvider implements AuthenticationProvider { 
    @Autowired 
    CustomUserDetailsService userDetails; 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     String username = authentication.getName(); 
     String password = authentication.getCredentials().toString(); 

     System.out.println(userDetails == null); 

     Customer customer = userDetails.loadUserByUsername(username); 

     if(customer == null) { 
      throw new BadCredentialsException("Username errato"); 
     } 

     if(!password.equals(customer.getPassword())) { 
      throw new BadCredentialsException("Password errata"); 
     } 

     List<GrantedAuthority> authorities = new ArrayList<>(); 
     authorities.add(new SimpleGrantedAuthority(customer.getRole())); 

     return new UsernamePasswordAuthenticationToken(customer, password, authorities); 
    } 

    @Override 
    public boolean supports(Class<?> clazz) { 
     return clazz.equals(UsernamePasswordAuthenticationToken.class); 
    } 
} 

CustomUserDetailsService

@Service 
public class CustomUserDetailsService implements UserDetailsService { 
    @Autowired 
    private CustomerDao customerDao; 

    @Override 
    public Customer loadUserByUsername(String username) throws UsernameNotFoundException { 
     return customerDao.findCustomerByUsername(username); 
    } 
} 

CustomerDaoImpl

@Repository 
public class CustomerDaoImpl implements CustomerDao { 
    private static final String COLLECTION = "Customer"; 
    @Autowired 
    private MongoTemplate mongoTemplate; 

    @Override 
    public void create(Customer customer) { 
     this.mongoTemplate.insert(customer, COLLECTION); 
    } 

    @Override 
    public Customer findCustomerByUsername(String username) { 
     Query query = new Query(); 
     query.addCriteria(Criteria.where("username").is(username)); 
     System.out.println(query.toString()); 
     return this.mongoTemplate.findOne(query, Customer.class); 
    } 
} 

трассировки стека

java.lang.NullPointerException 
    service.CustomUserDetailsService.loadUserByUsername(CustomUserDetailsService.java:18) 
    service.CustomAuthenticationProvider.authenticate(CustomAuthenticationProvider.java:32) 
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167) 
    org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192) 
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:93) 
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:120) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) 
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) 
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 

Где я ошибаюсь? Спасибо заранее.

EDIT: Я не инициализировал автоматически измененную переменную вручную, только плохую пасту, я отредактировал свой код.

EDIT2: как это было предложено @iMysak я удалить боб декларацию CustomerDAO из весенне-mvc.xml и 3 услуги боба декларация от пружинного security.xml

новой трассировка стека

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#1' while setting bean property 'sourceList' with key [1]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#1': Cannot create inner bean '(inner bean)#5adbfd3' of type [org.springframework.security.web.authentication.logout.LogoutFilter] while setting constructor argument with key [4]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5adbfd3': Cannot resolve reference to bean 'logoutSuccessHandler' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:382) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:753) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) 
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444) 
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326) 
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) 
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4853) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145) 
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408) 
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398) 
    at java.util.concurrent.FutureTask.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.DefaultSecurityFilterChain#1': Cannot create inner bean '(inner bean)#5adbfd3' of type [org.springframework.security.web.authentication.logout.LogoutFilter] while setting constructor argument with key [4]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5adbfd3': Cannot resolve reference to bean 'logoutSuccessHandler' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:313) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:129) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:382) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:157) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634) 
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 26 more 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#5adbfd3': Cannot resolve reference to bean 'logoutSuccessHandler' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634) 
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:140) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:299) 
    ... 40 more 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'logoutSuccessHandler' is defined 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 48 more 

Я также попытался добавить зависимости aop, tx и выражений, как предложено here, но я получаю следующую трассировку стека

+0

Попробуйте добавить эту строку в весенне-security.xml: <боб ID = «customerDao» class = «dao.CustomerDaoImpl»> –

+0

Да, как CustomerDao (интерфейс), так и CustomerDaoImpl находятся в пакете dao – andy

ответ

2

Это может быть проблема с использованием нескольких context:component-scan теги. Пожалуйста, попробуйте еще:

<context:component-scan base-package="controller model dao service" /> 

вместо декларации отдельно.

+0

такая же ошибка даже при изменении компонента-сканирования, как вы предложили – andy

+0

@andy вы можете удалить эти пропущенные объявления bean из ** spring-security.xml ** и положить в ** spring- mvc.xml **? customUserDetailsService и другие. просто для обеспечения – iMysak

+0

Я пробовал, но я получаю «Ошибка создания bean-компонента с именем« org.springframework.security.filterChains »« – andy

1

Вы сделали классическую ошибку весны.Вы аннотированный боб:

@Autowired 
CustomUserDetailsService userDetails; 

Вы под названием новый:

userDetails = new CustomUserDetailsService(); 

Это либо под контролем Spring или ваш. В тот момент, когда вы назвали новое, это было из рук Весны.

Если вы хотите, чтобы пружина зависала автоматически, вы не можете вызвать new для инициализации ссылки. Пусть весна это сделает.

+0

У меня действительно нет userDetails = new CustomUserDetailsService() в моем коде, извините за плохую пасту: я попытался удалить всю аннотацию Autowired и инициализировать вручную dao и службу, возвращаясь, я забыл удалить эту строку. Я знаю, что мне не нужно инициализировать переменные, если они автообновлены. Я отредактировал свой вопрос – andy

0

Вы можете попробовать избавиться от

<beans:bean id="customAuthenticationProvider" class="service.CustomAuthenticationProvider"> 
</beans:bean> 

и

<beans:bean id="customUserDetailsService" class="service.CustomUserDetailsService"> 
    </beans:bean> 

Я думаю, что декларация XML может быть избыточными с аннотацией декларации и компонент сканирования

+0

удалив эти строки. Я получаю сообщение об ошибке «Создание bean-компонента с именем« org.springframework.security.filterChains »и т. Д. – andy

-1

Когда вы объявляли @Autowired класс перкутанции

Например, @Autowired CustomerDao customerDao;

  1. Имя поля должно совпадать с объявленным именем bean в файле xml.
  2. Вам необходимо реализовать метод сеттера, поскольку автоустановка выполняется в три этапа инжекции конструктора, инъекции метода установки и инъекции интерфейса.
  3. Так что, если вы не создаете сеттер метод будет бросать NullPointerException при использовании autowired объекта:

public void setCustomerDao(CustomerDao customerDao) { 
    this.customerDao= customerDao; 
} 
+0

см. Https: // www.tutorialspoint.com/spring/spring_autowired_annotation.htm –