@Autowired ne fonctionne pas -> NullPointerException
Bonjour,
J'ai remarqué que certains sujets traitaient de ce problème mais aucun ne m'a apporté de réponse à mon problème.
J'essaye d'implémenter l'exemple du livre intitulé "Spring Security" et tout fonctionne bien excepté l'injection des éléments SaltSource et PasswordEncoder que j'ai pourtant définis dans le fichier applicationContext-business.xml comme suit:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
<bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="salt"/>
</bean>
<bean id="jdbcUserServiceCustom" class="springsecurity.security.CustomJdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
<property name="enableGroups" value="true"/>
<property name="enableAuthorities" value="true"/>
<property name="usersByUsernameQuery">
<value>SELECT username, password, enabled, salt FROM users WHERE username = ?</value>
</property>
</bean>
...
<context:annotation-config />
<context:component-scan base-package="springsecurity.security"/> |
J'obtiens un NullPointerExcpetion à l'invocation de la méthode changePassword:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
package springsecurity.security;
//imports...
public class CustomJdbcDaoImpl extends JdbcDaoImpl {
// Ch 4 Password Encoder and Salt Exercise
@Autowired
private PasswordEncoder passwordEncoder;// = new Md5PasswordEncoder();
@Autowired
private SaltSource saltSource;
//private ReflectionSaltSource saltSource = new ReflectionSaltSource();
public void changePassword(String username, String password) {
/*getJdbcTemplate().update(
"UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?",
password, username);*/
// Ch 4 After password encoder and salt exercise using the username
UserDetails user = loadUserByUsername(username);
//saltSource.setUserPropertyToUse("salt");
String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));
getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", encodedPassword, username);
} |
Voici le fichier applicationContext-Security.xml:
Code:
1 2 3 4 5 6 7 8
|
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="jdbcUserServiceCustom">
<password-encoder ref="passwordEncoder">
<salt-source ref="saltSource"/>
</password-encoder>
</authentication-provider>
</authentication-manager> |
Voici le fichier dispatch servlet bank-servlet.xml:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean name="/listAccounts.html" class="bigbank.web.ListAccounts">
<constructor-arg ref="bankService"/>
</bean>
<bean name="/post.html" class="bigbank.web.PostAccounts">
<constructor-arg ref="bankService"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<context:annotation-config />
<context:component-scan base-package="springsecurity.security"/>
</beans> |
Voici mon fichier web.xml:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-business.xml
/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>tutorial.root</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>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>bank</servlet-name> <!-- reference to bank-servlet.xml-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>bank</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.do</url-pattern>
</servlet-mapping> |
Et voici l'erreur:
Code:
1 2 3 4 5 6
|
ATTENTION: StandardWrapperValve[bank]: PWC1406: Servlet.service() for servlet bank threw exception
java.lang.NullPointerException
at springsecurity.security.CustomJdbcDaoImpl.changePassword(CustomJdbcDaoImpl.java:40)
at springsecurity.security.AccountController.submitChangePasswordPage(AccountController.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) |
Il n'y a pas d'erreur au déploiement et tout fonctionne sans problème jusqu'à l'exécution de la méthode changePassword. Évidemment tout fonctionne aussi très bien si je contourne les injections en instanciant les objets directement dans le bean. Je tiens aussi a signaler qu'une injection de l'élément CustomJdbcDaoImpl dans le Bean AccountController avec l'annotation @Controller fonctionne elle très bien
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
package springsecurity.security;
//imports
@Controller
public class AccountController extends BaseController {
@Autowired
private CustomJdbcDaoImpl changePasswordDao;
@RequestMapping("home.do")
public void accountHome() {
}
@RequestMapping(value = "changePassword.do", method = RequestMethod.GET)
public void showChangePasswordPage() {
System.out.println("GET submitChangePasswordPage");
}
@RequestMapping(value = "changePassword.do", method = RequestMethod.POST)
public String submitChangePasswordPage(@RequestParam("password") String newPassword) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = principal.toString();
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
}
System.out.println("USERNAME: "+username+" "+newPassword);
changePasswordDao.changePassword(username, newPassword);
SecurityContextHolder.clearContext();
return "redirect:";//nothing means home
}
} |
Je vous remercie par avance.
Bou