Tutoriel Java

Présentation du tutoriel

L'objectif de ce tutoriel est de réaliser une application "Todo List" en langage Java avec une interface graphique écrite en Swing. Ce tutoriel est destiné aux développeurs qui débutent en Java.

Caractéristiques techniques

Description de l'application

Le but de cette application est de créer des tâches qui sont assignées à un utilisateur.

La première fonctionnalité consiste donc à identifier l'utilisateur via un écran de login. Cependant, la première fois que l'application est utilisée, il n'y a pas d'utilisateur enregistré en base de données. Il faut donc prévoir un écran qui permet l'enregistrement d'un utilisateur. Une fois connecté, l'utilisateur pourra visualiser la liste de toutes les tâches enregistrées, y compris celles des autres utilisateurs. A partir de cette liste, il pourra aussi ajouter une nouvelle tâche ou modifier une tâche existante.

Organisation du développement

Nous commencerons par bâtir la couche métier de l'application, i.e. :

Pour tester le code produit dans la couche métier, nous utiliserons JUnit.

Nous développerons ensuite l'interface graphique.

Installation

Pour pouvoir réaliser ce tutorial, vous devez installer :

Vous devez par ailleurs télécharger le fichier mysql-connector-java-5.X.X-bin.jar, qui nous permettra de nous connecter à MySQL depuis Java.

Il faut ensuite passer le script SQL suivant pour créer la base de données :

create database todolist default character set latin1 collate latin1_swedish_ci;

use todolist;

grant all privileges on todolist.* to scott@127.0.0.1 identified by 'tiger';

create table utilisateur (
       identifiant varchar(10) not null, 
       mot_de_passe varchar(10) not null,
       nom varchar(30) not null,
       prenom varchar(30) not null,
       primary key(identifiant)) type=InnoDB;
	
create table tache (
       id integer not null auto_increment, 
       libelle varchar(100) not null, 
       date_fin date not null,
       priorite int(11) not null,
       utilisateur_id varchar(10),
       primary key(id)) type=InnoDB;
	
alter table tache
  add constraint fk_tache_utilisateur foreign key (utilisateur_id) references utilisateur (identifiant);

Développement de la couche métier

Création du projet

Ouvrir Netbeans et aller dans le menu File -> New Project. Sélectionner la catégorie Java, puis le type de projet Java Class Library.

TutJava1.png


Cliquer ensuite sur le bouton Next et renseigner le nom de projet TodoListService, et cliquer enfin sur le bouton Finish :

TutJava2.png

Création des classes d'entité

Une application Java est composée d'un ensemble de classes qui définissent chacunes une petite partie de l'application. A terme, l'application pourra comporter un grand nombre de classes. A des fins de lisibilités, et aussi pour éviter des conflits de nommage, les classes ne doivent pas être toutes créées au même endroit. Il faut donc les organiser dans des packages, notion objet qui correspond à peu près à une arborescence de répertoires. Commençons donc par créer un package pour nos classes d'entités :

TutJava3.png


Votre package doit maintenant apparaître dans votre projet comme ci-dessous :

TutJava4.png


Nous pouvons maintenant créer nos classes d'entités, qui correspondent plus ou moins aux tables définies en base de données. Les classes à créer sont les suivantes :

Pour cela, sélectionner le package créé précédemment, et par clic droit, sélectionner le menu New -> Java Class... et entrer le nom de classe Utilisateur (encore une fois, faites bien attention à la casse !).

TutJava5.png


Cliquer sur le bouton Finish. Vous devriez obtenir ceci :

TutJava6.png


Notez que le nom du package est spécifié dans le code généré, ainsi bien sûr que le nom de la classe. Cette classe que nous venons de créer est aussi un nouveau type que nous pourrons utiliser par la suite.

Dans la classe Utilisateur, ajouter le code suivant qui consiste à définir les propriétés d'un utilisateur :

package info.jtips.model;

public class Utilisateur {
   private String identifiant;
   private String nom;
   private String prenom;
   private String motDePasse;

   public String getIdentifiant() {
       return identifiant;
   }

   public void setIdentifiant(String identifiant) {
       this.identifiant = identifiant;
   }

   public String getMotDePasse() {
       return motDePasse;
   }

   public void setMotDePasse(String motDePasse) {
       this.motDePasse = motDePasse;
   }

   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;
   }

}

Chaque utilisateur est caractérisé par un identifiant, un nom, un prénom et un mot de passe. Ces informations sont de type chaîne de caractères, soit String en syntaxe Java. Par convention, pour définir une propriété au sens Java, il faut aussi ajouter les méthodes getters et setters. Ces méthodes doivent respecter les règles de nommage qui apparaissent dans le code ci-dessus.


De la même façon, vous pouvez créer la classe Tache :

package info.jtips.model;

import java.util.Date;

public class Tache {
   private int id;
   private String libelle;
   private Date dateFin;
   private int priorite;

   public Date getDateFin() {
       return dateFin;
   }

   public void setDateFin(Date dateFin) {
       this.dateFin = dateFin;
   }

   public int getId() {
       return id;
   }

   public void setId(int id) {
       this.id = id;
   }

   public String getLibelle() {
       return libelle;
   }

   public void setLibelle(String libelle) {
       this.libelle = libelle;
   }

   public int getPriorite() {
       return priorite;
   }

   public void setPriorite(int priorite) {
       this.priorite = priorite;
   }
}

Remarques sur le code ci-dessus :

Nous venons de définir les entités Utilisateur et Tache, ainsi que leur propriétés. En fait, ces classes ne sont pas indépendantes, elles sont liées de la façon suivante :

En notation UML, cela donne le schéma suivant :

TutJava7.png


Les relations entre classes qui apparaissent sur le schéma ci-dessus s'appellent associations. En Java, une association se code comme une propriété :

package info.jtips.model;

import java.util.Date;

public class Tache {
   private int id;
   private String libelle;
   private Date dateFin;
   private int priorite;
   
   private Utilisateur utilisateur;

   public Utilisateur getUtilisateur() {
       return utilisateur;
   }

   public void setUtilisateur(Utilisateur utilisateur) {
       this.utilisateur = utilisateur;
   }
   // autres getters et setters...
}
package info.jtips.model;

import java.util.List;

public class Utilisateur {
   private String identifiant;
   private String nom;
   private String prenom;
   private String motDePasse;

   private List<Tache> taches;

   public List<Tache> getTaches() {
       return taches;
   }

   public void setTaches(List<Tache> taches) {
       this.taches = taches;
   }
   // autres getters et setters...

}

Remarque sur le code ci-dessus :

Pour terminer avec les classes d'entités, nous allons coder une méthode nommée ajouterTache qui permet d'ajouter une tâche à un utilisateur :

package info.jtips.model;

import java.util.List;

public class Utilisateur {
   private String identifiant;
   private String nom;
   private String prenom;
   private String motDePasse;

   private List<Tache> taches;

   public void ajouterTache(Tache t) {
       if (taches == null) taches = new ArrayList<Tache>();
       taches.add(t);
       t.setUtilisateur(this);
   }

   // getters et setters...
}

Remarques sur le code de la méthode ajouterTache(Tache t) ci-dessus :

Création des classes DAO

Les DAO sont des classes d'accès aux données. Il s'agit de classes qui fournissent des méthodes dont le but est d'exécuter des requêtes SQL. De plus, ces méthodes sont chargées de la traduction des données tabulaires en objet et réciproquement. Une bonne pratique pour mettre en oeuvre les DAO consiste à d'abord spécifier les méthodes qu'elles doivent mettre en oeuvre. A cette fin, nous allons créer des types Java qui ne sont pas des classes, mais des interfaces (à la différence d'une classe, une interface n'est pas instanciable).

Dans votre projet NetBeans, créer le package info.jtips.dao et créer l'interface nommée UtilisateurDao (menu New -> Java Interface...). Vous ajouterez aussi le code de spécification des méthodes qui figurent ci-dessous.

package info.jtips.dao;

import info.jtips.model.Utilisateur;

public interface UtilisateurDao {
   Utilisateur findById(String identifiant);
   void create(Utilisateur u);
}

Remarque : les méthodes créées ci-dessus ne possèdent pas de corps pour ajouter du code; nous avons simplement défini la signature des différentes méthodes

De la même façon, créer l'interface TacheDao :

package info.jtips.dao;

import info.jtips.model.Tache;
import java.util.List;

public interface TacheDao {
   List<Tache> findAll();
   Tache findById(int id);
   void create(Tache t);
   void update(Tache t);
   void delete(Tache t);
}

Pour continuer, ajoutons la classe UtilisateurDaoImpl dans le package info.jtips.dao.impl :

package info.jtips.dao.impl;

import info.jtips.dao.UtilisateurDao;
import info.jtips.model.Utilisateur;

public class UtilisateurDaoImpl implements UtilisateurDao {

   public Utilisateur findById(String identifiant) {
       return null;
   }

   public void create(Utilisateur u) {
       
   }

}

Cette classe réalise l'interface que nous avons définie précédemment :

Voyons maintenant comment coder cette classe de telle sorte que l'on puisse mettre en oeuvre le requêtage SQL nécessaire. Nous allons pour cela utiliser l'API JDBC, qui consiste à :

Commençons par créer une méthode pour établir la connexion sur la base de données (MySQL en l'occurence) :

package info.jtips.dao.impl;

import info.jtips.dao.UtilisateurDao;
import info.jtips.model.Utilisateur;
import java.sql.Connection;
import java.sql.DriverManager;

public class UtilisateurDaoImpl implements UtilisateurDao {

   public Utilisateur findById(String identifiant) {
       return null;
   }

   public void create(Utilisateur u) {
       
   }

   private Connection getConnexion() throws Exception {
       // Chargement du driver
       Class.forName("com.mysql.jdbc.Driver");

       // Obtention de la connexion
       String url = "jdbc:mysql://localhost:3306/todolist";
       Connection cx = DriverManager.getConnection(url, "scott", "tiger");
       return cx;
   }

}

Remarque sur le code de la méthode getConnexion() :

Nous pouvons maintenant coder la méthode findById() :

package info.jtips.dao.impl;

import info.jtips.dao.UtilisateurDao;
import info.jtips.model.Utilisateur;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UtilisateurDaoImpl implements UtilisateurDao {

   public Utilisateur findById(String identifiant) {
       Connection cx = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       Utilisateur utilisateur = null;
       try {
           cx = getConnexion();
           st = cx.prepareStatement("select nom, prenom, mot_de_passe from utilisateur where identifiant = ?");
           st.setString(1, identifiant);
           rs = st.executeQuery();
           if (rs.next()) {
               String nom = rs.getString(1);
               String prenom = rs.getString(2);
               String motDePasse = rs.getString(3);
               
               utilisateur = new Utilisateur();
               utilisateur.setIdentifiant(identifiant);
               utilisateur.setNom(nom);
               utilisateur.setPrenom(prenom);
               utilisateur.setMotDePasse(motDePasse);
           }

       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (rs != null) rs.close(); } catch (SQLException sqle) {}
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }

       return utilisateur;
   }

   public void create(Utilisateur u) {}

   private Connection getConnexion() throws Exception {
       // Chargement du driver
       Class.forName("com.mysql.jdbc.Driver");

       // Obtention de la connexion
       String url = "jdbc:mysql://localhost:3306/todolist";
       Connection cx = DriverManager.getConnection(url, "scott", "tiger");
       return cx;
   }

}

Remarques sur le code de la méthode findById() :

Pour terminer le code de cette première DAO, il nous reste à compléter la méthode create(Utilisateur u). Contrairement à la méthode précédente, il s'agit d'une requête d'écriture; le code est donc légèrement différent :

   public void create(Utilisateur u) {
       Connection cx = null;
       PreparedStatement st = null;
       try {
           cx = getConnexion();
           st = cx.prepareStatement("insert into utilisateur (identifiant, nom, prenom, mot_de_passe) values (?, ?, ?, ?)");
           st.setString(1, u.getIdentifiant());
           st.setString(2, u.getNom());
           st.setString(3, u.getPrenom());
           st.setString(4, u.getMotDePasse());

           st.executeUpdate();
       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }
   }


De la même façon, nous codons la classe DAO pour les tâches :

package info.jtips.dao.impl;

import info.jtips.dao.TacheDao;
import info.jtips.model.Tache;
import info.jtips.model.Utilisateur;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TacheDaoImpl implements TacheDao {

   public List<Tache> findAll() {
       Connection cx = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       List<Tache> taches = new ArrayList<Tache>();
       try {
           cx = getConnexion();
           st = cx.prepareStatement("select id, libelle, priorite, date_fin, utilisateur_id from tache");
           rs = st.executeQuery();
           while (rs.next()) {
               int id = rs.getInt(1);
               String libelle = rs.getString(2);
               int priorite = rs.getInt(3);
               Date dateFin = rs.getDate(4);
               String utilisateurId = rs.getString(5);

               Tache t = new Tache();
               t.setId(id);
               t.setLibelle(libelle);
               t.setDateFin(dateFin);
               t.setPriorite(priorite);

               Utilisateur u = new Utilisateur();
               u.setIdentifiant(utilisateurId);
               t.setUtilisateur(u);

               taches.add(t);
           }

       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (rs != null) rs.close(); } catch (SQLException sqle) {}
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }

       return taches;
   }

   public Tache findById(int id) {
       Connection cx = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       Tache t = null;
       try {
           cx = getConnexion();
           st = cx.prepareStatement("select id, libelle, priorite, date_fin, utilisateur_id from tache where id = ?");
           st.setInt(1, id);
           rs = st.executeQuery();
           if (rs.next()) {
               String libelle = rs.getString(2);
               int priorite = rs.getInt(3);
               Date dateFin = rs.getDate(4);
               String utilisateurId = rs.getString(5);

               t = new Tache();
               t.setId(id);
               t.setLibelle(libelle);
               t.setDateFin(dateFin);
               t.setPriorite(priorite);

               Utilisateur u = new Utilisateur();
               u.setIdentifiant(utilisateurId);
               t.setUtilisateur(u);
           }

       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (rs != null) rs.close(); } catch (SQLException sqle) {}
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }

       return t;
   }

   public List<Tache> findByUtilisateur(Utilisateur u) {
       Connection cx = null;
       PreparedStatement st = null;
       ResultSet rs = null;
       List<Tache> taches = new ArrayList<Tache>();
       try {
           cx = getConnexion();
           st = cx.prepareStatement("select id, libelle, priorite, date_fin from tache where utilisateur_id = ?");
           st.setString(1, u.getIdentifiant());
           rs = st.executeQuery();
           while (rs.next()) {
               int id = rs.getInt(1);
               String libelle = rs.getString(2);
               int priorite = rs.getInt(3);
               Date dateFin = rs.getDate(4);

               Tache t = new Tache();
               t.setId(id);
               t.setLibelle(libelle);
               t.setDateFin(dateFin);
               t.setPriorite(priorite);
               t.setUtilisateur(u);

               taches.add(t);
           }

       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (rs != null) rs.close(); } catch (SQLException sqle) {}
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }

       return taches;
   } 
 
   public void create(Tache t) {
       Connection cx = null;
       PreparedStatement st = null;
       try {
           cx = getConnexion();
           st = cx.prepareStatement("insert into tache (libelle, priorite, date_fin, utilisateur_id) values (?, ?, ?, ?)");
           st.setString(1, t.getLibelle());
           st.setInt(2, t.getPriorite());
           Date df = t.getDateFin();
           java.sql.Date dateFin = new java.sql.Date(df.getTime());
           st.setDate(3, dateFin);
           st.setString(4, t.getUtilisateur().getIdentifiant());

           st.executeUpdate();
       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }
   }

   public void update(Tache t) {
       Connection cx = null;
       PreparedStatement st = null;
       try {
           cx = getConnexion();
           st = cx.prepareStatement("update tache set libelle = ?, priorite = ?, date_fin = ?, utilisateur_id = ? where id = ?");
           st.setString(1, t.getLibelle());
           st.setInt(2, t.getPriorite());
           st.setDate(3, new java.sql.Date(t.getDateFin().getTime()));
           st.setString(4, t.getUtilisateur().getIdentifiant());
           st.setInt(5, t.getId());

           st.executeUpdate();
       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }
   }

   public void delete(Tache t) {
       Connection cx = null;
       PreparedStatement st = null;
       try {
           cx = getConnexion();
           st = cx.prepareStatement("delete from tache where id = ?");
           st.setInt(1, t.getId());

           st.executeUpdate();
       } catch (Exception e) {
           throw new RuntimeException(e);
       } finally {
           try { if (st != null) st.close(); } catch (SQLException sqle) {}
           try { if (cx != null) cx.close(); } catch (SQLException sqle) {}
       }
   }

   private Connection getConnexion() throws Exception {
       // Chargement du driver
       Class.forName("com.mysql.jdbc.Driver");

       // Obtention de la connexion
       String url = "jdbc:mysql://localhost:3306/todolist";
       Connection cx = DriverManager.getConnection(url, "scott", "tiger");
       return cx;
   }

}

Tester les DAO avec JUnit

Nos DAO sont prêtes, nous allons maintenant les tester avec JUnit. Avant toute chose, il faut installer le driver MySQL, faute de quoi, nous ne pourrons pas nous connecter à la base de données. Pour cela, il suffit de sélectionner le menu Add JAR/Folder... par clic droit sur le répertoire Librairies de votre projet :

TutJava8.png


Après la sélection du driver MySQL, vous devriez le voir apparaître dans votre explorateur de projet sous NetBeans :

TutJava9.png


Ajoutons maintenant la classe de test JUnit pour la DAO Utilisateur :

TutJava10.png


Rentrer ensuite le nom classe de la classe de test : UtilisateurDaoTest, puis sélectionner les cases à cocher comme ci-dessous :

TutJava11.png


Choisir enfin JUnit 4 comme librairie de test :

TutJava12.png


Le code généré par NetBeans est le suivant :

package info.jtips.dao;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class UtilisateurDaoTest {

   public UtilisateurDaoTest() {
   }

   @BeforeClass
   public static void setUpClass() throws Exception {
   }

   @AfterClass
   public static void tearDownClass() throws Exception {
   }

}


Complétons cette classe afin de tester l'insertion d'un utilisateur en base de données en ajoutant la méthode testCreate() :

package info.jtips.dao;

import info.jtips.dao.impl.UtilisateurDaoImpl;
import info.jtips.model.Utilisateur;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class UtilisateurDaoTest {

   public UtilisateurDaoTest() {
   }

   @BeforeClass
   public static void setUpClass() throws Exception {
   }

   @AfterClass
   public static void tearDownClass() throws Exception {
   }

   @Test
   public void testCreate() {
       Utilisateur u = new Utilisateur();
       u.setIdentifiant("bb");
       u.setPrenom("Bugs");
       u.setNom("Bunny");
       u.setMotDePasse("mp");

       UtilisateurDao dao = new UtilisateurDaoImpl();
       dao.create(u);

       System.out.println("Terminé");// permet d'afficher le message "Terminé" en console
   }

}

Remarque sur le code de la classe de test :


Pour exécuter ce code, sélectionner le menu Test File par clic droit sur la classe UtilisateurDaoTest. Vous devriez obtenir le rapport JUnit suivant :

TutJava13.png


Vous pouvez aussi vérifier en base de données la création du nouvel enregistrement.

Pour terminer la classe de test, nous ajoutons la méthode testFindById() :

package info.jtips.dao;

import info.jtips.dao.impl.UtilisateurDaoImpl;
import info.jtips.model.Utilisateur;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class UtilisateurDaoTest {

   public UtilisateurDaoTest() {
   }

   @BeforeClass
   public static void setUpClass() throws Exception {
   }

   @AfterClass
   public static void tearDownClass() throws Exception {
   }

   @Test
   public void testCreate() {
       Utilisateur u = new Utilisateur();
       u.setIdentifiant("bb");
       u.setPrenom("Bugs");
       u.setNom("Bunny");
       u.setMotDePasse("mp");

       UtilisateurDao dao = new UtilisateurDaoImpl();
       dao.create(u);

       System.out.println("Terminé");// permet d'afficher le message "Terminé" en console
   }

   @Test
   public void testFindById() {
       UtilisateurDao dao = new UtilisateurDaoImpl();
       Utilisateur u = dao.findById("bb");
       assertEquals("bb", u.getIdentifiant());
       assertEquals("Bugs", u.getPrenom());
       assertEquals("Bunny", u.getNom());
       assertEquals("mp", u.getMotDePasse());
   }

}

Remarque sur le code de la méthode testFindById() :


Si vous relancez l'exécution du test, vous devriez obtenir le résultat suivant :

TutJava14.png


Nous constatons que le test de la méthode findById() a réussi (rapport vert), tandis que le test de la méthode create() a échoué (rapport rouge). C'est normal, puisque nous avons tenté de créer un nouvel enregistrement avec une clé primaire déjà présente en base (enregistrement créé lors de l'exécution précédente).


Voici enfin la classe de test pour la DAO des tâches  :

package info.jtips.dao;

import info.jtips.dao.impl.TacheDaoImpl;
import info.jtips.model.Tache;
import info.jtips.model.Utilisateur;
import java.util.Date;
import java.util.List;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class TacheDaoTest {

   public TacheDaoTest() {
   }

   @BeforeClass
   public static void setUpClass() throws Exception {
   }

   @AfterClass
   public static void tearDownClass() throws Exception {
   }

   @Test
   public void testCreate() {
       Utilisateur u = new Utilisateur();
       u.setIdentifiant("bb");
       u.setPrenom("Bugs");
       u.setNom("Bunny");
       u.setMotDePasse("mp");

       Tache t1 = new Tache();
       t1.setLibelle("Une première tâche");
       t1.setDateFin(new Date());
       t1.setPriorite(1);
       u.ajouterTache(t1);

       Tache t2 = new Tache();
       t2.setLibelle("Une deuxième tâche");
       t2.setDateFin(new Date());
       t2.setPriorite(1);
       u.ajouterTache(t2);

       TacheDao dao = new TacheDaoImpl();
       dao.create(t1);
       dao.create(t2);

       System.out.println("Terminé");
   }

   @Test
   public void testFindById() {
       TacheDao dao = new TacheDaoImpl();
       Tache t = dao.findById(1);
       assertEquals(1, t.getId());
       assertEquals("Une première tâche", t.getLibelle());
       assertEquals("bb", t.getUtilisateur().getIdentifiant());
   }

   @Test
   public void testFindAll() {
       TacheDao dao = new TacheDaoImpl();
       List<Tache> taches = dao.findAll();
       assertEquals(2, taches.size());
   }

   @Test
   public void testUpdate() {
       TacheDao dao = new TacheDaoImpl();
       Tache t = dao.findById(2);
       t.setLibelle("Tâche modifiée");
       dao.update(t);
   }

   @Test
   public void testDelete() {
       TacheDao dao = new TacheDaoImpl();
       Tache t = dao.findById(1);
       dao.delete(t);
   }
    
}

Refactoring !

Après le développement des classes présentées ci-dessus, je me suis aperçu que je m'étais trompé dans les noms de package. En effet, il serait souhaitable d'ajouter le nom de l'application "TodoList" dans les noms de package. Nous allons donc utiliser la fonctionnalité de refactoring offerte par NetBeans. Pour cela, sélectionner le package à renommer, puis par clic droit, naviguer vers le menu Refactor -> Rename... :

TutJava15.png

Nous renommons ainsi l'ensemble de nos packages, sans oublier les classes de test, suivant la règle de nommage info.jtips.todolist.xxx, ce qui donne au final :

TutJava16.png

Création des classes de service métier

Cf article Partie 2 : écrire une couche de service métier.

Téléchargement du projet

Le projet NetBeans correspondant à cette première partie.

Création des classes de présentation (Swing)

Bientôt un nouvel article pour traiter le sujet...