Intermédiaire

Présentation de MVC 1.0 aka JSR 371, l’autre framework web Java Standard

Qu’est-ce que le pattern MVC ? Pour résumer, c’est un modèle de conception permettant de séparer la présentation, le traitement métier, et la base de données. Ce modèle de conception est utilisé dans les frameworks web pour la création d’interfaces utilisateurs, car il permet au designer et au développeur de travailler conjointement.

A l’heure actuelle, on distingue deux grands courants dans les technologies Java qui implémentent ce pattern : Les frameworks orientés « action » popularisés par Struts 1, 2, Spring MVC, et ceux orientés « composants » comme JSF, Wicket, et Tapestry.

Les origines de la JSR

En Mars 2014, ont été publiés les résultats de plusieurs sondages soumis à la communauté java (4 500 votants ). Ces sondages [1] portaient sur les futurs api de la plateforme  JAVA EE 8 et parmi les résultats, MVC a obtenu 60,8% de réponses positives.

 mvc-support1

Dans le graphique [2] ci-dessous, chaque section est affichée avec le pourcentage de votes obtenus.  On peut remarquer un pourcentage assez important pour « MVC » (7,8%), qui le place en 5e position dans les features les plus demandées.

 ResultChart-MVC

Pourquoi un autre framework MVC ?

 Alors que JSF (Java server Face) est la technologie Java de référence depuis 2004 pour la conception d’applications web. Il est légitime de se demander pourquoi un autre framework MVC ? Fondamentalement, ces 2 types reposent toujours sur le modèle MVC, mais diffèrent dans leurs modes de fonctionnement.

JSF a été pensé au départ pour faciliter la création de pages web, par l’inclusion de “composants” à l’aide de librairies de tags, à la manière d’une application lourde écrite avec la bibliothèque “Swing”. Le principal avantage pour le développeur est qu’il n’a pas à se soucier du code html/javascript/css côté client.

Citons les autres caractéristiques de JSF, les plus importantes à mon sens:

  • Une librairie de composants “riches”, réutilisables, personnalisables, et extensibles.
  • Indépendant de la technologie de présentation (jsp, Facelet, etc..).
  • Moins de code html/javascript à écrire car encapsulé par les composants.
  • Abstraction du cycle de vie des requêtes HTTP.

Bien que JSF soit adapté à la création rapide d’applications web, il y a en revanche peu de possibilités de personnaliser le rendu html/javascript/css. Enfin, de par son mode de fonctionnement, la courbe d’apprentissage de JSF est plus longue que pour un framework MVC dit “classique”.

JSF présente beaucoup d’avantages mais ne répond pas à tous les besoins. MVC se présente comme une alternative plus simple, ce qui explique les résultats des sondages.

Présentation des couches Modèle-Vue-Controleur de MVC

Un des points importants concernant la JSR 371, est que la spécification est basée sur celle de JAX-RS. Ce n’est pas anodin, car au départ, les experts du groupe en charge de la spécification hésitaient entre la spécification Servlet et JAX-RS.

JAX-RS a été logiquement choisi car, premièrement, il implémente déjà la spécification Servlet 3.0, ce qui évite de dupliquer les api entre MVC et JAX-RS et, deuxièmement, les développeurs déjà familiers avec JAX-RS pourront facilement appréhender MVC. Troisièmement, cela permet à MVC d’être compatible avec les spécifications CDI et Bean validations.

On va regarder les différentes api et leurs utilisations dans l’architecture MVC [2]. Le schéma ci-dessous résume les différentes interactions entre les couches :

jsfactionframework-2280469

Les contrôleurs

Les contrôleurs dans le pattern MVC, sont chargés d’associer une interface avec le modèle de données afin de produire une page web.

Les Contrôleurs de la JSR-371 sont des ressources JAX-RS déclarées par une annotation @Controller. Lorsque cette annotation est sur une méthode, celle-ci devient un “controller”,  et on parle de classe “hybride”, car les autres méthodes peuvent être des ressources JAX-RS en @GET par exemple. Si l’annotation @Controller est déclarée au niveau de la classe, les ressources de la classe sont toutes vues comme des “controllers”. Naturellement, un controller peut être défini comme étant en @GET, @PUT @DELETE ou @POST.

Exemple de classe “full” Controller :

@Controller
@Path("persons")
public class PersonsController {

 @Inject
 private Models model;

 @GET
 public String listPersons(){

 List<String> persons = new ArrayList<>();
 persons.add("Michel");
 persons.add("David");
 persons.add("Jérome");
 model.put("persons", persons);

 return "/persons.jsp";
 }
}

Exemple de classe Hybride :

@Path("hybrid")
public class HybridResources {
 @Inject
 private Models model;

 @GET
 @Controller
 @Path("mvc")
 public String hybridController(){
 model.put("modelhybrid", "come from controller method");
 return "/hybrid.jsp";
 }

 @GET
 @Path("jaxrs")
 @Produces(MediaType.APPLICATION_JSON)
 public Person jaxrsResource(){
 Person person = new Person("firstname","lastname");
 return person;
 }
}

Il existe plusieurs manières de définir la vue avec un controller MVC suivant le type de retour de la méthode :

void:  dans ce cas là, il est obligatoire de définir la vue via une annotation @View :


 @GET
 @Path("void")
 @View("/voidview.jsp")
 public void voidController(){
 model.put("voidview", "return from void type controller method");
 }

String: on renvoi le chemin relatif du fichier “/view.jsp”

 @GET
 @Path("string")
 public String stringController(){
 model.put("stringview", "return from string type controller method");
 return "/stringview.jsp";
 }

Viewable : un objet qui encapsule le chemin de la vue et le modèle de données associés.

 @GET
 @Path("viewable")
 public Viewable viewableController(){
 model.put("viewableview", "return from viewable type controller method");
 return new Viewable("/viewableview.jsp");
 }

 

Type Java : une classe dont la méthode surchargée toString() permet de retourner la chemin relatif vers la vue

private class CustomView{
   @Override
   public String toString() {
    return "/javatype.jsp";
   }
 }

 @GET
 @Path("javatype")
 public CustomView customViewController(){
 model.put("javatype", "return from javatype type controller method");
 return new CustomView();
 }

 

Response : permet de retourner un objet ayant un contrôle sur le statut, le header, la vue et d’autres paramètres.

 @GET
 @Path("response")
 public Response responseController(){
 model.put("response", "return from response type controller method");
 return Response.status(Status.OK).entity("/responseview.jsp").build();
 }

 

Le Modèle

Le modèle de données, qui est combiné avec la vue, peut être initié de 2 manières au sein d’une classe “Controller”,

Tout d’abord, la façon la plus recommandée est de créer un bean géré par un conteneur CDI (Context and Dependency Injection).

Dans l’exemple ci-dessous un bean annoté avec @Named permet au conteneur CDI de gérer celui-ci. L’identifiant du bean au sein du context CDI est le nom de la classe par défaut, mais il est possible de le surcharger de la façon suivante :

 @Named("othername")

Il est également possible de définir la durée de vie du bean avec les annotations suivantes :

  • @RequestScope : Signifie que le bean sera créé au début et détruit à la fin d’une request.
  • @SessionScope : Le bean existe durant la session d’un utilisateur.
  • @ApplicationScope : Un bean de scope Application peut être partagé par toutes les sessions de plusieurs utilisateurs d’une même application web.
  • @Dependent : Le scope par défaut des beans non annotés. Ceux-ci ne sont jamais partagés et sont dépendants des autres beans. une nouvelle instance est créée à chaque fois que le bean “host” est créé.

Exemple :

@Named
@RequestScoped
public class HelloWorld {

 public HelloWorld() {
 }

 private String message;

 public String getMessage() {
 return message;
 }

 public void setMessage(String message) {
 this.message = message;
 }
}

 

La deuxième manière (mais pas recommandée) de gérer les données est d’utiliser l’interface javax.mvc.Models, qui est une Map permettant d’associer une clé avec sa valeur, l’implémentation de référence passe par une HashMap<String,Object>.


 @Inject
 private Models model;

 @GET
 @Controller
 @Path("mvc")
 public String hybridController(){
   model.put("modelhybrid", "come from controller method");
   return "/hybrid.jsp";
 }

 

La vue

On définit la vue comme étant le template d’une page web associé avec un ou plusieurs modèles de données.  MVC 1.0 a la capacité de gérer plusieurs technologies d’interfaces : Jsp, Facelet, Freemarker, Thymeleaf, Velocity, Mustache. Toutes ces technologies intègrent des moteurs de templates chargés d’extraire les données du modèle et de le combiner avec le template pour obtenir le rendu final de la page web.

Dans l’exemple ci-dessous: la donnée qui nous intéresse est portée par le bean “HelloWorld” . EL (Expression Language) nous permet de récupérer cette donnée afin de l’afficher.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
 <head></head>

<body>


<div>
 Message test : ${helloWorld.message} !
</div>


</body>
</html>

Premier pas avec Ozark, l’implémentation de référence de la JSR 371

Débuté en Octobre 2014, Ozark est toujours en cours de réalisation, puisque les spécifications de MVC 1.0 ne sont pour l’instant qu’à la Early Draft Release 2.

Pour tester Ozark, il faut télécharger au minimum la dépendance Maven suivante :

<dependency>
    <groupId>org.glassfish.ozark</groupId>
    <artifactId>ozark</artifactId>
    <version>1.0.0-m02</version>
    <scope>runtime</scope>
</dependency>

Ensuite, après avoir généré un war, il faut le déployer sur un Glassfish 4.1.1 (minimum), car pour l’instant c’est le seul serveur d’applications compatible.

Que peut apporter MVC 1.0 ?

Avec la multitude de framework web, pour quelle raison on pourrait utiliser MVC 1.0 ? La première raison pourrait être sa compatibilité avec les autres JSR telles que CDI et Bean validations. Avoir un projet pleinement standard dans les technologies Java permet d’avoir moins de dépendances, ce qui n’est pas négligeable quand on génère un livrable.

Il reste encore beaucoup de notions que l’on n’a pas vues et qui sont dans la spécification, comme la gestion et la soumission de “Form”, les exceptions, les redirects et les forwards.  Si vous êtes intéressés sachez que la spécification est en cours d’écriture et que l’api peut changer, et je vous invite donc à suivre l’évolution de cette JSR, qui sera finalisée pour le troisième trimestre 2016.

 Vous trouverez tous les exemples de codes sur le GitHub de SOAT.

 

Liens:

JSR 371 Specification Requests

Java EE MVC 1.0 Tutorial

 

Référénces:

Java EE 8 Community Survey

Why another MVC ? – Oracle

Nombre de vue : 410

AJOUTER UN COMMENTAIRE