V. Implémentation de la solution dans un projet Maven2▲
Les principales étapes sont:
- Création du projet avec Maven2.
- Configuration du projet.
- JSF : création des BackingBean et des jsp associées.
- Création des Handler qui ont été déclarés dans le workflow (cf IIIIII).
V-1. Le projet Maven2▲
V-1-1. Structure du projet ▲
Nous avons mis en place un projet Maven2 multi-module :
Ci-dessous la structure du projet webapp (c'est notre projet 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-1-2. Les divers fichiers de configuration de notre webapp▲
Un des gros avantage avec Alfresco est que nous ne re-développons pas notre webapp de zero: 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-1-2-1. 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'appuit 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 configuration 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-1-2-2. 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-1-2-2-1. 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-1-2-2-2. 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-1-2-2-3. 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-1-2-2-4. 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-2V-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-1-2-2-5. 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-1-2-2-6. 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-1-2-3. Internationalisation ▲
Les divers fichiers d'internationalisation sont pris en compte via les configurations Spring custom-repository-context.xml et workflow-credit-context.xml.
V-1-2-4. Les configurations Spring▲
V-1-2-4-1. 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-1-2-4-2. 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-1-2-5. 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-2. 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.
V-2-1. 'Dialog' relatif à la création, modification et visualisation d'un dossier de crédit▲
V-2-1-1. 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-2-1-2. 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-2-1-3. 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-2-2. 'Dialog' relatif à l'upload de pièces jointes ▲
V-2-2-1. 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-2-2-2. 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-2-2-3. Les dialogs Alfresco correspondants▲
Nous avons les dialogues suivants :
- Ajouter la fiche de paye (add_piece_pay).
- Ajouter la fiche d'impôt (add_piece_tax).
- Ajouter le contrat scanné (add_scan_contrat).
- Ajouter la fiche de paye (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-2-3. Dialog Alfresco relatif aux tâches du workflow▲
V-2-3-1. 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-2-3-2. 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-2-3-3. 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-2-4. Dialog Alfresco relatif à la suppression des spaces▲
V-2-4-1. 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.
NB: il est à noter que l'opération de suppression n'est possible qu'au noeud CreditForm du workflow et donc effectuée par un membre du groupe ConseillerClient.
V-2-4-2. 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-2-4-3. 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-3. 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-3-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-3-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-3-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-3-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 noeud CreditForm du workflow, les utlisateurs 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-3-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-3-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 jointe.
<
action-group id=
"view_piece_content">
<
action idref=
"view_content_properties" />
<
/action-group>
V-4. 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 que 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-4-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-4-2. L'action handler CreditFormActionHandler▲
Cet ActionHandler est exécuté au niveau du task-node CreditForm lors de l'évènement node-enter.
V-4-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-4-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 noeuds associés au dossier de crédit et ensuite on teste le type de chaque noeud :
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-4-5. L'action handler ApprovalCommitteActionHandler▲
Cet ActionHandler est exécuté au niveau du task-node ApprovalCommitte lors de l'évènement node-enter.
V-4-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-4-7. L'action handler FinancialServiceActionHandler▲
Cet ActionHandler est exécuté au niveau du task-node FinancialService lors de l'évènement node-enter.
V-4-8. L'action handler CreditContratActionHandler▲
Cet ActionHandler est exécuté au niveau du task-node CreditContract lors de l'évènement node-enter.
V-4-9. L'action handler PaymentActionHandler▲
Cet ActionHandler est exécuté au niveau du task-node Payment lors de l'évènement node-enter.
V-4-10. L'action handler ArchivingActionHandler▲
Cet ActionHandler est exécuté au niveau du task-node Archiving lors de l'évènement node-enter.
V-4-11. L'action handler EndActionHandler▲
Cet ActionHandler est exécuté au niveau du end-state lors de l'évènement node-enter.