Aller au contenu

A drop in the ocean

Another drop in computer science ocean

Definition and usage

JMS message delivery delaying is simply sending a JMS message, but wait a defined amount of time before handling it and triggering the associated treatment. Curiously, this feature is not standardized in JMS. Most JMS providers have their own implementation to handle message delaying, but how to do when you need this feature in a portable way ?
In most case, you don’t have the choice of the JMS provider to use, since it depends of the softwares deployed in your company. Moreover, you have sometimes a different application server between development environments and production environments (for any cost or philosophical reasons).

In these cases, having a portable way to schedule JMS message can be usefull.

Principle

The solution is quite simple : we use the message selector feature included in the JMS API. Message selectors allows to consume only messages that satisfy a defined expression. In our case, the expression is simple :

_DeliverAfter_ <= System.currentTimeMillis()

where « _DeliverAfter_ » is a message property containing the value after which deliver the message.


Implementation

Using Spring

Spring is widely used and provides a very good support of JMS.
To send message, I created a subclass of Spring’s JmsTemplate which adds a timestamp parameter to each existing convertAndSend() method:

public class ScheduleJMSTemplate extends JmsTemplate {
//...
    public void convertAndSend(Object message, long scheduleTimestamp) throws JmsException {
        MessagePostProcessor postProcessor =
        new ScheduleMessagePostProcessor(scheduleTimestamp);
        super.convertAndSend(message, postProcessor);
    }

//...
}

To receive delayed messages, I extended DefaultMessageListenerContainer. The ScheduleDefaultMessageListenerContainer class acts as a drop-in replacement of DefaultMessageListenerContainer.

The full source code is available for download here : SpringJMSSchedule

D’oh ! I’m not using Spring

So let’s look how to do with plain JMS API :

Sending a message :

public void producesMessage(Session session, Destination destination) throws JMSException {
	MessageProducer producer = session.createProducer(destination);
	Message message = session.createTextMessage("I will be delivered in one week...");

	// Delay my message for 1 week (time in ms)
	long scheduleTimestamp = System.currentTimeMillis() + 7 * 24 * 60 * 1000;
	message.setLongProperty("_DeliverAfter_", scheduleTimestamp);

	producer.send(message);
}

The code above is straightforward : just create the JMS message as usual, and set the timestamp property.

Receiving the message :

	public void consumesMessage(Session session, Destination destination) throws JMSException {
		while (myCondition) {
			String messageSelector = "_DeliverAfter_ <= " + System.currentTimeMillis();
			MessageConsumer consumer = session.createConsumer(destination, messageSelector);

			Message message = consumer.receive();
			// Do something usefull with the message...
		}
	}

Consuming the message is simple : the MessageConsumer is created with a message selector that use the property set in the message.

Pitfalls

There’s a few pitfalls to avoid when using message delivery delaying :

  • Check message persistancy. You must ensure that your messages are saved in a persistent way, especially if you’re using long delays, otherwise you could lose some messages.
  • Use TextMessage. You must store messages in a format that could always be read, even if the version of application that send the message is different from the version that will read the message. In particular, you must avoid using ObjectMessage since its content is tightly coupled with classes used when creating the message. If your classes change before reading the message, you can encounter deserialization errors.

Google Reader est un aggregateur de flux RSS ô combien pratique, mais il lui manque quelques fonctionnalités qui permettent de faciliter son utilisation au quotidien.

De mon coté, il suffit d’une journée sans pouvoir consulter les news pour me retrouver avec plus de 200 articles non lus. Bon ok, j’ai une part de responsabilité : je devrais peut-être supprimer quelques abonnements ou affiner mes filtres RSS. Mais il n’en reste pas moins qu’avec de nombreux éléments non lus, il devient rapidement difficile de naviguer parmi les articles.

J’aime profiter des « temps d’attente imposés » (lancement de builds Maven, exécution des tests, etc.) pour faire de la veille techno et donc regarder rapidement GReader. Or, avec de nombreux éléments, la liste apparaît comme étant dense et il est plus difficile de fixer son regard sur des éléments précis.

Le besoin

Le problème est simple :

  • Pouvoir grouper les éléments de la liste, pour la rendre plus facilement lisible.
  • Pouvoir marquer l’ensemble des éléments d’un groupe comme étant lus.

J’avoue n’avoir fait que peu de recherches pour trouver un plugin ou script qui reponde à ce besoin, car je voulais en profiter pour utiliser Greasemonkey et hacker un peu en Javascript :)

Soyez donc indulgents si à la vue du script, vous vous rendez compte que vous en utilisez un semblable depuis des années.

Le résultat

Voici un screenshot des modifications apportées par le script :

Le seul ajout visible est la barre horizontale au dessus de chaque groupe de 4 éléments. Il suffit de cliquer sur cette barre pour marquer les éléments du groupe comme lus.

Au quotidien, il me suffit désormais de poser les yeux sur un groupe d’articles, en ouvrir 1 ou 2, et cliquer sur la barre pour marquer les autres comme lus.

Obtenir le script

Le script est disponible ici : greader_group_entries.user.js

Le nombre d’éléments dans le groupe peut être modifié en éditant la constante GE_GROUP_SIZE au début du script.

Le script fonctionne sur Firefox avec Greasemonkey. Il faut que je regarde pour le rendre compatible avec Chrome.

Cela faisait un petit bout de temps que l’idée me trottait dans la tête… Faire un blog qui me permettrait de partager quelques éléments de ce qui occupe mes journées et une grande partie de mon temps libre : l’informatique et en particulier le développement logiciel. Un blog de « geek » de plus en somme.

Ce qui se reflète dans le nom : A drop in the ocean.

Je suis amené tous les jours à lire des news, des tutoriels et exemples, des trucs et astuces, bref tout un ensemble d’éléments qui me permettent de découvrir de nouvelles technos et améliorer mon quotidien. J’ai donc choisi ce nom car il symbolise mon ressenti : apporter une modeste contribution (a drop, « la goutte ») parmi la myriade de blogs (the ocean, « l’océan ») traitant d’informatique.

Je profiterai de cet espace pour partager divers éléments que j’ai pu développer au fil de mes besoins.

N’hésitez pas à me faire des retours et bonne lecture à tous !

Guillaume