Parmis les nombreux apports de Seam il y en a un qui est à mes yeux particulièrement utile : la gestion des évènements (Events). Et là ou cela devient vraiment interessant, c’est dans la simplicité de leur utilisation.
Tout d’abord quel est l’intérêt ? Admettons que vous avez un composant qui réalise une tâche interne à votre application (ajout de donnée, modification, visualisation d’une page … tout et n’importe quoi en fait).
Or suite à cette action vous avez un ou plusieurs process à effectuer après, par exemple envoi d’un mail, enregistrement d’un status en base etc … bref votre action première, doit être suivi d’autres.
Dans un développement classique vous allez enchaîner les appels de méthode pour pouvoir réaliser votre process complet.
Or si ce process change, cela deviens vite laborieux de modifier votre enchevêtrement de méthodes et/ou de tests.
Et bien c’est là qu’est l’intérêt des évènements : vous allez pouvoir pour une action donnée déclencher un évènement, une sorte de message qui sera reçu par un ou plusieurs composants de l’applications, complètement indépendant de votre emetteur d’évènements.
Tout d’abord ce modèle présente un avantage majeur : vous developpez vraiment des composants indépendants : vous devez juste spécifier quels messages ils attendent. Cela vous évite donc les modèles classiques d’objets interdépendants, ou la gestion des dépendance devient laborieuse dans une grosse application.
Tout ce que vous avez à faire dans l’action de base c’est déclencher un évènement sans vous préoccuper de quel ou combien de composants seront appelés après, ou de quel appel sera réalisé après.
Ensuite à vous de mettre en place les “Observeurs’ de l’évènement en question.
Mettons en place un exemple simple : Ici un objet héritant d’EntityHome<TextEntry> ou TextEntry est un EJB entity déjà défini, mais peu importe l’entity lorsqu’on utilise une EntityHome de Seam pour le mettre en relation CRUD avec la base.
@Name("textEntryHome")
public class TextEntryHome extends EntityHome {
private static final long serialVersionUID = 3141975971653011468L;
@RequestParameter
private Long textEntryId;
@Override
public Object getId() {
if (textEntryId == null) {
return super.getId();
} else {
return textEntryId;
}
}
@Override @Begin
public void create() {
super.create();
}
@Override
public String persist() {
Events.instance().raiseEvent("postAdded", this.getInstance().getId());
return super.persist();
}
}
La ligne interessante est donc celle ci :
Events.instance().raiseEvent("postAdded", this.getInstance().getId());
Simplement, lorsqu’une Entité de type TextEntry est persistée, on déclenche l’évenèmenets “postAdded” avec comme paramètre l’Id de l’entity.
Vous pouvez passer ce que vous voulez en paramètre et le récupérer plus tard lors du traitement de l’évènements.
Vous pouvez aussi déclencher un évènement sur l’appel d’une méthode grâce à l’annotation
@RaiseEvent(“nomEvent”) au lieu de faire un appel dans la méthode.
Cela vous permet de complètement sortir l’événement du code métier.
Enfin vous pouvez aussi décider d’envoyer l’événement de manière Asynchrone en utilisant raiseAsynchronousEvent au lieu de raiseEvent. Imaginez alors les possibilité d’un tel fonctionnement. Si vous déclenchez un événement de manière asynchrone celui-ci sera géré par le service timer d’EJB3.
Maintenant occupons nous de l’observeur :
public class TextEntryManager {
@Logger
private Log logger;
@In
private EntityManager entityManager;
@Observer("postAdded")
@Asynchronous
public void processEvent(Long id) {
TextEntry textEntry = entityManager.find(TextEntry.class, id);
if (textEntry != null) {
logger.info("Text entry with title : #0 has been added ", textEntry.getTitle());
}
}
}
Voilà, comme vous pouvez le voir ce qu’on fait ici est simple : grâce à l’id passé en paramètre, on récupère l’entity insérée précédemment, puis on met un message de log. Ce cas n’a pas vraiment d’intérêt il est juste là pour illustrer le fonctionnement. On vois que l’annotation @Observer sur une méthode, avec en paramètre le nom de l’événement suffit à récupérer celui-ci. Les paramètres de la méthode doivent avoir le même ordre que ceux passés à l’événement pour pouvoir les récupérer. Seule une annotation suffit donc pour récupérer l’évènement et ses paramètres, et vous pouvez mettre autant d’Observers que vous le souhaitez en écoute du même événement.
Enfin ici la méthode a été annoté @Asynchronous pour rendre le processus de traitement complètement asynchrone, afin d’optimiser le traitement des événements.
Et voilà, cette approche était une initiation,mais si vous maitrisez le concept, et commencez à le mettre en oeuvre avec JMS ou Quartz, vous pouvez arrivez à une gestion vraiment très fine et optimisée de vos processus tout en développant des objets qui deviennent réelement des composants.
Attention cependant à ne pas abuser des événements, ce mécanisme n’est pas fait pour être utilisé à tout bout de champ et vous risquez la confusion si vous en utilisez trop dans votre application : ciblez les cas qui nécessitent vraiment un traitement semblable.