Skip to content

Commit

Permalink
[MODEXPS-273] Improve step execution conditions
Browse files Browse the repository at this point in the history
  • Loading branch information
Saba-Zedginidze-EPAM committed Dec 30, 2024
1 parent 12886be commit 39a787a
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import lombok.extern.log4j.Log4j2;
import org.folio.dew.domain.dto.ExportType;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecutionListener;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
Expand All @@ -22,16 +21,18 @@ public class EdifactExportJobConfig {
public static final String POL_MEM_KEY = "poLineIds";

private Job constructEdifactExportJob(JobBuilder jobBuilder,
JobExecutionListener listener,
Step... steps) {
var builder = jobBuilder
.incrementer(new RunIdIncrementer())
.listener(listener)
.start(steps[0]);
for (int i = 1; i < steps.length; i++) {
builder = builder.next(steps[i]);
}
return builder.build();
EdiExportJobCompletionListener ediExportJobCompletionListener,
Step mapToFileStep,
Step saveToMinIOStep,
Step saveToFTPStep,
Step createExportHistoryRecordsStep) {
return jobBuilder.incrementer(new RunIdIncrementer())
.listener(ediExportJobCompletionListener)
.start(mapToFileStep)
.next(saveToMinIOStep)
.next(saveToFTPStep)
.next(createExportHistoryRecordsStep)
.build();
}

@Bean
Expand All @@ -43,9 +44,9 @@ public Job edifactOrdersExportJob(EdiExportJobCompletionListener ediExportJobCom

@Bean
public Job edifactClaimsExportJob(EdiExportJobCompletionListener ediExportJobCompletionListener, JobRepository jobRepository,
Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep) {
Step mapToEdifactClaimsStep, Step saveToFTPStep, Step saveToMinIOStep, Step createExportHistoryRecordsStep) {
return constructEdifactExportJob(new JobBuilder(ExportType.CLAIMS.getValue(), jobRepository),
ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep);
ediExportJobCompletionListener, mapToEdifactClaimsStep, saveToFTPStep, saveToMinIOStep, createExportHistoryRecordsStep);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static org.folio.dew.batch.acquisitions.edifact.jobs.EdifactExportJobConfig.POL_MEM_KEY;
import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME;
import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT;
import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING;

import java.util.Collections;
import java.util.Date;
Expand All @@ -22,19 +23,18 @@
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.extern.log4j.Log4j2;

@RequiredArgsConstructor
@SuperBuilder
@Component
@StepScope
@Log4j2
public class ExportHistoryTasklet implements Tasklet {
public class ExportHistoryTasklet extends FilterableTasklet {

private final KafkaService kafkaService;
private final ObjectMapper ediObjectMapper;
Expand All @@ -43,7 +43,7 @@ public class ExportHistoryTasklet implements Tasklet {
@Value("#{jobParameters['jobId']}")
private String jobId;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) {
var exportHistory = buildExportHistory(chunkContext);
kafkaService.send(KafkaService.Topic.EXPORT_HISTORY_CREATE, null, exportHistory);

Expand Down Expand Up @@ -83,4 +83,10 @@ List<String> getPoLineIdsFromExecutionContext(StepExecution stepExecutionContext
return Collections.emptyList();
}
}

@Override
protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) {
return exportConfig.getIntegrationType() == ORDERING;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.folio.dew.batch.acquisitions.edifact.jobs;

import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT;

import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.extern.log4j.Log4j2;

@RequiredArgsConstructor
@Log4j2
@SuperBuilder
public abstract class FilterableTasklet implements Tasklet {

private final ObjectMapper objectMapper;

@Override
public final RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
var ediExportConfig = objectMapper.readValue((String) chunkContext.getStepContext().getJobParameters().get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class);
if (shouldExecute(ediExportConfig)) {
return execute(ediExportConfig, contribution, chunkContext);
}
return RepeatStatus.FINISHED;
}

/**
* Check if the tasklet should be executed, by default always returns true.
* Override this method to provide custom logic.
*
* @param exportConfig the export configuration
* @return true if the tasklet should be executed
*/
protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) {
return true;
}


/**
* This method should be overridden to provide the tasklet logic with predefined filtering.
*
* @param exportConfig the export configuration
* @param contribution the step contribution
* @param chunkContext the chunk context
* @return the repeat status
* @throws Exception if an error occurs
*/
protected abstract RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) throws Exception;

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,23 @@

import org.apache.commons.collections4.CollectionUtils;
import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper;
import org.folio.dew.batch.acquisitions.edifact.services.OrdersService;
import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService;
import org.folio.dew.domain.dto.Piece;
import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig;
import org.folio.dew.domain.dto.acquisitions.edifact.ExportHolder;
import org.folio.dew.error.NotFoundException;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.experimental.SuperBuilder;

@SuperBuilder
@Component
@StepScope
public class MapToEdifactClaimsTasklet extends MapToEdifactTasklet {

private final ExportResourceMapper edifactMapper;
private final ExportResourceMapper csvMapper;

public MapToEdifactClaimsTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService,
ExportResourceMapper edifactMapper, ExportResourceMapper csvMapper) {
super(ediObjectMapper, organizationsService, ordersService);
this.edifactMapper = edifactMapper;
this.csvMapper = csvMapper;
}

@Override
protected ExportResourceMapper getExportResourceMapper(VendorEdiOrdersExportConfig ediOrdersExportConfig) {
return switch (ediOrdersExportConfig.getFileFormat()) {
Expand All @@ -62,7 +53,7 @@ protected List<String> getExportConfigMissingFields(VendorEdiOrdersExportConfig
}

@Override
protected ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig, Map<String, Object> jobParameters) {
protected ExportHolder buildEdifactExportHolder(VendorEdiOrdersExportConfig ediExportConfig, Map<String, Object> jobParameters) {
var pieces = ordersService.getPiecesByIdsAndReceivingStatus(ediExportConfig.getClaimPieceIds(), Piece.ReceivingStatusEnum.CLAIM_SENT);
if (pieces.isEmpty()) {
throw new NotFoundException(Piece.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,18 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.folio.dew.batch.acquisitions.edifact.mapper.ExportResourceMapper;
import org.folio.dew.batch.acquisitions.edifact.services.OrdersService;
import org.folio.dew.batch.acquisitions.edifact.services.OrganizationsService;
import org.folio.dew.client.DataExportSpringClient;
import org.folio.dew.domain.dto.ExportConfigCollection;
import org.folio.dew.domain.dto.ExportType;
import org.folio.dew.domain.dto.VendorEdiOrdersExportConfig;
import org.folio.dew.domain.dto.acquisitions.edifact.ExportHolder;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.experimental.SuperBuilder;
import lombok.extern.log4j.Log4j2;

@SuperBuilder
@Component
@StepScope
@Log4j2
Expand All @@ -44,14 +41,6 @@ public class MapToEdifactOrdersTasklet extends MapToEdifactTasklet {
private final DataExportSpringClient dataExportSpringClient;
private final ExportResourceMapper edifactMapper;

public MapToEdifactOrdersTasklet(ObjectMapper ediObjectMapper, OrganizationsService organizationsService, OrdersService ordersService,
DataExportSpringClient dataExportSpringClient,
ExportResourceMapper edifactMapper) {
super(ediObjectMapper, organizationsService, ordersService);
this.edifactMapper = edifactMapper;
this.dataExportSpringClient = dataExportSpringClient;
}

@Override
protected List<String> getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig) {
List<String> missingFields = new ArrayList<>();
Expand All @@ -64,7 +53,7 @@ protected List<String> getExportConfigMissingFields(VendorEdiOrdersExportConfig
}

@Override
protected ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig, Map<String, Object> jobParameters) {
protected ExportHolder buildEdifactExportHolder(VendorEdiOrdersExportConfig ediExportConfig, Map<String, Object> jobParameters) {
var poLineQuery = getPoLineQuery(ediExportConfig);
var compOrders = getCompositeOrders(poLineQuery);
return new ExportHolder(compOrders, List.of());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,31 @@
import org.folio.dew.error.NotFoundException;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.xlate.edi.stream.EDIStreamException;
import lombok.RequiredArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.extern.log4j.Log4j2;

@RequiredArgsConstructor
@SuperBuilder
@Log4j2
public abstract class MapToEdifactTasklet implements Tasklet {
public abstract class MapToEdifactTasklet extends FilterableTasklet {

private final ObjectMapper ediObjectMapper;
private final OrganizationsService organizationsService;
protected final OrdersService ordersService;

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) throws Exception {
log.info("execute:: Executing MapToEdifactTasklet with job: {}", chunkContext.getStepContext().getJobName());
var jobParameters = chunkContext.getStepContext().getJobParameters();
var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class);
validateEdiExportConfig(ediExportConfig);

var holder = buildEdifactExportHolder(chunkContext, ediExportConfig, jobParameters);
var holder = buildEdifactExportHolder(ediExportConfig, jobParameters);
persistPoLineIds(chunkContext, holder.orders());

String jobName = jobParameters.get(JobParameterNames.JOB_NAME).toString();
Expand Down Expand Up @@ -144,7 +143,7 @@ private <T> T convertTo(Object value, Class<T> c) {

protected abstract List<String> getExportConfigMissingFields(VendorEdiOrdersExportConfig ediOrdersExportConfig);

protected abstract ExportHolder buildEdifactExportHolder(ChunkContext chunkContext, VendorEdiOrdersExportConfig ediExportConfig,
Map<String, Object> jobParameters) throws JsonProcessingException, EDIStreamException;
protected abstract ExportHolder buildEdifactExportHolder(VendorEdiOrdersExportConfig ediExportConfig, Map<String, Object> jobParameters)
throws JsonProcessingException, EDIStreamException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE;
import static org.folio.dew.domain.dto.JobParameterNames.ACQ_EXPORT_FILE_NAME;
import static org.folio.dew.domain.dto.JobParameterNames.EDIFACT_ORDERS_EXPORT;
import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.IntegrationTypeEnum.ORDERING;
import static org.folio.dew.domain.dto.VendorEdiOrdersExportConfig.TransmissionMethodEnum.FTP;

Expand All @@ -15,21 +14,20 @@
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.SuperBuilder;
import lombok.extern.log4j.Log4j2;

@RequiredArgsConstructor
@SuperBuilder
@Component
@StepScope
@Log4j2
public class SaveToFileStorageTasklet implements Tasklet {
public class SaveToFileStorageTasklet extends FilterableTasklet {

private static final String SFTP_PROTOCOL = "sftp://";

Expand All @@ -38,15 +36,8 @@ public class SaveToFileStorageTasklet implements Tasklet {

@Override
@SneakyThrows
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
var jobParameters = chunkContext.getStepContext().getJobParameters();
var ediExportConfig = ediObjectMapper.readValue((String) jobParameters.get(EDIFACT_ORDERS_EXPORT), VendorEdiOrdersExportConfig.class);
if (ediExportConfig.getIntegrationType() != ORDERING && ediExportConfig.getTransmissionMethod() != FTP) {
log.info("execute:: Transmission method is not FTP, skipping the step");
return RepeatStatus.FINISHED;
}

String host = ediExportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, "");
public RepeatStatus execute(VendorEdiOrdersExportConfig exportConfig, StepContribution contribution, ChunkContext chunkContext) {
String host = exportConfig.getEdiFtp().getServerAddress().replace(SFTP_PROTOCOL, "");
// skip ftp upload if address not specified
if (StringUtils.isEmpty(host)) {
return RepeatStatus.FINISHED;
Expand All @@ -55,9 +46,19 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon
var stepExecution = chunkContext.getStepContext().getStepExecution();
var fileName = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE_NAME);
var edifactOrderAsString = (String) ExecutionContextUtils.getExecutionVariable(stepExecution, ACQ_EXPORT_FILE);
ftpStorageService.uploadToFtp(ediExportConfig, edifactOrderAsString.getBytes(StandardCharsets.UTF_8), fileName);
ftpStorageService.uploadToFtp(exportConfig, edifactOrderAsString.getBytes(StandardCharsets.UTF_8), fileName);

return RepeatStatus.FINISHED;
}

@Override
protected boolean shouldExecute(VendorEdiOrdersExportConfig exportConfig) {
// Always execute if the integration type is not ORDERING, or execute for other integration types if the transmission method is FTP
if (exportConfig.getIntegrationType() == ORDERING || exportConfig.getTransmissionMethod() == FTP) {
return true;
}
log.info("execute:: Transmission method is not FTP, skipping the step");
return false;
}

}
Loading

0 comments on commit 39a787a

Please sign in to comment.