Je suis actuellement en train de tester la JSR 352 ( ou JAVA BATCH). Cette API est une des nouveautés de la spécification JAVA EE 7. Elle permet ( entre autres ) de lancer des BATCHS depuis un serveur JEE.
Mais vous allez me dire : il y a SPRING BATCH ! Oui, JAVA BATCH est une standardisation de JAVA BATCH avec l’ intégration du moteur dans un serveur JEE. D’ailleurs, SPRING BATCH est désormais compatible avec cette API.
Ce dernier offre la possibilité de contrôler l’état des jobs à travers l’outil d’administration du serveur via le JOB REPOSITORY.
Pour ceux qui connaissent SPRING BATCH et le monde chatoyant des ETL, le concept de la JSR 352 sera assez simple à appréhender :
Un batch est spécifié avec un job qui a plusieurs steps qui sont découpés en étapes de lecture, de transformation et de chargement (ETL).
Avantages
Les principaux avantages à faire tourner les batchs dans un contexte JEE ( si si il y en a ) sont les suivants :
- On peut utiliser l’outillage du serveur pour monitorer les jobs
- On dispose de toute la stack JEE (CDI, JPA, JTA,JAX-RS,…) pour développer des batchs
- Un batch peut être déclenché de plusieurs manières (script, service REST,…)
- Par rapport aux solutions ETL du marché, on peut avoir des tests unitaires, de la qualimétrie de code avec SONARQUBE,…
Inconvénients
C’est une V1. Il y a encore des choses à améliorer ( gestion des properties par ex)
Définition d’un job
Le job se définit par un fichier XML
Les références des différents élements font appel aux références des beans CDI développés. Dans mon exemple, je n’ai pas utilisé de processor car je ne devais pas transformer les données. J’ai cependant eu besoin de séparer les différents traitements en les parallélisant dans des partitions. Pour déterminer les données de chaque partition, j’ai utilisé un mapper.
Le reader
@Named
@Dependent
public class MyReader extends AbstractItemReader {
@Inject
JobContext jobContext;
@Inject
StepContext stepContext;
@Inject
@BatchProperty(name = "PROP")
String service;
@Override
public void open(Serializable serializable) throws Exception {
// charge toutes les données
}
@Override
public Object readItem() throws Exception {
// lit les données chargées
}
}
On voir dans l’exemple que l’injection se fait par CDI. Il faut spécifier le scope Dependent
pour que les beans soient accessibles dans le contexte BATCH.
La récupération des données se fait via la méthode open()
. Logiquement , on doit récupérer toutes les données à ce moment. Ca peut être problématique avec des très grosses volumétries . Dans ce cas on pourra privilégier le lazy loading.
La lecture de chaque item (ex. une ligne ) se fait dans la méthode readItem()
. L’une des choses que je trouve un peu dommage dans l’API BATCH est le manque de générique. En effet, ça aurait été un peu plus “sympa” d’avoir une classe AstractItemReader
qui paramètre la méthode readItem().
Le writer
De la même manière on spécifie le writer
@Named
@Dependent
public class MyWriter extends AbstractItemWriter {
@Override
public void writeItems(List<Object> list) throws Exception {
for (Object current : list) {
// ecriture des differents items
}
}
}
Sur l’utilisation de la méthode writeItems()
, j’ai la même remarque que pour la méthode readItem()
. Un peu de générique, ça n’aurait pas été du luxe….
Le mapper
@Named
@Dependent
public class MyPartitionMapper implements PartitionMapper {
@Inject
JobContext jobContext;
@Override
public PartitionPlan mapPartitions() throws Exception {
PartitionPlan partitionPlan = new PartitionPlanImpl();
Properties[] props = new Properties[TAILLE];
int i = 0;
// @TODO voir pour un stream
for (String current : LISTE) {
if (current != null) {
props[i] = new Properties();
props[i].setProperty("PROP", current);
++i;
}
}
partitionPlan.setPartitions(props.length);
partitionPlan.setPartitionProperties(props);
return partitionPlan;
}
}
La propriété “PROP” définie dans le fichier XML et utilisée dans le reader est définie pour chaque partition. Les différentes partitions sont stockées dans un partitionPlan.
Démarrage du batch
Le batch peut se démarrer de la manière suivante
JobOperator jobOperator = BatchRuntime.getJobOperator();
Properties jobProperties = new Properties();
jobProperties.setProperty("DATE", "2015-07-08");
jobOperator.start("myJob", jobProperties);
Ce code peut être appelé depuis une servlet, un service REST …..
Monitoring
Pour suivre l’exécution du batch on peut utiliser les outils du serveur d’applications. Sous glassfish on peut utiliser la commande asadmin.
asadmin list-batch-jobs -l
JOBNAME APPNAME INSTANCECOUNT INSTANCEID EXECUTIONID BATCHSTATUS STARTTIME ENDTIME EXITSTATUS
myJob myProject 137 817 817 COMPLETED Wed Jul 08 00:00:01 CEST 2015 Wed Jul 08 00:00:01 CEST 2015 COMPLETED
myJob myProject 137 811 811 COMPLETED Tue Jul 07 10:51:42 CEST 2015 Tue Jul 07 10:51:42 CEST 2015 COMPLETED
myJob myProject 137 805 805 COMPLETED Tue Jul 07 00:00:01 CEST 2015 Tue Jul 07 00:00:02 CEST 2015 COMPLETED
myJob myProject 137 799 799 COMPLETED Mon Jul 06 15:58:42 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
myJob myProject 137 793 793 COMPLETED Mon Jul 06 15:58:42 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
myJob myProject 137 787 787 COMPLETED Mon Jul 06 15:58:42 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
myJob myProject 137 781 781 COMPLETED Mon Jul 06 15:58:42 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
myJob myProject 137 775 775 COMPLETED Mon Jul 06 15:58:41 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
myJob myProject 137 769 769 COMPLETED Mon Jul 06 15:58:41 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
myJob myProject 137 763 763 COMPLETED Mon Jul 06 15:58:41 CEST 2015 Mon Jul 06 15:58:43 CEST 2015 COMPLETED
On peut également utiliser les beans JMX pour monitorer les jobs.
Conclusion
La stack JSR 352 est assez simple à utiliser. Elle est certes perfectible ( absence de générique, gestion des propriétés assez compliquée de prime abord) mais fait le boulot.
Par rapport aux autres solutions (spring batch) elle permet la supervision des batchs via les outils du serveur d’application et peut facilement s’intégrer dans une application JAVAEE.
Original post of Littlewing.Votez pour ce billet sur Planet Libre.