Posts tagged: CDI

JSF2.2 – Hello world

By , 14/03/2014

Voici un exemple d’une application JSF2.2 minimaliste. Une vue xhtml un bean Java contenant le message “Hello world !”. Une configuration minimaliste aussi pour pouvoir déployer l’application dans le serveur wildfly.

Vue d’ensemble et configurations

Pour cette application il est suffisant d’avoir un fichier Java porteur des données (le model), un fichier xhtml décrivant la vue et un quelques fichiers de configuration :

  • beans.xml : ce fichier est vide dans cet exemple. Il permet à l’application de bénéficier du CDI
  • faces-config.xml : ce fichier est vide dans cet exemple. Il permet de configurer tout ce qui est en lien avec JSF
  • web.xml : ce fichier est facultatif je l’ai ajouté pour avoir un exemple de namespace XML pour la bonne version du serveur wildfly

Pour rappel, JSF est une technologie qui se base sur le modèle MVC-2. Le rôle du contrôleur est joué par la servlet JSF qui centralise les demandes provenant de la vue et qui redirige vers les bons traitements Java (avec JSF on parle en général d’actions).

Le model (Bean Java)

L’objet Java qui va contenir les données, c’est à dire le message “Hello world !” est un String. Cet objet va être créé par un producer en scope Request. A chaque nouvel appel à la vue, une nouvelle requête sera nécessaire et l’objet sera recréé de toute pièce.

package org.eiw.data;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Named;

/***
 * Le producer est dans le scope Request,
 * il sera recréé à chaque nouvelle requête HTTP.
 */
@RequestScoped
public class HelloWorldProducer {
	private String message;

	/**
	 * La méthode qui produit l'objet de données vis à vis de la page XHTML.
	 */
	@Named
	@Produces
	public String getMessage() {
		return message;
	}

	/**
	 * La méthode qui initialise l'objet,
	 * à chaque nouvelle requête HTTP.
	 */
	@PostConstruct
	public void initMessage() {
		message = "Hello world !";
	}
}

La vue (XHTML)

Dans ce fichier, nous allons utiliser le conteneur CDI pour récupérer l’objet Java des données vu ci-dessus. Nous allons ensuite l’associer à un tag JSF pour formater son affichage :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
	<h:outputText value="#{message}" />
</h:body>

Pour récupérer l’objet, il faut utiliser son nom qui est égal par défaut au nom de l’instance avec le langage EL : #{maVariable}.

Le déploiement

Pour déployer cette application, il suffit d’utiliser le plugin wildfly avec la commande suivante : mvn wildfly:run. Ensuite de se rendre sur l’adresse http://localhost:8080/hello-world/index.jsf  et de visualiser le résultat :

Remarque : s’il s’agit de la première fois que vous utilisez le plugin wildfly, il vous faudra un peu de temps pour démarrer l’application car il est nécessaire de télécharger, dans le repository maven local, le serveur complet avant de le démarrer.

Ce tutoriel est disponible sur GitHub à l’adresse suivante : https://github.com/yanLanglois/jsf-2.2-tutoriel/tree/master/hello-world.

J2EE 6 : @Inject ou @EJB

By , 26/02/2014

Depuis J2EE5 et la spécification EJB (JSR-318), l’annotation @javax.ejb.EJB permet d’injecter une instance d’un EJB dans une variable.

Grâce à J2EE6 et la spécification Dependency Injection (JSR-330), l’annotation @javax.inject.Inject permet d’injecter n’importe quelle sorte de POJO (Plain Old Java Object) dont, bien entendu, des EJB dans une variable. Quelle annotation utiliser ?

Dans la plupart des cas, il est préférable d’utiliser l’annotation @javax.inject.Inject au lieu de @javax.ejb.EJB car elle est globale à toutes les sortes d’objets. Il faudra impérativement utiliser @javax.ejb.EJB lorsque :

  • Le conteneur où est déployée l’application n’est pas compatible avec CDI
  • L’EJB à injecter est un EJB remote

Comme indiqué dans la documentation de référence de Weld, si l’on souhaite utiliser l’annotation @javax.inject.Inject pour injecter un EJB remote, il est nécessaire de passer par un autre objet référenceant l’EJB remote via l’annotation @javax.ejb.EJB :

@Produces @EJB(ejbLink="../their.jar#PaymentService")
PaymentService paymentService;

Pour plus d’information, lire la documentation de Weld ou ce message intéressant sur le forum JBoss : https://community.jboss.org/thread/179388?start=15&tstart=0,

J2EE : Singletons

By , 08/02/2014

Développer soit-même un singleton, cela n’a plus aucun intérêt. Des annotations sont faites pour cela :

  • @javax.ejb.Singleton – Un nouveau type d’EJB provenant dans la JSR-318. Il est utilisé pour obtenir une seule instance partagée d’une même EJB. Cette instance est thread safe et transactionnelle.
  • @javax.inject.Singleton – Provient de la JSR-330, la classe annotée de cette manière ne sera instanciée qu’une seule fois.
  • @javax.enterprise.inject.ApplicationScoped – Un scope provenant de la JSR-299 (CDI), le bean est dans le scope application.
  • @javax.faces.bean.ApplicationScoped – Définie dans JSF 2.0 (JSR-314) Managed Beans, c’est un managed bean JSF qui est placé dans le scope application.

Toutes ces annotations vont nous permettre d’obtenir des singletons. Mais quelles sont les différences entre elles ?

La différence entre les deux annotations @javax.enterprise.inject.ApplicationScoped et @javax.faces.bean.ApplicationScoped c’est le contexte de déploiement. Si le conteneur utilisé est compatible CDI il faut utiliser l’annotation CDI  sinon, si le conteneur n’est pas compatible CDI (par exemple Tomcat) il faut utiliser l’annotation JSF2.0.

Quelles sont donc les différences entre les trois premières annotations ?

L’annotation EJB - @javax.ejb.Singleton – est la seule à proposer les services  “entreprise”, c’est à dire la gestion des transactions et de la concurrence. Il faut donc l’utiliser quand ces services “entreprise” sont nécessaires. Remarque, dans ce cas, il est tout à fait possible d’utiliser un EJB statefull avec un scope application - @javax.enterprise.inject.ApplicationScoped. Cet objet sera gérer de façon différente par le conteneur CDI mais il aura exactement les mêmes caractéristiques qu’un EJB @javax.ejb.Singleton. Donc, à mon avis, autant utiliser l’EJB singleton plutôt que le statefull en scope application.

Si vous n’avez pas besoin des services “entreprise”, autant utiliser un POJO normal, managed bean dans J2EE, avec le scope application. C’est à dire @javax.enterprise.inject.ApplicationScoped.

L’annotation @javax.inject.Singleton ne sera vraiment utile que dans un contexte J2SE. Pour plus d’information, il faut lire la documentation de référence de weld concernat le pseudo-scope Singleton.

J2EE 6 : Doublons dans les scopes @…Scoped

By , 06/02/2014

Dans J2EE6 il existe deux spécifications qui parlent de scopes applicatifs : JSR 314: JavaServer Faces 2.0 et JSR 299: Contexts and Dependency Injection for the JavaTM EE platform (CDI). La difficulté vient du fait que ces scopes ont le même nom et la même fonction :

  • @javax.faces.bean.RequestScoped (JSF) et @javax.enterprise.context.RequestScoped (CDI).
  • @javax.faces.bean.SessionScoped (JSF) et @javax.enterprise.context.SessionScoped (CDI).
  • @javax.faces.bean.ApplicationScoped (JSF) et @javax.enterprise.context.ApplicationScoped (CDI).

Lesquels utilisés ? Comme pour certaines autres annotations qui semblent dupliquées dans J2EE, ces annotations sont identiques, elle diffèrent uniquement suivant le contexte de déploiement. JSF2.0 propose ses propres annotations pour laisser la possibilité aux développeurs de déployer des applications JSF2.0 dans des conteneurs dépourvus de CDI (Tomcat par exemple) mais en conservant l’avantage de l’outjection proposée par la JSR CDI.

Sachant cela, la sélection de ces annotations doit se faire en fonction du contexte de déploiement. Il faut bien entendu préférer les annotations CDI à JSF si le conteneur est compatible avec la JSR-299.

Il existe cependant un scope proposé par JSF2.0 et inexistant dans CDI : @ViewScoped. Il est possible dans ce cas d’utiliser la librairie DeltaSpike JSF ou Seam 3 Face Module pour avoir accès à une version CDI du scope.

@Model versus @Named versus @ManagedBean

By , 04/02/2014

Lorsque l’on débute en J2EE il est parfois difficile de voir la différence entre certaines annotations. Elles proviennent souvent de spécifications (JSR) différentes et peuvent avoir un rôle similaire ou totalement identique. Certaines fois, il s’agit uniquement d’une différence de contexte dans lequel le code est développé ou déployé.

Les annotations suivantes sont utiles pour déclarer des objets Java qui vont être accessibles dans le langage EL via les symboles #{} (on parle d’outjection par opposition à injection).

@javax.faces.bean.ManagedBean

Cette annotation arrive avec la JSR-314 JavaServer Faces 2.0. Grâce à elle, il n’est plus nécessaire de déclarer les Managed Bean JSF dans le fichier XML faces-config.xml. Elle n’est utile que lorsque le l’application développée est déployée dans un contexte où le conteneur CDI n’existe pas, comme Tomcat par example.

De plus, elle peut facilement être confondue avec l’annotation suivante @java.annotation.ManagedBean.

@javax.annotation.ManagedBean

Cette annotation est définie dans la JSR-250. Elle est utilisée pour déclarer un managed bean spécifié dans la JSR-316. Il ne faut pas confondre avec les managed bean JSF. Le principe de la JSR-316 est de pouvoir transformer n’importe quel POJO (Plain Old Java Object) en objet pouvoir avoir un cycle de vie, des intercepteurs, etc.

Dans un contexte CDI, cette annotation est obsolète car le principe du CDI est de transformer tous les POJO en Managed Bean. Donc cette annotation n’est pas du tout utile. Elle n’aura d’ailleurs aucun impact visible sur l’exécution du code.

@javax.enterprise.inject.Model @javax.inject.Named

L’annotation @Model est équivalante à l’annotation @Named à laquel il a été rajouté le contexte @RequestScoped (@javax.enterprise.context.RequestScoped).

Ces annotations proviennent de la JSR 299 “contexts and dependency injection” (CDI). Cette JSR offre beaucoup plus de possibilités d’utilisation que celle sur JSF2.0. Dans un contexte où une application est déployée dans un conteneur compatible CDI il est donc préférable d’utiliser les annotations CDI plutôt que JSF2.0.

Conclusion

Le choix de l’annotation à utiliser dépend essentiellement du conteneur où l’application sera déployée. Il est toujours préférable d’utiliser les annotations provenant de la JSR-299 (CDI) dans le cas où le conteneur est compatible avec CDI.

Pour plus d’information cet article est très intéressant : Is @javax.faces.bean.ManagedBean Dead on Arrival?

OfficeFolders theme by Themocracy