EJB 3.1: les nouveautés avec Java EE 6

Celinio FERNANDES

Cet article a pour but de présenter les nouvelles fonctionnalités apportées par la spécification EJB 3.1

- Titre : EJB 3.1: les nouveautés avec Java EE 6

- Auteur : Celinio FERNANDES

- Parution : 25 juin 2008

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Celinio FERNANDES. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Historique

- II. Plus besoin d'interfaces locales !

- III. Le Singleton Bean et la concurrence d'accès

- IV. EJB Timer

- V. Appels asynchrones

- VI. EJB dans un WAR

- VII. Support des stateful web services

- VIII. Profils et EJB Lite

- VIII-A. Profils

- VIII-B. EJB Lite

- IX. Liens

- X. Remerciements

I - Historique

Un premier jet des spécifications EJB 3.1 a été mis en ligne fin mars 2008 par le groupe d'experts de la JCP. Elles feront partie de la plate-forme Java EE 6.

Les EJBs ont 10 ans. Les dates correspondent aux spécifications (releases) finalisées.

- EJB 1.0 : 21 mars 1998

- EJB 1.1 : 12 décembre 1999

- EJB 2.0 : 14 août 2001

- EJB 2.1 : 12 novembre 2003

- EJB 3.0 : 18 décembre 2005 (JSR 220, plate-forme Java EE 5)

- EJB 3.1 : 21 février 2008, la JSR 318 non finalisée (disponible avec la plate-forme Java EE 6, prévu fin 2008)

Jusqu'à la version 2.1, les EJB bénéficiaient d'une mauvaise réputation à cause de leur complexité. Depuis la version 3.0, leur mise en place est grandement simplifiée: plus besoin de descripteur de déploiement, plus de Home interface, plus besoin de faire un lookup via JNDI pour récupérer des EJBs, il suffit de passer par l'annotation @EJB, etc ...

La version 3.1 va vers encore plus de simplicité et de portabilité. Il faut espérer que les vendeurs de serveurs d'application implémentent rapidement cette nouvelle spécification pour pouvoir l'utiliser dès que possible.

Cet article n'est pas exhaustif, les spécifications finales étant encore en cours d'écriture mais il permettra au lecteur d'avoir un aperçu rapide des nouveautés dans les EJB 3.1, par rapport à la version 3.

II - Plus besoin d'interfaces locales !

Il n'est plus nécessaire d'implémenter une interface locale pour écrire des sessions beans, ce qui était déjà le cas avec les JPA entités et les Message Driven Beans.

1. @Stateless

2. public class MonStatelessBean {

4. public String pause(Temps temps) {

5. return "Un thé";

6. }

7. }

On voit qu'il n'est plus nécessaire d'utiliser l'annotation @Local et d'implémenter une interface. Un simple POJO suffit, annoté avec @Stateless ou @Stateful .

III - Le Singleton Bean et la concurrence d'accès

Le Singleton Bean correspond bien évidemment au classique design pattern Singleton.
C'est un POJO avec des annotations.
Le but est d'obtenir un objet transactionnel, thread-safe et qui fournit tous les services d'un container EJB : concurrence, sécurité ...
On a ainsi une instance unique d'un stateful session bean qui est partagé par tous les clients et qui supporte les accès concurrents.

Exemple d'un singleton avec des données en écriture :

1. @Singleton @ReadOnly

2. public class ContextBean implements ContextPartage  {

4. @PostConstruct

5. public void init() {

6. //on initialise le contexte de l'application

7. }

8. ...

9. }

On peut gérer la concurrence d'accès à ce singleton avec les annotations @ReadOnly et @ReadWrite qui permettent de poser un verrou en lecture-écriture sur l'instance unique.
La méthode init() sera lancée une seule fois, quand le container démarre l'application, à l'initialisation.
Les singletons peuvent donc être injectés (design pattern Inversion of Control IoC).

Exemple d'un singleton avec des données changeables :

1. @Singleton

2. public class ContextBean implements ContextPartage {

4. private ContextPartage contextePartage;

6. @ReadWrite public void condition(...) {

7. // mise à jour du contexte partage

8. ...

9. }

11. @ReadOnly public int getValeur() {

12. return contextePartage.valeur;

13. }

14. ...

15. }

La concurrence d'accès peut être gérée soit par le container, soit par le développeur du bean (@BeanManagedConcurrency).

Note (mars 2010) : les annotations @ReadOnly et @ReadWrite sont remplacées par @Lock(LockType.READ) et @Lock(LockType.WRITE)

IV - EJB Timer

Une nouvelle annotation fait son apparition : @Schedule

1. @Schedule(hour="10", dayOfMonth="1")

2. public void uneTache() {

3. ...

4. }

Cette tâche est lancée le 1er jour de chaque mois, à 10h00.
Il est maintenant possible d'activer un scheduler similaire à la Crontab sous Unix.
Avant on devait passer par l'interface javax.ejb.TimerService:

1. @Stateless

2. public class ControleTrafficBean implements ControleTraffic {

3. @Resource TimerService timerService;

5. public void controleTrain(Train train) {

6. ...

7. // en millisecondes

8. // createTimer(long initialDuration, long intervalDuration, Serializable info)

9. timerService.createTimer(10*60*1000, 60*60*1000, train);

10. ...

11. }

13. @Timeout

14. public void annulerTrain(Timer timer) {

15. ...

16. Train train = (Train) timer.getInfo();

17. ...

18. }

19. }

Ici on crée un intervalle de 10 minutes, qui se répète toutes les heures.
La méthode annotée avec @Timeout est activée quand l'intervalle de 10mn est passé.
Avec la version 3.1, les choses deviennent encore plus simples, on écrit de manière déclarative :

1. @Stateless

2. public class ControleTrafficBean implements ControleTraffic {

4. @Schedule(second="0", minute="10", hour="*",    dayOfMonth="*", month="*", year="*")

5. public void controleTrain(Train train) {

6. ...

7. }

8. }

On peut donc automatiquement créer des timers.

V - Appels asynchrones

Avec les EJB 3.0, les appels asynchrones se font exclusivement via les Message Driven Beans et JMS.
Depuis les EJB 3.1, les méthodes des sessions beans peuvent aussi être appelées de façon asynchrone:
quand le client appelle une méthode asynchrone, le container redonne la main au client et continue l'appel de cette méthode asynchrone dans un autre thread.
Pour cela, on utilise l'annotation @Asynchronous :

1. @Stateless @Remote(DemandeFacade.class)

2. public class DemandeFacadeBean implements DemandeFacade{

4. @Asynchronous

5. public void enregistre(Demande demande) {

6. // ...

7. }

9. @Asynchronous

10. public Future autorise(Demande demande) {

11. // ...

12. return new AsyncResult(DemandeEtat.OUI);

13. }

14. }

Les 2 méthodes ci-dessus sont asynchrones.
Les types de retour possibles sont void ou java.util.concurrent.Futurecomme c'est le cas pour la méthode autorise(...) .
Cette interface fournit des méthodes qui permettent de vérifier le résultat d'un appel asynchrone, l'annuler ...
La méthode autorise(...) utilise la classe helper javax.ejb.AsyncResult qui possède un constructeur qui prend comme paramètre le résultat. Cette classe implémente Future.

VI - EJB dans un WAR

Pour faciliter le déploiement, il est maintenant possible de packager / déployer des composants EJB 3 dans une archive WAR.
Il n'est plus nécessaire de créer une archive JAR et une archive EAR, tout peut être contenu dans une unique archive WAR.
Les classes peuvent aller dans le répertoire WEB-INF/classes, ainsi que le descripteur de déploiement ejb-jar.xml s'il est utilisé,
ou bien le JAR des EJB peut aller directement sous WEB-INF/lib/ .
On peut désormais appeler des EJB directement dans un container de servlet comme Tomcat, tout tient dans un .WAR.

VII - Support des stateful web services

Les EJB 3.0 supportent les stateless web services. Avec la version 3.1, les stateful web services seront aussi supportés.

1. @WebService

2. @Stateful

3. public class BonjourBean {

5. public String direBonjour() {

6. return "Bonjour";

7. }

8. }

Note (mars 2010) : cette nouveauté n'est finalement pas supportée.

VIII - Profils et EJB Lite

VIII-A - Profils

Java EE 6 introduira la notion de profil : les profils offriront différents types de services JEE.

- Profil A : c'est une version légère (Servlet, JSP etc).

- Profil B : il inclut le profile A + EJB 3.1 Lite, JTA, JPA, JSF et les WebBeans.

- Profil C : c'est une version complète de la plate-forme constituée du profil B + JMS, JAX-WS etc.

VIII-B - EJB Lite

L'idée est de permettre une implémentation d'un sous-ensemble des EJB 3.1 en enlevant les choses les moins utilisées, comme les Message Driven Beans et les EJB Timer services.

Caractéristiques

EJB Lite

EJB

Stateless beans

oui

oui

Stateful beans

oui

oui

Singleton beans

oui

oui

Message driven beans

non

Pas d'interfaces

oui

oui

Interfaces locales

oui

oui

Remote interfaces beans

oui

Interfaces Web Services

oui

Invocation asynchrone

oui

Interceptors

oui

oui

Sécurité déclarative

oui

oui

Transactions déclaratives

oui

oui

Transactions programmatiques

oui

oui

Timer service

oui

Support EJB 2.X

oui

Interopérabilité CORBA

oui

IX - Liens

- La JSR 318 sur les EJB 3.1

- Java EE 5

- JSR 316: Java EE 6 Specification

- New Features in EJB 3.1 - Part 1 (Janvier 2008)

- New Features in EJB 3.1 - Part 2 (Mars 2008)

- New Features in EJB 3.1 - Part 3 (Avril 2008)

- New Features in EJB 3.1 - Part 4 (Juin 2008)

- Le blog de Ken Saks, le responsable des specs

X - Remerciements

Je tiens à remercier Hikage, Ricky81 pour les conseils, remarques et relectures, ainsi qu'Aspic pour la correction orthographique.

Je remercie aussi www.developpez.comme permettant de publier cet article et Nono40 pour ses outils.