J2EE Spring - Annotations non prises en compte
Bonsoir amis développeurs,
(Contexte - Vous pouvez vous rediriger vers la section Demande si vous ne souhaitez pas perdre de temps.)
Récemment, j'ai suivi de nombreux tutoriels pour me lancer dans la création d'un site internet en J2EE.
Basée sur les Frameworks Spring, Hibernate et Primefaces, l'application évolue lentement mais sûrement...
C'est alors que j'ai été confronté à l'utilisation des annotations avec Spring.
J'ai vu de nombreux sujets sur le forum developpez.net qui parlaient de ses fameuses annotations, et ai pu rectifier quelques erreurs.
Typiquement, je n'avais pas activé la gestion des annotations dans Spring.
Malgré le parcours de X tutoriels sur Spring, je ne parviens toujours pas à faire fonctionner les annotations d'injection.
J'ai ajouté ces deux lignes dans le fichier de configuration de Spring (applicationContext.xml) :
Code:
1 2
| <context:component-scan base-package="com.mickaelcalmettes.siteweb" />
<context:annotation-config /> |
Je n'ai pas déclaré ces balises ailleurs (car apparemment cela pose problème de scanner plusieurs fois le projet).
(Demande)
Concrètement, j'ai annoté tous mes DAOImpl avec l'annotation @Repository("nomDuDAO"), tous mes ServiceImpl avec l'annotation @Service("nomDuService"), et toutes mes références aux IDAO et IServices avec @Autowired.
J'ai créé un backing bean qui appelle un service de test, et lors de cet appel, je reçois un NullPointerException.
Les détails ci-après.
(Informations sur le code)
La vue :
Code:
1 2
| <h:commandButton value="Test création catégorie avec todos inexistants" action="#{testHibernateBean.creerCategorie()}" />
<h:commandButton value="Test création todo avec une catégorie inexistante" action="#{testHibernateBean.creerTodo()}" /> |
Ces boutons appelent le backingBean "TestHibernateBean" :
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| @ManagedBean(name = "testHibernateBean")
@ViewScoped
public class TestHibernateBean implements Serializable {
private Categorie categorie1;
private final Set<TodoMemo> todoSet = new HashSet();
private TodoMemo todo;
private Categorie categorie2;
@Autowired
private ITodoService todoService;
@Autowired
private ICategorieService categorieService;
@PostConstruct
public void init() {
this.initTests();
}
private void initTests() {
// Création du jeu de données
categorie1 = new Categorie();
categorie2 = new Categorie();
categorie1.setLibelleCategorie("Catégorie avec plusieurs TODO");
categorie2.setLibelleCategorie("Catégorie avec un seul TODO");
todo = new TodoMemo();
todo.setDateTodo(new Date());
todo.setPriorite(5);
todo.setTodo("Todo relié à la catégorie 'Catégorie avec un seul TODO'");
for(int i=1 ; i<5 ; i++){
TodoMemo tempTodo = new TodoMemo();
tempTodo.setDateTodo(new Date());
tempTodo.setPriorite(i);
tempTodo.setTodo("Todo relié à la catégorie 'Catégorie avec plusieurs TODO' n°" + i);
todoSet.add(tempTodo);
}
// Liaisons
categorie1.setTodo(todoSet);
todo.setCategorie(categorie2);
}
public void creerCategorie(){
// Test création catégorie avec plusieurs TODO associés
categorieService.saveCategorie(categorie1);
}
public void creerTodo(){
// Test création todo avec catégorie associée
todoService.saveTodo(todo);
}
public Categorie getCategorie1() {
return categorie1;
}
public void setCategorie1(Categorie categorie1) {
this.categorie1 = categorie1;
}
public TodoMemo getTodo() {
return todo;
}
public void setTodo(TodoMemo todo) {
this.todo = todo;
}
public Categorie getCategorie2() {
return categorie2;
}
public void setCategorie2(Categorie categorie2) {
this.categorie2 = categorie2;
}
public ITodoService getTodoService() {
return todoService;
}
public void setTodoService(ITodoService todoService) {
this.todoService = todoService;
}
public ICategorieService getCategorieService() {
return categorieService;
}
public void setCategorieService(ICategorieService categorieService) {
this.categorieService = categorieService;
}
} |
Lors de l'appel de l'une des deux méthodes creerCategorie() ou creerTodo(), Spring ne parvient pas à retrouver le service appelé malgré les annotations.
Il me génère un NullPointerException (au besoin je peux insérer la trace de l'erreur). J'ai testé d'appeler le service via le service implémenté (CategorieServiceImpl par exemple), et il n'y a plus d'erreur. Enfin, si, mais le NullPointerException se génère dans le service lors de l'appel du DAO.
Voici l'interface du service "ICategorieService" :
Code:
1 2 3
| public interface ICategorieService {
public void saveCategorie(Categorie categorie);
} |
Voici le service "CategorieServiceImpl" qui devrait être appelé par Spring grâce aux annotations :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Service("categorieService")
public class CategorieServiceImpl implements ICategorieService {
@Autowired
ICategorieDAO categorieDAO;
@Override
public void saveCategorie(Categorie categorie) {
categorieDAO.saveCategorie(categorie);
}
public ICategorieDAO getCategorieDAO() {
return categorieDAO;
}
public void setCategorieDAO(ICategorieDAO categorieDAO) {
this.categorieDAO = categorieDAO;
}
} |
Et enfin, voici les fichiers de configuration.
"applicationContext.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
| <?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
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
">
<context:component-scan base-package="com.mickaelcalmettes.siteweb" />
<context:annotation-config />
<!-- <bean id="categorieDAO" class="com.mickaelcalmettes.siteweb.dao.impl.CategorieDAOImpl" />
<bean id="todoDAO" class="com.mickaelcalmettes.siteweb.dao.impl.TodoDAOImpl" />
<bean id="categorieService" class="com.mickaelcalmettes.siteweb.services.impl.CategorieServiceImpl" />
<bean id="todoService" class="com.mickaelcalmettes.siteweb.services.impl.TodoServiceImpl" />-->
</beans> |
"dispatcher-servlet.xml" : Je ne me sers pas de ce fichier de configuration, il a été créé automatiquement par Netbeans. Je peux fournir le code au besoin.
"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 34 35 36 37 38 39 40 41 42 43 44
| <?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>CONFIG_PATH</param-name>
<param-value>/WEB-INF</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>Pages/Tests/pageTestTemplateAccueil.xhtml</welcome-file>
</welcome-file-list>
</web-app> |
Merci beaucoup par avance de votre aide.
Je m'excuse de la longueur du message, je tenais à le rendre le plus clair possible.
En vous souhaitant une agréable soirée,
M20K8X.