Architecture JEE classique

Introduction

Dans l'approche JEE traditionnelle, la pile de spécifications prévues est la suivante :

  • CDI (Context and Dependency Injection) : Injection de dépendances.
  • JPA : Accès aux données.
  • EJB (Enterprise Java Bean) : Construction des services métiers.
  • JSF (Java Server faces) : Construction des applications WEB par une approche composants et événements.
  • JAX-RS : Construction d'API REST.

CDI: Context and Dependency Injection

Définition d'un POJO avec un nom et une portée :

package myapp.cdisample;

import java.io.Serializable;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;

@RequestScoped
@Named("normal")
public class Home implements Serializable {

    private static final long serialVersionUID = 1L;

    String place;

    // getter / setter
}

Injection via les annotations :

package myapp.cdisample;

import java.io.Serializable;
import jakarta.inject.Inject;
import jakarta.inject.Named;

@Named("person")
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;

    @Inject @Named("normal")
    private Home home;

    // getter / setter
}

Autres possibilités :

  • Qualification des instances,
  • producteurs et recycleurs d'instances,
  • abonnement à des événements,

EJB: Enterprise java Bean Stateless

Figure figures/intro/ejb-principes

Déroulement (exploitation des architectures multi-processeurs-coeurs) :

thread 1 : <--- C1 sur A1 ---><--- C2 sur A1 --->
thread 2 : <------- C3 sur A2 ------->
thread 3 : <---- C4 sur B1 ---->

Avec une troisième instances de A :

thread 1 : <--- C1 sur A1 --->
thread 4 : <--- C2 sur A3 --->
thread 2 : <------- C3 sur A2 ------->
thread 3 : <---- C4 sur B1 ---->

La montée en charge implique une augmentation du nombre d'instances.

Gestion automatique (mais paramétrée) par le serveur d'applications.

EJB Statefull

EJB avec état utilisé par un seul client (non simultanément).

Figure figures/intro/ejb-statefull

Utilité : représentation d'un utilisateur et fonctions associées.

EJB Singleton

EJB a instance unique (avec état) utilisé par plusieurs clients.

Figure figures/intro/ejb-singleton

Déroulement (parallélisme des read et mise en série des write) :

<---- read 1 ---->                        <----- read 5 ----->
    <----- read 2 ------> <-- write 3 --> <-- read 4 -->

EJB: Mise en oeuvre de JPA

@PersistenceContext(unitName = "myBase")
EntityManager em;

public List<User> findAllUsers() {
    TypedQuery<Person> q = em.createNamedQuery("findAllUsers", User.class);
    return q.getResultList();
}

Le serveur d'applications gère (via les proxys) :

  • l'ouverture de la transaction
  • la validation de la transaction
  • les erreurs d'exécution

Approche transactionnelle (très utile pour les opérations complexes).

EJB: Autres fonctions

  • définition de traitements périodiques (similaire à cron d'UNIX)
  • mise en place d'intercepteur (programmation par aspects)
  • définition de traitements asynchrones (pour les traitements longs)
  • EJB orientés message : traitement d'un file de messages (requêtes)

JSF: Java Server Faces

Principes : Framework WEB basé sur l'architecture MVC:

  • View : facelet (document XML doté d'un langage d'expression)
  • Controler : Managed beans instanciés par le framework
  • Model : POJO et Managed beans

Caractéristiques :

  • Utilisation d'une approche composant
  • Mise en correspondance automatique entre POJO et Facelet
  • Framework Javascript de gestion des pages (AJAX)
  • Processus de validation
  • Présence de nombreuses librairies externes (PrimeFaces, ...)

JSF: Un premier exemple

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" >
    <h:body>
        <h1><h:outputText value="#{helloControler.hello}" /></h1>
    </h:body>
</html>
package myapp;

import jakarta.faces.bean.ManagedBean;
import jakarta.faces.bean.SessionScoped;

@ManagedBean(name = "helloControler") @SessionScoped
public class MyControler {

    private String hello = "Hello, world";

    public String getHello() { return hello; }
    public void setHello(String hello) { this.hello = hello; }
}

JSF: Utilisation d'un formulaire

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html" >

<h:body>
    <h1><h:outputText value="#{helloControler.hello}" /></h1>

    <h:form>
        <h:inputText id="text" value="#{helloControler.hello}"
            required="true" requiredMessage="Le texte est obligatoire">
            <f:validateLength minimum="3" maximum="15" />
        </h:inputText>
        <h:message errorClass="error" for="text" />
        <br/>

        <h:commandButton value="Submit" action="#{helloControler.sayHello}" />
    </h:form>
</h:body>
</html>

Amélioration du contrôleur :

package myapp;

import jakarta.faces.bean.ManagedBean;
import jakarta.faces.bean.SessionScoped;

@ManagedBean(name = "helloControler") @SessionScoped
public class MyControler {

    private String hello = " Hello, world";

    // getter / setter
    public String getHello() { return hello; }
    public void setHello(String hello) { this.hello = hello; }

    public String sayHello() {
        hello = hello.toUpperCase();
        return null;
    }

}

JSF: Autres caractéristiques

  • Grande facilité de mise en place d'AJAX
  • Possibilités de navigation avancées
  • Cinq portés disponibles:
    • application
    • session
    • conversation (notion de sous-session)
    • vue (on reste sur la même page JSF)
    • requête
  • Traitement des événement HTML (éventuellement en AJAX)
  • Possibilité de couplage avec bootstrap ou Angular

Intégration

Dans une application, l'API CDI va

  • Injecter les EntityManager dans les EJB.
  • Injecter les EJB dans d'autres EJB et dans les contrôleurs JSF
  • Injecter les beans de portée vue, requêtes, session dans les contrôleurs JSF