Aujourd’hui, je vais vous parler d’une tâche que tout le monde utilise dans Nuxeo : la mise en application de règles métier, côté serveur.

Et les avantages sont nombreux : génération d’un rapport hebdomadaire ou mensuel, « archivage » trimestriel des documents obsolètes, connexion journalière à un service externe, etc.

Le principe est assez simple :

  • Un ordonnanceur envoie un événement de façon périodique.
  • Un gestionnaire est affecté à cet événement et s’exécute à chaque fois que l’événement est initié.

Ordonnanceur, Événement, Gestionnaire : leur configuration est très simple avec Nuxeo Studio, le meilleur outil de la planète (mais je l’ai peut-être déjà dit dans d’autres articles).

Dans cet article, nous allons prendre pour exemple d’un cas de « gestion des ressources expirées ».

Je dispose de documents image, vidéo et audio, et certains sont associés à une date d’expiration (champ dc:expired). Tout le monde peut y accéder, mais une fois leur date d’expiration atteinte, je veux les archiver. Dans cet exemple, nous aller utiliser une logique assez simple : une fois expiré, le document passe à un autre état de son cycle de vie (« obsolète ») et ses droits d’accès sont modifiés pour que seuls les administrateurs et les membres du groupe Validateurs puissent y accéder. Mais ce n’est qu’un exemple et il existe de nombreuses façons de gérer les ressources expirées en fonction de vos règles et processus métier.

Nous allons passer en revue les différents éléments dans l’ordre suivant :

  • Tout d’abord, l’ordonnanceur (qui est la base)
  • Ensuite, le gestionnaire (ici, une simple chaîne d’automatisation)
  • Et enfin, l’événement

Ordonnanceur

Nuxeo s’appuie sur une architecture Component Model dans laquelle tous les éléments sont traités comme des plug-ins, configurables grâce aux points d’extension. Et puisque Nuxeo propose la plateforme de services de contenu la plus cool du marché, elle propose notamment un service d’ordonnanceur personnalisable permettant d’ajouter autant d’ordonnanceurs que nécessaire.

L’ordonnanceur fonctionne de manière assez simple, il suffit de définir les quatre propriétés suivantes :

  • Un ID unique. Il est intéressant de noter que c’est l’un des moyens de contourner les ordonnanceurs Nuxeo par défaut. Par exemple, nuxeo-imap-connector vérifie la présence de nouveaux messages toutes les cinq minutes, mais si vous souhaitez changer cette fréquence, il vous suffit de copier la définition et de changer la cronExpression (voir ci-dessous).
  • L’ID de l’événement à envoyer.
  • Une catégorie d’événement (« défaut » fonctionne).
  • L’expression cron définissant la fréquence de l’événement.

Parenthèse culturelle : puisque le fait d’être développeur n’implique pas nécessairement d’être un sauvage, on peut aussi s’intéresser à l’étymologie. J’ai donc cherché l’origine du terme « cron » sur Wikipedia et la voici : « Cron est le diminutif de crontab, lui-même le diminutif de chrono table qui signifie « table de planification » (en grec, chronos (χρόνος) signifie le temps). » C’est donc tout à fait logique.

L’expression à utiliser est détaillée dans cette page de documentation (et comporte des exemples). Dans notre cas, nous voulons vérifier la présence de ressources expirées tous les jours à 3 h du matin et notre cronExpression devrait donc être…
* * 3 * * ?
… ce qui signifie (de gauche à droite) : à la seconde 0 ; minute ; lorsque l’heure est égale à trois ; n’importe quel jour du mois ; n’importe quel mois ; quel que soit le jour.

Je ne sais pas pour vous, mais je n’ai pas l’habitude de me réveiller à 3 h du matin pour vérifier si mon ordonnanceur fonctionne. Et ce n’est clairement pas idéal quand on a une démo à préparer.

Pour notre exemple de test, nous allons exécuter l’ordonnanceur toutes les 30 secondes. L’expression suivante l’exécute précisément à hh:mm:00 et hh:mm30. Copiez cette extension XML et collez-la dans votre projet Studio dans CONFIGURATION > Advanced Settings > XML Extensions :

<extension
           target="org.nuxeo.ecm.core.scheduler.SchedulerService"
           point="schedule">
  <schedule id="`HandleExpiredAssets`">
    <event>`HandleExpiredAssets`</event>
    <eventCategory>default</eventCategory>
    <!-- Tous les jours à 3 h : * * 3 * * ? →
    <!-- Pour notre test, toutes les 30 secondes à hh:mm:00 et hh:mm:30-->
    <cronExpression>0/30 * * * * ?</cronExpression>
  </schedule>
</extension>

Cela permet de définir un nouvel ordonnanceur portant l’ID HandleExpiredAssets et déclenchant l’événement HandleExpiredAssets toutes les 30 secondes. J’ai utilisé les mêmes valeurs pour l’ID de l’ordonnanceur et de l’événement, mais ce n’est pas obligatoire.

Et c’est tout. Notre ordonnanceur est configuré. Quand je vous disais que c’était simple ! Plus sérieusement, lorsqu’on sait comment faire, créer un ordonnanceur ne requiert pas plus de 15 secondes.

Gestionnaire

Il faut ensuite écrire la chaîne d’automatisation qui gère nos ressources expirées. Il nous suffit de :

  1. Chercher les ressources ayant un champ dc:expired avec une date antérieure à celle d’aujourd’hui et n’ayant pas encore été traitées.
  2. Les traiter.

Dans notre exemple nous allons :

  1. Changer leur statut.
  2. Changer les permissions pour que seuls les administrateurs et les membres du groupe Validateurs puissent y accéder.

Nous souhaitons gérer uniquement les nouvelles ressources expirées et dans cet exemple nous allons nous appuyer sur le cycle de vie suivant (utilisé pour les images, vidéos et fichiers audio) :

Handler lifecyle

Notre requête cherche uniquement les ressources avec le statut « approved » et les passe au statut « obsolete ». Voici la requête NXQL à utiliser lors de la configuration de ce processus automatisé (sans modification des versions et des proxys) :

SELECT * FROM Document WHERE
ecm:primaryType IN ('Picture','Video', 'Audio')
AND ecm:currentLifeCycleState = 'approved'
AND dc:expired < DATE '@{CurrentDate.format("yyyy-MM-dd")}'
AND ecm:isVersion = 0 AND ecm:isProxy = 0

Pour modifier le statut d’une ressource, il vous suffit d’utiliser l’opération Document.FollowLifecycleTransition.

Modifions maintenant les permissions, ce qui implique de :

  • Supprimer les permissions « locales » (s’il y en a).
  • Bloquer les héritages (les administrateurs deviennent automatiquement les seuls à pouvoir voir les documents).
  • Créer une nouvelle permission pour les Validateurs.

Ce degré d’automatisation est incroyablement puissant ! Automatiser la gestion de listes entières de documents grâce à cette seule opération vous permettra de gagner beaucoup de temps et de ressources.

Il convient de ne pas négliger deux éléments qui sont liés au fait que la chaîne est exécutée à partir de l’ordonnanceur. Lors de son démarrage, il n’y a pas de Context ou de CoreSession. Vous devez donc commencer par supprimer l’opération Fetch > ContextDocument que Studio ajoute par défaut. Ensuite, il faut appeler LoginAs avant toute requête afin de créer une CoreSession. Vous trouverez ci-dessous la chaîne dans son intégralité. J’ai ajouté un journal pour superviser les opérations et comprendre le fonctionnement de notre ordonnanceur, le déclenchement de l’événement et l’exécution de notre chaîne :

Handler Chain

Ça semble cool, n’est-ce pas ? Après avoir analysé l’ordonnanceur et le gestionnaire, il ne nous reste plus qu’à créer l’événement qui les relie.

Événement

Comme les étapes précédentes, configurer un événement est très simple. Il suffit de créer un nouveau Event Handler qui :

  1. Écoute notre événement HandleExpiredAssets.
  2. Exécute la chaîne HandleExpiredAssets lorsque l’événement est récupéré.

(Oui, j’ai tendance à utiliser les mêmes désignations un peu partout. N’hésitez pas à inventer les vôtres si vous préférez).

La création d’un gestionnaire d’événements est assez simple dans Studio, mais dans notre cas, nous avons un petit problème à résoudre.

HandleExpiredAssets est un événement personnalisé et Nuxeo sait seulement qu’il ne fait pas partie de la configuration par défaut. C’est ici que les registres Studio entrent en jeu. Ces registres vous permettent de déclarer les éléments que Studio ne connaît pas afin de pouvoir les utiliser. Il suffit d’aller dans SETTING > Registries > Core Events et d’ajouter notre événement personnalisé. Par exemple :

Registry

Nous pouvons désormais créer un nouveau gestionnaire d’événements et utiliser notre événement, désormais visible. C’est très simple : créez un événement, sélectionnez l’événement et la chaîne d’automatisation, et c’est tout !

Event Listener

Déployez, profitez

Il ne s’agit que d’un exemple de configuration rapide, certainement plus rapide que la lecture de cet article.

Mon conseil ? Enregistrez tout, déployez la configuration sur votre serveur de test et analysez votre journal. N’oubliez pas que nous utilisons deux éléments spécifiques : un cycle de vie personnalisé et un groupe personnalisé (Validateurs). Commencez par ouvrir un document image, modifiez son champ dc:expired à la date d’hier et vérifiez dans le journal s’il a été trouvé. Et s’il ne l’était plus 30 secondes plus tard.

Il s’agit d’un exemple assez simple, et votre logique métier sera certainement plus complexe. Mais avec Nuxeo Studio, vous avez tous les outils nécessaires pour y arriver. Par exemple, vous voudrez peut-être mettre fin aux notifications par e-mail une semaine avant la date d’expiration pour qu’un utilisateur puisse vérifier la ressource et modifier sa date d’expiration si besoin.

En tout cas, j’espère que mon chef ne verra pas que j’ai atteint ma date d’expiration il y a bien longtemps !