Devoxx 2011 : What’s probably coming in Java Message Service 2.0

Cette session de Nigel Deakin présentée à Devoxx 2011 avait pour objectif de montrer l’avancée des travaux sur JMS 2.0 (Java Message Service) aussi connu sous le doux nom de JSR 343. Elle est, à ce jour, en version early draft et devrait être intégrée à JEE7.

Pour la repositionner dans son contexte, la JSR343 fait suite à JMS 1.1 (JSR 914) et a pour but de :

  • Simplifier l’API de JMS :
    • En utilisant CDI (Context Dependency Injection).
    • En clarifiant certaines ambiguïtés présentes dans les spécifications.
  • Améliorer l’intégration de JMS avec les serveurs d’application :
    • En intégrant plus facilement les problématiques de PaaS (Platform As A Service).
    • En permettant le multi-tenancy.
    • En clarifiant ses relations avec les autres spécifications de JEE7 (ou même ultérieure) : cela est notamment vrai avec la partie MDB (Message-Driven Beans) de la spécification des EJB.
  • Ajouter des nouvelles fonctionnalités à l’API.

Cet article a donc pour vocation de tenter de retranscrire ce que nous a présenté Nigel.
Je ne reviendrai pas sur ce qu’est JMS (Java Message Service) si ce n’est que sa version actuelle est la 1.1 et qu’elle date de 2003.

Le fait que la spécification JMS n’ait pas évoluée depuis 2003 montre bien qu’elle était solide et qu’elle répondait bien à ce pour quoi elle avait été écrite. Cependant, autant il n’y a rien à redire quant à la réception d’un message, autant la partie émission était souvent verbeuse puisqu’il était nécessaire pour émettre un message, dans le cas des EJB, de :

  • injecter les factory (ConnectionFactory et Destination) à l’aide de l’annotation @Resource,
  • créer la Connection à l’aide de la ConnectionFactory,
  • créer la Session à l’aide de la Connection,
  • créer le MessageProducer à l’aide de la Session.

C’est seulement suite à toutes ces actions que l’émission d’un message était possible via la méthode send().

En outre, à cela, il fallait, bien sûr, gérer les exceptions checkées (JMSException pour ceux à qui cela parle ;-)) mais également la fermeture de la Session et de la Connection

Enfin, lors de l’utilisation conjointe de JMS et des EJB, certains paramètres de méthodes (notamment lors de la création de la Session) étaient redondants car gérés par le conteneur EJB (createSession(boolean transacted, int acknowledgeMode)).

Un des principaux prérequis de cette nouvelle version de la spécification est donc la simplification… simplification mais pas à n’importe quel prix puisqu’il était nécessaire de conserver la rétro compatibilité avec les versions ultérieures de la spécification.

Nigel nous a donc présenté certaines pistes qu’ils avaient (pistes encore ouvertes à discussion). Ce sont ces dernières que je vais essayer de retranscrire ci-dessous dans l’ordre dans lesquelles il les a énoncées.

Simplification sur la création de Sessions

Les autres simplifications d’API envisageables pourraient être :

  • Ajout d’une méthode createSession(SessionMode sessionMode) pour JavaSE où la classe SessionMode pourrait être une classe ayant comme variable d’instance le mode de transaction et le type d’acknowledge.
  • Ajout d’une méthode createSession() qui serait utilisée et présente seulement pour Java EE.

Supprimer la lourdeur des close()

Afin de rendre moins verbeuse l’utilisation des Connection et des Session, une proposition plausible pourrait être de leur faire implémenter l’interface java.lang.AutoCloseable.

Ainsi, il serait alors possible d’avoir les résultats suivants (pour rappel, il ne s’agit que de propositions car cela est toujours à l’étude) :

  • avec Java 7 dans un contexte JEE :
@Resource(mappedName="...")

ContextFactory contextFactory;

@Resource(mappepdName="...")
Queue orderQueue;

public void sendMessage(String payload) {
try (messagingContext mCtx = contextFactory.createContext() 😉 {
TextMessage textMessage = mCtx.createTextMessage(payload);
mCtx.send(orderQueue, textMessage);
}
}
  • avec CDI dans un contexte JEE :
@Resource(mappedName="...")
Queue orderQueue;

@Inject
@MessagingContext(lookup="...")
MessagingContext mCtx;

@Inject
TextMessage textMessage;

public void sendMessage(String payload) {
textMesage.setText(payload);
mCtx.send(orderQueue, textMessage);
}
  • toujours avec Java 7 dans un contexte JEE :
@Inject
@JMSConnection(lookup="...")
@JMSDestination(lookup="...")
MessageProducer producer;

@Inject
TextMessage textMessage;

public void sendMessage(String payload) {
try {
textMessage.setText(payload);
producer.send(textMessage);
} catch (JMSException e) {
//todo
}
}

Autres simplifications

Les autres simplifications d’API envisageables pourraient être :

  • de ne pas avoir à créer préalablement un objet de type Message (ce qui pourrait permettre de faire directement : producer.send(String/Serializable); ). Cependant, ce type d’API ne permettrait pas de positionner des propriétés sur le message et ne serait pas adapté pour des messages de types BytesMessage ou StreamMessage. A ajouter à cela la question de son pendant pour la réception.
  • de simplifier la gestion des DurableSubscriber (http://download.oracle.com/javaee/1.4/api/javax/jms/Session.html#createDurableSubscriber(javax.jms.Topic, java.lang.String)), qui, au jour d’aujourd’hui, doivent obligatoirement posséder un identifiant client et un nom de souscription. Ces deux paramètres pourraient être rendus optionnels dans le cadre d’une utilisation conjointe avec les EJB 3.2.

Vers le futur…

Autre que la simplification des APIs, Nigel nous a présenté ce que pourrait apporter JMS 2.0 dans nos besoins de demain.

Ainsi, JMS 2.0 devra, pour répondre aux besoins des problématiques de type SaaS (Software As A Service), permettre de déclarer ses ressources créées dans un serveur d’applications et de les enregistrer dans un annuaire JNDI (comme c’est actuellement le cas pour les DataSource).

Pour ce faire, de nouvelles annotations pourraient voir le jour (par exemple : @JMSConnectionFactoryDefinition et @JMSDestinationDefinition) mais également un SPI (Service Provider Interface) pour le faire de manière programmatique.

Concernant une meilleure intégration avec les serveurs d’applications (ce qui permettrait d’utiliser n’importe quel JMS Provider dans n’importe quel serveur d’application Java EE), Nigel propose la solution de JCA (Java Connector Architecture), un peu comme ce qui existe avec le driver de bases de données.

Nouvelles features

Concernant les nouvelles features de l’API, Nigel nous a ensuite présenté ce qui pourrait arriver, à savoir (en vrac) :

  • l’émission de messages avec un acquittement asynchrone du serveur,
  • la possibilité pour un client JMS d’utiliser des Future,
  • la possibilité d’émettre un message et de ne pas avoir à attendre la réception d’un acquittement pour savoir si le message a bien été émis.

Il se pourrait également que la propriété JMSXDeliveryCount ne soit plus optionnelle, ce qui permettrait aux serveurs d’applications de mieux gérer le flood.

De même, la gestion des Topics hiérarchiques pourraient être rendue obligatoire.

Enfin, une meilleure gestion des batch pourrait être possible via de nouvelles API comme par exemple l’introduction de la méthode receive(Message[]).

Conclusion

En conclusion, je suis assez mitigé par cette session. En effet, autant, je trouve que certaines propositions permettraient de rendre moins verbeuses l’utilisation de JMS, autant, je ne suis pas convaincu que pouvoir faire la même chose de différentes manières soit une bonne chose (et, cela, même si ça simplifie le travail du développeur…).

En outre, je trouve que, pour la majorité des propositions (même si elles sont totalement viables), l’axe de Java EE est trop important.

Enfin, cela reste tout de même une bonne introduction sur la direction que pourrait prendre JMS dans un futur proche mais, comme nous l’a fréquemment fait remarquer Nigel, il ne s’agit que de pistes et, d’ailleurs, toutes les contributions sont les bienvenues.

Nombre de vue : 6

AJOUTER UN COMMENTAIRE