Tutoriel développement Alfresco : modélisation de contenu et utilisation de jasper report

| Landry KOUAM (Centre de Service Alfresco/jBPM, Koossery Technology) | Baké Jc. BAKENEGHE  (Software Coordinator, Koossery Technology) | landry05 |

Cet article traite d'un exemple de développement GED Alfresco : modélisation de contenu et utilisation de jasper report.
Il s'adresse aux développeurs Java de projet GED/ECM à base d'Alfresco.

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

- Titre : Tutoriel développement Alfresco : modélisation de contenu et utilisation de jasper report

- Auteurs : Landry KOUAM (Centre de Service Alfresco/jBPM, Koossery Technology), Baké Jc. BAKENEGHE  (Software Coordinator, Koossery Technology), landry05

- Parution : 24 juin 2009

- Mise à jour : 6 mars 2020

- Licence :

Sommaire

- I. INTRODUCTION

- II. ÉTUDE DE CAS : SPÉCIFICATIONS FONCTIONNELLES DE L'EXEMPLE

- III. MODÉLISATION DE CONTENU DANS ALFRESCO

- III-A. Modèle de données

- III-B. Modélisation du contenu Alfresco

- III-B-1. Petit rappel sur le dictionnaire de données Alfresco

- III-B-2. Modèle M2 de notre projet : productModel.xml

- III-B-3. Internationalisation I18N relative au modèle M2 (productModel.xml)

- III-B-4. Enregistrement du modèle M2 (productModel.xml) et des bundles d'internationalisation i18n

- IV. CONFIGURATION DU CLIENT WEB DANS ALFRESCO

- IV-A. Configuration du client web

- IV-A-1. Sous section de définition des actions

- IV-A-2. Sous-section de définition des menus

- IV-A-3. Section de définition du Dialog

- IV-B. Dialog Alfresco - Formulaire de saisie

- IV-B-1. Design de la JSP

- IV-B-2. Externalisation et internationalisation des labels de la JSP

- IV-B-3. Écriture du code du Bean Managé

- IV-B-4. Configuration JSF du Bean Managé

- V. UTILISATION DE JASPER REPORT

- V-A. Génération du document PDF avec Jasper Report et enregistrement

- V-A-1. Création du template jasper de la fiche du produit

- V-A-2. Compilation du template jasper report

- V-A-3. Utilisation du template dans le projet et génération du PDF

- VI. COMPILATION ET DÉPLOIEMENT DU PROJET

- VI-A. Import de l'extension dans le SDK Alfresco

- VI-B. Construction du WAR

- VI-C. Déploiement sur un Web Container

- VII. EXÉCUTION : CRÉATION, RECHERCHE FULL-TEXT, MODIFICATION, VERSIONNING

- VII-A. Création d'une fiche produit

- VII-B. Modification et versionnage d'une fiche produit

- VII-C. Historique des versions d'une fiche produit

- VII-D. Recherche d'une fiche produit : 'recherche full-text'

- VIII. TÉLÉCHARGEMENT CODE SOURCE DU PROJET

I - INTRODUCTION

Le Centre de Compétences AlfrescojBPM de Koossery Technology publie à travers cet article un tutoriel traitant :

- de la modélisation de contenus dans Alfresco ;
- de l'utilisation de Jasper Report pour la production de documents au format PDF qui sont par la suite stockés dans le Repository Alfresco ;
- enfin de l'archivage, de la recherche full-text, du versionning et de l'historisation des documents PDF stockés.

II - ÉTUDE DE CAS : SPÉCIFICATIONS FONCTIONNELLES DE L'EXEMPLE

Soit une entreprise qui souhaite archiver les fiches contenant des informations sur les produits dans un système de GED (gestion électronique de documents). Pour cela les étapes sont les suivantes :

- le système de GED doit présenter un formulaire de saisie des informations du produit ;

- une fiche du produit au format PDF est générée sur la base des informations saisies ;

- la fiche ci-dessus (format PDF) est enregistrée dans le système de GED ;

- le système de GED doit donner la possibilité de faire une recherche full-text d'une fiche produit, d'y effectuer des modifications et de l'enregistrer de nouveau. Le système de GED doit versionner la fiche produit et aussi permettre d'avoir un historique complet de cette fiche.

III - MODÉLISATION DE CONTENU DANS ALFRESCO

III-A - Modèle de données

La figure ci-dessous présente le modèle de données du projet. On distingue les entités 'Product' et 'Picture'.

Figure 1: modèle de données du projet

III-B - Modélisation du contenu Alfresco

III-B-1 - Petit rappel sur le dictionnaire de données Alfresco

Pour que les entités du modèle de données du paragraphe soient prises en compte et gérées sous forme de contenus dans Alfresco, il faut décrire ces entités à l'aide du dictionnaire de données Alfresco.

Le dictionnaire de données Alfresco est un ensemble de modèles de base (appelés modèles M1) qui permettent de décrire la structure des contenus à traiter.
Un modèle M1 contient la définition des types primitifs comme 'Double', 'Float', 'Integer', etc., ou des types complexes comme le type 'content' (type contenu pour contenir l'information sous forme binaire), 'folder' (pour les dossiers), 'person' (pour les personnes), etc.

Il existe plusieurs fichiers XML constituant le modèle M1. On peut citer :

- dictionaryModel.xml (types primitifs) ;
- contentModel.xml (types complexes) .

Pour avoir une vue plus complète sur le dictionnaire de données d'Alfresco, le Centre de Compétences AlfrescojBPM de Koossery Technology conseille la documentation ci-dessous :

1

http://wiki.alfresco.com/wiki/Data_Dictionary_Guide

III-B-2 - Modèle M2 de notre projet : productModel.xml

Les entités de notre projet vont être décrites sous forme de contenus dans un nouveau modèle dit modèle M2. Ce modèle M2 est construit en utilisant les types de données des modèles M1 (voir paragraphe).

Le modèle M2 de l'entité produit est défini dans le fichier productModel.xml dont le contenu est dans la figure ci-dessous :

Figure 2: Alfresco Content Model: productModel.xml

1<?xml version="1.0" encoding="UTF-8"?>
2
3<!-- Definition of new Model -->
4<model name="product:model" xmlns="http://www.alfresco.org/model/dictionary/1.0">
5
6   <!-- Optional meta-data about the model -->
7   <description>Custom Content Model</description>
8  <author>KOOSSERY TECHNOLOGY (Centre de Compétences Alfresco-jBPM)</author>
9   <version>1.0</version>
10
11   <!-- ici nos imports de modèles M1  -->
12   <imports>
13         <!-- Import Alfresco Dictionary Definitions -->
14      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
15      <!-- Import Alfresco Content Domain Model Definitions -->
16      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
17   </imports>
18
19<!-- ci-dessous notre modèle M2 pour ce projet  -->
20
21   <!-- on définit le namespace de notre modèle M2 -->
22   <namespaces>
23      <namespace uri="http://www.koossery-tech.com/model/product/1.0" prefix="product"/>
24   </namespaces>
25
26   <types>
27       <!-- The product type -->
28      <type name="product:product">
29           <title>Product</title>
30         <parent>cm:content</parent>
31         <properties>
32             <property name="product:name">
33               <title>Name</title>
34               <type>d:text</type>
35               <mandatory>true</mandatory>
36            </property>
37            <property name="product:description">
38               <title>Description</title>
39               <type>d:text</type>
40            </property>
41            <property name="product:ref">
42               <title>REF</title>
43               <type>d:text</type>
44               <mandatory>true</mandatory>
45            </property>
46            <property name="product:prize">
47               <title>Prize</title>
48               <type>d:float</type>
49               <mandatory>true</mandatory>
50            </property>
51            <property name="product:stock">
52               <title>Stock</title>
53               <type>d:int</type>
54            </property>
55         </properties>
56
57         <associations>
58             <!--  ci-dessous l'association qui lie le produit à ses images   -->
59             <association name="product:image">
60                 <target>
61                     <class>product:picture</class>
62                     <mandatory>false</mandatory>
63                     <many>false</many>
64                 </target>
65             </association>
66         </associations>
67
68         <!--  on greffe les aspects/comportements versionables et auditables  -->
69         <mandatory-aspects>
70             <aspect>cm:versionable</aspect>
71             <aspect>cm:auditable</aspect>
72         </mandatory-aspects>
73      </type>
74
75      <!-- The product image -->
76      <type name="product:picture">
77          <title>Picture</title>
78         <parent>cm:content</parent>
79         <properties>
80             <property name="product:pictureLegend">
81               <title>Legend</title>
82               <type>d:text</type>
83               <mandatory>false</mandatory>
84            </property>
85          </properties>
86      </type>
87
88    </types>
89
90</model>

Décrivons de bout en bout le contenu de ce fichier.

- Ligne 4 : le modèle est défini dans le corps de la balise « model ». L'attribut « name » représente le nom du modèle : ce nom doit être unique au sein de la plateforme Alfresco. Le nom du modèle ici est « product:model ». Remarquez qu'il est formé de deux mots séparés par un deux-points « : ». Le premier mot représente le préfixe du modèle. Le préfixe est un symbole de votre choix qui permet d'identifier le modèle une fois enregistré dans la plateforme. Ce préfixe doit être unique. Pour finir, on distingue l'URL du modèle de base du dictionnaire de données : http://www.alfresco.org/model/dictionary/1.0.

- Ligne 7 à ligne 9 : on distingue les sous-éléments de description d'auteur et de version du modèle.

- Ligne 12 à ligne 17 : la déclaration des imports des modèles de base M1. Tout modèle M2 est construit à partir d'éléments des modèles de base M1. Ici nous importons le modèle M1 (identifié par le préfixe 'd') des types primitifs et le modèle M1 (identifié par le préfixe 'cm') des types de contenu.

- Ligne 23 : on déclare le namespace de notre modèle que nous sommes en train d'écrire. Nous avons donné comme préfixe (qui doit être unique dans le système Alfresco) le mot 'product'. Nous avons donné comme uri l'URL 'http://www.koosseryech.com/model/product/1.0'

- Ligne 28 : définition du type de contenu 'product'.Ce type de contenu correspond à la modélisation de l'entity 'Product' du paragraphe. L'attribut 'name' du type de contenu doit être au format 'prefix : nom' où 'prefix' représente le préfixe de notre modèle et 'nom' représente le nom qu'on veut donner au type de contenu.
Chaque propriété de notre type de contenu est définie dans un sous élément « property ». On distingue pour une propriété les éléments suivants : son titre, son type, son caractère non obligatoire ou pas (« mandatory »).

- Ligne 57 à ligne 66 : on représente l'association entre un produit et son image. Cette association ici est représentée par la composition « child-association »: la destruction d'un produit entraîne la destruction de son image.

- Ligne 69 à ligne 72 : une autre partie très importante lors de la définition d'un type de contenu est la partie de la déclaration des aspects, représentée par le l'élément « mandatory-aspects ». Celui-ci permet de greffer un aspect générique (ou comportement générique). Dans notre exemple, deux aspects sont greffés au modèle : l'aspect de versioning et l'aspect d'audit du contenu.

- Ligne 76 à ligne 86 : définition du type de contenu « image ».

Les types de contenu ainsi définis vont représenter le contrat entre le client web et le Server Repository d'Alfresco pour ce qui concerne les manipulations sur le produit. Lorsque le client web va afficher le formulaire de saisie des informations d'un produit, les labels qui seront affichés seront les valeurs de l'élément « title » des propriétés de notre type de contenu 'product:product'. Comme dans toute application web les labels sont externalisés et définis dans des bundles d'internationalisation i18n. C'est l'objet du paragraphe.

III-B-3 - Internationalisation I18N relative au modèle M2 (productModel.xml)

Alfresco donne la possibilité d'externaliser les labels dans un fichier de bundle et de permettre ainsi leur internationalisation i18n. La saisie des informations concernant un produit se fera via le système de GED Alfresco. Pour cela il y aura différents écrans de saisie de fiche d'un produit. Ces écrans vont présenter des labels et des zones de saisies correspondant à toutes les propriétés d'un produit et de ses images.

Dans notre cas nous n'allons définir que les ressources pour les langues française (fr_FR) et anglaise (en_EN). La figure ci-dessous montre le contenu de la ressource fr_FR défini dans le fichier properties product-model_fr_FR.properties.

Figure 3: Ressource bundle fr_FR d'internationalisation des labels du modèle de contenu 'product:product'

# Display labels for Content Domain Model
product_model.description=Modèle de contenu de l'entité produit

product_model.type.product_product.title=Produit
product_model.type.product_product.description=Produit
product_model.type.product_picture.title=Photo
product_model.type.product_picture.description=Photo du produit

product_model.property.product_name.title=Nom
product_model.property.product_name.description=Nom du produit
product_model.property.product_description.title=Description
product_model.property.product_description.description=Description du produit
product_model.property.product_ref.title=Reférence
product_model.property.product_ref.description=Reférence du produit
product_model.property.product_prize.title=Prix
product_model.property.product_prize.description=Prix du produit
product_model.property.product_stock.title=Nombre en stock
product_model.property.product_stock.description=Nombre en stock

product_model.property.product_pictureLegend.title=Légende
product_model.property.product_pictureLegend.description=Légende de la photo

product_model.child-association.product_image.title=Image
product_model.child-association.product_image.description=Images du produit

III-B-4 - Enregistrement du modèle M2 (productModel.xml) et des bundles d'internationalisation i18n

L'enregistrement du modèle productModel.xml et des bundles d'internationalisation se fait à l'aide de Spring dans le fichier product-context.xml. La figure ci-dessous montre un extrait du fichier product-context.xml :

Figure 4: Fichier contexte Spring product-context.xml

<!-- ici on enregistre notre modèle  avec les bundles des labels -->
<bean id="productContent.dictionaryBootstrap" parent="dictionaryModelBootstrap"
depends-on="dictionaryBootstrap">
<property name="models">
<list>
<value>com/koossery/alfresco/tuto/model/productModel.xml</value>
</list>
</property>
<property name="labels">
<list>
<value>com/koossery/alfresco/tuto/model/product-model</value>
</list>
</property>
</bean>

Le modèle productModel.xml et ses bundles sont enregistrés dans le Repository via le bean 'productContent.dictionaryBootstrap'.

IV - CONFIGURATION DU CLIENT WEB DANS ALFRESCO

Une fois que toutes les opérations relatives à la définition du modèle de contenu de l'exemple sont terminées, l'opération suivante est la configuration du client web. Pour notre exemple il s'agit de :

- construire un formulaire permettant de saisir les informations sur les produits ;

- construire une action qui permettra à travers les menus d'ouvrir le formulaire de saisie pour la création d'un nouveau produit ;

- construire une autre action qui permettra de modifier les informations d'un produit.

IV-A - Configuration du client web

La saisie des informations sur les produits se fera à partir un client web.
Alfresco offre un mécanisme puissant permettant de construire des pages jsp par simple assemblage de composants. Nous allons voir comment construire notre page jsp et l'intégrer dans le client web de la plateforme Alfresco.

La première des choses consiste à configurer les composants de notre vue. Ce mécanisme d'Alfresco est réalisé dans un fichier XML de l'extension nommé conventionnellement web-client-config-custom.xml et placé dans un package alfresco.extension. La figure ci-dessous montre un extrait de ce fichier pour notre extension.

Figure 5: web-client-config-custom.xml

<config>
<actions>

<!-- action :créer une fiche  produit -->
<action id="create_product">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<label-id>create_product</label-id>
<image>/images/icons/add.gif</image>
<action-listener>#{SaveProductDialog.setupFlagCreate}</action-listener>
<action>dialog:save_product</action>
</action>

<!-- action :modifier une fiche  produit -->
<action id="update_product">
<permissions>
<permission allow="true">Write</permission>
</permissions>
<evaluator>com.koossery.web.action.evaluator.UpdateProductEvaluator</evaluator>
<label-id>update-product</label-id>
<image>/images/icons/update.gif</image>
<action-listener>#{SaveProductDialog.setupContentAction}</action-listener>
<action>dialog:save_product</action>
<params>
<param name="id">#{actionContext.id}</param>
</params>
</action>

<!-- ici on ajoute l'action 'créer produit' dans le groupe  'browse_create_menu'-->
<action-group id="browse_create_menu">
<action idref="create_product" />
</action-group>

<!-- ici on ajoute l'action 'créer produit' dans le groupe  'document_browse'-->
<action-group id="document_browse">
<action idref="update_product" />
</action-group>

</actions>
</config>

<!-- configuration du Dialog-->
<config>
<dialogs>
<dialog name="save_product" page="/jsp/extension/content/save-product-dialog.jsp"
managed-bean="SaveProductDialog"
icon="/images/icons/new_content_large.gif" title-id="save_product_dialog_title"
description-id="save_product_description_dialog">
</dialog>
</dialogs>
</config>

Le fichier web-client-config-custom.xml de la figure 5 contient deux grandes sections de configuration : les actions (une action est en quelque sorte une commande avec son menu), et les dialog (un dialog est une page jsp) de création/modification des fiches de produit.
Dans les paragraphes qui suivent, nous allons voir les configurations des actions et des dialog en détail.

IV-A-1 - Sous section de définition des actions

Dans le fichier web-client-config-custom.xml de la figure 5, les actions sont définies dans les sous-éléments « action » de l'élément « actions ». Nous avons défini deux actions : l'action de création d'une fiche produit (cette action est identifiée par l'id « create_product ») et l'action de modification d'une fiche produit (d'id « update_product »).
La structure d'un élément « action » est la suivante$:

- permissions : permet de définir les permissions que l'utilisateur doit avoir pour exécuter l'action. Pour modifier une fiche, l'utilisateur doit avoir une permission 'write' ;

- evaluator : permet d'évaluer certaines conditions indispensables à l'exécution de l'action. L'evaluator peut être spécifié via une classe Java. La classe évaluator ('com.koossery.web.action.evaluator.UpdateProductEvaluator') de l'action de modification vérifie si le contenu courant qu'on veut modifier est un contenu de type « product:product ». Sinon l'action ne s'exécute pas ;

- label-id : représente l'id de la traduction du label de l'action qui sera affiché comme lien cliquable ;

- image : c'est l'image qui sera affichée comme icône de l'action ;

- action-listener : on peut configurer un listener sur l'action. Cela permet de monitorer l'évènement émis au moment de l'exécution de l'action et d'effectuer des traitements désirés (exemple= charger certaines informations pouvant être utiles à l'exécution de l'action).

- action : il s'agit de l'action (en quelque sorte la commande) à exécuter. Il peut s'agir d'afficher un Dialog (formulaire) ou un Wizard. Dans l'un ou l'autre des cas, l'identification conventionnelle Alfresco du composant doit être spécifiée. Dans notre cas les actions lancent le formulaire en mode création ou modification et cela est spécifié par 'dialog:save_product'. Le mot « dialog » signifie au noyau Alfresco que l'on veut ouvrir un Dialog. « save_product » est l'id du dialog qu'on veut ouvrir. Voir paragraphe pour la configuration des Dialogs Alfresco.

- params : définit les paramètres du listener. Dans notre cas l'id du nœud courant est passé au listener comme paramètre. Avec cette id le listener va retrouver le nœud du contenu à modifier et placer le dialog en mode modification.

IV-A-2 - Sous-section de définition des menus

L'intégration des liens des actions dans le client web se fait dans les menus. Le client web possède un certain nombre de menus listant des actions exécutables par simple clic sur leur lien. L'ajout d'une action sur un menu se fait à partir du action-group de ce menu. Un action-group est un groupe d'actions présenté dans le client web sous forme de menu déroulant dont les items sont les actions du groupe. Dans notre cas nous devons ajouter nos deux actions dans des action-group qui vont permettre de les rendre accessibles dans le client web.

Pour ajouter une action dans un menu, il suffit d'ajouter un sous-élément <action/> dans le groupe. Nous voulons que l'action de création des fiches de produit soit accessible à partir du menu « Créer » du client web (voir figure 6).

Figure 6: Menu 'Créer'

Dans la plateforme Alfresco, l'action groupe du menu « créer » est identifiée par l'id « browse_create_menu ». Nous ajoutons donc l'item « create_product » à ce groupe.

Figure 7: Configuration de l'item menu 'create_product'

<!-- Actions Menu for Create in Browse screen -->
<action-group id="browse_create_menu">
<action idref="create_product" />
</action-group>

D'autre part nous voulons que l'action de modification d'une fiche produit soit disponible dans le menu contextuel du nœud de ce document. La zone entourée en rouge de la figure 8 ci-dessous montre le menu contextuel d'une fiche produit.

Figure 8 : Menu contextuel d'une fiche produit

Dans la plateforme Alfresco, l'action groupe du menu contextuel des documents est identifiée par l'id « document_browse ». Nous ajoutons donc l'item « update_product » à ce groupe.

Figure 9: Configuration de l'item menu 'update_product'

<!-- Actions for a document in the Browse screen -->
<action-group id="document_browse">
<action idref="update_product" />
</action-group>

IV-A-3 - Section de définition du Dialog

La configuration d'un Dialog Alfresco est simple. Elle s'effectue dans un sous-élément « dialog » de l'élément « dialogs ». La description est la suivante :

- name : définit le nom unique de ce dialog. Il est utilisé pour identifier le dialog ;

- page : définit la page jsp du Dialog ;

- managed-bean : définit l'id du backing-bean (au sens JSF) associé ;

- icon : définit le chemin de l'icône qui sera affichée dans la vue conteneur du Dialog ;

- title-id : définit l'id de la traduction dans la ressource I18N du titre de la page du Dialog ;

- description-id : définit l'id de la traduction dans la ressource I18N de la description qui sera affichée pour ce dialog.

IV-B - Dialog Alfresco - Formulaire de saisie

IV-B-1 - Design de la JSP

Il s'agit de construire la page jsp qui va présenter le formulaire de saisie des informations du nouveau produit en cours de création. Cette page est construite par assemblage de JSF « UI Components ».
La jsp du Dialog est create-product-dialog.jsp. Elle est assez simple et nous invitons le lecteur à l'examiner (voir le code source du projet au chapitre).

IV-B-2 - Externalisation et internationalisation des labels de la JSP

En restant conforme avec les conventions d'Alfresco, les labels présents dans les pages jsp sont externalisés i18n dans le bundle 'customcontent-webclient'.

Figure 10: Ressource i18N fr_FR des labels de la page create-product-dialog.jsp

# Create New product Dialog
save_product_title_dialog=Création/Modificaiton d'un produit
save_product_description_dialog=Saisir les informations du produit

# Actions Labels
create_product=Nouveau Produit
update-product=Modifier le produit

# General
new_product=Nouveau Produit
name=Nom du Produit
description=Description
reference=Reférence
prize=Prix Unitaire
stock=Nombre en Stock
legend=Légende de la photo
photo=Photo du produit

IV-B-3 - Écriture du code du Bean Managé

Le Bean Managé d'un Dialog doit être une classe de type BaseDialogBean. Les méthodes suivantes doivent être implémentées :

- init( Map ) : elle permet au développeur de réaliser les opérations d'initiation du Dialog comme l'instanciation des DTO, la recherche des données à modifier, etc. ;

- String finishImpl(FacesContext, String) : cette méthode est exécutée lorsque l'utilisateur a fini ses saisies et qu'il enregistre la fiche (clic sur le bouton 'Terminer') de notre Dialog. Elle est utilisée pour enregistrer les informations dans le Repository Alfresco.

IV-B-4 - Configuration JSF du Bean Managé

La configuration JSF du Bean managé de l'extension se fait dans le fichier faces-config-custom.xml. C'est une convention Alfresco du mécanisme d'extension.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>

<managed-bean>
<managed-bean-name>SaveProductDialog</managed-bean-name>
<managed-bean-class>
com.koossery.alfresco.web.bean.content.SaveProductDialog
</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>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-bean>

</faces-config>

Il s'agit de la configuration JSF du Bean Managé SaveProductDialog qui réalise la création et la modification d'une fiche produit. Il est de scope session et on voit que les services du Repository sont injectés.

V - UTILISATION DE JASPER REPORT

V-A - Génération du document PDF avec Jasper Report et enregistrement

Pour la génération de la fiche du produit au format PDF, cela est fait avec le standard Jasper Report avec son outil iReport. Avant de présenter l'utilisation de l'API Jasper dans le projet pour la génération du PDF, nous allons d'abord brièvement faire un rappel de l'utilisation de iReport pour la construction du template.

V-A-1 - Création du template jasper de la fiche du produit

Dans l'interface d'iReport nous créons un nouveau rapport vierge et nous déplions les zones : title, detail et pageFooter.

Dans la zone title représentant le titre et le logo du document qui sera produit, nous allons placer un composant image et des zones de textes statiques.

Lors de la génération du rapport, le moteur doit prendre en entrée un objet de type InputStream contenant les binaires de l'image. Les Stream de l'image seront passés au le moteur Jasper Report à travers le paramètre : PRODUCT_REPORT_KOOSSERY_LOGO de type java.io.InputStream. Les valeurs des zones de textes statiques sont directement saisies (voir la figure ci-dessous).

Dans la zone detail nous allons placer un composant image pour le positionnement de l'image du produit et des zones d'entrée de textes pour les informations du produit.
Il a aussi cinq zones de textes statiques affichant les labels du nom du produit, la description du produit, la référence du produit, le prix unitaire et le stock. Les valeurs sont passées au travers des paramètres :
- PRODUCT_REPORT_NAME de type java.lang.String ;
- PRODUCT_REPORT_PRIZE de type java.lang.Float ;
- PRODUCT_REPORT_REFERENCE de type java.lang.String ;
- PRODUCT_REPORT_STOCK de type java.lang.Integer ;
- PRODUCT_REPORT_DESCRIPTION de type java.lang.String.
- Les Stream de l'image sont passés à partir du paramètre PRODUCT_REPORT_IMAGE de type java.io.InputStream.

Dans la zone pageFooter nous allons placer des zones de textes statiques.

Figure 12 : Création du fichier jasper avec iReport 1.3.3

Pour avoir des notions approfondies sur la création des rapports avec Jasper Report, le Centre de Compétences AlfrescojBPM de Koossery Technology conseille les nombreuses documentations du site developpez.com, dans la rubrique 'Java'. Quelques exemples de tutoriels :

1

Génération de rapport avec Jasper Report  par Eric Reboisson (Site Web)

2

Initiation à JasperReports - iReport  par Jean-Philippe Guilloux (Site Web)

V-A-2 - Compilation du template jasper report

La compilation du template se fait dans l'outil iReport à partir du menu Créer -> Compiler. Nous avons compilé et produit le fichier Product.jasper.

V-A-3 - Utilisation du template dans le projet et génération du PDF

L'utilisation du template Product.jasper dans le projet pour la génération du PDF de la fiche produit se fait dans la méthode String finishImpl(FacesContext arg0, String arg1) du backing bean. Nous allons présenter dans les détails.

Tout d'abord les labels des paramètres déclarés dans le template, les noms doivent être identiques aux noms des paramètres déclarés dans le template :

/* --------------- Report Parameters  --------------- */
private  final String PRODUCT_REPORT_DESCRIPTION = "PRODUCT_REPORT_DESCRIPTION";
private  final String PRODUCT_REPORT_IMAGE = "PRODUCT_REPORT_IMAGE";
private  final String PRODUCT_REPORT_KOOSSERY_LOGO = "PRODUCT_REPORT_KOOSSERY_LOGO";
private  final String PRODUCT_REPORT_NAME = "PRODUCT_REPORT_NAME";
private  final String PRODUCT_REPORT_PRIZE = "PRODUCT_REPORT_PRIZE";
private  final String PRODUCT_REPORT_REFERENCE = "PRODUCT_REPORT_REFERENCE";
private  final String PRODUCT_REPORT_STOCK = "PRODUCT_REPORT_STOCK";

Puis les images et le fichier jasper du template :

/* --------------- JASPER REPORT FILE AND RESSOURCES  --------------- */
private ClassPathResource JASPER_REPORT_CONTEXT_PATH=
new ClassPathResource("/jasperreport/Product.jasper");

private ClassPathResource JASPER_REPORT_KOOSSERY_LOGO_PATH=
new ClassPathResource("/images/logo/logo_koossery.jpg");

En dernier le chargement des données dans le template et la production du PDF :

// - Parameters to send to the report
Map parameters = new HashMap();
/* Product Report */
parameters.put(PRODUCT_REPORT_DESCRIPTION, this.productData.getDescription());
parameters.put(PRODUCT_REPORT_IMAGE, this.productData.getPhotoInputStream());
parameters.put(PRODUCT_REPORT_KOOSSERY_LOGO,
new FileInputStream(JASPER_REPORT_KOOSSERY_LOGO_PATH.getFile()));
parameters.put(PRODUCT_REPORT_NAME, this.productData.getName());
parameters.put(PRODUCT_REPORT_PRIZE, this.productData.getPrize());
parameters.put(PRODUCT_REPORT_REFERENCE, this.productData.getRef());
parameters.put(PRODUCT_REPORT_STOCK, this.productData.getStock());

File file = JASPER_REPORT_CONTEXT_PATH.getFile();

// - Execution
JasperPrint jasperPrint = JasperFillManager.fillReport(new FileInputStream(file),
parameters,new JREmptyDataSource());

// - Create report as PDF FIle
this.reportBytes = JasperExportManager.exportReportToPdf(jasperPrint);

VI - COMPILATION ET DÉPLOIEMENT DU PROJET

Le projet est une extension Alfresco et a été développé dans le SDK Alfresco.
Le Centre de Compétences AlfrescojBPM de Koossery Technology recommande fortement aux développeurs de travailler dans un SDK Alfresco.
La procédure à suivre pour installer un environnement de développement (SDK) Alfresco est décrite dans le Le Guide du développeur Alfresco.

VI-A - Import de l'extension dans le SDK Alfresco

Le SDK Alfresco est l'ensemble des bibliothèques Alfresco nécessaires aux développements d'extensions. Nous avons choisi Eclipse comme EDI pour monter notre environnement SDK Alfresco.
Il est indispensable d'ajouter le projet AlfrescoEmbedded du SDK dans les dépendances de l'extension.
La figure ci-dessous montre l'arborescence du projet.

Figure 15 : Arborescence du projet

VI-B - Construction du WAR

La compilation est effectuée avec l'outil Ant. Nous devons personnaliser le fichier build.xml en remplacer le chemin du WAR Alfresco par le notre.

Figure 16 : Personnalisation du fichier Ant

Nous devons télécharger les bibliothèques itext-1.3.1.jar et jasperreports-1.3.3.jar et les placer dans WEB-INF/lib.
Le Target ANT à choisir est le Target « integrate-extension ».

VI-C - Déploiement sur un Web Container

Avant de déployer notre .war il faut mettre à jour le fichier de propriétés repository.properties afin d'indiquer le répertoire pour le stockage du contenu ainsi que les paramètres de connexion à la base de données utilisée par Alfresco.
Après avoir démarré le Web Container, lançons notre navigateur et tapons l'URL http://@IP:PORT/context-root (exemple: http://localhost:8080/archiveproduit) et connectons-nous.

Figure 19 : Interface de connexion

VII - EXÉCUTION : CRÉATION, RECHERCHE FULL-TEXT, MODIFICATION, VERSIONNING

VII-A - Création d'une fiche produit

Allons dans notre page d'accueil (panneau de gauche de la page d'accueil) et plaçons-nous dans le dossier dédié au stockage du contenu des produits pour créer un nouveau produit. Puis allons dans le groupe de menu 'Créer' et cliquons 'Nouveau Produit'

La page de création des produits apparaît :

Après avoir saisi les informations sur un produit, appuyez sur le bouton 'OK' pour l'enregistrement. Les informations vont être traitées par Jasper report et un document PDF va être généré et stocké dans le dossier consacré aux fiches produits. La figure ci-dessous montre les fiches de produits créées dans le dossier « Produits ».

Figure 22: Fiches produits archivées

Vous pouvez consulter les documents en ligne en cliquant directement dessus. La figure ci-dessous montre un document PDF d'un produit :

Figure 23: Fiche produit

VII-B - Modification et versionnage d'une fiche produit

Pour modifier une fiche de produit, il suffit de cliquer sur l'icône de modification de la fiche du menu contextuel du nœud représentant le document. Pour enregistrer vos modifications, cliquez sur le bouton OK du Dialog de modification. Du fait que nous avons pris le soin de greffer l'aspect 'versionnable' sur le type de contenu 'product:product', le système de GED Alfresco va créer une nouvelle version du document.

VII-C - Historique des versions d'une fiche produit

Pour voir les versions d'une fiche produit, il suffit d'afficher les détails du document (cliquez sur « visualiser les détails » dans le menu contextuel du document) et rendez-vous à la section « historique des versions ». Vous pouvez ainsi télécharger une version antérieure ou revenir sur elle.

Figure 24: Historique des versions d'une fiche produit

VII-D - Recherche d'une fiche produit : 'recherche full-text'

La plateforme Alfresco fournit un composant UI qui permet de faire la recherche full-text d'un document. La recherche se fait en s'appuyant sur le contenu et sur les propriétés. Le composant est configuré dans le fichier de configuration du client web à partir de l'élément « advanced-search ». La figure ci-dessous montre la configuration du composant de recherche pour la recherche full-text d'un document de type « product:product ».

<config evaluator="string-compare" condition="Advanced Search">
<advanced-search>
<content-types>
<type name="product:product"/>
</content-types>
<custom-properties>
<meta-data type="product:product" property="product:name" />
<meta-data type="product:product" property="product:description" />
<meta-data type="product:product" property="product:ref" />
<meta-data type="product:product" property="product:prize" />
<meta-data type="product:product" property="product:stock" />
</custom-properties>
</advanced-search>
</config>

Nous pouvons remarquer que nous avons spécifié à travers l'élément « content-types » le type de l'entité des produits. Ceci permet de spécifier à la plateforme que la recherche doit être faite sur les documents de ce type.

Dans la configuration du composant search, nous avons spécifié que la recherche d'une fiche produit peut se faire sur : le titre, la description, le prix, le stock et la référence.

En plus de ces critères, Alfresco permet aussi par défaut de rechercher un contenu en se basant sur l'auteur, la date de modification, le type de dossier, le type de contenu et le format de contenu.
La figure ci-dessous montre un exemple de recherche d'une fiche produit contenant le mot « fleur ».

Figure 25: Recherche avancée

Nous saisissons le mot « fleur » dans la description et clic sur le bouton 'rechercher'. La figure ci-dessous affiche le résultat :

VIII - TÉLÉCHARGEMENT CODE SOURCE DU PROJET

Le code source du projet est téléchargeable ici : zip du projet

Tous les remerciements au comité de relecture developpez.com.