Contenu connexe Similaire à Spring & SpringBatch FR (20) Spring & SpringBatch FR2. 2Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Plan & Objectifs
Plan
1. Un tour au pays de Spring & Spring-Boot
2. C’est quoi un Batch et Spring-Batch ?
3. Comment cela fonctionne ?
4. Notions avancées et applications.
5. Un bon exemple de la vrai vie.
Objectifs
1. Assimiler Spring-Batch
2. Détecter les cas d’usages
3. Pouvoir faire du Batch et aller encore plus loin avec…
4. 4Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring Framework (Le Cœur 1/3)
Framework Java open-source créé en 2003 par « Pivotal Software »
Un conteneur léger (contrairement aux EJBs)
S’appui essentiellement sur l’injection de dépendance et l’AOP
Intégration facile d’autre Framework (Hibernate , JSF, Thymeleaf ,…)
5. 5Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring Framework (Le Boot 2/3)
Peu de configuration (auto-configurable tant que c’est possible)
Application Runnable , autonome même en production.
Embarque même un Tomcat (+ Jetty) , plus besoin du War
Plus besoin des fichiers XML (context.xml, web.xml, …) @annotations
6. 6Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring Framework (La tendance 3/3 @GoogleTrend)
8. 8Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Batch (C’est quoi ? 1/2)
Traitement de données par lots successifs
Gros volumes de données
Plusieurs opérations s'enchainent pour chaque lot
Déclenchement automatique ou manuel
9. 9Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Batch (Par l’exemple 2/2)
Un exemple concret : import des commandes journalières
Lecture d’un lot
de commandes
depuis un fichier
Vérification des
commandes
Sauvegarde du
lot de
commandes
dans le ST
Répéter ce cycle pour chaque lot de commandes jusqu’à la dernière
Déclencher par CRON, tous les jours à 5H, avant l’arrivée des collaborateurs
10. 10Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring-Batch (C’est quoi encore ? 1/6)
Framework open-source pour le Batch Processing
Application Batch robuste (Entreprise application)
Des fonctions réutilisables pour le traitement des données
Ajoute une approche standard pour définir les Jobs Batch
11. 11Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring-Batch (En plus 2/6)
La gestion des transactions (Commit interval & Rollback)
Traitement par lot facilement (Chuncked process)
Gestion des erreurs, de la reprise et l’arrêt des Jobs
Le tous dans Spring…
12. 12Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring-Batch (le concept 3/6)
Un Job est défini par un Flow de Step (un ou plusieurs)
Un Step définie généralement un Reader, un Processor et Writer
Un Step peut définir aussi un simple Tasklet
Un référentiel de Job (JobRepository) et un exécuteur de Job
(JobLauncher)
Source : Spring.io
13. 13Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring-Batch (le fonctionnement 4/6)
Le Reader lit un élément à la fois
Le Processor traite un élément à la fois
Quand le lot est lu et traité, le Writer l’écrit
Source : Spring.io
14. 14Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring-Batch (Notions avancées 5/6)
Flow de Step séquentiel, conditionnel ou parallèle
Traitement parallèle (Split Flow) et Multi-threading
Des Listeners (StepExecutionListener, ChunkListener, ItemReadListener,…)
Gestions intégrée des exceptions
15. 15Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Spring-Batch (Diagramme 6/6)
Source : Cépria FR
16. 16Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Par l’exemple
comme dans la vrai vie …
17. 17Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Contexte 1/8)
Application Web pouvant faire appel à des Jobs via l’IHM
Suivre le statut des Jobs
Permettre de jouer les Jobs en Synchrone et en Asynchrone
Trois Jobs, un premier pour importer des fichiers CSV en Base de
données, un deuxième pour exporter les données en fichier JSON et un
dernier Job pour faire l’import et l’export d’un grand volume de données
(200 000 lignes) en moins de 10 minutes
18. 18Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Besoin métier 2/8)
Import Job :
• Input : un fichier CSV contenant les informations des employées et leurs
salaires brutes annuels
• Output : les informations transformées et les taxes calculées et
enregistrées dans la base de donnés
Export Job :
• Input : les informations des employées et les taxes calculées et
enregistrées dans la base de donnés
• Output : un fichier JSON contenant toutes les données.
PLUS : une API REST pour effectuer le calcule des taxes et la validation
19. 19Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Architecture & choix techniques 3/8)
Utilisation du Spring-Boot avec Spring-MVC et Srping-Batch
Intégration du Thymeleaf comme moteur de Templating (+ nekohtml)
MySQL Driver, Mokito pour les tests et Jackson pour le support du JSON
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
…
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
…
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
…
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
…
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
…
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
…
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
20. 20Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Diagramme de la solution 4/8)
21. 21Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Code source 5/8)
Une interface est disponible pour définir un Tasklet
public interface ItemReader<T> {
T read() throws Exception, UnexpectedInputException , ParseException;
}
public interface ItemWriter<T> {
void write(List<? extends T> items) throws Exception;
}
public interface ItemProcessor<I, O> {
O process(I item) throws Exception;
}
Trois interfaces sont disponibles pour définir un Reader, Processor et Writer
public interface Tasklet {
RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception
}
Une interface est disponible pour définir un Partionner
public interface Partitioner {
Map<String, ExecutionContext> partition(int gridSize);
}
22. 22Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Un Job par annotation 6/8)
@Bean
public ItemReader<Person> reader() {
return new PersonReaderFromFile();
}
@Bean
public ImportPersonItemProcessor processor() {
return new ImportPersonItemProcessor();
}
@Bean
public ItemWriter<Person> writer() {
return new PersonWriterToDataBase();
}
@Bean
public Tasklet cleaner() {
return new CleanDBTasklet ();
}
@Bean
public Job importUserJob() {
return jobBuilderFactory.get("importUserJob").incrementer(new RunIdIncrementer()).flow(stepClean())
.next(stepImport()).end().listener(new ImportJobExecutionListener(reader())
.validator(new FileNameParameterValidator()).build();
}
@Bean
public Step stepImport() {
return stepBuilderFactory.get("stepImport").<Person, Person>chunk(10).reader(reader()).processor(processor()).writer(writer()).build();
}
@Bean
public Step stepClean() {
return stepBuilderFactory.get("stepClean").tasklet(cleaner()).build();
}
23. 23Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (Deux Jobs par XML 7/8)
<batch:job id="importUserJob">
<batch:step id="stepClean" next="importStep">
<batch:tasklet ref="cleanDBTasklet" />
</batch:step>
<batch:step id="importStep">
<batch:tasklet>
<batch:chunk reader="reader" writer="writer" processor="processor" commit-interval="10" />
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="reader" class="com.capgemini.reader.PersonReaderFromFile" scope="step" />
<bean id="processor" class="com.capgemini.processor.ImportPersonItemProcessor" scope="step" />
<bean id="writer" class="com.capgemini.writer.PersonWriterToDataBase" scope="step" />
<bean id="cleanDBTasklet" class="com.capgemini.tasklet.CleanDBTasklet" />
<batch:job id=“exportUserJob">
<batch:step id=“exportStep">
<batch:tasklet>
<batch:chunk reader="reader" writer="writer" processor="processor" commit-interval="10" />
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="reader" class="com.capgemini.reader.PersonReaderFromDataBase" scope="step" />
<bean id="processor" class="com.capgemini.processor.ExportPersonItemProcessor" scope="step" />
<bean id="writer" class="com.capgemini.writer.PersonWriterToFile" scope="step" />
24. 24Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Exemple d’usage (L’application enfin 8/8)
26. 26Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
La démo (Résultat et Conclusion1/6)
Import de fichier de petite ou moyenne taille :
• Pour les petit fichiers, une moyenne de 4 secondes pour les modes
Synchrone et Asynchrone
• Pour les fichiers de taille moyenne (10.000 lignes), une moyenne de 43
secondes de traitement entre Synchrone et Asynchrone
Import de fichier de grande taille: Une moyenne de traitement de 13
minutes
Export 1000 ligne ou 10.000 lignes: Pour les 1000 ligne, une moyenne de
4 secondes de traitement, et pour les 100.000 ligne, une moyenne de 30
secondes
Export des 200.000 lignes : Une moyenne de traitement de 12 minutes
=> Pour un import et export des 200.000 lignes on dépasse les 10 minutes
27. 27Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
La démo (Solution 2/6)
Pour effectuer l’import et l’export des 200.000 lignes en moins de 10 minutes,
le multi-threading est l’une des solutions
Multi-threading : plusieurs Threads, effectuent une tâche en parallèle
Un nouveau problème : le FileReader et FileWriter ne sont pas des
ThreadSafe
La solution pour le FileReader : splitter le fichier en entrée pour que
chaque ficher soit traité par un Thread
La solution pour le FileWriter: paginer les données de la base de données
pour en exporter plusieurs fichiers et les concaténer à la fin du Process.
28. 28Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
La démo (Le configuration de la solution 3/6)
<batch:job id="transformJob">
<batch:step id="deleteDir" next="cleanDB">
<batch:tasklet ref="fileDeletingTasklet" />
</batch:step>
<batch:step id="cleanDB" next="countThread">
<batch:tasklet ref="cleanDBTasklet" />
</batch:step>
<batch:step id="countThread" next="split">
<batch:tasklet ref="countThreadTasklet" />
</batch:step>
<batch:step id="split" next="partitionerMasterImporter">
<batch:tasklet>
<batch:chunk reader="largeCSVReader" writer="smallCSVWriter"
commit-interval="#{jobExecutionContext['chunk.count']}" />
</batch:tasklet>
</batch:step>
<batch:step id="partitionerMasterImporter" next="partitionerMasterExporter">
<partition step="importChunked" partitioner="filePartitioner">
<handler grid-size="10" task-executor="taskExecutor" />
</partition>
</batch:step>
<batch:step id="partitionerMasterExporter" next="concat">
<partition step="exportChunked" partitioner="dbPartitioner">
<handler grid-size="10" task-executor="taskExecutor" />
</partition>
</batch:step>
<batch:step id="concat">
<batch:tasklet ref="concatFileTasklet" />
</batch:step>
</batch:job>
29. 29Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
La démo (Le configuration 4/6)
<batch:step id="importChunked">
<batch:tasklet>
<batch:chunk reader="smallCSVFileReader" writer="dbWriter"
processor="importProcessor" commit-interval="500">
</batch:chunk>
</batch:tasklet>
</batch:step>
<batch:step id="exportChunked">
<batch:tasklet>
<batch:chunk reader="dbReader" writer="jsonFileWriter" processor="exportProcessor" commit-
interval="#{jobExecutionContext['chunk.count']}">
</batch:chunk>
</batch:tasklet>
</batch:step>
<bean id="jsonFileWriter" class="com.capgemini.writer.PersonWriterToFile" scope="step">
<property name="outputPath" value="csv/chunked/paged-#{stepExecutionContext[page]}.json" />
</bean>
<bean id="dbReader" class="com.capgemini.reader.PersonReaderFromDataBase" scope="step">
<property name="iPersonRepository" ref="IPersonRepository" />
<property name="page" value="#{stepExecutionContext[page]}"/>
<property name="size" value="#{stepExecutionContext[size]}"/>
</bean>
<bean id="countThreadTasklet" class="com.capgemini.tasklet.CountingTasklet" scope="step">
<property name="input" value="file:csv/input/#{jobParameters[filename]}" />
</bean>
<bean id="cleanDBTasklet" class="com.capgemini.tasklet.CleanDBTasklet" />
<bean id="fileDeletingTasklet" class="com.capgemini.tasklet.FileDeletingTasklet">
<property name="directory" value="file:csv/chunked/" />
</bean>
30. 30Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
La démo (Le configuration 5/6)
<bean id="concatFileTasklet" class="com.capgemini.tasklet.FileConcatTasklet">
<property name="directory" value="file:csv/chunked/" />
<property name="outputFilename" value="csv/output/export.json" />
</bean>
<bean id="filePartitioner" class="com.capgemini.partitioner.FilePartitioner">
<property name="outputPath" value="csv/chunked/" />
</bean>
<bean id="dbPartitioner" class="com.capgemini.partitioner.DBPartitioner" scope="step">
<property name="pageSize" value="#{jobExecutionContext['chunk.count']}" />
</bean>
<bean id="largeCSVReader" class="com.capgemini.reader.LineReaderFromFile" scope="step">
<property name="inputPath" value="csv/input/#{jobParameters[filename]}" />
</bean>
<bean id="smallCSVWriter" class="com.capgemini.writer.LineWriterToFile" scope="step">
<property name="outputPath" value="csv/chunked/"></property>
</bean>
<bean id="smallCSVFileReader" class="com.capgemini.reader.PersonReaderFromFile" scope="step">
<constructor-arg value="csv/chunked/#{stepExecutionContext[file]}" />
</bean>
<bean id="importProcessor" class="com.capgemini.processor.ImportPersonItemProcessor" />
<bean id="exportProcessor" class="com.capgemini.processor.ExportPersonItemProcessor" />
<bean id="dbWriter" class="com.capgemini.writer.PersonWriterToDataBase">
<property name="iPersonRepository" ref="IPersonRepository" />
</bean>
31. 31Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Le test
En multi-threading
32. 32Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Le Test (Résultat 1/3)
33. 33Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Le Test (Les Threads 2/3)
Avant le
lancement du Job
Pendant
l’exécution du Job
34. 34Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Le Test (Output 3/3)
36. 36Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Récap (Les points + 1/2)
Définit un pattern pour les Batchs
Embarquer les Batchs dans tout type d’application Spring facilement
Fiabilité, maintenabilité
Fonctions avancés par simple configuration tel que le « Multi-Threading »
Intégrée des tests au Batchs
Tolérance aux erreurs et de la reprise suite à une erreur
37. 37Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Récap (Les points – 2/2)
Le projet Spring Batch Admin n’est plus maintenue : passage obligatoire au
Spring Cloud Data Flow
Difficulté à exécuter un Job définit par annotation dans un projet sous
paquetage JAR embarquant plusieurs Jobs
Des problèmes de compatibilité de version entre Spring Batch et H2
Database , très utile pour tester les Jobs
39. 39Copyright © 2017 Capgemini. Tous droits réservés
CSD | Octobre 2017
Liens utiles
Code source complet du projet : https://gitlab.com/mmohamed/spring-batch
Documentations :
• http://projects.spring.io/spring-batch/#quick-start
• https://blog.octo.com/spring-batch-par-quel-bout-le-prendre
• https://blog.netapsys.fr/spring-batch-par-lexemple-2
• http://jeremy-jeanne.developpez.com/tutoriels/spring/spring-batch/
40. www.capgemini.com
The information contained in this presentation is proprietary.
© 2017 Capgemini. All rights reserved. Rightshore® is a trademark belonging to Capgemini.
About Capgemini
With more than 190,000 people, Capgemini is present in over 40
countries and celebrates its 50th Anniversary year in 2017. A
global leader in consulting, technology and outsourcing services,
the Group reported 2016 global revenues of EUR 12.5 billion.
Together with its clients, Capgemini creates and delivers
business, technology and digital solutions that fit their needs,
enabling them to achieve innovation and competitiveness. A
deeply multicultural organization, Capgemini has developed its
own way of working, Collaborative Business ExperienceTM, and
draws on Rightshore®, its worldwide delivery model
Learn more about us at www.capgemini.com
Rightshore® is a trademark belonging to Capgemini
Notes de l'éditeur Les classes n’ont pas besoin d’implémenter une quelconque interface pour être prises en charge par le framework (au contraire des serveur d'applications J2EE et des EJBs).
La programmation orientée aspect, ou POA est un paradigme de programmation qui permet de traiter séparément les préoccupations transversales, qui relèvent souvent de la technique, des préoccupations métier, qui constituent le cœur d'une application Mode Auto-configuration basé sur les annotations
Fonctionne sans fichier XML Déclenché par CRON ou par commande Bash Importation des commandes de la veille du Front (Boutique en ligne) vers le SI de traitement des commandes clients
Intégrer les commandes avant le début du service Un JobInstance = un Job + JobParameters
Un JobExecution = JobInstance + Execution - Le commit-interval est au niveau du Writer - Flow conditionnel :
<job id="job">
<step id="stepA">
<next on="FAILED" to="stepB" /> <next on="*" to="stepC" />
</step>
<step id="stepB" next="stepC" />
<step id="stepC" />
</job>
-Split Flow :
<step id="stepA" next="stepB"/>
<split id="stepB" next="stepC">
<flow>
<step id="stepB11" next="stepB12"/>
<step id="stepB12"/>
</flow>
<flow>
<step id="stepB21"/>
</flow>
</split>
<step id="stepC"/> Run Tier : a pour mission la planification et le lancement des Jobs (produits tiers généralement)
Job Tier : responsable de l‘exécution globale du Job
Application Tier : contient les composants requis pour exécuter le Job
Data Tier : fournit l'intégration avec les sources de données physiques pouvant inclure bases de données, fichiers ou files d'attente