Sep 5, 2016 5:37:13 PM Isa Isa avatar   942    

Réalisation d'un batch avec Spring Batch

Introduction

Des applications ont besoin de synchroniser des données depuis d'autres applications. En général, ces traitements sont effectués la nuit par des Batchs. Lutèce propose l'utilisation de Spring Batch afin de réaliser ces traitements.

Attention : Spring Batch n'est pas intégré dans le coeur de Lutèce. Il s'agit d'aider au développement d'une application externe dédié à la synchronisation de ces données.

Spring Batch

Spring Batch est un framework dédié aux batchs. Il propose des fonctionnalités communes aux batchs :

  • Lecture depuis différentes sources de données
  • Ecriture sur différentes cible
  • Gestion d'un traitement paginé
  • Gestion des transactions
  • Gestion des erreurs
  • Ordonnancement des étapes du batch...

Développement d'un batch

Pom parent pour les batch

Lutèce préconise l'utilisation d'un pom parent pour les batch :

<parent>
		<artifactId>batch-parent</artifactId>
		<groupId>fr.paris.lutece.batches</groupId>
		<version>1.0.0</version>
	</parent>

Ce pom parent a pour but de :

  • Récupérer les dépendances Spring batch,
  • Récupérer la dépendance au driver MySQL,
  • Récupérer les dépendances JUnit, Log4J, Apache Commons...
  • Récupérer Jalopy afin de respecter facilement les règles de développement Lutèce pour la mise en forme du code.
  • Il préconfigure les options de compilation (version de Java)
  • Il configure le repository de déploiement.

Ecriture du batch

Les exemples ci-dessous sont basés sur le batch-ivoire [1] De la documentation complémentaire est disponible chez Spring [2]

pom.xml

Ci-dessous un exemple de (les dépendances fr.paris.lutece.batches.* sont décrites plus loin dans ce document) :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <parent>
       <artifactId>batch-parent</artifactId>
       <groupId>fr.paris.lutece.batches</groupId>
       <version>1.0.0</version>
   </parent>

   <modelVersion>4.0.0</modelVersion>
   <groupId>fr.paris.lutece.batches</groupId>
   <artifactId>batch-ivoire</artifactId>
   <version>1.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
   <name>Batch Ivoire</name>
   <description>
       <![CDATA[Synchronize the Ivoire application states with PASU application workflow actions.]]>
   </description>

   <repositories>
       <repository>
           <id>lutece</id>
           <name>luteceRepository</name>
           <url>http://dev.lutece.paris.fr/maven_repository</url>
           <snapshots>
               <enabled>false</enabled>
           </snapshots>
       </repository>
   </repositories>

   <properties>
       <json.version>2.4</json.version>
       <componentName>batch-ivoire</componentName>
       <jiraProjectName>BATCHIVOIRE</jiraProjectName>
       <jiraComponentId>10637</jiraComponentId>
   </properties>

   <dependencies>
       <dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-httpaccess</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>
       <dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-signrequest</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>
       <dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-logger</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>
       <dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-notification</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>
       <dependency>
           <groupId>net.sf.json-lib</groupId>
           <artifactId>json-lib</artifactId>
           <version>${json.version}</version>
           <classifier>jdk15</classifier>
       </dependency>
   </dependencies>

   <build>
       <plugins>
           <plugin>
               <artifactId>maven-assembly-plugin</artifactId>
               <configuration>
                   <finalName>
                       ${pom.artifactId}-${project.version}
                   </finalName>
                   <descriptors>
                       <descriptor>
                           src/assembly/src.xml
                       </descriptor>
                   </descriptors>
               </configuration>
               <executions>
                   <execution>
                       <id>make-assembly</id>
                       <phase>package</phase> 
                       <goals>
                           <goal>single</goal>
                       </goals>
                   </execution>
               </executions>
           </plugin>
       </plugins>
   </build>

   <scm>
       <connection>scm:svn:http://dev.lutece.paris.fr/svn/lutece/portal/trunk/batches/batch-ivoire</connection>
       <developerConnection>scm:svn:https://dev.lutece.paris.fr/svn/lutece/portal/trunk/batches/batch-ivoire</developerConnection>
       <url>http://dev.lutece.paris.fr/viewvc/portal/trunk/batches/batch-ivoire</url>
   </scm>

</project>

Principes généraux

  • Le lancement d'un batch consiste au lancement d'un ou plusieurs Jobs (tâches réalisées par le batch).
  • Le JobLauncher permet de lancer un Job.
  • Un Job est composé de plusieurs Step, correspondant au étapes de la Job.
  • Les ItemReader permettent la lecture d'un flux (exemple : un fichier)
  • De nombreuses classes utilitaires permettent par exemple la lecture de fichier avec séparateur, ou la lecture en base...
  • Les ItemWriter permettent l'écriture d'un flux (exemple : un fichier)
  • Les ItemProcessors permettent de transformer un flux d'un type à un autre (exemple : l'objet lu à partir du fichier vers un autre type d'objet métier)
  • Des Listeners permettent d'écouter les évènements à chaque niveau (step, reader, writer, job...)

Structure du projet

  • src
  • main
  • assembly : descripteur pour le packaging du batch
  • bin : scripts de lancement du batch
  • java : les sources Java
  • logs
  • resources : les ressources - contexte Spring, loggers, propriétés de l'application
  • tmp
  • test : répertoires utilisés pour les tests
  • pom.xml

Contexte Spring

L'ensemble des classes à implémenter doivent être référencées dans le context Spring de l'application. Il doit contenir le header suivant :

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:sb="http://www.springframework.org/schema/batch"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:jdbc="http://www.springframework.org/schema/jdbc"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:p="http://www.springframework.org/schema/p"
   xsi:schemaLocation="
       http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
       http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

Afin d'externaliserles propriétés, il faut utiliser un property-placeholder :

<context:property-placeholder location="classpath:batch_ivoire.properties" />

Il peut également être utile de déclarer la configuration par annotation :

<context:annotation-config />

Assembly

Le dossier assembly contient un fichier src.xml décrivant le packaging du batch.

<assembly>
   <id/>
   <formats>
       <format>tar.gz</format>
   </formats>
   <fileSets>
       <fileSet>
           <directory>target</directory>
           <outputDirectory>lib</outputDirectory>
           <includes>
               <include>batch-ivoire*.jar</include>
           </includes>
       </fileSet>
       <fileSet>
           <directory>src/bin</directory>
           <outputDirectory>bin</outputDirectory>
       </fileSet>
       <fileSet>
           <directory>src/conf</directory>
           <outputDirectory>conf</outputDirectory>
       </fileSet>
       <fileSet>
           <directory>src/tmp</directory>
           <outputDirectory>tmp</outputDirectory>
       </fileSet>    
       <fileSet>
           <directory>src/main/resources</directory>
           <outputDirectory>conf</outputDirectory>
           <includes>
               <include>*.properties</include>
           </includes>            
       </fileSet>        
       <fileSet>
           <directory>src/lib-ext</directory>
           <outputDirectory>lib-ext</outputDirectory>        
       </fileSet>
       <fileSet>
           <directory>src/logs</directory>
           <outputDirectory>logs</outputDirectory>
       </fileSet>
   </fileSets>
   <dependencySets>
       <dependencySet>
             <outputDirectory>/lib-ext</outputDirectory>
             <excludes>
               <exclude>batch-ivoire*.jar</exclude>
             </excludes>
       </dependencySet>
   </dependencySets>
</assembly>

Réalisation

JobLauncher

La surcharge d'un SimpleJobLauncher permet d'effectuer des traitements en cas d'erreur du Job. L'interface JobExecutionListener permet d'effectuer des traitement pre et post Job.

Job

Un Job peut être assimilé à une tâche réalisée par le batch. Un SimpleJob permet d'exécuter séquentiellement les Step. Exemple de définition d'un Job (simpleJob peut être utilisé pour plusieurs jobs) :

<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob" abstract="true"
    p:jobRepository-ref="jobRepository"
    p:restartable="false" />
<sb:job id="job" parent="simpleJob">
    <sb:step id="executeActionStep" parent="simpleStep">
        <sb:tasklet>
            <sb:chunk reader="executeActionReader" processor="executeActionProcessor" writer="executeActionWriter" 
                     commit-interval="${job.commit.interval}" />
         </sb:tasklet>
    </sb:step>
</sb:job>

Step

Un step définit un reader, un processor, un writer.

Reader

Un reader permet de lire une source de données. Différentes implémentations permettent de gérer facilement les accès Fichiers, JDBC, Hibernate, JPA... Exemple de reader basé sur la lecture de fichier :

<bean id="executeActionReader" class="fr.paris.lutece.batches.ivoire.job.IvoireItemReader">
       <property name="resource" value="file:${ivoire.file.path}" />
       <property name="file" value="file:${ivoire.file.path}" />
       <property name="lineMapper">
           <bean class="fr.paris.lutece.batches.ivoire.job.internal.IvoireLineMapper">
               <property name="lineTokenizer">
                   <bean class="fr.paris.lutece.batches.ivoire.util.transform.LengthLineTokenizer"
                       p:names="idIvoire,idFolder,processType,idDemandDemat,idMerchantAccount,ivoireCode,labelIvoireCode,dateFinalVisa,inspectorLastNameFirstName,inspectorPhoneNumber"
                       p:listLengthDelimiters="11,13,11,20,50,3,100,19,60,14" 
                       p:strict="false" />
               </property>
               <property name="fieldSetMapper">
                   <bean class="fr.paris.lutece.batches.ivoire.job.internal.IvoireFieldSetMapper" />
               </property>
           </bean>
       </property>
   </bean>

L'interface ItemReadListener permet de gérer les erreurs de lecture, et des pre/post traitement.

Writer

ItemWriter est l'interface qui définit l'écriture des données. Des implémentations facilitent cette écriture. L'interface ItemWriteListener permet de gérer les erreurs de d'écriture, et des pre/post traitement.

Lancement du batch

Il faut utiliser le CommandLineJobRunner de Spring, et initialiser le classpath, l'emplacement des logs, JAVA_OPTS...

$JAVA -cp $TMP_CP $JAVA_OPTS -Dproducts.home=$PRODUCTS_HOME -Dlogs.home=$PRODUCTS_HOME/logs org.springframework.batch.core.launch.support.CommandLineJobRunner batch_ivoire_context.xml job >> $PRODUCTS_HOME/logs/batch-ivoire.out 2>&1

Libraries

Lutèce propose plusieurs libraries pouvant se montrer utiles dans le développement d'un batch

batch-library-signrequest

Ce librairie permet de signer des liens.

Déclaration

<dependency>     
	<groupId>fr.paris.lutece.batches</groupId>
	<artifactId>batch-library-signrequest</artifactId>
	<version>1.0.0</version>
	</dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch le bean correspondant au request authenticator de la manière suivante :

<bean id="hashService" class="fr.paris.lutece.batches.util.signrequest.security.Sha1HashService" />
<bean id="requestAuthenticator" class="fr.paris.lutece.batches.util.signrequest.HeaderHashAuthenticator"
        p:hashService-ref="hashService"
        p:privateKey="${workflow.ws.rest.privateKey}" />

Il faut églamenent déclarer la clé de hash de la manière suivante :

workflow.ws.rest.privateKey=MyPrivateKey

Utilisation

@Autowired
private RequestAuthenticator _requestAuthenticator;

batch-library-httpaccess

Cette library permet de se connecter en HTTP à une application distante, et supporte la signature des requêtes.

Déclaration

<dependency>
   <groupId>fr.paris.lutece.batches</groupId>
   <artifactId>batch-library-httpaccess</artifactId>
   <version>1.0.0</version>
</dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch le bean correspondant au httpaccess de la manière suivante :

<bean id="httpAccess" class="fr.paris.lutece.batches.util.httpaccess.HttpAccess"
       p:proxyHost="${httpAccess.proxyHost}"
       p:proxyPort="${httpAccess.proxyPort}"
       p:proxyUserName="${httpAccess.proxyUserName}"
       p:proxyPassword="${httpAccess.proxyPassword}"
       p:hostName="${httpaccess.hostName}"
       p:domainName="${httpAccess.domainName}"
       p:realm="${httpaccess.realm}"
       p:noProxyFor="${httpAccess.noProxyFor}"
       p:contentCharset="${httpAccess.contentCharset}" />

Et avoir dans le fichier de properties du batch :

################################################################
## Proxy settings

httpAccess.proxyHost=
httpAccess.proxyPort=
httpAccess.proxyUserName=
httpAccess.proxyPassword=
# computer name
httpaccess.hostName=
# domain name
httpAccess.domainName=
httpaccess.realm=
httpAccess.noProxyFor=127.0.0.1,localhost,*mdp
# Content charset - optionnal
httpAccess.contentCharset=UTF-8

Utilisation

@Autowired
private HttpAccess _httpAccess;

batch-library-logger

Cette library fournit des faciliter le logging, avec 3 loggers.

Déclaration

<dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-logger</artifactId>
           <version>1.0.0</version>
       </dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch le bean correspondant au logger choisi (cf. ci-dessous) de la manière suivante :

<bean id="logger" class="<classLogger>" scope="singleton"
       p:loggerInfo="<nomLoggerInfo>"
       p:loggerDebug="<nomLoggerDebug>"
       p:loggerError="<nomLoggerError>"
       p:appenderInfo="<nomAppenderInfo>"
       p:appenderDebug="<nomAppenderDebug>"
       p:appenderError="<nomAppenderError>"
/>

Il faut ensuite configurer le fichier log4j.properties (ou log4j.xml) de façon classique.

Utilisation

SimpleLogger : Permet de loguer simplement dans le logger log4j. SimpleBatchLogger : En plus de loguer dans le logger log4j, il va stocker les erreurs sous forme de String et les ajouter dans une liste qui peut être récupérer en appelant la méthode getErrors( ). SimpleErrorListBatchLogger : C'est la même chose que le SimpleBatchLogger, excepté qu'il stocke les erreurs dans un objet implémentant l'interface IError. AbstractErrorMapBatchLogger : C'est une classe abstraite permettant de stocker les erreurs dans une map (utilisé par exemple pour une gestion d'erreur par ligne).

batch-library-notification

Cette library permet des notifications par mail.

Déclaration

<dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-notification</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch le bean correspondant au mail service de la manière suivante :

<bean id="mailService" class="fr.paris.lutece.batches.util.notification.MailService"
       p:mailingList="${mail.mailinglist}"
       p:mailSubject="${mail.subject}"
       p:mailHost="${mail.host}"
       p:mailType="${mail.type.html}"
       p:mailNoReply="${mail.noreply.email}"
       p:mailEncoding="${mail.encoding}" />

Et dans le fichier de properties du batch :

################################################################
# Mail settings

mail.host=smtpmail.mdp
mail.noreply.email=noreply@paris.fr
mail.type.html=text/html;charset="utf-8"
# list of mails separated by a comma (,) to be notified when there are errors
mail.mailinglist=lutece@paris.fr
mail.subject=Notification d'erreurs du batch Ivoire
mail.encoding=UTF-8

Utilisation

@Autowired
private INotificationService _mailService;

batch-library-workflow

Cette library apporte les services de workflow Lutèce dans un batch. Il permet en outre de pouvoir récupérer l'ensemble des informations (actions, tâches, etc...) mais également de pouvoir exécuter des actions de workflow. Déclaration

<dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-workflow</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch l'import du fichier de context de la librarie :

<import resource="classpath:libraries/workflow_context.xml" />

Ajouter le bean correspondant au dataSource de workflow :

<bean id="workflow.dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
		p:driverClassName="${batch.jdbc.workflow.driver}"
		p:url="${batch.jdbc.workflow.url}"
		p:username="${batch.jdbc.workflow.user}"
		p:password="${batch.jdbc.workflow.password}"
		p:validationQuery="${batch.jdbc.workflow.validationQuery}"
		p:testWhileIdle="${batch.jdbc.workflow.testWhileIdle}" />

Ajouter la configuration du dataSource de workflow dans le fichier de properties du batch :

batch.jdbc.workflow.driver=com.mysql.jdbc.Driver
batch.jdbc.workflow.url=jdbc:mysql://localhost/lutece?autoReconnect=true&useUnicode=yes&characterEncoding=utf8
batch.jdbc.workflow.user=root
batch.jdbc.workflow.password=lutece
batch.jdbc.workflow.testWhileIdle=true
batch.jdbc.workflow.validationQuery=SELECT 1

Utilisation

@Autowired
private IIWorkflowService _workflowService;

Exemple

Un exemple de batch utilisant cette librairie est disponible sur http://dev.lutece.paris.fr/svn/lutece/portal/trunk/batches/batch-workflowsample/

batch-library-workflow-notifycrm

Cette library apporte le service de notification CRM de workflow dans un batch. Il permet en outre de pouvoir exécuter les actions de notification vers une webapp CRM.

Déclaration

<dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-workflow-notifycrm</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch l'import du fichier de context de la librarie :

<import resource="classpath:libraries/workflow-notifycrm_context.xml" />

Ajouter les bean correspondant aux dataSources de workflow-notifycrm et directory :

<bean id="workflow-notifycrm.dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
		p:driverClassName="${batch.jdbc.workflow-notifycrm.driver}"
		p:url="${batch.jdbc.workflow-notifycrm.url}"
		p:username="${batch.jdbc.workflow-notifycrm.user}"
		p:password="${batch.jdbc.workflow-notifycrm.password}"
		p:validationQuery="${batch.jdbc.workflow-notifycrm.validationQuery}"
		p:testWhileIdle="${batch.jdbc.workflow-notifycrm.testWhileIdle}" />
<bean id="directory.dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
		p:driverClassName="${batch.jdbc.directory.driver}"
		p:url="${batch.jdbc.directory.url}"
		p:username="${batch.jdbc.directory.user}"
		p:password="${batch.jdbc.directory.password}"
		p:validationQuery="${batch.jdbc.directory.validationQuery}"
		p:testWhileIdle="${batch.jdbc.directory.testWhileIdle}" />

Ajouter la configuration des dataSources de workflow-notifycrm et directory dans le fichier de properties du batch :

batch.jdbc.workflow-notifycrm.driver=com.mysql.jdbc.Driver
batch.jdbc.workflow-notifycrm.url=jdbc:mysql://localhost/lutece_workflow_notifycrm?autoReconnect=true&useUnicode=yes&characterEncoding=utf8
batch.jdbc.workflow-notifycrm.user=root
batch.jdbc.workflow-notifycrm.password=lutece
batch.jdbc.workflow-notifycrm.testWhileIdle=true
batch.jdbc.workflow-notifycrm.validationQuery=SELECT 1

batch.jdbc.directory.driver=com.mysql.jdbc.Driver
batch.jdbc.directory.url=jdbc:mysql://localhost/lutece_directory?autoReconnect=true&useUnicode=yes&characterEncoding=utf8
batch.jdbc.directory.user=root
batch.jdbc.directory.password=lutece
batch.jdbc.directory.testWhileIdle=true
batch.jdbc.directory.validationQuery=SELECT 1

Info

Si les 2 plugins utilisent le même dataSource, il est possible d'utiliser des alias, ce qui évite de déclarer plusieurs fois le même dataSource avec des IDs différents :

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
 		p:driverClassName="${batch.jdbc.driver}"
 		p:url="${batch.jdbc.url}"
 		p:username="${batch.jdbc.user}"
 		p:password="${batch.jdbc.password}"
 		p:validationQuery="${batch.jdbc.validationQuery}"
 		p:testWhileIdle="${batch.jdbc.testWhileIdle}" />
 	<alias name="dataSource" alias="directory.dataSource" />
 	<alias name="dataSource" alias="workflow-notifycrm.dataSource" />

Exemple

Un exemple de batch utilisant cette librairie est disponible sur Exemple

batch-library-crmclient

Cette librairie apporte l'implémentation du DAO pour ajouter des notifications CRM en queue de traitement, afin que le batch de notification CRM de la webapp CRM puisse envoyer les notifications.

Déclaration

<dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-crmclient</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch l'import du fichier de context de la librarie :

<import resource="classpath:libraries/crmclient_context.xml" />

Ajouter les bean correspondant au dataSource de crmclient :

<bean id="crmclient .dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
		p:driverClassName="${batch.jdbc.crmclient .driver}"
		p:url="${batch.jdbc.crmclient .url}"
		p:username="${batch.jdbc.crmclient .user}"
		p:password="${batch.jdbc.crmclient .password}"
		p:validationQuery="${batch.jdbc.crmclient .validationQuery}"
		p:testWhileIdle="${batch.jdbc.crmclient .testWhileIdle}" />

Ajouter la configuration du dataSource de crmclient dans le fichier de properties du batch :

batch.jdbc.crmclient .driver=com.mysql.jdbc.Driver
batch.jdbc.crmclient .url=jdbc:mysql://localhost/lutece_directory?autoReconnect=true&useUnicode=yes&characterEncoding=utf8
batch.jdbc.crmclient .user=root
batch.jdbc.crmclient .password=lutece
batch.jdbc.crmclient .testWhileIdle=true
batch.jdbc.crmclient .validationQuery=SELECT 1

Une fois que le batch ait été packagé (mvn package), il faut configurer le fichier conf/libraries/crmclient.properties et configurer la Base URL de la webapp CRM :

crmclient.crm.rest.webapp.baseurl=http://localhost:8080/lutece
]]]

**Exemple**

Un exemple de batch utilisant cette librairie est disponible sur[[ http://dev.lutece.paris.fr/svn/lutece/portal/trunk/batches/batch-workflowsample/| http://dev.lutece.paris.fr/svn/lutece/portal/trunk/batches/batch-workflowsample/]]


=== batch-library-freemarker ===

Cette librairie apporte l'implémentation du service FreeMarker. Il permet en outre de pouvoir transformer les messages de notification contenant des labels freemarker.

**Déclaration**

{{{
       <dependency>
           <groupId>fr.paris.lutece.batches</groupId>
           <artifactId>batch-library-freemarker</artifactId>
           <version>1.0.0</version>
           <type>jar</type>
       </dependency>

Configuration

Il faut ajouter dans le fichier context.xml du batch l'import du fichier de context de la librarie :

<import resource="classpath:libraries/freemarker_context.xml" />

Une fois que le batch ait été packagé (mvn package), il faut configurer le fichier conf/libraries/freemarker.properties et configurer le chemin absolu vers la webapp Lutèce

freemarker.webapp.path=/home/user/apps/tomcat/webapps/lutece/

Exemple

Un exemple de batch utilisant cette librairie est disponible sur http://dev.lutece.paris.fr/svn/lutece/portal/trunk/batches/batch-workflowsample/