Tutoriel Alfresco et jBoss BPM : exemple d'implémentation d'un workflow avancé de gestion des dossiers de crédit

| Raphaël-Ledoux FONGANG , Armand MODI-DIFFO et Baké Jc. BAKENEGHE | (Centre de Développements Alfresco-jBPM, Koossery Technology) | Ricky81 |

Dans cet article nous allons voir comment la plate-forme Alfresco combinée à la plate-forme jBoss BPM permet d'implémenter un exemple d'application qui combine les points suivants : la gestion électronique de documents (GED), la gestion de contenu (ECM) et les workflows avancés BPM.

- Liste des nouveautés dans cette version de l'article :

Cette version de l'article a été enrichie avec des paragraphes sur les Handlers, les Dialogs Alfesco et les Action-group.

Par ailleurs un annuaire LDAP est utilisé pour la gestion des authentifications.

Enfin le projet est en Maven2 et est disponible en téléchargement.

- Titre : Tutoriel Alfresco et jBoss BPM : exemple d'implémentation d'un workflow avancé de gestion des dossiers de crédit

- Auteurs : Raphaël-Ledoux FONGANG , Armand MODI-DIFFO et Baké Jc. BAKENEGHE, (Centre de Développements Alfresco-jBPM, Koossery Technology), Ricky81

- Parution : 12 mai 2009

- Mise à jour : 21 février 2020

- Licence :

Sommaire

- I. Frameworks standards et outillages utilisés

- I-A. Alfresco

- I-B. Eclipse jPDL Graphical Designer

- I-C. jBoss BPM

- I-D. Console Web jBPM

- I-E. Annuaire openLDAP

- I-F. Jasper report

- I-G. Maven 2

- II. Les spécifications de l'exemple

- III. Le workflow jBPM et sa transcription en modèle Alfresco (Task Model)

- III-A. Diagramme du workflow jBPM

- III-A-1. Nœuds du Processus jBPM

- III-B. Assignation des tâches

- III-C. Transcription du workflow jBPM en Task Model Alfresco

- IV. Modélisation Alfresco du dossier de Crédit

- IV-A. Modèle de donnée du dossier de crédit

- IV-B. Alfresco Content Type Model

- V. Implémentation de la solution dans un projet Maven2

- V-A. Le projet Maven2

- V-A-1. Structure du projet

- V-A-2. Les divers fichiers de configuration de notre webapp

- V-A-2-a. Le fichier application.propeties

- V-A-2-b. Le fichier web-client-config-custom.xml

- V-A-2-b-i. Les langues disponibles

- V-A-2-b-ii. Les configurations pour la recherche de documents

- V-A-2-b-iii. Les interfaces utilisateur des task-node

- V-A-2-b-iv. Les actions Alfresco

- V-A-2-b-v. Les 'dialogs' Alfresco

- V-A-2-b-vi. Le dashboard Alfresco

- V-A-2-c. Internationalisation

- V-A-2-d. Les configurations Spring

- V-A-2-d-i. Le fichier custom-repository-context.xml

- V-A-2-d-ii. Le fichier worflow-credit-context.xml

- V-A-2-e. Ldap

- V-B. Développement de la webapp : quelques exemples de développements complets de 'dialogs' Alfresco

- V-B-1. 'Dialog' relatif à la création, modification et visualisation d'un dossier de crédit

- V-B-1-a. Le backing bean

- V-B-1-b. Configuration du fichier face-config-custom.xml

- V-B-1-c. Les dialogs Alfresco correspondants

- V-B-2. 'Dialog' relatif à l'upload de pièces jointes

- V-B-2-a. Le backing bean

- V-B-2-b. Configuration du fichier face-config-custom.xml

- V-B-2-c. Les dialogs Alfresco correspondants

- V-B-3. Dialog Alfresco relatif aux tâches du workflow

- V-B-3-a. Le backing bean

- V-B-3-b. La configuration du face-config-custom.xml

- V-B-3-c. Les dialogs Alfresco correspondants

- V-B-4. Dialog Alfresco relatif à la suppression des spaces

- V-B-4-a. Le backing bean

- V-B-4-b. Le fichier face-config-custom.xml

- V-B-4-c. Les dialogs Alfresco correspondants

- V-C. Développement de la webapp : les action-group Alfresco

- V-C-1. L'action-group workflow_action_menu

- V-C-2. L'action-group add_credit_record_actions

- V-C-3. L'action-group edit_credit_record_item_actions

- V-C-4. L'action-group view_credit_record_item_actions

- V-C-5. L'action-group edit_piece_content

- V-C-6. L'action-group view_piece_content

- V-D. Développement de la webapp: les classes ActionHandler

- V-D-1. L'action handler DocumentStateActionHandler

- V-D-2. L'action handler CreditFormActionHandler

- V-D-3. L'action handler SimulationActionHandler

- V-D-4. L'action handler ResultSimulationActionHandler

- V-D-5. L'action handler ApprovalCommitteActionHandler

- V-D-6. L'action handler LegalServiceActionHandler

- V-D-7. L'action handler FinancialServiceActionHandler

- V-D-8. L'action handler CreditContratActionHandler

- V-D-9. L'action handler PaymentActionHandler

- V-D-10. L'action handler ArchivingActionHandler

- V-D-11. L'action handler EndActionHandler

- VI. Téléchargement du code source du projet

I - Frameworks standards et outillages utilisés

Nous utilisons les frameworks et outils suivants :

- Alfresco ;

- Eclipse jPDL Graphical Designer ;

- jBoss BPM ;

- Console Web jBPM ;

- Annuaire openLDAP ;

- Jasper Report ;

- Maven 2.

I-A - Alfresco

Alfresco est une plate-forme de Gestion de Contenu d'Entreprise (ECM), Gestion de Documents, Travail Collaboratif, Gestion d'archivages légaux, Gestion de Contenu Web et de Gestion de Documents Numériques.

Nous nous appuyons sur Alfresco pour le développement de projets de GED.

I-B - Eclipse jPDL Graphical Designer

Grâce au plugin Eclipse jBPM il est possible d'utiliser l'environnement Eclipse jPDL Graphical Designer pour modéliser les processus métiers d'entreprise.

I-C - jBoss BPM

jBoss BPM est un moteur de workflow qui permet :

- l'orchestration des tâches de processus ;

- la gestion des instances de processus ;

- la persistance du contexte et de l'état du processus dans un SGBD.

I-D - Console Web jBPM

C'est la console d'administration de la plate-forme jBoss BPM. Cette console permet de :

- piloter et superviser les processus BPM ;

- faire du reporting sur l'activité relative aux processus.

De façon plus générale, cette console permet de faire du Business Activity Monitoring (BAM).

I-E - Annuaire openLDAP

Dans notre projet la gestion des authentifications, des utilisateurs et des groupes d'utilisateurs est faite en utilisant un serveur d'authentification d'entreprise.

Nous nous appuyons sur l'implémentation open source openLDAP.

I-F - Jasper report

Jasper Report nous permet de générer les rapports au format .doc, .pdf etc. en partant du contenu résidant dans le Repository Alfresco et en nous appuyant sur des templates réalisés avec l'outil iReport.

I-G - Maven 2

Notre projet est un projet Maven2.

II - Les spécifications de l'exemple

Un organisme de crédit à la consommation souhaite mettre en place un workflow d'approbation de crédit qui combine l'étude du dossier de crédit avec son passage par plusieurs étapes, de l'approbation jusqu'à son archivage.

Il est possible d'effectuer une recherche full-text des dossiers archivés.

Ci-dessous les différentes étapes du workflow d'approbation.

1) La première étape du workflow est la constitution du dossier de demande de crédit. Les informations d'identification de l'emprunteur et sur le crédit (type, montant, etc.) sont saisies dans le formulaire de demande de crédit.

Les pièces justificatives suivantes sont numérisées via une chaîne de dématérialisation et ensuite jointes au dossier de crédit :

- les fiches de paie ;

- la fiche d'impôts.

L'ensemble des données saisies dans le formulaire et les pièces numérisées jointes constituent un dossier de crédit.

2) La deuxième étape du workflow est constituée de calculs de simulation du crédit. Ici sont invoqués des services du back-end en charge de vérifier la véracité des données saisies et d'appliquer des algorithmes permettant de savoir si la demande de crédit peut être satisfaite ou pas.

À l'issue de cette étape, soit la demande est approuvée, soit elle est rejetée par le système des simulations. En cas de rejet, les raisons du rejet sont signalées et un agent de la banque ayant les autorisations adéquates peut intervenir pour faire des rectifications et resoumettre le dossier au système de simulation.

N.B. Les dossiers approuvés à l'issue de simulation sont notés Vert et les dossiers rejetés sont notés Rouge.

3) La troisième étape consiste à soumettre les dossiers issus de la simulation au Comité d'Octroi de Crédit. Un agent de crédit se connecte dans le système et afin d'analyser les dossiers issus de la simulation. Un dossier de crédit Vert après la simulation ne peut être rejeté c'est-à-dire que la seule option possible dont dispose l'agent est d'envoyer ledit dossier au Comité d'Octroi de crédit.

Si le dossier est Rouge, alors trois cas sont possibles :

- soit l'agent rejette définitivement le dossier et un mail de refus de crédit est automatiquement envoyé au client ;

- soit l'agent prend note des raisons du rejet et constate qu'il est possible de faire des rectificatifs sur le dossier afin qu'il puisse être accepté. Sur accord du client, l'agent modifie la demande et soumet de nouveau le dossier à la simulation ;

- soit l'agent décide malgré tout d'envoyer le dossier au COC (COC pour Comité d'Octroi de Crédit). Dans ce cas il ajoute une annotation dans laquelle il indique les motivations qui l'emmènent à soumettre le dossier au COC malgré un échec de la simulation.

4) La quatrième étape consiste en l'étude de l'octroi du crédit par le Comité d'Octroi de Crédit.

À réception du dossier, le COC émet un avis définitif sur le dossier: le dossier est soit définitivement approuvé, soit définitivement rejeté.

Notons que les dossiers verts ne peuvent être rejetés par le COC et sont donc systématiquement définitivement approuvés, sauf situation exceptionnelle (exemple: le COC est brusquement informé du manque de fonds propres suite une grave crise financière qui vient d'éclater et qui touche de plein fouet l'organisme de crédit !).

Le COC n'étudie que les dossiers rouges motivés (annotés). Lorsque le dossier est approuvé, un contrat est automatiquement généré et transmis au service juridique. En même temps le dossier de crédit est transmis au service financier.

Dans la suite on suppose que le dossier est approuvé.

5) La cinquième étape est constituée de deux actions en simultané :

- le service juridique reçoit le contrat généré. Il s'occupe de le compléter par des engagements des deux parties sur des clauses diverses (clauses clés de pénalités, garanties, etc..). En gros le service juridique réajuste le contrat généré automatiquement par le système ;

- la cellule financière quant à elle formalise le décaissement des fonds sur la base du dossier reçu.

6) À la sixième étape, la Direction Administrative et Financière est notifiée du bouclage administratif et financier du crédit. L'organisme contacte alors le client. À l'arrivée du client dans les locaux de l'organisme, le contrat est imprimé et ce dernier y appose sa signature ainsi que le Directeur Administratif ou son P.O. Après la signature du contrat, celui-ci est numérisé via une chaîne de dématérialisation et automatiquement pris en charge dans le système de GED puis archivé. Lors de l'introduction du contrat numérisé dans le système de GED, il est procédé à :

- la capture du document avec extraction automatique des métadonnées ;

- la catégorisation du document ;

- la correction et amélioration automatique des images.

Il est par la suite possible de rechercher un contrat archivé via :

- une recherche simple : juste basée sur un mot qui peut être le nom du document ou un mot clé dans le contenu ;

- la catégorie ;

- la date de création ;

- le client concerné par le crédit.

Remarque

À chaque passage du dossier dans une étape, une signature électronique doit être portée sur le dossier pour mesures de sécurité. La signature électronique n'est pas abordée dans cet article.

III - Le workflow jBPM et sa transcription en modèle Alfresco (Task Model)

Il s'agit de :

- réaliser le diagramme du workflow jBPM ;

- modéliser les tâches et leurs assignations ;

- ressortir la cartographie fonctionnelle associée au processus ;

- traduire tous les nœuds du workflow jBPM dans le modèle Alfresco (Task Model).

III-A - Diagramme du workflow jBPM

Le diagramme de workflow jBPM ci-dessous a été fait avec Eclipse jPDL Graphical Designer.

Figure 1: Process design du workflow d'approbation du crédit

III-A-1 - Nœuds du Processus jBPM

- Start

Notre processus jBPM commence par un nœud de type start-state.

Figure 2: Définition Noeud Start

<start-state name="Start">
<task name="wfcm:start" swimlane="initiator"></task>
<transition to="CreditForm" name="trCreditForm"></transition>
</start-state>

Une tâche de nom 'wfcm:start' est définie au niveau de ce nœud. L'initiator est l'utilisateur qui démarre le workflow. La transition trCrediForm permet d'aller sur le nœud CreditForm.

- CreditForm

C'est au niveau de ce nœud que sont faites les différentes saisies en vue de constituer le dossier de crédit.

Figure 3: Définition du noeud CreditForm

<task-node name="CreditForm">
<task name="wfcm:creditForm" swimlane="initiator"></task>
<event type="node-enter">
<action name="CreditFormActionHandler"
class="com.koossery.workflow...handler..CreditFormActionHandler">
</action>
</event>
<transition to="Simulation" name="trSimulation"></transition>
</task-node>

Une tâche de nom 'wcfm:creditForm' est définie ici. C'est pendant l'exécution de cette tâche qu'est enregistré le formulaire avec ses pièces jointes. C'est toujours l'initiator qui agit sur cette tâche. Nous définissons un ActionHandler (cette notion sera expliquée plus tard: cf V-4) CreditFormActionHandler pour récupérer les informations sur le nœud. Ces informations seront utilisées pour obtenir la position d'un dossier de crédit dans le workflow pendant la recherche. La transition trSimulation nous mène au nœud Simulation.

- Simulation

Au niveau de ce nœud, nous avons défini l'action à exécuter pour simuler un dossier. Cette simulation permettra de dire si un dossier est RED (Rouge) ou GREEN (Vert).

Figure 4: Définition du noeud Simulation

<node name="Simulation">
<event type="node-enter">
<action name="SimulationActionHandler"
class="com.koossery...workflow...handler...SimulationActionHandler">
</action>
</event>
<transition to="ResultSimulation" name="trResultSimulation2"></transition>
</node>

Contrairement aux nœuds précédents qui sont tous de type 'task-node', on remarque que le nœud Simulation est simplement de type 'node': aucune tâche n'est définie ici. Le seul élément que nous avons défini est l'ActionHandler SimulationActionHandler: c'est lui qui exécute l'opération de simulation et retourne l'état du dossier de crédit (RED ou GREEN). Cet ActionHandler est exécuté à l'entrée du Node (event type = node-enter).

La transition trResultSimulation nous mène sur le nœud ResultSimulation.

- ResultSimulation

Ce nœud permet de visualiser l'état du dossier de crédit passé en simulation.

Figure 5: Définition du noeud ResultSimulation

<task-node name="ResultSimulation">
<task name="wfcm:resultSimulation" swimlane="initiator"></task>
<event type="node-enter">
<action name="ResultSimulationActionHandler"
class="com.koossery...workflow...handler...ResultSimulationActionHandler">
</action>
</event>
<event type="node-leave">
<action name="ResultSimulationActionHandler"
class="com.koossery...workflow...handler...ResultSimulationActionHandler">
</action>
</event>

<transition to="ApprovalCommitte" name="trApprovalCommitte"></transition>
<transition to="CreditForm" name="trCreditForm2"></transition>
<transition to="End" name="trEnd"></transition>
</task-node>

Une tâche de nom wfcm:resultSimulation est définie ici. C'est l'initiator qui agit sur cette tâche. Cette tâche comporte deux variables qui sont: wfcm_statusDocument (variable sur l'état du document) et wcfm_piecesNumber (variable sur le nombre de pièces jointes). L'ActionHandler ResultSimulationActionHandler y a été défini. Il permet d'avoir des informations sur le nœud courant et met à jour la variable wcfm_piecesNumber.

La transition trApprovalCommitee nous mène au nœud ApprovalCommitte.

- ApprovalCommitte

C'est le nœud de validation de la demande de crédit par le Comité d'Octroi de Crédit.

Figure 6: Noeud ApprovalCommitte

<task-node name="ApprovalCommitte">
<task name="wfcm:approvalCommittee" swimlane="ApprovalMember"></task>
<event type="node-enter">
<action name="ChoixTransitionActionHandler"
class="com.koossery...workflow...handler...ChoixTransitionActionHandler" >
</action>
</event>
<event type="node-leave">
<action name="ChoixTransitionActionHandler"
class="com.koossery...workflow...handler...ChoixTransitionActionHandler" >
</action>
</event>
<transition to="End" name="trEnd2"></transition>
<transition to="forkApprovalCommitte" name="trFork"></transition>
</task-node>

Une tâche est définie ici : wfcm:approvalCommitte. Cette tâche comporte deux variables : wfcm_statusDocument (variable sur l'état du document) et wcfm_piecesNumber (variable sur le nombre de pièces jointes). Il faut être un utilisateur du groupe ApprovalMember pour pouvoir exécuter cette tâche. Nous avons défini un ActionHandler ApprovalCommitteActionHandler à l'entrée du nœud pour obtenir certaines informations nécessaires pour la recherche.

Lorsque le dossier est approuvé, le workflow continue par la transition forkApprovalCommitte et celle-ci nous mène vers le fork. Dans le cas contraire, le workflow se termine et un mail est envoyé au client pour lui signaler le rejet de son dossier.

- Fork

Dans un workflow jPDL, un Fork est utilisé lorsqu'on veut réaliser des tâches en parallèle. La continuation de l'exécution du workflow au-delà du fork n'est possible que si les tâches effectuées en parallèle sont toutes achevées.

Figure 7: Noeud Fork

<fork name="forkApprovalCommitte">
<transition to="LegalService" name="trLegalService"></transition>
<transition to="FinancialService" name="trFinancialService"></transition>
</fork>

Les tâches qui seront effectuées en parallèle sont faites dans les task-node LegalService et FinancialService.

- LegalService

C'est le nœud d'élaboration du contrat stipulant les engagements des deux parties. Ce contrat s'élabore sur la base des données provenant du dossier de crédit. La procédure d'élaboration consiste à générer un contrat pré rempli et à le réajuster par la suite.

Figure 8: Noeud LegalService

<task-node name="LegalService">
<task name="wfcm:prepareContrat" swimlane="LegalMember"></task>
<event type="node-enter">
<action name="LegalServiceActionHandler"
class="com.koossery...workflow...handler...LegalServiceActionHandler">
</action>
</event>
<transition to="joinApprovalCommitte" name="trJoinLegalService"></transition>
</task-node>

Une tâche est définie au niveau de ce nœud: wfcm:prepareContrat. Cette tâche est assignée au groupe LegalMember. Nous avons défini un ActionHandler LegalServiceActionHandler pour la génération du contrat. Ce handler utilise le framework Jasper Report. Il permet aussi de recueillir des informations nécessaires à la recherche d'un dossier de crédit. La transition trJoinLegalService nous mène sur le nœud joinApprovalCommitte.

- FinancialService

Figure 9: Noeud FinancialService

<task-node name="FinancialService">
<task name="wfcm:prepareOutlay" swimlane="FinancialMember"></task>
<event type="node-enter">
<action name="FinancialServiceActionHandler"
class="com.koossery...workflow...handler...FinancialServiceActionHandler">
</action>
</event>
<transition to="joinApprovalCommitte" name="trJoinFinancialService"></transition>
</task-node>

Une tâche est définie au niveau de ce nœud : wfcm:prepareOutlay. Cette tâche est assignée au groupe FinancialMember. À l'entrée du nœud, le handler FinancialServiceActionHandler est appelé pour obtenir des informations importantes pour la recherche. La transition trJoinFinancialService nous mène au nœud joinApprovalCommitte.

- Join

C'est lui qui marque la fin de réalisation des tâches simultanées précédemment citées dans notre workflow jBPM.

Figure 10: Noeud Join

<join name="joinApprovalCommitte">
<transition to="CreditContract"></transition>
</join>

La transition trCreditContrat nous mène sur le nœud CreditContrat.

- CreditContract

À ce niveau la direction administrative et financière contacte le client et les deux parties signent le contrat.

Figure 11: Noeud CreditContrat

<task-node name="CreditContract">
<task name="wfcm:signContract"
swimlane="AdministrativeFinancialManagement"></task>
<event type="node-enter">
<action name="CreditContractActionHandler"
class="com.koossery...workflow...handler...DCreditContractActionHandler">
</action>
</event>
<transition to="Archiving" name="trArchivingNode"></transition>
</task-node>

Ce nœud contient la tâche: wfcm:creditContrat. Cette tâche consiste à joindre le contrat signé et scanné comme pièce jointe au dossier de crédit. Cette tâche est assignée au groupe AdministrativeFinancialManagement. Nous avons défini un ActionHandler: CreditContratStateActionHandler. La transition trArchiving nous mène au nœud Archiving.

- Archiving

C'est ici que le dossier de crédit est archivé.

Figure 12: Noeud Archiving

<task-node name="Archiving">
<task name="wfcm:archiving" swimlane="AdministrativeFinancialManagement"></task>
<event type="node-enter">
<action name="ArchivingActionHandler"
class="com.koossery...workflow...handler...ArchivingActionHandler"></action>
</event>
<transition to="Payment" name="trPayment"></transition>
</task-node>

L'archivage est géré par le module record management de Alfresco. Ce module sera vu dans les prochaines itérations de cet article. Après l'archivage, on passe au nœud de Paiement.

- Paiement

Le paiement consiste à remettre au client le crédit demandé.

Figure 13: Noeud Payement

<task-node name="Payment">
<task name="wfcm:payment" swimlane="AdministrativeFinancialManagement"></task>
<event type="node-enter">
<action name="PaymentActionHandler"
class="com.koossery...workflow...handler...PaymentActionHandler"></action>
</event>
<transition to="End" name="trEnd3"></transition>
</task-node>

Lorsque le paiement est effectué, le workflow est terminé; ce qui nous conduit au nœud end-state.

- End

Ce nœud marque la fin du workflow.

Figure 14: Noeud End

<end-state name="End"></end-state>

À l'entrée de ce nœud, on définit un ActionHandler EndActionhandler qui permettra de savoir à partir de la recherche si un dossier de crédit se trouve à la fin du workflow.

III-B - Assignation des tâches

Assigner une tâche c'est designer l'acteur ou le pool d'acteurs qui a le droit de réaliser ladite tâche. Dans le langage jPDL, l'assignation des tâches se fait à partir des rôles déclarés à travers l'élément swimlane.

Dans le cas du worflow crédit, les tâches sont assignées à un pool. Même l'initiator appartient à un pool bien précis. Ci-dessous quelques pools d'acteurs que nous avons définis dans notre workflow crédit.

- AdviserCustomer

Ce pool est chargé de démarrer le workflow. C'est le pool auquel appartient le conseiller client ou encore l'acteur (initiator). Nous n'avons pas défini ce pool dans le process définition du workflow.

- ApprovalMember

<swimlane name="ApprovalMember">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<pooledactors>#{people.getGroup('GROUP_ApprovalMember')}</pooledactors>
</assignment>
</swimlane>

Pool d'acteurs faisant partie du comité d'octroi de crédit. Les acteurs de ce pool ont les autorisations pour intervenir au niveau de la tâche 'wfcm:approvalCommittee' se trouvant dans le nœud ApprovalCommitte.

- LegalMember

< swimlane name="LegalMember">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<pooledactors>#{people.getGroup('GROUP_LegalMember')}</pooledactors>
</assignment>
</ swimlane >

Pool d'acteurs faisant partie du service juridique. Les acteurs de ce pool ont les autorisations pour intervenir au niveau de la tâche 'wfcm:prepareContrat' se trouvant dans le nœud LegalService.

- FinancialMember

<swimlane name="FinancialMember">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<pooledactors>#{people.getGroup('GROUP_FinancialMember')}</pooledactors>
</assignment>
</swimlane>

Pool d'acteurs faisant partie du service financier. Les acteurs de ce pool ont les autorisations pour intervenir au niveau de la tâche 'wfcm:prepareOutlay' se trouvant dans le nœud FinancialService.

- AdministrativeFinancialManagement

<swimlane name="AdministrativeFinancialManagement">
<assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
<pooledactors>#{people.getGroup('GROUP_AdministrativeFinancialManagement)}
</pooledactors>
</assignment>
</swimlane>

Ce pool a les autorisations pour intervenir au niveau des tâches 'wfcm:creditContract', 'wfcm:archiving' et 'wfcm:payment' se trouvant dans les nœuds CreditContract, Archiving et Payment.

III-C - Transcription du workflow jBPM en Task Model Alfresco

Pour chaque tâche d'un task-node défini dans le workflow jBPM, on écrit sa modélisation dans Alfresco à l'aide du dictionnaire Alfresco. Nous avons les éléments suivants.

- Les imports

<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/>
</imports>

- Le namespace

<namespaces>
<namespace uri="http://www.koossery-tech.com/model/workflow/credit/1.0"
prefix="wfcm"/>
</namespaces>

Ci-dessous les types correspondants aux différentes tâches du workflow :

- wcfm :start

<type name="wfcm:start">
<parent>bpm:startTask</parent>
<!-- this overrrides is used to remove the actions in the start workflow -->
<overrides>
<property name="bpm:packageActionGroup">
<default>void</default>
</property>
<property name="bpm:packageItemActionGroup">
<default>void</default>
</property>
</overrides>
</type>

Nous pouvons remarquer que ce type hérite du type de base 'bpm:startTask'. 'overrides' est utilisé pour définir des actions à afficher au niveau de l'interface utilisateur d'une tâche: les actions définies remplacent celles mises par défaut dans Alfresco. Dans notre cas nous avons déclaré deux types de groupe d'actions :

- bpm:packageActionGroup : groupe d'actions définies sur les ressources. Dans notre cas, la valeur est void ;

- bpm:packageItemActionGroup : groupe d'actions définies sur une ressource de la tâche correspondante. Dans notre cas, la valeur est void.

La valeur void est utilisée lorsqu'on ne définit aucune action dans le groupe d'action. Dans notre cas la tâche wfcm:start n'aura donc aucune action de groupe et aucune action sur une ressource.

La notion de groupe d'actions est traitée en profondeur plus tard : cf V-3.

- wfcm:creditForm

<type name="wfcm:creditForm">
<parent>bpm:workflowTask</parent>
<overrides>
<property name="bpm:packageActionGroup">
<default>add_credit_record_actions</default>
</property>
<property name="bpm:packageItemActionGroup">
<default>edit_piece_content</default>
</property>
</overrides>
</type>

Ce type hérite du type de base bpm:workflowTask.

La propriété 'bpm:packageActionGroup' a pour valeur le groupe d'actions 'add_credit_record_actions'. Ce groupe d'actions contient les actions permettant de créer un nouveau dossier de crédit. La propriété 'bpm:packageItemActionGroup' a pour valeur le groupe d'actions 'edit_piece_content'. Ce groupe d'actions contient les actions permettant d'éditer les métas-données des pièces jointes qui ont été introduites dans le dossier.

- wcfm:resultSimulation

<type name="wfcm:resultSimulation">
<parent>bpm:workflowTask</parent>
<properties>
<property name="wfcm:statusDocument">
<type>d:text</type>
<default>RED</default>
</property>
<property name="wfcm:piecesNumber">
<type>d:long</type>
<default>0</default>
</property>
<property name="wfcm:annotation">
<type>d:text</type>
</property>
</properties>
<overrides>
<property name="bpm:packageItemActionGroup">
<default>edit_piece_content</default>
</property>
</overrides>
</type>

Ce type hérite aussi du type de base 'bpm:workflowTask'. On définit les propriétés :

- wfcm:statusDocument : cette propriété représente le statut du document RED ou GREEN ;

- wcfm:piecesNumber : cette propriété représente le nombre de pièces jointes ;

- wcfm:annotation : cette propriété est de type 'text' et contient le texte que le Conseiller client saisit en annotation lorsque le statut du document est RED.

- wcfm:approvalCommittee

<type name="wfcm:approvalCommittee">
<parent>wfcm:resultSimulation</parent>
<overrides>
<property name="bpm:packageItemActionGroup">
<default>view_piece_content</default>
</property>
</overrides>
</type>

Ce type hérite du type wcfm:resultSimulation et donc on hérite des mêmes propriétés que wcfm:resultSimulation.

- wcfm:prepareContrat

<type name="wfcm:prepareContrat">
<parent>bpm:workflowTask</parent>
<overrides>
<property name="bpm:packageItemActionGroup">
<default>view_piece_content</default>
</property>
</overrides>
</type>

Ce type hérite du type de base bpm:workflowTask. Le groupe d'actions 'view_piece_content' a été défini pour afficher les métas-données d'une pièce jointe. Les métadonnées d'une pièce jointe ne seront visibles qu'en lecture seule.

- wcfm:prepareOutlay

<type name="wfcm:prepareOutlay">
<parent>bpm:workflowTask</parent>
<overrides>
<property name="bpm:packageItemActionGroup">
<default>view_piece_content</default>
</property>
</overrides>
</type>

- wcfm:creditContract

<type name="wfcm:creditContract">
<parent>bpm:workflowTask</parent>
</type>

- wcfm:archiving

<type name="wfcm:archiving">
<parent>bpm:workflowTask</parent>
<overrides>
<property name="bpm:packageItemActionGroup">
<default>edit_achiving_item_actions</default>
</property>
</overrides>
</type>

- wcfm:payment

<type name="wfcm:payment">
<parent>bpm:workflowTask</parent>
<overrides>
<property name="bpm:packageItemActionGroup">
<default>view_credit_record_item_actions</default>
</property>
</overrides>
</type>

Le groupe d'action 'view_credit_record_item_actions' a été défini pour afficher en lecture seule le dossier de crédit archivé.

IV - Modélisation Alfresco du dossier de Crédit

IV-A - Modèle de donnée du dossier de crédit

Figure 2 : Entity model

Dans ce diagramme :

- CreditRecord représente le dossier de crédit ;

- GenerateContrat représente le contrat généré ;

- ScanContrat représente le contrat scanné ;

- ScanPaySlip représente la fiche de paie ;

- ScanTaxSlip représente la fiche d'impôt.

IV-B - Alfresco Content Type Model

Nous écrivons ici le content type model de chaque entité citée ci-dessus (paragraphe IV.1) à l'aide du dictionnaire de données et du content type model de base de Alfresco.

- Importation des modèles d'Alfresco

<imports>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
</imports>

- La définition du namespace pour notre projet

<namespaces>
<namespace uri="http://www.koossery-tech.com/model/wc/1.0" prefix="wc"/>
</namespaces>

- Le dossier de crédit

<type>
<parent>cm:folder</parent>
<properties>
<property name="wc:civility">
<title>Civility</title>
<type>d:text</type>
<mandatory>true</mandatory>
<default>Mister</default>
<constraints>
<constraint ref = "wc:valueCivility"></constraint>
</constraints>
</property>
<property name="wc:name">
<title>Name</title>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="wc:surname">
<title>Surname</title>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="wc:birthdate">
<title>BirthDate</title>
<type>d:date</type>
<mandatory>true</mandatory>
</property>
<property name="wc:cni">
<title>CNI</title>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="wc:familySituation">
<title>FamilySituation</title>
<type>d:text</type>
<mandatory>true</mandatory>
<default>Married</default>
<constraints>
<constraint ref = "wc:valueFamilySituation"></constraint>
</constraints>
</property>
<property name="wc:childNumber">
<title>ChildNumber</title>
<type>d:long</type>
<mandatory>true</mandatory>
</property>
<property name="wc:childNumberInCharge">
<title>ChildNumberInCharge</title>
<type>d:long</type>
<mandatory>true</mandatory>
</property>
<property name="wc:email">
<title>Email</title>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="wc:professionnelSituation">
<title>ProfessionnelSituation</title>
<type>d:text</type>
<mandatory>true</mandatory>
</property>
<property name="wc:since">
<title>Since</title>
<type>d:date</type>
<mandatory>true</mandatory>
</property>
<property name="wc:borrowAmount">
<title>BorrowAmount</title>
<type>d:long</type>
<mandatory>true</mandatory>
</property>
<property name="wc:reimbursementDuration">
<title>ReimbursementDuration</title>
<type>d:long</type>
<mandatory>true</mandatory>
</property>
<property name="wc:monthlySalary">
<title>MonthlySalary</title>
<type>d:long</type>
<mandatory>true</mandatory>
</property>
<property name="wc:loanType">
<title>LoanType</title>
<type>d:text</type>
<mandatory>true</mandatory>
<default>Personnal loan</default>
<constraints>
<constraint ref = "wc:valueTypeLoan"></constraint>
</constraints>
</property>
<property name="wc:disbursementType">
<title>DisbursementType</title>
<type>d:text</type>
<mandatory>true</mandatory>
<default>Transfert</default>
<constraints>
<constraint ref = "wc:valueTypeDisbursement"></constraint>
</constraints>
</property>
<property name="wc:countNumber">
<title>CountNumber</title>
<type>d:long</type>
<mandatory>true</mandatory>
</property>
<property name="wc:stateDocument">
<title>State on document</title>
<type>d:text</type>
<mandatory>true</mandatory>
<default>No Created</default>
</property>
</properties>
<associations>
<association name="wc:hasScanPaySlip">
<target>
<class>wc:scanPaySlip</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
<association name="wc:hasScanTaxSlip">
<target>
<class>wc:scanTaxSlip</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
<association name="wc:hasScanContrat">
<target>
<class>wc:scanContrat</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
<association name="wc:hasGenerateContrat">
<target>
<class>wc:generateContrat</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
</associations>
<mandatory-aspects>
<aspect>cm:versionable</aspect>
</mandatory-aspects>
</type>

Notre dossier de crédit a pour type parent 'cm:folder' afin qu'il puisse hériter des propriétés d'un dossier et qu'il puisse être physiquement représenté par un dossier. Les propriétés qu'on retrouve dans ce modèle sont celles citées dans le paragraphe III.

Par ailleurs nous avons les associations suivantes :

- hasScanPaySlip : association qui lie la fiche de paie au dossier de crédit ;

- hasScanTaxSlip : association qui lie la fiche d'impôt au dossier de crédit ;

- hasScanContrat : association qui lie le contrat scanné au dossier de crédit ;

- hasGenerateContrat : association qui lie le contrat généré au dossier de crédit.

Nous distinguons aussi l'aspect suivant :

- versionable : permet de rendre le dossier de crédit versionable c'est-à-dire qu'il aura plusieurs versions.

- Modélisation d'une pièce jointe: la fiche de paie

<type name="wc:scanPaySlip">
<title>Pay Slip scanned</title>
<parent>cm:content</parent>
<properties>
<property name="wc:titlePay">
<title>Title Pay Slip scanned</title>
<type>d:text</type>
<mandatory>false</mandatory>
</property>
<property name="wc:descriptionPay">
<title>Description</title>
<type>d:text</type>
<mandatory>false</mandatory>
</property>
</properties>
</type>

Nous héritons du type de base 'cm:content' d'Alfresco, car nous gérons la fiche de paie comme un contenu du dossier de crédit.

V - Implémentation de la solution dans un projet Maven2

Les principales étapes sont :

1. Création du projet avec Maven2 ;

2. Configuration du projet ;

3. JSF : création des BackingBean et des jsp associées ;

4. Création des Handler qui ont été déclarés dans le workflow (cf III).

V-A - Le projet Maven2

V-A-1 - Structure du projet

Nous avons mis en place un projet Maven2 multimodule :

Figure 3: projet Alfresco multimodules maven 2

Ci-dessous la structure du projet webapp (c'est notre projet Alfresco):

Figure 4: le projet worflow.credit.webapp basé sur Alfresco

Dans 'src/main/java' on trouve nos classes java avec notamment nos handlers et nos backing bean.

Dans 'src/main/resources' on trouve les packages suivants :

- alfresco.extension : contient les fichiers *-context.xml, les fichiers de configuration de la webapp ainsi que les fichiers d'authentification au serveur ldap ;

- alfresco.extension.jasperreport : contient les fichiers de configuration pour jasper report ;

- alfresco.extension.workflows.credit : contient les fichiers de configuration du workflow jBPM.

Dans 'src/main/propreties' on trouve les packages suivants :

- local : contient toutes les configurations relatives à l'environnement de travail LOCAL. On y trouve notamment le fichier application.properties. Ce fichier contient toutes des configurations centrales pour Alfresco ;

- messages : contient les fichiers d'internationalisation.

Le répertoire '/tools' contient divers scripts utilitaires: .sh, ou .bat.

V-A-2 - Les divers fichiers de configuration de notre webapp

Un des gros avantages avec Alfresco est que nous ne redéveloppons pas notre webapp de zéro: nous nous appuyons sur la webapp de base d'Alfresco et nous en réalisons une extension.

Nous devons configurer ou adapter un certain nombre de fichiers de configuration :

- web-client-config-custom.xml ;

- faces-config-custom.xml ;

- les fichiers properties (fichiers d'internationalisation, applications.properties et ldap-authefication.properties) ;

- les fichiers de type *-context.xml.

V-A-2-a - Le fichier application.propeties

- Configuration repository Alfresco

dir.root=${alfresco.data.location}
index.recovery.mode=NONE
integrity.failOnError=true

'dir.root' représente le répertoire de stockage du repository. Le placeholder ${alfersco.data.location} a été défini dans le pom.

- Configuration des accès à la base de données

db.driver=org.gjt.mm.mysql.Driver
db.url=jdbc:mysql://localhost/${alfresco.db.name}
db.username=${alfresco.db.username}
db.password=${alfresco.db.password}
db.pool.initial=10
db.pool.max=100

hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect

Dans notre projet, Alfresco stocke les métas donnés dans une base de données. Alfresco s'appuie sur le framework de mapping O/R Hibernate et ci-dessus on positionne le dialect pour attaquer MySQL. Tous les placeholders de cette configuration ont été définis dans le pom.

- Configuration SMB/CIFS

smb.server.enabled=false
smb.server.name=CFS_SHARE_LOCAL
smb.server.domain=koossery-tech.com
smb.server.bindto=xxx.xxx.xxx.xxx
smb.tcpip.port=xxx

SMB (Server Message Block) est un protocole permettant le partage de ressources (fichiers et imprimantes) sur des réseaux locaux avec des PC sous Windows. Sous Windows NT 4, il est appelé CIFS. Nous avons désactivé ce service, car nous ne l'utilisons pas dans notre projet.

- Configuration NETBIOS

netbios.session.port=xxxx
netbios.name.port=xxxx
netbios.datagram.port=xxxx

NETBIOS (Network Basic Input/output System) est un protocole de transfert de fichiers. CIFS utilise les configurations NETBIOS sur le serveur de fichiers Windows existant.

- Configuration FTP

ftp.server.enables=false
ftp.port=xxxx
ftp.authenticator=koossery-tech

FTP (File Transfer Protocol) est un protocole de transfert de fichier. Nous l'avons désactivé dans notre projet.

- Configuration LDAP

authentication.chain=ldap1:ldap

Cette configuration indique qu'on va utiliser un annuaire LDAP. La configuration LDAP est dans le fichier ldap-authentication.properties qui se trouve dans le package alfresco.extension.

V-A-2-b - Le fichier web-client-config-custom.xml

Cette configuration est utilisée pour l'interface graphique affichée à l'utilisateur. Pour notre projet les principaux points que nous avons adaptés sont :

- la liste des langues disponibles ;

- les configurations pour la recherche de documents (recherche full-text, recherche basée sur la catégorisation ou la localisation, etc.) ;

- les propriétés à afficher sur l'interface utilisateur de chaque tâche ;

- les actions et les actions-group ;

- les dialogs Alfresco ;

- l'organisation du tableau de bord (dashboard) de alfresco.

V-A-2-b-i - Les langues disponibles

<config evaluator="string-compare" condition="Languages">
<languages>
<language locale="fr_FR">Francais</language>
<language locale="en_EN">English</language>
</languages>
</config>

V-A-2-b-ii - Les configurations pour la recherche de documents

- Configuration des méthodes de recherche

<config>
<client>
<search-and-terms>true</search-and-terms>
</client>
</config>

Cette configuration permet l'ajout du terme 'AND' dans une recherche.

- Configuration de la recherche avancée

<config evaluator="string-compare" condition="Advanced Search">
<advanced-search>
...
</advanced-search>
</config>

La recherche avancée nous permet de trouver les dossiers de crédit existants dans le système et les différentes pièces jointes le constituant. L'on peut décider de faire une recherche :

- par rapport au dossier de crédit

<folder-types>
<type name="wc:creditRecord"/>
</folder-types>

- par rapport aux pièces jointes: fiche de paie, fiche d'impôt, contrat scanné et contrat généré.

<content-types>
<type name="wc:scanPaySlip"/>
<type name="wc:scanTaxSlip"/>
<type name="wc:scanContrat"/>
<type name="wc:generateContrat"/>
</content-types>

Pour chaque type de pièce sur lequel la recherche peut se baser, on définit les propriétés qui pourront être utilisées comme critères :

<custom-properties>
<meta-data type="wc:creditRecord" property="wc:name" />
<meta-data type="wc:creditRecord" property="wc:surname" />
<meta-data type="wc:creditRecord" property="wc:familySituation" />
<meta-data type="wc:creditRecord" property="wc:borrowAmount" />
<meta-data type="wc:scanPaySlip" property="wc:titlePay" />
<meta-data type="wc:scanTaxSlip" property="wc:titleTax" />
<meta-data type="wc:scanContrat" property="wc:titleContrat" />
<meta-data type="wc:generateContrat" property="wc:titleGenContrat" />
</custom-properties>

V-A-2-b-iii - Les interfaces utilisateur des task-node

- Configuration des champs à afficher à l'utilisateur pendant le workflow

<config evaluator="node-type" condition="wfcm:start" replace="true">
<property-sheet>
<separator name="sep1"
display-label-id="separator_start_workflow"
component-generator="HeaderSeparatorGenerator" />
<show-property name="bpm:workflowDescription"
component-generator="TextAreaGenerator" />
<show-property name="bpm:workflowPriority" />
</property-sheet>
</config>

Cette configuration indique d'afficher les champs: workflowDescription et workflowPriority sur la vue de l'utilisateur lorsque l'on sera sur la tâche wcfm:start. Les configurations de l'interface utilisateur pour ce qui concerne les autres tâches du workflow sont définies de façon similaire.

V-A-2-b-iv - Les actions Alfresco

Une action Alfresco est une unité de travail.

- Exemple de configuration d'une action Alfresco

<action id="create_credit_record">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_add_credit_record</label-id>
<image>/images/icons/add.gif</image>
<action>dialog:save_credit_record</action>
<action-listener>#{CreditFormBackingBean.initAdd}</action-listener>
</action>

Cette action a pour libellé 'action_add_credit_record' et ce libellé est défini dans les fichiers d'internationalisation. L'icône à afficher est : /images/icons/add.gif. Le dialog Alfresco associé à cette action est 'save_credit_record'. Les dialogs sont détaillés dans la suite de ce document (paragraphe V-2).

Lorsque l'action create_credit_record est invoquée, la méthode initAdd() de la classe CreditFormBackingBean est exécutée.

- Exemple de configuration de groupe d'action

<action-group id="add_credit_record_actions">
<action idref="create_credit_record" />
</action-group>

Un action-group est un groupe d'actions. Dans notre cas l'action-group 'add_credit_record' contient l'action 'create_credit_record'.

V-A-2-b-v - Les 'dialogs' Alfresco

Un 'dialog' Alfresco est une unité de travail qui met en relation une page jsp et une classe Java (Backing Bean). Le procédé s'appuie en réalité sur la technologie JSF.

- Exemple de configuration d'un dialogue Alfresco

<dialog     name="save_credit_record"
page="/jsp/extension/creditform/creditform.jsp"
managed-bean="CreditFormBackingBean"
icon="/images/icons/add_content_large.gif"
title="Add credit Record"
description="Add credit Record"
/>

Le dialog ci-dessus contient un ensemble d'éléments :

- name : le nom du dialog à afficher sur la page web ;

- page : c'est la page jsp à afficher ;

- managed-bean : le Backing Bean qui est référencé dans la page jsp ;

- icon : l'icône du dialogue à afficher sur la page web ;

- title : le titre du dialogue à afficher sur la page web, ;

- description.

V-A-2-b-vi - Le dashboard Alfresco

Le dashboard est le tableau de bord affiché dès qu'on se connecte à l'application.

- Configuration du dashboard

<config evaluator="string-compare" condition="Dashboards">
<dashboards>
<dashlets>
<!-- the default dashlet must have the id of 'getting-started' -->
<dashlet id="start-workflow-menu" label-id="dashlet_startworkflowmenu_label"
description-id="dashlet_startworkflowmenu_desc"
jsp="/jsp/dashboards/dashlets/start-workflow-menu.jsp"
allow-narrow="false" />
</dashlets>
</dashboards>

<dashboards>
<default-dashlets>
<dashlet id="start-workflow-menu" />
<dashlet id="tasks-todo" />
<dashlet id="pooled-tasks" />
<dashlet id="tasks-completed" />
</default-dashlets>
</dashboards>

</config>

Nous avons créé un dashlet pour permettre le lancement du workflow sur le dashboard. Ce dashlet affiche la page start-workflow-menu.jsp.

Le dashboard affichera dans l'ordre les éléments (dashlet) suivants :

- start-workflow-menu : permet de démarrer le workflow ;

- ltasks-todo : liste les tâches à effectuer par un utilisateur ;

- pooled-tasks : liste les tâches à effectuer par un pool ;

- tasks-completed : liste les tâches terminées.

V-A-2-c - Internationalisation

Les divers fichiers d'internationalisation sont pris en compte via les configurations Spring custom-repository-context.xml et workflow-credit-context.xml.

V-A-2-d - Les configurations Spring

V-A-2-d-i - Le fichier custom-repository-context.xml

<beans>

<!-- overriding to point to custom properties -->
<bean id="repository-properties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders">
<value>true</value>
</property>
<property name="locations">
<list>
<value>classpath:alfresco/repository.properties</value>
<value>classpath:alfresco/version.properties</value>
<value>classpath:alfresco/domain/transaction.properties</value>
<!-- Override basic repository properties, dir.root and hibernate dialect -->
<value>
classpath:alfresco/extension/ldap-authentication.properties
</value>
<value>
classpath:alfresco/extension/${env}/application.properties
</value>
</list>
</property>
</bean>

<bean id="hibernateConfigProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:alfresco/domain/hibernate-cfg.properties</value>
</list>
</property>
</bean>

</beans>

Dans ce fichier on configure le bean Spring PropertyPlaceholderConfigurer afin d'indiquer où se trouvent les différents fichiers de propriétés contenant les valeurs des placeholders.

V-A-2-d-ii - Le fichier worflow-credit-context.xml

<bean id="credit.workflowBootstrap" parent="workflowDeployer">
<!-- Registration of new models -->
<property name="models">
<list>
<value>alfresco/extension/models/CreditModel.xml</value>
<value>alfresco/extension/models/WorkflowCreditModel.xml</value>
</list>
</property>
<!-- Registration of workflow -->
<property name="workflowDefinitions">
<list>
<props>
<prop key="engineId">jbpm</prop>
<prop key="location">/.../.../processdefinition.xml</prop>
<prop key="mimetype">text/xml</prop>
<prop key="redeploy">true</prop>
</props>
</list>
</property>
<property name="labels">
<list>
<value>alfresco/extension/messages/workflow-data</value>
</list>
</property>
</bean>

<bean id="resourceBundlesWebApp"
class="org.alfresco.web.app.ResourceBundleBootstrap">
<property name="resourceBundles">
<list>
<value>alfresco.extension.messages.webclient-custom</value>
<value>alfresco.extension.messages.creditform</value>
<value>alfresco.extension.messages.webclient-jsp</value>
</list>
</property>
</bean>
</beans>

Le bean WorkflowDeployer est utilisé pour déployer les modèles de l'application (les fichiers CreditModel.xml et WorkflowCreditModel.xml), le process définition et les fichiers contenant les labels des pages des task-nodes.

Le bean ResourceBundleBootstrap permet de déployer les labels qui ne sont pas liés au process definition.

V-A-2-e - Ldap

Nous avons configuré les fichiers ldap-autentication.properties et ldap-authentication-context.xml. Le fichier ldap-autentication.properties contient les valeurs des placeholders qui sont référencés dans le fichier ldap-authentication-context.xml.

V-B - Développement de la webapp : quelques exemples de développements complets de 'dialogs' Alfresco

Développer un dialogue Alfresco revient à :

- concevoir la page jsp relative au dialogue et écrire le backing bean correspondant ;

- configurer de façon adéquate le fichier face-config-custom.xml ;

- configurer les actions Alfresco associées ;

- et enfin configurer les dialogs Alfresco correspondants.

Figure 5: étapes de développement d'un 'dialog' Alfresco

V-B-1 - 'Dialog' relatif à la création, modification et visualisation d'un dossier de crédit

V-B-1-a - Le backing bean

Le bean CreditFormBackingBean est le backing bean du formulaire de demande de crédit. Les méthodes suivantes ont été définies :

- initAdd() : initialiser le formulaire de crédit pour une nouvelle demande de crédit ;

- initUpdate() : préparer un formulaire de crédit pour modification ;

- initView() : préparer un formulaire de crédit pour affiche en lecture seule ;

- save() : enregistrer une nouvelle demande de crédit ;

- update() : mettre à jour une demande de crédit.

V-B-1-b - Configuration du fichier face-config-custom.xml

<managed-bean>
<managed-bean-name>CreditFormBackingBean</managed-bean-name>
<managed-bean-class>com.koossery...CreditFormBackingBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value>
</managed-property>
<managed-property>
<property-name>contentService</property-name>
<value>#{ContentService}</value>
</managed-property>
<managed-property>
<property-name>browseBean</property-name>
<value>#{BrowseBean}</value>
</managed-property>
<managed-property>
<property-name>serviceRegistry</property-name>
<value>#{ServiceRegistry}</value>
</managed-property>
<managed-property>
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>navigator</property-name>
<value>#{NavigationBean}</value>
</managed-property>
</managed-bean>

V-B-1-c - Les dialogs Alfresco correspondants

Configurer un dialog Alfresco revient à indiquer la page jsp, le backing bean et les actions Alfresco.

Ici nous avons configuré deux dialogs Alfresco : 'save_credit_record' et 'view_credit_record'.

- save_credit_record : concerne la création et la mise à jour.

<dialog name="save_credit_record"
page="/jsp/extension/creditform/creditform.jsp"
managed-bean="CreditFormBackingBean"
icon="/images/icons/add_content_large.gif"
title="Add credit Record"
description="Add credit Record" />

<!--ci-dessous les actions du dialog-->

<action id="create_credit_record">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_add_credit_record</label-id>
<image>/images/icons/add.gif</image>
<action>dialog:save_credit_record</action>
<action-listener>#{CreditFormBackingBean.initAdd}</action-listener>
</action>
<action id="update_credit_record">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_update_credit_record</label-id>
<image>/images/icons/update.gif</image>
<action>dialog:save_credit_record</action>
<action-listener>#{CreditFormBackingBean.initUpdate}</action-listener>
</action>

- view_credit_record : concerne l'affichage en lecture seule.

<dialog name="view_credit_record" page="/jsp/extension/creditform/creditform.jsp"
managed-bean="CreditFormBackingBean"
icon="/images/icons/view_content_large.gif" title="View credit Record"
description="view credit Record" show-ok-button="false"/>

<!--ci-dessous les actions du dilog-->

<action id="view_credit_record">
<permissions>
<permission allow="true">Read</permission>
</permissions>
<label-id>action_view_credit_record</label-id>
<image>/images/icons/View_details.gif</image>
<action>dialog:view_credit_record</action>
<action-listener>#{CreditFormBackingBean.initView}</action-listener>
<params>
<param name="id">#{actionContext.id}</param>
</params>
</action>

V-B-2 - 'Dialog' relatif à l'upload de pièces jointes

V-B-2-a - Le backing bean

Le bean PieceBackingBean permet de gérer l'upload de pièces jointes. Nous y avons défini des méthodes pour :

- uploader un fichier ;

- enregistrer un fichier uploadé dans le repository en prenant soin de respecter l'association entre la pièce uploadée et le dossier de crédit ;

- ajouter un fichier comme ressource du workflow.

V-B-2-b - Configuration du fichier face-config-custom.xml

<managed-bean>
<description>
The bean that backs up the Add Content Dialog
</description>
<managed-bean-name>PieceBackingBean</managed-bean-name>
<managed-bean-class>com.koossery.workflow...PieceBackingBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
...
</managed-bean>

V-B-2-c - Les dialogs Alfresco correspondants

Nous avons les dialogues suivants :

- ajouter la fiche de paie (add_piece_pay) ;

- ajouter la fiche d'impôt (add_piece_tax) ;

- ajouter le contrat scanné (add_scan_contrat) ;

- ajouter la fiche de paie (add_piece_pay)

<dialog name="add_piece_pay"
page="/jsp/extension/piece/piece.jsp" managed-bean="PieceBackingBean"
icon="/images/icons/add_content_large.gif"
title-id="add_content_dialog_title"
description-id="add_content_dialog_desc"/>

<!-- configuration des actions du dialog-- >
<action id="add_piece_pay">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_add_piece_pay</label-id>
<image>/images/icons/add.gif</image>
<action>dialog:add_piece_pay</action>
<action-listener>#{PieceBackingBean.initAdd}</action-listener>
<params>
<param name="piece">pay</param>
</params>
</action>

- Ajouter la fiche d'impôt (add_piece_tax)

<dialog name="add_piece_tax"
page="/jsp/extension/piece/piece.jsp"
managed-bean="PieceBackingBean"
icon="/images/icons/add_content_large.gif"
title-id="add_content_dialog_title"
description-id="add_content_dialog_desc"/>

<!-- configuration des actions du dialog-- >
<action id="add_piece_tax">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_add_piece_tax</label-id>
<image>/images/icons/add.gif</image>
<action>dialog:add_piece_tax</action>
<action-listener>#{PieceBackingBean.initAdd}</action-listener>
<params>
<param name="piece">tax</param>
</params>
</action>

- Ajouter le contrat scanné (add_scan_contrat)

<dialog name="add_scan_contrat"
page="/jsp/extension/piece/piece.jsp"
managed-bean="PieceBackingBean"
icon="/images/icons/add_content_large.gif"
title-id="add_content_dialog_title"
description-id="add_content_dialog_desc"/>

<!-- configuration des actions du dialog-- >
<action id="add_scan_contrat">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_add_scan_contrat</label-id>
<image>/images/icons/add.gif</image>
<action>dialog:add_scan_contrat</action>
<action-listener>#{PieceBackingBean.initAdd}</action-listener>
<params>
<param name="piece">tax</param>
</params>
</action>

NB: dans le workflow credit nous ne permettons pas d'ajouter deux pièces de même type.

V-B-3 - Dialog Alfresco relatif aux tâches du workflow

V-B-3-a - Le backing bean

Le bean CustomManageTaskDialog est la customisation du bean ManageTaskDialog d'Alfresco. Ce bean comme son nom l'indique permet de gérer les dialogues relatifs aux tâches du workflow. Nous l'avons étendu afin de tenir compte des spécificités de notre projet. Ainsi nous avons procédé à :

- la redéfinition de la méthode getResources() ;

- la redéfinition de la méthode updateResources() ;

- la surcharge de la méthode removePackageItem().

La page jsp Manage-task-dialog.jsp fait référence à notre backing bean. Nous avons retouché cette jsp de sorte que la disposition des packageActionGroup convienne mieux à notre projet.

V-B-3-b - La configuration du face-config-custom.xml

<managed-bean>
<description>
The bean that backs up the Manage Task Dialog
</description>
<managed-bean-name>ManageTaskDialog</managed-bean-name>
<managed-bean-class>com...managetask.CustomManageTaskDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
. . .
<managed-property>
<property-name>creditFormBackingBean</property-name>
<value>#{CreditFormBackingBean}</value>
</managed-property>
</managed-bean>

V-B-3-c - Les dialogs Alfresco correspondants

Nous n'avons pas de 'dialog' particulier à configurer pour ce backingbean. En effet les dialogs natifs configurés dans Alfresco (fichier web-client-config-dialog.xml) conviennent à notre projet.

De même, nous n'avons pas d'actions à configurer. Les actions par défaut qui se trouvent dans web-client-config-actions.xml conviennent à notre projet.

V-B-4 - Dialog Alfresco relatif à la suppression des spaces

V-B-4-a - Le backing bean

Le bean CustomDeleteSpaceDialog est une customisation du bean DeleteSpaceDialog d'Alfresco. Il permet de gérer la suppression des spaces. Notre customisation permet de :

- supprimer une pièce jointe donnée du dossier de crédit ;

- supprimer tout le dossier de crédit.

N.B. Il est à noter que l'opération de suppression n'est possible qu'au nœud CreditForm du workflow et donc effectuée par un membre du groupe ConseillerClient.

V-B-4-b - Le fichier face-config-custom.xml

<managed-bean>

<managed-bean-name>CustomDeleteSpaceDialog</managed-bean-name>
<managed-bean-class>com....space.CustomDeleteSpaceDialog</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
. . .
<managed-property>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
</managed-property>
</managed-bean>

V-B-4-c - Les dialogs Alfresco correspondants

Nous n'utilisons qu'un seul dialog Alfresco pour gérer la suppression du dossier de crédit et des pièces jointes.

<dialog name="remove_credit_record"
page="/jsp/extension/space/delete-space.jsp"
managed-bean="CustomDeleteSpaceDialog"
icon="/images/icons/view_content_large.gif" title="remove credit Record"
description="remove credit Record"/>

<!-- configuration des actions du dialog-- >
<action id="remove_piece">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>action_add_piece</label-id>
<image>/images/icons/remove_item.gif</image>
<action>dialog:remove_piece</action>
<action-listener>#{PieceBackingBean.initRemove}</action-listener>
<params>
<param name="id">#{actionContext.id}</param>
</params>
</action>

V-C - Développement de la webapp : les action-group Alfresco

Un action-goup est un groupe d'actions. Les action-group se configurent dans le fichier web-client-config-custom.xml.

Dans notre projet nous avons configuré les action-group suivants :

- workflow_action_menu ;

- add_credit_record_actions ;

- edit_credit_record_item_actions ;

- view_credit_record_item_actions ;

- edit_piece_content ;

- view_piece_content.

V-C-1 - L'action-group workflow_action_menu

Cet action-group permet de configurer les liens (link) de démarrage du workflow. Nous avons fait cette configuration parce que de base Alfresco ne permet de démarrer un workflow qu'à partir d'un document. Or dans notre projet nous souhaitons démarrons le workflow à partir d'un link avant d'ajouter les documents.

<action-group id="workflow_action_menu">
<action idref="start_workflow" />
</action-group>

V-C-2 - L'action-group add_credit_record_actions

Cet action-goup permet de créer et d'ajouter le dossier de crédit dans le workflow. Une fois le dossier de crédit ajouté, nous enlevons cette action-group pour empêcher les utilisateurs de dupliquer le dossier. C'est la raison pour laquelle l'action create_credit_record ne pouvait être mise dans le même action-group que les autres actions.

<action-group id="add_credit_record_actions">
<action idref="create_credit_record" />
</action-group>

V-C-3 - L'action-group edit_credit_record_item_actions

Permet de gérer la mise à jour, l'affichage en lecture seule ainsi que la suppression d'un dossier de crédit.

<action-group id="edit_credit_record_item_actions">
<action idref="update_credit_record" />
<action idref="view_credit_record" />
<action idref="remove_credit_record" />
</action-group>

V-C-4 - L'action-group view_credit_record_item_actions

Nous avons un action-group spécifique pour la l'affichage, car après avoir passé le nœud CreditForm du workflow, les utilisateurs ne doivent plus avoir la possibilité de modifier ou de supprimer le dossier de crédit.

<action-group id="view_credit_record_item_actions">
<action idref="view_credit_record" />
</action-group>

V-C-5 - L'action-group edit_piece_content

Cet action-group regroupe les actions d'affichage et d'édition des propriétés des pièces jointes du dossier de crédit.

<action-group id="edit_piece_content">
<action idref="view_content_properties" />
<action idref="edit_content_properties" />
</action-group>

V-C-6 - L'action-group view_piece_content

Cet action-group contient uniquement l'action d'affichage des propriétés des pièces jointes du dossier. C'est action-group est nécessaire dans la mesure où après le Node CreditForm du workflow, les utilisateurs n'ont plus le droit d'éditer les pièces jointes.

<action-group id="view_piece_content">
<action idref="view_content_properties" />
</action-group>

V-D - Développement de la webapp: les classes ActionHandler

Un ActionHandler est une classe dans laquelle on définit des méthodes qui sont invoquées dès qu'un évènement (node-enter-event, node-leave-event, transition-event, before-signal-event, after-signal-event, process-start-event, process-end-event, superstate-enter, superstate-leave, subprocess-created, subprocess-end, task-create-event, task-assign-event, task-start-event, task-end-event, timer-event) intervient sur un task-node.

Le design pattern utilisé ici est le design Observer.

Un ActionHandler doit toujours implémenter l'interface org.jbpm.graph.def.ActionHandler et c'est la méthode execute() qui est invoquée suite à un évènement.

V-D-1 - L'action handler DocumentStateActionHandler

Cet notre action handler de base et il est étendu par les autres actions handler du projet. Il permet de récupérer le nom du task-node en cours, ce qui nous permet de connaître la position du dossier de crédit dans le workflow.

nodeService.setProperty(
creditFormData.getCreditRecordData().getCreditRecordNodeRef(),
CreditRecordModel.PROP_STATEDOCUMENT,arg0.getNode().getName()
);

V-D-2 - L'action handler CreditFormActionHandler

Cet ActionHandler est exécuté au niveau du task-node CreditForm lors de l'évènement node-enter.

V-D-3 - L'action handler SimulationActionHandler

Cet ActionHandler est exécuté au niveau du node Simulation lors de l'évènement node-enter. Il appelle les services du back-end pour effectuer la simulation de la demande de crédit.

On met à jour le paramètre SIMULATION_DOCUMENT_STATE du workflow avec le résultat de la simulation.

arg0.setVariable(CreditConstant.SIMULATION_DOCUMENT_STATE,
KTCreditRecordUtil.simulationCreditRecord()
);

La variable 'document_state' a été déclarée dans le process definition du workflow.

<variable name="wfcm_statusDocument"
access="read"
mapped-name="wfcm_statusDocument">
</variable>

V-D-4 - L'action handler ResultSimulationActionHandler

Cet ActionHandler est exécuté au niveau du task-node ResultSimulation lors des évènements node-enter et node-leave.

Il met à jour le nombre de pièces jointes au niveau de l'interface de la tâche wcfm:resultSimulation.

Dans le code ci-dessous on parcourt les nœuds associés au dossier de crédit et ensuite on teste le type de chaque nœud :

NodeRef nodeRef = new NodeRef(Repository.getStoreRef(), id);

List<AssociationRef> assocRefs =
nodeService.getTargetAssocs(nodeRef,
RegexQNamePattern.MATCH_ALL);
DictionaryService dd =
Repository.getServiceRegistry(
FacesContext.getCurrentInstance()).getDictionaryService();

if(assocRefs != null){
for (AssociationRef associationRef : assocRefs) {
if(associationRef.getTargetRef() != null){
if(dd.isSubClass(
nodeService.getType(associationRef.getTargetRef()),
CreditRecordModel.PROP_SCANPAYSLIP))
{
pieceNumber++;

if(dd.isSubClass(
nodeService.getType(associationRef.getTargetRef()),
CreditRecordModel.PROP_SCANTAXSLIP)){

pieceNumber++;

...

arg0.setVariable(CreditConstant.SIMULATION_PIECE_NUMBER, pieceNumber.longValue());

La variable SIMULATION_PIECE_NUMBER a été déclarée dans le process definition du workflow.

<variable name="wfcm_piecesNumber"
access="read"
mapped-name="wfcm_piecesNumber">
</variable>

V-D-5 - L'action handler ApprovalCommitteActionHandler

Cet ActionHandler est exécuté au niveau du task-node ApprovalCommitte lors de l'évènement node-enter.

V-D-6 - L'action handler LegalServiceActionHandler

Cet ActionHandler est exécuté au niveau du task-node LegalService lors de l'évènement node-enter. Il permet de générer le contrat du client et de le joindre comme pièce au dossier de crédit.

La génération du contrat est faite avec JasperReport. Pour générer un Contrat de Crédit on :

- récupère les données du dossier de crédit dans le repository :

//Get NodeRef of Credit record
NodeRef creditFormNode = new NodeRef(Repository.getStoreRef(), id);

//init datat in Credit form Backing bean
creditRecordData.setupContent(id);

- génère le contrat via JasperReport :

//we generate Contrat with Jasper
generateContratWithJasperReport();

- sauvegarde le contrat :

//We save contrat
saveGenerateContrat(reportBytes,creditFormNode);

- ajoute enfin le contrat généré comme ressource du workflow :

//Set ressources
manageTask.AddItemToPackageItemToAdd(generateData.getNodeRef().toString());
manageTask.updateResources();

V-D-7 - L'action handler FinancialServiceActionHandler

Cet ActionHandler est exécuté au niveau du task-node FinancialService lors de l'évènement node-enter.

V-D-8 - L'action handler CreditContratActionHandler

Cet ActionHandler est exécuté au niveau du task-node CreditContract lors de l'évènement node-enter.

V-D-9 - L'action handler PaymentActionHandler

Cet ActionHandler est exécuté au niveau du task-node Payment lors de l'évènement node-enter.

V-D-10 - L'action handler ArchivingActionHandler

Cet ActionHandler est exécuté au niveau du task-node Archiving lors de l'évènement node-enter.

V-D-11 - L'action handler EndActionHandler

Cet ActionHandler est exécuté au niveau du end-state lors de l'évènement node-enter.

VI - Téléchargement du code source du projet

Le projet de cet article est disponible sur le lien suivant : projet Alfresco jBPM workflow.credit.

Koossery Technology est une entreprise spécialisée dans les développements de projets au forfait (.NET & Java J2ee) et dispose pour cela d'une cellule Architecture Technique & Outillages ainsi que d'une Usine Logicielle.

Koossery Technology dispose aussi d'un Centre de Services pour les développements GED à base d'Alfresco et workflow avancés à base de jBoss jBPM.

Tous nos remerciements au comité developpez.com.

Vos réactions par l'intermédiaire de ce fil : Commentez .