Affichage et sauvegarde d’une liste d’élément contenu dans un tableau avec Struts2

Affichage et sauvegarde d’une liste d’élément contenu dans un tableau

java logo  struts jsp  hibernate

Quelque soit l’application développé, il est toujours intéressant de pouvoir lier des modèles. Pour notre exemple, nous allons lier une liste de TVA sélectionnable dans une facture.

Voici nos fameux éléments représentant des Taux de TVA.

TVA

Il est possible d’enregistrer plusieurs services ou produits ayant des taux de TVA différents. Ci-dessous, une réservation avec un taux de TVA. Il est possible d'ajouter plusieurs réservations a des taux différents. Bref, les exemples et les combinaisons possibles sont infinis.

Struts_Tva

1. Petit rappel sur le framework Struts 2 :

Pour ce qui ne sont pas familié avec le concepte de Struts2, voici un petit tour d'horizon.

Ce framework évolue sur le modèle de conception de type MVC (Modèle, Vue, Contrôleur). Il repose sur une déclaration de l'architecture sous forme de fichiers XML (ou annotations Java) localisées dans les fichiers des classes d'actions. Struts 2 est un framework orienté actions.

Les actions sont décomposées en trois rôles :

- Les actions encapsulent le traitement et le travail à réaliser par le service.

- Les actions permettent de manipuler automatiquement les données des requêtes lors des transferts.

- Le framework détermine quel résultat doit être retourné et la Vue à afficher en réponse à un traitement. La Vue est un fichier JSP au format XML.

Les actions Struts 2 implémentent des objets JavaBeans (simple objet Java : classe publique, constructeur par défaut, publique, sans paramètre, attributs non publics, déclarer getter et setter) pour chaque groupe de données envoyées dans la requête. Chaque paramètre de la requête est déclaré dans la classe d'action avec un nom identique pour réaliser automatiquement le mapping des valeurs. La finalité d'une action étant de retourner une chaîne de caractères permettant de sélectionner le résultat à afficher.

2. La classe action :

Commençons par déclarer l’attribut tvaList qui est une liste de type TVA.

private List<TVA> tvaList ;



La classe TVA est un JavaBean. C’est une classe persistante dans la stratégie de mapping est de type “Joined”.

@SuppressWarnings("serial")

@Entity

@Inheritance(strategy=InheritanceType.JOINED)

public class TVA extends EmobiliaEntity {

   

   private Long id;

   private Integer version;

   private boolean enabled=true;

   private Integer rate;

   private String label;

   private Account account;

//---------------

Get / Set

//---------------

@ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.EAGER)

   public Account getAccount() {

      return account;

   }

   public void setAccount(Account account) {

      this.account = account;

   }

Quelques explications sur ces annotations Hibernate :

@Entity : Cette dernière est persistante et donc associée à une table dans la base de données.

@Inheritance(strategy=InheritanceType.JOINED) : La stratégie de mapping est de type “Joined”. Il y a une table et une jointure par table. Ainsi les informations sont répartis sur plusieurs tables. La seule colonne commune entre les tables est la colonne ID qui permet de faire les jointures table mère et table fille.    

@ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.EAGER) :

  • On parle de persistance des données avec une relation n:1.

  • Le comportement cascade REFRESH effectue en cascade l'opération de rafraîchissement sur les entités associées si refresh() est appelée.

  • Enfin, la jointure sql s’effectue dès que l'objet est récupéré pour initialiser la collection.

La classe Account est aussi un JavaBean.



Toujour dans la classe action, la liste tvaList est initialisé en l'insérant dans la méthode initSelecList().

private void initSelectList() throws ServiceException {

          ParametreCompta param = parametreComptaService.getDefaultParam();

          this.tvaList = param.getTvaSelectionFactureHotel();

          this.accountList = param.getCompteSelectionFactureHotel();

          }



@EJB private ParametreComptaService parametreComptaService;

L'annotation @EJB permet de préciser les sessions beans que le container EJB va instancier et initialiser automatiquement.

L'annotation peut être utilisée avec des variables pour indiquer au container EJB d'y injecter automatiquement l'instance des sessions beans.

L'injection des instances des sessions beans est faite avant que les méthodes métiers ne soient invoquées.



3. Les classes JavaBeans :

La classe ParametreCompta est aussi un javaBean

private List<TVA> tvaSelectionFactureHotel;

private TVA tvaDefautFactureHotel;

@OneToMany(cascade=CascadeType.REFRESH,fetch=FetchType.EAGER)

   @Cascade(value=org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

   @Column(nullable=true)

   @Fetch(FetchMode.SUBSELECT)

   @JoinTable(name = "tva_selectionnable_facture_hotel")

   public List<TVA> getTvaSelectionFactureHotel() {

      return tvaSelectionFactureHotel;

   }

   public void setTvaSelectionFactureHotel(List<TVA> tvaSelectionFactureHotel) {

      this.tvaSelectionFactureHotel = tvaSelectionFactureHotel;

   }

@ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.EAGER)

   public TVA getTvaDefautFactureHotel() {

      return tvaDefautFactureHotel;

   }

   public void setTvaDefautFactureHotel(TVA tvaDefautFactureHotel) {

      this.tvaDefautFactureHotel = tvaDefautFactureHotel;

   }

Les deux attributs déclarés sont :

  • La liste des TVA permettant l’édition et l’enregistrement de la TVA

  • L’attribut de type TVA pour l’affichage de la TVA

L’annotation @Column détermine la façon dont l'entity manager injecte les valeurs dans les instances de cette classe. L’attribut nullable empêche cette colonne de porter des valeurs nulles.

L’annotation CascadeType.DELETE_ORPHAN : La plupart du temps, l'existence d'une entité (père) n'a de sens que si elle est en relation avec une autre entité (fils). Effacer l’entité père doit alors entraîner l'effacement de l’entité fils.

@Fetch : La stratégie fetch est déclarée dans la relation de mapping pour définir comment Hibernate récupère et lie les collections aux entités.

Le mode Fetch- "subselect" regroupe la collection dans une instruction de sous-sélection.

@Jointable : Utilisé pour le mapping des associations. Permet de générer une table intermédiaire.



Classe HotelPartnerBillingItem.java permet de définir les attributs liés à la JSP. C’est une classe persistante.

private TVA tva;

@ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.EAGER)

   public TVA getTva() {

      return tva;

   }

   public void setTva(TVA tva) {

      this.tva = tva;

   }

   

   @Transient

   public String getTvaId(){

      if(tva!=null){

          return String.valueOf(tva.getId());

      }

      return null;

   }

   @Transient

   public void setTvaId(String tvaId)

   {

      if(tvaId!=null && !tvaId.equals("-1")){

          tva = new TVA();

          tva.setId(Long.valueOf(tvaId));

      }else{

          tva = null;

      }

   }

L’annotation @Transient est liée à la sérialisation des classes Java. Il permet d'interdire la sérialisation de certaines variables d'une classe. La valeur de la variable reste transitoire et n’est pas enregistré en bdd.

4. La classe Fascade :

La variable tvaId récupère l’id numérique de la TVA, les valeur de cette id sont récupéré dans la classe HotelPartnerBillingFacadeBean.java

Lors de la construction de la facture, la méthode buildLigneFacture() permet de les informations liées à l’id TVA, notamment son Taux.



@EJB private TVAService tvaService;

private void buildLigneFacture(HotelPartnerBillingItem hb,Facture f){

//----

if(hb.getTvaId()!=null){

              try {

                  TVA tva = tvaService.find(Long.valueOf(hb.getTvaId()));

                  l.setTva(tva);

                  hb.setTva(tva);

                  l.setTauxTva(tva.getRate());

              } catch (ServiceException e) {

                  logger.error(e);

              }

          }



5. La vue JSP :

Enfin, voici le fichier JSP qui permet de modifier la vue.

<s:select list="tvaList" headerKey="-1" headerValue="Choisir une TVA"

              listKey="id" listValue="label"

                     name="listItem[%{count}].tvaId"

                     value="%{billItem.tvaId}" key="label.tauxTva">

</s:select>       

Dans le select :

La list est le nom de la liste déroulante qui est appelée.

Le name permet de remplir la liste lors de l’enregistrement de la page.

La value permet de remplir la liste lors du chargement de la page.

La key représente le nom du label appelé dans un fichier de properties.

Le headerValue permet de définir un label par défaut lors de l'apparition de la liste dont le choix n’a pas encore été définis.

Le HeaderKey est la clé pour le premier élément dans la liste.



Sous Struts 2, l’organisation des classes s’effectue entre la classe Action - les classes JavaBeans et les Vues.

J’espère que cet article vous a aidé dans vos recherches.

@JonathanC

Tags :
Java
Struts2
JSP
Hibernate