Pour la réalisation de cette documentation sur l’utilisation de Spring, je vais décrire pas à pas au travers d’un exemple d’application les étapes nécessaires à la mise en œuvre du Framework Spring. Il s’agit d’une simple application qui permet de gérer une simple liste de personnes. Cette application sera réalisé avec l’aide de l’environnement Eclipse.
Création du projet
Nous allons créer un premier projet dans Eclipse, le projet web que nous souhaitons créer correspond à un Dynamic Web Project.
Vous pouvez ensuite cliquer directement sur Finish pour avoir les paramètres par défaut d’un projet Eclipse ou sur Next et personnaliser votre projet.
L’arborescence des fichiers
Les projets Web sous Eclipse reprennent tous la même arborescence.
- Les sources : C’est là ou doivent être placés les différents fichiers source de votre projet. On peut voir qu’Eclipse a inclus les librairies de Tomcat et la version de Java souhaitée.
- Le répertoire WebContent :
- La racine du répertoire doit contenir les fichiers qui ne nécessitent pas de protection et sont accessibles à tout le monde. Typiquement, les fichiers JavaScript, Css, images.
- Le répertoire WEB-INF qui contient les fichiers qui ne sont pas accessible directement mais protégée par un Servlet pour les jsp par exemple.
- Le sous-répertoire lib qui contient toute les librairies nécessaires à votre projet. Celles-ci seront incluses dans l’archive à installer sur le futur Tomcat de production
L’arborescence des packages
Un projet respectant une architecture 3-Tiers doit pouvoir se distinguer dès le départ par son arborescence de package. Trop de projets consistent à mettre l’intégralité des sources dans un seul et même package. Ils rendent ainsi difficile, voir impossible, de bien différencier les sources utilisées pour la partie métier, de celles utilisées pour l’interface. Une bonne arborescence permet de classer les sources de son projet et de faciliter la reprise de code par d’autres développeurs. L’arborescence présentée ci-dessous n’est en aucun cas une obligation mais il s’agit d’une préconisation couramment utilisée et adoptée, libre à vous toutefois de l’adopter ou de vous en inspirer pour vos projets.
- demo : Il s’agit du package principal. Le nom du projet est souvent utilisé.
- demo.model ou demo.bean : L’ensemble des entités de votre application appelé beans se trouve dans le package : personne, table, voiture, billet, etc.
- demo.service : Dans ce package on met l’ensemble des interfaces définissant les services disponibles de la partie métier (les managers)
- demo.service.impl : L’ensemble des managers implémentant les services sont dans ce package.
- demo.exception: Les exceptions qui peuvent être retourné par les services.
- demo.dao : Dans ce package on met l’ensemble des interfaces définissant les méthodes d’accès disponibles pour l’accès au donnée. Ce package est indépendant de l’implémentation choisie
- demo.dao.impl : Les DAO implémentant les interfaces. Le cas échéant, cela peut être des dao d’accès avec JDBC, Hibernate ou autres.
- demo.web : Dans ce package, on met l’ensemble des sources en rapport avec la partie web et l’interface de l’application
Il faut bien comprendre l’importance des interfaces. Elles permettent l’évolution rapide de vos applications en s’assurant qu’aucune de vos méthodes ne sera oubliée. Si votre application se connecte en JDBC à votre base de données, et que vous souhaitez utiliser une nouvelle méthode d’accès Hibernate, il vous suffit juste d’implémenter les interfaces déjà existantes sans avoir à retoucher l’intégralité du code. Outre cet aspect pratique et organisé, l’utilisation des interfaces devient indispensable pour mettre correctement en place le framework Spring et utiliser pleinement ses fonctionnalités.
Les packages Spring
Il faut dans un premier temps télécharger les librairies nécessaires sur le site de Spring (www.springsource.com). Attention, regardez bien les différentes versions : la dernière version correspond souvent à des « Development Releases » destinées aux développeurs et non à un environnement de production, il faut donc prendre la version «Production release » Dans l’archive, récupérez spring.jar et toutes les librairies du répertoire « modules » et copiez les dans le répertoire lib de votre projet Eclipse.
Les beans
Nous allons maintenant créer le premier Bean au sein du package demo.model Le bean doit respecter les conventions de nommage des attributs et des accesseurs.
package demo.model; import java.util.Date; public class Personne { private int id; private String nom; private String prenom; private Date dateNaissance; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } public String getPrenom() { return prenom; } public void setPrenom(String prenom) { this.prenom = prenom; } public Date getDateNaissance() { return dateNaissance; } public void setDateNaissance(Date dateNaissance) { this.dateNaissance = dateNaissance; } }
Attention, il est important selon les besoins de définir vos méthodes equals et hashCode
Les services
Nous allons créer nos services (application métier) qui permettent de gérer ces objets personnes.
Les interfaces Manager
Pour cela, nous commençons par l’interface qui permet de définir l’ensemble des méthodes disponibles et mises à disposition de l’interface (qu’elles soient Web ou autres). Nous créons donc une interface PersonneManager dans le package demo.service.
package demo.service; import java.util.Collection; import demo.model.Personne; import demo.service.exception.BeanAlreadyExistException; import demo.service.exception.BeanNotExistException; public interface PersonneManager { public void createPersonne(Personne p) throws BeanAlreadyExistException; public void updatePersonne(Personne p) throws BeanNotExistException; public Personne getPersonne(int id); public Collection<Personne> listePersonnes(); }
Quelque soit l’implémentation du service choisi, elle devra impérativement définir ces quatre fonctions. On peut noter également ici que les fonctions ne retournent pas des booléens pour signaler le succès ou non succès de l’appel mais des exceptions en cas d’erreur. Le retour d’un booléen pour une fonction est une pratique couramment utilisée dans les programmes en C, mais elle est à bannir en Java qui supporte les exceptions. Par exemple, supposons que nous utilisions un booléen pour la fonction createPersonne. Les retours possibles sont :
- Vrai : L’opération a réussi
- Faux : L’opération n’a pas réussit (doublons, objet non valide)
- Faux : Une erreur SQL s’est produite
Si la fonction retourne faux, le programme n’est alors pas capable de savoir si la fonction a retourné faux pour signaler que la personne existe déjà ou s’il y a eu une erreur SQL. L’utilisation des exceptions permet de bien distinguer ces différents cas.
Les Exceptions
Une classe exception est relativement simple à déclarer. Il faut déclarer dans le package demo.exception une classe héritant d’Exception et surcharger le constructeur.
package demo.exception; public class BeanAlreadyExistException extends Exception { /** * Constructeur de classe de l'exception. * * @param message message à retourner. */ public BeanAlreadyExistException(String message) { super(message); } }
Les interfaces DAO
On déclare l’interface du Dao Personne dans le package demo.dao
package demo.dao; import java.util.Collection; import demo.exception.BeanAlreadyExistException; import demo.exception.BeanNotExistException; import demo.model.Personne; public interface PersonneDao { void createPersonne(Personne p) throws BeanAlreadyExistException; void updatePersonne(Personne p) throws BeanNotExistException; Personne getPersonne(int id); Collection<Personne> listePersonnes(); int countPersonnes(); }
Les implémentations du Manager
Pour le moment, on a défini les interfaces des Managers et des DAO, on va maintenant pouvoir commencer à implémenter notre manager. Pour info, une fois que la classe implémente l’interface, Eclipse permet de générer automatiquement les fonctions et méthodes présentes dans l’interface
package demo.service.impl; import java.util.Collection; import demo.dao.PersonneDao; import demo.exception.BeanAlreadyExistException; import demo.exception.BeanNotExistException; import demo.model.Personne; import demo.service.PersonneManager; public class PersonneManagerImpl implements PersonneManager { private PersonneDao personneDao; public void createPersonne(Personne p) throws BeanAlreadyExistException { personneDao.createPersonne(p); } public Personne getPersonne(int id) { return personneDao.getPersonne(id); } public Collection<Personne> listePersonnes() { return personneDao.listePersonnes(); } public void updatePersonne(Personne p) throws BeanNotExistException { personneDao.updatePersonne(p); } public PersonneDao getPersonneDao() { return personneDao; } public void setPersonneDao(PersonneDao personneDao) { this.personneDao = personneDao; } }
Notre manager consiste principalement ici à appeler les méthodes du DAO. Veuillez remarquer qu’on n’a pas encore défini l’implémentation du DAO, et il n’est tout simplement pas nécessaire de la connaître pour développer notre manager. Le manager ci-dessus fait appel à l’interface PersonneDao. C’est à l’exécution grâce au module Spring Core et à la configuration que nous allons définir plus loin que le manager sera quelle implémentation appeler. C’est justement le principe d’injection de dépendance. Spring se chargera de passer à la méthode setPersonneDao la bonne implémentation.
Les implémentations du Dao
Pour le moment, la partie Dao n’étant pas notre priorité, je vous propose une implémentation de Test qui nous retourne des données fictives.
package demo.dao.impl; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import demo.dao.PersonneDao; import demo.exception.BeanAlreadyExistException; import demo.exception.BeanNotExistException; import demo.model.Personne; public class PersonneDaoTest implements PersonneDao { private Collection<Personne> liste = new ArrayList<Personne>(); public void createPersonne(Personne p) throws BeanAlreadyExistException { liste.add(p); } public Personne getPersonne(int id) { Personne p = new Personne(); p.setNom("Doe"); p.setPrenom("John"); p.setId(id); p.setDateNaissance(new Date()); return p; } public Collection<Personne> listePersonnes() { return liste; } public void updatePersonne(Personne p) throws BeanNotExistException { liste.add(p); } public int countPersonne() { return liste.size() ; } }
On voit très vite l’intérêt d’une telle pratique lors d’un développement horizontal. Le développeur responsable de l’interface web se charge de créer les interfaces avec leurs implémentations de test, et ensuite, le développeur responsable de la base de données développe l’implémentation finale avec les accès à la base.
La configuration de Spring
Les classes métiers de notre application sont maintenant réalisées. Pour le moment, je n’ai pas parlé de la partie web de notre application car Spring peut être mis en place aussi bien dans une application client qu’une application web. La structure présentée et la logique de configuration décrite ci-dessous peut donc s’appliquer indépendamment de l’environnement choisi. Toutefois, la mise en place dépend bien évidemment de l’environnement choisi.
Contexte d’application
Le contexte d’application de Spring permet de définir par l’intermédiaire de fichiers XML les objets accessibles de l’application et les injections de dépendances entre les objets. Ce fichier Xml sera la référence centrale de votre projet, vous serez amené à le modifier et le compléter régulièrement pour y référencer vos objets et leurs dépendances. Voilà le fichier XML correspondant à notre application. Ce fichier s’appelle applicationContext.xml et doit se trouver dans le répertoire source de votre application. Certain le mette également dans le répertoire WEB-INF.
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- Manager --> <bean id="personneManager" class="demo.service.impl.PersonneManagerImpl"> <property name="personneDao" ref="personneDao" /> </bean> <!-- Dao --> <bean id="personneDao" class="demo.dao.impl.PersonneDaoTest"> </bean> </beans>
Qu’avons-nous fait ? Dans un premier temps, nous avons défini le Bean PersonneManager et son implémentation. Nous avons aussi défini via la balise « property » la dépendance nécessaire à personneDao. Le framework de Spring va alors se charger d’instancier un objet personneManager et il va remplir son attribut personneDao de type PersonneDao en utilisant son accesseur (convention de nommage set). Il va lui transmettre l’implémentation de l’objet personneDao telle que décrite ci-dessous dans le fichier XML. Le deuxième Bean déclaré est justement le bean personneDao et son implémentation « PersonneDaoTest ». Le jour où l’implémentation JDBC sera créée, il suffira juste de modifier la classe implémentée par personneDao dans ce fichier XML, et l’application prendra automatiquement en compte cette nouvelle classe. Il n’y a aucun code source à modifier où que ce soit. Bien qu’un seul fichier soit très largement suffisant pour notre exemple, il est conseillé de créer plusieurs fichiers XML correspondant aux différentes couches et d’y répartir les beans pour améliorer la lisibilité :
- applicationContext-dao.xml
- applicationContext-dwr.xml
- applicationContext-ldap.xml
- applicationContext-sap.xml
Une fois ces fichiers créés, il faut dire à notre application de lancer le framework Spring en utilisant ces fichiers de configuration. Cette partie est spécifique à une application web, la mise en place pour une application cliente est légèrement différente. Dans le fichier web.xml, voilà les instructions nécessaires pour charger le contexte d’application Spring :
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>DemoSpring</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext*.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> </web-app>
Si vous avez placé vos fichiers XML dans le répertoire WEB-INF, le classpath sera :
<param-value>/WEB-INF/applicationContext*.xml</param-value>
Spring Dao
Bien que la mise en place du framework Hibernate soit grandement facilitée par Spring, sa non-utilisation n’implique par nécessairement un retour en arrière et l’utilisation classique des connexions JDBC. Spring a en effet intégré des outils (JdbcTemplate) qui facilitent considérablement la mise en place d’une connexion à une base et les requêtes à effectuer. On va d’abord commencer par définir un DataSource dans le fichier de contexte XML. A noter que le concept de DataSource est une spécificité Java et non Spring, Spring n’a pas réinventé la roue et s’appuie sur cette classe pour proposer ses fonctionnalités. Le DataSource permet de définir le driver à utiliser et les informations de connexions à votre base.
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" driverClassName="org.gjt.mm.mysql.Driver" url="jdbc:mysql://localhost/spring" username="spring" password="spring"> </bean>
Il faut bien sûr intégrer au répertoire lib de votre projet la librairie jar du connecteur JDBC. Dans notre exemple basé sur MySQL, la librairie est mysql-connector-java, nous définissons donc:
- le driverClassName : qui définit le driver à utiliser
- L’url qui définit la chaine de connexion et varie en fonction du type de base
- L’username et le password
Nous allons maintenant créer notre implémentation MySQL de Personne Dao. Il suffit de créer une classe PersonneDaoImp qui implémente l’interface PersonneDao. Eclipse devrait alors s’activer et annoncer une erreur, il vous proposera ensuite pour d’implémenter automatiquement les méthodes nécessaires. Pour créer des requêtes avec le JDBC Template de Spring, l’instance de PersonneDaoImp doit le connaitre. On va donc ajouter un attribut jdbcTemplate de type SimpleJdbcTemplate. Pour créer un objet SimpleJdbcTemplate, il faut lui spécifier lors de l’appel au constructeur un objet DataSource. Ça tombe bien, on en a justement définit un dans notre fichier xml. Il suffit donc de définit notre fichier xml pour lui dire de transmette le dataSource par injection :
<bean id="personneDao" class="demo.dao.impl.PersonneDaoImpl"> <property name="dataSource" ref="dataSource" /> </bean>
Spring va par conséquent chercher le setter de l’attribut dataSource, par conséquent une méthode setDataSource qui prend en paramètre un objet DataSource. Désormais il y a 2 possibilités :
- soit vous n’utilisez par le Jdbc Template. Dans ce cas, vous devez déclarer un attribut dataSource dans votre classe et définir les accesseurs.
- Soit vous utilisez le Jdbc Template. Dans ce cas, il n’est pas nécessaire de conserver la référence au dataSource. Le setteur doit tout de même être présent.
Voici le code source de PersonneDaoImpl tel qu’il doit être si vous utilisez l’outil JdbcTemplate.
package demo.dao.impl; import java.util.Collection; import javax.sql.DataSource; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; import demo.dao.PersonneDao; import demo.exception.BeanAlreadyExistException; import demo.exception.BeanNotExistException; import demo.model.Personne; /** Implémentation MySQL. */ public class PersonneDaoImpl implements PersonneDao { private SimpleJdbcTemplate jdbcTemplate; @Override public void createPersonne(Personne p) throws BeanAlreadyExistException { // TODO Auto-generated method stub } @Override public Personne getPersonne(int id) { // TODO Auto-generated method stub return null; } @Override public Collection<Personne> listePersonnes() { // TODO Auto-generated method stub return null; } @Override public void updatePersonne(Personne p) throws BeanNotExistException { // TODO Auto-generated method stub } @Override public int countPersonnes() { // TODO Auto-generated method stub return 0; } /** Setteur dataSource qui permet de créer le JDBCTemplate. * @param dataSource * dataSource */ public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); } /** * @return the jdbcTemplate */ public SimpleJdbcTemplate getJdbcTemplate() { return jdbcTemplate; } /** * @param jdbcTemplate * the jdbcTemplate to set */ public void setJdbcTemplate(SimpleJdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } }
Avant d’aller plus loin, je vais présenter la table Mysql avec laquelle nous allons devoir dialoguer. (C’est mieux pour effectuer les requêtes)
JdbcTemplate offre une solution qui permet de mapper automatiquement les attributs d’un objet avec les champs d’une table et permet ainsi d’utiliser un fonctionnement similaire aux solutions de persistance relationnel comme Hibernate (Attention toutefois on ne peut pas parler de persistance pour autant). On va donc définir une méthode qui va permettre pour chaque ligne d’une requête renvoyée de la retourner sous forme d’objet.
private static ParameterizedRowMapper<Personne> mapper = new ParameterizedRowMapper<Personne>() { public Personne mapRow(ResultSet rs, int rowNum) throws SQLException { Personne personne = new Personne(); personne.setId(rs.getInt("personneId")); personne.setPrenom(rs.getString("personnePrenom")); personne.setNom(rs.getString("personneNom")); personne.setDateNaissance(rs.getDate("personneDate")); return personne; } };
Jusque là, ca ressemble beaucoup à JDBC classique avec son ResultSet et ses noms de colonnes. Pour apaiser les esprits et justifier l’utilisation de JdbcTemplate, voilà l’implémentation (très longue :-)) de la fonction qui retourne la liste des personnes.
public Collection<Personne> listePersonnes () { return jdbcTemplate.query("select * from personnes", mapper); }
C’est quand même beaucoup plus simple que l’ancienne méthode qui pouvait ressembler à cela dans le meilleur des cas.
public static Collection<Personne> listePersonneAnciennMethode() { Connection cnx = null; Statement stmt = null; ResultSet rs = null; Collection<Personne> listes = new ArrayList<Personne>(); StringBuffer requete; requete = new StringBuffer("SELECT * FROM personnes"); try { cnx = dataSource.getConnexion(); stmt = cnx.createStatement(); if (stmt != null) { rs = stmt.executeQuery(requete.toString()); if (rs != null) { while (rs.next()) { Personne personne = new Personne(); personne.setId(rs.getInt("personneId")); personne.setPrenom(rs.getString("personnePrenom")); personne.setNom(rs.getString("personneNom")); personne.setDateNaissance(rs.getDate("personneDate")); listes.add(personne); } rs.close(); } } }catch (SQLException e) { logger.error("Erreur SQL (listePersonne)", e); } finally { dataSource.closeStatement(stmt); dataSource.closeStatement(cnx); } return listes; }
Que fait le JdbcTemplate ? Pour chaque ligne retournée par la requête, il va appeler la méthode mapper définit plus haut qui va créer l’objet et l’ajouter à la liste. La méthode query se charge également de gérer les erreurs d’accès et d’éviter de gérer les try catch finally. Attention, dans notre exemple on effectue une requête qui retourne tous les champs de la table et éventuellement des sous-tables jointes le cas échéant. Il faut toujours préciser les noms des champs surtout lorsqu’il s’agit d’une requête sur plusieurs tables. Cela améliore considérablement les performances des requêtes. Il nous reste plus qu’à implémenter les autres méthodes sur le même principe. La méthode update :
public void updatePersonne(Personne p) throws BeanNotExistException { int nb = jdbcTemplate.update("update personnes set personneNom=? ,personnePrenom=? ,personneDate=? where id=?" ,p.getNom() , p.getPrenom() , p.getDateNaissance() , p.getId()); if (nb == 0) { // Si aucun enregistrement n'a été modifié // C'est que le bean n'existe pas throw new BeanNotExistException("La personne n'existe pas"); } }
La méthode create :
public void createPersonne(Personne p) throws BeanAlreadyExistException { jdbcTemplate.update( "insert into personnes(personneNom,personnePrenom,personneDate) values(?, ?, ?)",p.getNom(), p.getPrenom(), p.getDateNaissance()); }
La méthode getPersonne :
public Personne getPersonne(int id) { return jdbcTemplate.queryForObject( "select * from personnes where personneId=?", mapper, id); }
La méthode count :
public int countPersonnes() { return jdbcTemplate.queryForInt("select count(*) from personnes"); }
Edit : Configuration DataSource
Après vérification, j’utilise désormais un objet dérivé de org.apache.commons.dbcp.BasicDataSource pour la définition de mon dataSource. Cette classe perso me permet de définir l’encodage utilisé et de forcer l’anglais pour la communication avec la base de données
import java.util.Locale; import org.apache.commons.dbcp.BasicDataSource; /** * @author ttropard Permet de forcer l'utilisation de l'encodage utf8 * */ public class CustomDataSource extends BasicDataSource { /** * */ public CustomDataSource() { super(); // Permet de s'assurer que le dialogue entre la base et l'appli est en anglais Locale.setDefault(Locale.ENGLISH); } /** * Indique si on utilise l'unicode. * * @param useUnicode * useUnicode */ public void setUseUnicode(boolean useUnicode) { addConnectionProperty("useUnicode", Boolean.toString(useUnicode)); } /** * Fonction permettant de spécifier l'encodage. * * @param characterEncoding * characterEncoding */ public void setCharacterEncoding(String characterEncoding) { addConnectionProperty("characterEncoding", characterEncoding); } }
Et voici la déclaration de mon DataSource
<bean id="dataSource" parent="dataSourceParent" class="CustomDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@<SERVEUR>:<PORT>:<SID>"/> <property name="username" value="w3blog"/> <property name="password" value="w3blog"/> <property name="useUnicode" value="true"/> <property name="characterEncoding" value="UTF-8"/> <property name="maxActive" value="10"/> <property name="minIdle" value="1"/> <property name="maxIdle" value="5"/> <!-- On vire l'ile au bout de 5h --> <property name="minEvictableIdleTimeMillis" value="18000000"/> <!-- Verification toute les heures --> <property name="timeBetweenEvictionRunsMillis" value="1800000"/> <!-- On test tous les ile --> <property name="numTestsPerEvictionRun" value="-1"/> </bean>
Super, cet article très simple et ultra clair m’a été d’une grande aide ! Juste une pointe de déception, qu’il n’y ait pas eu d’implémentation de la couche DAO en JPA (Hibernate en l’occurrence)
Merci pour ce commentaire.
Oui, j’avais pensé à faire un exemple avec Hibernate, mais le projet qui m’a servi à faire la démo ne l’utilisait pas à l’époque. Mais je compte bien en faire un prochainement.
Bonjour thibaut ,
cet article est superbe et il ma trop aidé…
j m demande si ta fait lexemple avec hibernate , si c l cas passe moi le lien stp
Merciii
Je cherche le code source de l’application, y a t-il quelqu’un qui peut me le transmettre ?
Malheureusement, je n’avais pas penser à faire une sauvegarde du projet à l’époque pour le proposer en téléchargement, il va falloir faire du copier-coller depuis l’article. Désolé, j’y penserais pour la prochaine fois.
Bonjour,
Un très bon tutoriel qui m’a permis d’approcher de près la configuration Spring.
J’aurai, cependant des petites remarques :
– La définition de la datasource est soit erronée, soit correspond à une certaine version de Spring car chez moi (Spring v3.1.1), l’objet bean ne peut posséder les attributs driverClassName, url, user et password, j’ai du définir des propriétés du bean.
– Je comprends que le tutoriel est axé sur Spring mais je reste sur ma fin de ne pas pouvoir concrètement exécuter le programme. Il aurait été sympa de finaliser le projet par de simples pages JSP pour avoir une exécution probante.
– Une seconde partie potentielle, comme le stipule Ismail, est d’approfondir le cas Hibernate via les annotations Spring… Cela aurait conclu superbement ce tutoriel…
Quoi qu’il en soit, merci pour votre travail tant technique que rédactionnel, il en faudrait plus des tutoriel du genre.
Je viens de mettre à jour l’article avec le dataSource utilisé pour mon dernier projet.
Salut Thibaut,
penses tu qu’avec SPRING JDBC on a plus de liberté qu’avec SPRING JPA?(c’est l’impression que j’ai actuellement surtout qu’avec JDBC on implémente nous mêmes nos propres requêtes).
Autre question: SPRING-STRUTS ou SPRING MVC?(Dans le cadre d’un petit projet universitaire)
Je te remercie d’avance.Bonne journée.Hani
JPA/Hibernate, une fois bien maîtrisé, est très puissant et productif. Pour une application de gestion qui ne fait que du CRUD (Create, read, update and delete), comme par exemple gérer une liste de personnes, de voitures, JPA est très bien adapté aussi bien pour le développement, que pour la production : Rapidité, cache, maintenabilité.
Après, pour des applications à forte volumétrie avec un grand schéma relationnel et des jointures dans tous les sens, les requêtes en JPA sont aussi compliqué que du SQL classique pour restituer l’information stocké. Mais il faut savoir que souvent dans ce type de cas,il faut envisager une solution basée sur un datawarehouse ou les données sont agrégés quotidiennement pour être pretes à l’emploi à des fin de statistiques (Graphisme, BI, extraction).
Au final, très peu de projet sont encore réalisés en Full SQL. Les tâches CRUD sont si facile à gérer en JPA, il sera dommage de s’en priver. Et après, j’aurais tendance à dire que les requêtes particulières ( avec jointure) sont quand même mieux géré par Hibernate grâce au cache.
Pour Struts, je ne peux pas donner mon avis, j’ai testé il y a plusieurs années, avant l’arrivée de Spring, je n’ai aucune idée de qu’ils rajoutés depuis (Je croyais même que c’était mort ;-))
Je te remercie pour ta réponse claire ^^.
donc je pense m’orienter aussi vers du Hibernate( et sa surcouche JPA) .Pour Struts ,il résiste bien 🙂 (Struts est mort ,vive Struts ^^) donc oui il est encore utilisé (de moins en moins certes mais il y’a pas mal d’applications qui utilisent encore cette technologie ,contrairement a GWT qui a fait un flop ,struts lui tient encore le coup).
Pour revenir a Hibernate/JPA ,je dois avouer que j’avais pas mal d’a priori dessus qui viennent d’étre balayer (notamment concernant les multiples contraintes que ce dernier pose).Je te remercie
Juste pour compléter et éclaircir quelques points:
JPA n’est pas la surcouche d’Hibernate. Devant la popularité d’Hibernate et des outils de persistance, il a été décidé de créer le standard JPA d’interface pour persistance relationnel Java. Hibernate étant de loin le plus populaire et le plus utilisé des outils, les concepteurs d’Hibernate ont été consultés et intégrés à l’équipe chargée de rédiger le standard. De ce fait, dès la sortie du standard JPA, Hibernate a été compatible avec celui-ci.
On parle donc du standard JPA, et de ses implémentation : Hibernate, Tapestry. Hibernate propose tout de fois un peu plus de fonctionnalités que le simple standard.
Devant la popularité d’un outil, il est courant de voir un standard apparaître après quelques années. C’est assez courant dans le monde Java d’avoir le standard/interface d’un côté, et d’avoir une ou plusieurs implémentations dont une prédominante.
On retrouve ça par exemple avec la librairie commons.logging d’Apache qui propose un standard pour la gestion des logs. Et ensuite, on a l’implémentation log4j qui est une des plus connues.
Dans ce cas, le standard ne sert que d’interface, il est absolument nécessaire de choisir une implémentation, sinon, l’application ne peux pas fonctionner.
Attention, ce n’est pas le cas de JEE 6 et Spring par exemple. Spring a apporté un avantage non négligeable aux développeurs d’application face à la complexité des Enterprise JavaBeans (EJB). La communauté Java a donc décidé de s’en inspirer librement et de proposer un équivalent standard JEE 6 qui commence doucement à s’imposer. Il ne s’agit pas ici d’une interface standard JEE et de l’implémentation Spring. JEE 6 est un Framework à part entière intégré par défaut à Java pour remplacer Spring.
Au niveau de l’injection, Spring reconnait tout de même quelques annotations du standard. Pour plus d’informations sur les Java Specification Requests (JSR) reconnues par Spring , je te recommande cette page sur le site Spring par la pratique
Très très intéressent.
C’est très bien fait comme tutorial je vous remercie beaucoup !!!
très bon article, je vous remercier infiniment pour cet article qui ma beaucoup aidé. pour le DataSource, est ce que on met le code dans le contexte ou bien je suis obligé de crier une fichier spécialement pour le DataSource,
Cordialement