Comment pouvez-vous redémarrer un échec de spring batch de l'emploi et de la laisser reprendre là où il l'avait laissé?
Selon le Spring Batch documentation redémarrage d'un emploi est pris en charge hors de la boîte, mais je ne peux pas l'obtenir à partir du point où il la gauche de la. par exemple, Si mon pas traitées de 10 enregistrements, il devrait commencer à enregistrer 11 avec le traitement dès que je redémarre. Dans la pratique, cela n'arrive pas. Il lit à partir de la beginnen en retraite tout.
Quelqu'un at-il une Java config en fonction de la configuration de un travail simple qui lit un fichier délimité et écrit le contenu d'une table db qui peut être redémarré à partir du point d'arrêt?
@Configuration
public class BatchConfiguration {
@Value("${spring-batch.databaseType}")
private String databaseType;
@Value("${spring-batch.databaseSchema}")
private String schemaName;
@Bean
public JobBuilderFactory jobBuilderFactory(final JobRepository jobRepository) {
return new JobBuilderFactory(jobRepository);
}
@Bean
public StepBuilderFactory stepBuilderFactory(final JobRepository jobRepository,
final PlatformTransactionManager transactionManager) {
return new StepBuilderFactory(jobRepository, transactionManager);
}
@Bean
public JobRepository jobRepository(final DataSource dataSource, final PlatformTransactionManager transactionManager) {
final JobRepositoryFactoryBean bean = new JobRepositoryFactoryBean();
bean.setDatabaseType(databaseType);
bean.setDataSource(dataSource);
if (StringUtils.isNotBlank(schemaName)) {
bean.setTablePrefix(schemaName);
}
bean.setTransactionManager(transactionManager);
try {
bean.afterPropertiesSet();
return bean.getObject();
} catch (final Exception e) {
throw new BatchConfigurationException("Invalid batch job repository configuration.", e);
}
}
@Bean
public JobLauncher jobLauncher(final JobRepository jobRepository) {
final SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
return jobLauncher;
}
}
@Configuration
@EnableScheduling
@ComponentScan("com.some.package")
public class BatchJobConfiguration {
@Resource
private JobBuilderFactory jobBuilderFactory;
@Resource
private StepBuilderFactory stepBuilderFactory;
@Value("${savings-transaction.file}")
private String savingsTransactionFile;
@Value("${savings-balance.file}")
private String savingsBalanceFile;
@Value("${processed-directory}")
private String processedDirectory;
private static final Integer IMPORT_CHUNKSIZE = 10;
@Bean
@DependsOn("stepBuilderFactory")
public Step savingsTransactionStep(final PlatformTransactionManager transactionManager,
@Qualifier("savingsTransactionItemReader") final ItemReader<SavingsTransactionItem> savingsTransactionItemReader,
@Qualifier("savingsTransactionProcessor") final ItemProcessor<SavingsTransactionItem, SavingsTransaction> processor,
@Qualifier("savingsTransactionItemWriter") final ItemWriter<SavingsTransaction> savingsTransactionItemWriter,
@Qualifier("savingsTransactionStepListener") final SavingsTransactionStepListener listener) {
return stepBuilderFactory.get("savingsTransactionStep")
.transactionManager(transactionManager)
.<SavingsTransactionItem, SavingsTransaction> chunk(IMPORT_CHUNKSIZE)
.reader(savingsTransactionItemReader)
.processor(processor)
.writer(savingsTransactionItemWriter)
.listener(listener)
.build();
}
@Bean
public Step savingsTransactionCleanUpStep(final PlatformTransactionManager transactionManager,
final JobRepository jobRepository) {
final TaskletStep taskletStep = new TaskletStep("savingsTransactionCleanUpStep");
final FileMovingTasklet tasklet = new FileMovingTasklet();
tasklet.setFileNamePattern(savingsTransactionFile);
tasklet.setProcessedDirectory(processedDirectory);
taskletStep.setTasklet(tasklet);
taskletStep.setTransactionManager(transactionManager);
taskletStep.setJobRepository(jobRepository);
try {
taskletStep.afterPropertiesSet();
} catch (final Exception e) {
throw new BatchConfigurationException("Failed to configure tasklet!", e);
}
return taskletStep;
}
@Bean
@DependsOn("jobBuilderFactory")
public Job job(final Step savingsTransactionStep,
final Step savingsTransactionCleanUpStep) {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.start(savingsTransactionStep)
.next(savingsTransactionCleanUpStep)
.on("FINISHED")
.end()
.build()
.build();
}
}
Code de test unitaire qui reprend le travail
final Date now = new Date();
jobMananger.processRegistrations(now);
final List<SavingsBalance> savingsBalances = savingsBalanceDao.findAll();
assertEquals(9, savingsBalances.size());
FileUtils.moveFile(new File("target/AEA001_20160610.dat"), new File("target/AEA001_20160610_invalid.dat"));
FileUtils.moveFile(new File("target/AEA001_20160610_valid.dat"), new File("target/AEA001_20160610.dat"));
jobMananger.processRegistrations(now);
final List<SavingsBalance> savingsBalances2 = savingsBalanceDao.findAll();
System.out.println(savingsBalances2.size());
int found = 0;
for (final SavingsBalance savingsBalance : savingsBalances2) {
final String id = savingsBalance.getId();
if ("12345".equals(id)) {
found++;
}
}
assertEquals("Invalid number of found balances!", 1, found);
Le gestionnaire de l'emploi mise en œuvre
public class JobManager {
@Resource
private JobLauncher jobLauncher;
@Resource
private Job job;
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void processRegistrations(final Date date) {
try {
final Map<String, JobParameter> parameters = new HashMap<>();
parameters.put("START_DATE", new JobParameter(date));
final JobParameters jobParameters = new JobParameters(parameters);
final JobExecution execution = jobLauncher.run(job, jobParameters);
LOG.info("Exit Status : " + execution.getStatus());
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException e) {
LOG.error("Failed to process registrations.", e);
}
}
}
Comment êtes-vous relancer la tâche ?
N'utilisez pas de nouvelles JobParameters si vous voulez reprendre votre travail
Que dois-je utiliser que?
Je pense que vous devriez enregistrer la date de début et l'utiliser quand vous le redémarrage de l'emploi.
OriginalL'auteur Tranquilized | 2016-08-09
Vous devez vous connecter pour publier un commentaire.
Il semble que vous devez configurer les éléments suivants haricots pour être en mesure de redémarrer votre travail.
Alors vous avez besoin pour récupérer le lot de l'id d'instance du lot de tables, pour être en mesure de redémarrer l'instance à l'aide de la jobOperator.
ScheduledTaskRegistrar
, en cela, je suis en appelant la méthodescheduleJobA()
et cette méthode lance l'emploi. EtbeforeJob()
méthode est appelée après que le travail est lancé par jobLauncher.Donc,je n'ai pas manqué l'id de la tâche.J'ai essayé beaucoup de liens. Mais je ne suis pas comment faire pour obtenir l'échec de la précédente ou l'id de la tâche et d'appeler la méthode de redémarrage. S'il vous plaît aider moi.Ai-je besoin de définir l'état de l'exécution des tâches en tant que
FAILED
? Et si c'est le cas, chaque fois qu'il sera a échoué et sera toujours le redémarrage de l'emploi, même si elle était en cours d'exécution avec succès(avant la définition de l'état commeFAILED
). Selon Michal Minella(et ce lien - forum.printemps.io/forum/printemps-projets/lot/...), nous avons pour définir manuellement le statut deINCOMPLETED
ouFAILED
. Est-ce donc? Suis-je correctement?je m en utilisant jobOperator.redémarrer(id) encore en train de la nouvelle instance de travail
ont commencé le travail avec joblauncher
OriginalL'auteur Tranquilized
À l'intérieur de votre JobManager en classe , au lieu d'utiliser JobLauncher , utilisez JobOperator.restart() nethod .
La raison pour laquelle votre travail n'est pas redémarré à partir de la dernière étape ayant échoué est parce JobLauncher vous êtes encore à commencer un nouveau travail et il est donc de commencer le travail à partir de l'étape un .
Assurez-vous que "redémarrage" de la propriété est définie sur true (Par défaut, elle est définie à true ) .
Voici un exemple de code .
Vous avez besoin pour obtenir le jobExecutionid de l'échec de l'emploi et de la passer à la méthode ci-dessus .
Veuillez noter qu'un travail qui est complété avec "FINI" le statut ne peut pas être redémarré .
Vous pouvez lire ce post aussi
Reprise d'un emploi
Puisque vous utilisez javaconfig , vous devriez avoir quelque chose comme ceci @Resource privé JobLauncher jobLauncher;
OriginalL'auteur DevG
Vous commencez votre travail avec de nouveaux JobParameters, de sorte que SB ne pas reprendre le Travail, mais il commence à nouveau.
Si vous voulez reprendre le Travail, vous devez supprimer incrementer de Travail bean config.
problème avec la première ou de la deuxième étape?
première étape.. c'est celui qui lit les lignes d'un fichier. Lors du redémarrage, il commence dès le début comme un nouvel emploi ferais bien que j'utilise exactement les mêmes paramètres de travail. Dois-je faire quelque chose de spécifique pour être en mesure de redémarrer un emploi?
Config semble ok
OriginalL'auteur Dmitry