Я работаю над приложением Spring Batch и реализовал собственный Partitioner, чтобы разделить обработку на несколько потоков. У меня возникли проблемы с написанием теста JUnit 4 для моего partition метод. Я издевался над своим DataSource и JdbcTemplate, но я не уверен, что я утверждаю правильные условия или правильна ли моя настройка. Этот код проверяет количество вхождений чего-либо, что может быть чем угодно, от записей до событий, как указано методом по dto (объекту передачи данных). Вот что делает логика, описанная простыми словами:
Код запрашивает у dto количество вхождений с помощью метода dto.getNumOfOccur().
Если количество вхождений равно нулю (это означает, что вхождений не было), код устанавливает для dto статус «НОВЫЙ», указывая, что все, что проверяется, является новым или не происходило ранее.
Если какое-либо число больше нуля (это означает, что произошло хотя бы одно событие), статус устанавливается на «СУЩЕСТВУЕТ», что указывает на то, что событие не является новым и происходило раньше.
Этот статус устанавливается с помощью метода dto.setNeworexist() с указанием «NEW» или «EXISTS» в качестве
```
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 lombok.extern.slf4j.Slf4j;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.io.IOException;
@Component
@StepScope
@Slf4j
public class LetterAggregatorTasklet implements Tasklet {
private static final String HEADER_FORMAT = "H %s SST TO MMPS FILE";
private static final String TRAILER_FORMAT = "T TOTAL RECORD COUNT %015d";
private static final DateTimeFormatter HEADER_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH.mm.ss");
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
String sourceDir = chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().getString("sourceDir");
validateDirectoryPath(sourceDir);
List letterTypes = List.of("NN3", "NN5", "NN8", "NN14", "NN28", "NN30");
for (String letterType : letterTypes) {
aggregateFilesForLetterType(sourceDir, letterType);
}
return RepeatStatus.FINISHED;
}
private void validateDirectoryPath(String path) {
if (path == null || path.trim().isEmpty()) {
throw new IllegalStateException("File directory path must not be null or empty for file watcher configuration");
}
}
private void aggregateFilesForLetterType(String sourceDir, String letterType) throws IOException {
Path sourcePath = Paths.get(sourceDir);
Pattern pattern = Pattern.compile(".*" + letterType + "Letter\\.txt");
try (Stream fileStream = Files.list(sourcePath)) {
List matchingFiles = fileStream
.filter(filePath -> pattern.matcher(filePath.getFileName().toString()).matches())
.sorted() // Ensure files are processed in a sorted order
.collect(Collectors.toList());
if (matchingFiles.isEmpty()) {
log.warn("No files found for letter type: {}", letterType);
return;
}
StringBuilder aggregatedContent = new StringBuilder();
String header = String.format(HEADER_FORMAT, LocalDateTime.now().format(HEADER_DATE_FORMAT));
aggregatedContent.append(header).append(System.lineSeparator());
int totalRecordsCount = 0;
for (Path filePath : matchingFiles) {
try {
List lines = Files.readAllLines(filePath);
if (lines.size() > 2) {
// Append all lines except the header and trailer
for (int i = 1; i < lines.size() - 1; i++) {
aggregatedContent.append(lines.get(i)).append(System.lineSeparator());
totalRecordsCount++;
}
}
log.info("Read and appended content from file: {}", filePath.getFileName());
} catch (IOException e) {
log.error("Error reading file: {}", filePath.getFileName(), e);
}
}
// Add the trailer with the total records count
String trailer = String.format(TRAILER_FORMAT, totalRecordsCount);
aggregatedContent.append(trailer).append(System.lineSeparator());
Path outputPath = sourcePath.resolve(letterType + "Letter.txt");
try {
Files.write(outputPath, aggregatedContent.toString().getBytes());
log.info("Aggregated content written to file: {}", outputPath.getFileName());
} catch (IOException e) {
log.error("Error writing to output file: {}", outputPath.getFileName(), e);
}
// Delete the temporary partitioned files
for (Path filePath : matchingFiles) {
if (!filePath.equals(outputPath)) { // Ensure not to delete the main file
try {
Files.delete(filePath);
log.info("Deleted temporary file: {}", filePath.getFileName());
} catch (NoSuchFileException e) {
log.error("File not found: {}", filePath.getFileName());
} catch (IOException e) {
log.error("Error deleting file: {}", filePath.getFileName(), e);
}
}
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... better-way