Un peu de vocabulaire :
- Operation : Action sur un objet du domaine
- OperationHandler : Fragment de code exécuté avant ou après l’opération
- OperationHook : OperationHandler exposé comme service REST
Un peu de vocabulaire :
L’abonnement à une opération passe par la création d’un document de classe OperationHandlerRegistration
. Les tags référencés par cette classe permettent de configurer l’abonnement :
Tag | Type | Description |
---|---|---|
OperationHandler |
string | Classe Java de l’OperationHandler ou l’URL d’un OperationHook |
ExecutionPhase |
choicelist | Phase d’exécution de l’opération |
Action |
choicelist | Action de l’opération |
ObjectType |
choicelist | Type d’objet auquel réagir |
Enabled |
boolean | Détermine si l’abonnement est actif ou inactif |
Asynchronous |
boolean | Détermine si l’OperationHandler doit être exécuté de manière asynchrone ou non |
RegistrationOrder |
integer | Ordonnancer les différents abonnements à une même opération |
StopOnException |
boolean | Détermine si l’exécution de l’opération doit être stoppée en cas d’exception (seulement si synchrone) |
Authorization |
string | chaîne d’autorisations basic à fournir au hook (générée en ligne grâce à blitter) |
FlowerDocs fournit nativement quelques OperationHandler
comme le :
com.flower.docs.core.tsp.operation.LogOperationHandler
: permet de logger le contexte pour lequel il est exécutécom.flower.docs.core.tsp.operation.DroolsOperationHandler
: permet d’appliquer des règles métiers (à travers une table de décision Drools)En plus de ceux fournis nativement, il est possible de développer son propre OperationHandler
.
package com.xxx.sample;
import org.springframework.stereotype.Component;
import com.flower.docs.operation.api.OperationContext;
import com.flower.docs.operation.api.OperationHandler;
@Component
public class OperationHandlerSample implements OperationHandler
{
public void process(OperationContext context)
{
}
}
Pour que cet OperationHandler
puisse être utilisé par FlowerDocs, il est nécessaire que :
com.xxx.sample
) soit scanné par Spring
Une fois ces deux étapes réalisées, l’OperationHandler
sera appelé conformément aux abonnements définis.
Cet OperationHandler s’appuie sur le moteur de règle Drools et une table de décision (fichier MS Excel) afin de déterminer les règles à appliquer.
Une table de décision est composée de deux types de colonnes :
Au sein d’une table de décision, il est possible d’utiliser les méthodes suivantes à partir de l’objet util
:
Tag | Description |
---|---|
getDocumentService() |
Récupère le service de gestion de document |
getFolderService() |
Récupère le service de gestion de dossier |
getTaskService() |
Récupère le service de gestion de tâche |
getVirtualFolderService() |
Récupère le service de gestion de dossier virtuel |
getService(Component component) |
Récupère le service de gestion de composant |
getClassService(Component component) |
Récupère le service de gestion des classes de composants |
getTagClassService() |
Récupère le service de gestion des classe de tags |
getAclService() |
Récupère le service de gestion d’ACL |
getFactDAO() |
Récupère la DAO de gestion de l’historique |
create(Component component) |
Crée le composant fourni en entrée et retourne celui réellement créé |
update(Component component) |
Modifie le composant fourni en entrée |
changeClass(Component component, String classId) |
Modifie la classe du component fourni en entrée et propage uniquement les tags en commun entre la classe initiale et la nouvelle |
getClassId(Component component) |
Récupère la valeur de la classe du composant sinon vide |
setClassId(Component component, String classId) |
Définie la valeur de la classe du composant |
getStatus(Component component) |
Récupère la valeur du statut du composant |
setStatus(Component component, Status status) |
Définie la valeur du statut du composant |
getTagValues(Component component, String tagName) |
Récupère la liste de valeurs d’un tag sinon null |
setTagValues(Component component, String tagName, List<String> values) |
Définie la liste de valeurs d’un tag en modifiant sa valeur s’il existe, sinon en ajoutant un tag |
setTagReadOnly(Component component, String tagName, boolean readonly) |
Modifie un tag en le mettant en lecture seule ou lecture écriture |
addTagValues(Component component, String tagName, List<String> values) |
Ajoute une liste de valeurs à un tag existant ou ajoute le tag |
getAnswerId(Task task) |
Récupère la dernière réponse appliquée sur une tâche |
log(String message) |
Affiche dans les logs un message préfixé par [Drools] en INFO |
Un OperationHook
est un OperationHandler
exposé en tant que service REST. Grâce à un OperationHook
, il pourra ainsi être possible de réagir aux opérations effectuées sur les composants depuis un service WEB distant.
En fonction de la catégorie de composant concerné par l’opération effectuée, une requête POST est envoyée sur les endpoints suivants :
/{{scope}}/documents/
/{{scope}}/folder/
/{{scope}}/virtual_folders/
/{{scope}}/tasks/
Il peut être développé avec n’importe quel language permettant d’exposer des services WEB.
Le corps des requêtes envoyées sur ces endpoints contient un objet décrivant le contexte d’exécution de l’opération et diffère donc en fonction des opérations.
Un OperationHook
peut être configuré de la même façon qu’un OperationHandler
classique. Son nom correspond à l’URL permettant d’accéder aux endpoints listés ci-dessus.
A partir de l’URL configurée, il doit être possible d’envoyer un POST sur {{hook URL}}/{{scope}}/documents/
.
Il est recommandé de sécuriser les OperationHook
déployés. Pour cela, FlowerDocs permet de configurer une chaîne de caractère fournie lors des appels REST dans une en-tête HTTP Authorization
.
Typiquement, une authentification BASIC peut être utilisée pour sécuriser un OperationHook
. Pour que FlowerDocs fournisse l’authentification définie, il est nécessaire de mettre à jour l’abonnement avec la chaîne d’autorisation à fournir.
Cette chaîne de caractère peut être générée en ligne grâce à blitter.
Par défaut, lors de l’exécution d’un OperationHook
, FlowerDocs Core log les erreurs renvoyées, par le service REST, en parsant le corps de la réponse HTTP.
Pour renvoyer des exceptions adaptées en fonction du contexte, il est nécessaire de fournir les en-têtes code
et message
sur la réponse HTTP.
Avec Spring, un ExceptionHandler
peut être défini facilement pour gérer toutes les exceptions FlowerDocs et les renvoyer correctement à FlowerDocs Core :
@ExceptionHandler(CodeBasedException.class)
public ResponseEntity<Object> handleCustomException(CodeBasedException ex, WebRequest request)
{
HttpHeaders headers = new HttpHeaders();
headers.add("code", ex.getCode());
headers.add("message", ex.getMessage());
return new ResponseEntity<Object>(headers, HttpStatus.INTERNAL_SERVER_ERROR);
}
Dans le cas d’OperationHook
synchrones, il est possible de renvoyer des messages d’erreurs personnalisés à l’utilisateur final.
Pour cela, il est nécessaire d’utiliser le code d’erreur F00039
:
throw ExceptionBuilder.createFunctionalException(F00039, "Custom error message");