From 92289f6b9fe4adda6edffa2ec11d4256d529f0e6 Mon Sep 17 00:00:00 2001 From: Raouf MAKHLOUF Date: Sun, 19 Nov 2023 10:23:12 +0100 Subject: [PATCH 1/4] feat: update dependencies --- pom.xml | 23 ++------ run-database-mongo.sh | 23 ++++++++ .../tutorial/batch/BatchConfiguration.java | 15 +++--- .../tutorial/batch/EmployeeItemReader.java | 14 +++-- .../tutorial/batch/EmployeeJobLauncher.java | 23 ++++---- .../listeners/JobCompletionListener.java | 24 ++++----- .../batch/mappers/EmployeeItemRowMapper.java | 17 +++--- .../processors/EmployeeItemProcessor.java | 49 +++++++++-------- .../EmployeeJobParametersValidator.java | 14 ++--- .../excel/tutorial/domain/Employee.java | 40 +++++--------- .../tutorial/service/EmployeeService.java | 3 +- .../support/poi/AbstractExcelPoi.java | 53 +++++++++---------- .../tutorial/support/poi/CellFactory.java | 11 ++-- .../tutorial/support/poi/package-info.java | 3 +- src/main/resources/application.yml | 7 +-- 15 files changed, 149 insertions(+), 170 deletions(-) create mode 100644 run-database-mongo.sh diff --git a/pom.xml b/pom.xml index 1d1ae9f..872689c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.4.4 + 2.7.15 com.springbatch.excel @@ -14,8 +14,8 @@ tutorial Demo project for Spring Boot - 1.8 - 4.1.2 + 20 + 5.2.4 @@ -58,22 +58,5 @@ - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - - diff --git a/run-database-mongo.sh b/run-database-mongo.sh new file mode 100644 index 0000000..3dbb690 --- /dev/null +++ b/run-database-mongo.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +# Exécuter MongoDB Container +docker run -d -p 27017:27017 \ + --name test-mongo \ + -v mongo-data:/data/db \ + -e MONGODB_INITDB_ROOT_USERNAME=admin \ + -e MONGODB_INITDB_ROOT_PASSWORD=pass \ + -e MONGODB_INITDB_DATABASE=spring_batch_excel_mongodb_db \ + mongo:latest + + +# Exécuter MongoDB Express Container +docker run --link test-mongo:mongo \ + -p 8222:8222 \ + -e ME_CONFIG_MONGODB_URL="mongodb://mongo:27017" \ + -e PORT=8222 \ + mongo-express + +# "Utilisateur MongoDB Express: admin" +# "Mot de passe MongoDB Express: pass" + + diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java b/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java index 4932ad7..4fd0338 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java @@ -4,6 +4,7 @@ import com.springbatch.excel.tutorial.batch.processors.EmployeeItemProcessor; import com.springbatch.excel.tutorial.batch.validators.EmployeeJobParametersValidator; import com.springbatch.excel.tutorial.domain.Employee; +import lombok.RequiredArgsConstructor; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParametersValidator; import org.springframework.batch.core.Step; @@ -27,17 +28,13 @@ */ @EnableBatchProcessing @Configuration +@RequiredArgsConstructor public class BatchConfiguration { public final JobBuilderFactory jobBuilderFactory; public final StepBuilderFactory stepBuilderFactory; - public BatchConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { - this.jobBuilderFactory = jobBuilderFactory; - this.stepBuilderFactory = stepBuilderFactory; - } - @Bean public JobParametersValidator jobParametersValidator() { return new EmployeeJobParametersValidator(); @@ -62,13 +59,16 @@ public ItemReader itemReader() { @Bean public MongoItemWriter writer(MongoTemplate mongoTemplate) { - return new MongoItemWriterBuilder().template(mongoTemplate).collection("employee") + return new MongoItemWriterBuilder() + .template(mongoTemplate) + .collection("employee") .build(); } /** * step declaration + * * @return {@link Step} */ @Bean @@ -81,10 +81,9 @@ public Step employeeStep(MongoItemWriter itemWriter) { .build(); } - - /** * job declaration + * * @param listener {@link JobCompletionListener} * @return {@link Job} */ diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeItemReader.java b/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeItemReader.java index 8e7715c..350bc4e 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeItemReader.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeItemReader.java @@ -3,9 +3,8 @@ import com.springbatch.excel.tutorial.batch.mappers.EmployeeItemRowMapper; import com.springbatch.excel.tutorial.domain.Employee; import com.springbatch.excel.tutorial.support.poi.AbstractExcelPoi; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.formula.eval.NotImplementedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.StepExecutionListener; @@ -15,10 +14,9 @@ import java.util.List; +@Slf4j @Component -public class EmployeeItemReader extends AbstractExcelPoi implements ItemReader , StepExecutionListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeItemReader.class); +public class EmployeeItemReader extends AbstractExcelPoi implements ItemReader, StepExecutionListener { private int employeeIndex = 0; @@ -40,7 +38,7 @@ public Employee read() { // read data in file employeeList = read(path, new EmployeeItemRowMapper()); - if(!employeeList.isEmpty()) { + if (!employeeList.isEmpty()) { if (employeeIndex < employeeList.size()) { employee = employeeList.get(employeeIndex); @@ -50,14 +48,14 @@ public Employee read() { } } } catch (Exception e) { - LOGGER.warn("Cannot read the excel file: {}", e.getMessage()); + log.warn("Cannot read the excel file: {}", e.getMessage()); } return employee; } @Override - public void write(String filePath , List aList) { + public void write(String filePath, List aList) { throw new NotImplementedException("No need to implement this method in the context"); } diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeJobLauncher.java b/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeJobLauncher.java index 7b118c5..4dd19f6 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeJobLauncher.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/EmployeeJobLauncher.java @@ -1,7 +1,7 @@ package com.springbatch.excel.tutorial.batch; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; @@ -19,11 +19,11 @@ /** * @author aek */ +@Slf4j @Component +@RequiredArgsConstructor public class EmployeeJobLauncher { - private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeJobLauncher.class); - private final Job job; private final JobLauncher jobLauncher; @@ -31,26 +31,21 @@ public class EmployeeJobLauncher { @Value("${employee.excel.processingfolder}") private String processingDir; - EmployeeJobLauncher(Job job, JobLauncher jobLauncher) { - this.job = job; - this.jobLauncher = jobLauncher; - } - // run every 2 min @Scheduled(fixedRate = 120000) void launchFileToJob() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobInstanceAlreadyCompleteException, JobRestartException { - LOGGER.info("Starting job"); + log.info("Starting job"); String excelFilePath = String.format("%s/employee.xlsx", processingDir); JobParameters params = new JobParametersBuilder() - .addLong("jobId",System.currentTimeMillis()) - .addDate("currentTime",new Date()) - .addString("excelPath",excelFilePath) + .addLong("jobId", System.currentTimeMillis()) + .addDate("currentTime", new Date()) + .addString("excelPath", excelFilePath) .toJobParameters(); jobLauncher.run(job, params); - LOGGER.info("Stopping job"); + log.info("Stopping job"); } } diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java b/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java index 6e0b779..6035a50 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java @@ -1,7 +1,6 @@ package com.springbatch.excel.tutorial.batch.listeners; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.listener.JobExecutionListenerSupport; @@ -9,32 +8,31 @@ import java.util.Date; +@Slf4j @Component public class JobCompletionListener extends JobExecutionListenerSupport { - private static final Logger LOGGER = LoggerFactory.getLogger(JobCompletionListener.class); - @Override public void afterJob(JobExecution jobExecution) { String jobId = jobExecution.getJobParameters().getString("jobId"); String excelFilePath = jobExecution.getJobParameters().getString("excelPath"); - // get job's start time + // get job's start time Date start = jobExecution.getCreateTime(); // get job's end time Date end = jobExecution.getEndTime(); - if(jobExecution.getStatus() == BatchStatus.COMPLETED) { + if (jobExecution.getStatus() == BatchStatus.COMPLETED) { - LOGGER.info("==========JOB FINISHED======="); - LOGGER.info("JobId : {}",jobId); - LOGGER.info("excel Path : {}",excelFilePath); - LOGGER.info("Start Date: {}", start); - LOGGER.info("End Date: {}", end); - LOGGER.info("=============================="); + log.info("==========JOB FINISHED======="); + log.info("JobId : {}", jobId); + log.info("excel Path : {}", excelFilePath); + log.info("Start Date: {}", start); + log.info("End Date: {}", end); + log.info("=============================="); } } -} \ No newline at end of file +} diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/mappers/EmployeeItemRowMapper.java b/src/main/java/com/springbatch/excel/tutorial/batch/mappers/EmployeeItemRowMapper.java index 85419c3..382f7bc 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/mappers/EmployeeItemRowMapper.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/mappers/EmployeeItemRowMapper.java @@ -10,15 +10,12 @@ public class EmployeeItemRowMapper extends CellFactory implements RowMapper implements ItemProcessor, StepExecutionListener { - - private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeItemProcessor.class); +@Slf4j +public class EmployeeItemProcessor extends AbstractExcelPoi implements ItemProcessor, StepExecutionListener { private static final List existingEmployees = new ArrayList<>(); @@ -46,7 +43,7 @@ public class EmployeeItemProcessor extends AbstractExcelPoi implement @Override public Employee process(Employee item) { - if(repository.findByNumber(item.getNumber()).isPresent()){ + if (repository.findByNumber(item.number()).isPresent()) { existingEmployees.add(item); return null; @@ -60,25 +57,32 @@ public void beforeStep(StepExecution stepExecution) { /* Nothing to do before */ } - @SneakyThrows + // @SneakyThrows @Override public ExitStatus afterStep(StepExecution stepExecution) { String jobId = stepExecution.getJobParameters().getString("jobId"); - if(stepExecution.getStatus() == BatchStatus.COMPLETED && !CollectionUtils.isEmpty(existingEmployees)) { + if (stepExecution.getStatus() == BatchStatus.COMPLETED && !CollectionUtils.isEmpty(existingEmployees)) { // create log file. if completed - String path = new ClassPathResource(resultsfolder).getFile().getPath(); - write(String.format("%s/employe-result-%s.xlsx", path, jobId),existingEmployees); + String path = null; + try { + path = new ClassPathResource(resultsfolder).getFile().getPath(); + } catch (IOException e) { + throw new RuntimeException(e); + } + write(String.format("%s/employe-result-%s.xlsx", path, jobId), existingEmployees); } return null; } + /** * Create and write results file. employee duplicate entries + * * @param filePath file path * @param aList list of employee */ @Override - public void write(String filePath , List aList) { + public void write(String filePath, List aList) { try (XSSFWorkbook workbook = new XSSFWorkbook()) { // Create a Sheet Sheet sheet = workbook.createSheet("RESULTS"); @@ -96,28 +100,27 @@ public void write(String filePath , List aList) { "Email", "Number" ); - createHeaderRow(sheet, headers,cellStyle); + createHeaderRow(sheet, headers, cellStyle); // Create Other rows and cells with BeneficiaryExtraction data int rowNum = 1; - for(Employee employee: aList) { + for (Employee employee : aList) { Row row = sheet.createRow(rowNum++); - createCell(row, 0, employee.getFirstName(), null); - createCell(row, 1, employee.getLastName(), null); - createCell(row, 2, employee.getEmail(), null); - createCell(row, 3, employee.getNumber(), null); + createCell(row, 0, employee.firstName(), null); + createCell(row, 1, employee.lastName(), null); + createCell(row, 2, employee.email(), null); + createCell(row, 3, employee.number(), null); } //lets write the excel data to file now try (FileOutputStream outputStream = new FileOutputStream(filePath)) { workbook.write(outputStream); - LOGGER.info("Results File written successfully"); + log.info("Results File written successfully"); } - } - catch (IOException e) { - LOGGER.warn("Cannot write results file: {}", e.getMessage()); - }finally { + } catch (IOException e) { + log.warn("Cannot write results file: {}", e.getMessage()); + } finally { existingEmployees.clear(); } } diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/validators/EmployeeJobParametersValidator.java b/src/main/java/com/springbatch/excel/tutorial/batch/validators/EmployeeJobParametersValidator.java index dc10653..aa781c5 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/validators/EmployeeJobParametersValidator.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/validators/EmployeeJobParametersValidator.java @@ -6,13 +6,13 @@ public class EmployeeJobParametersValidator implements org.springframework.batch.core.JobParametersValidator { - @Override - public void validate(final JobParameters jobParameters) throws JobParametersInvalidException { - String fileName = jobParameters != null ? jobParameters.getString("excelPath") : null; + @Override + public void validate(final JobParameters jobParameters) throws JobParametersInvalidException { + String fileName = jobParameters != null ? jobParameters.getString("excelPath") : null; - if (fileName !=null && !StringUtils.endsWithIgnoreCase(fileName, "xlsx")) { - throw new JobParametersInvalidException("The file type must be in xlsx format"); - } - } + if (fileName != null && !StringUtils.endsWithIgnoreCase(fileName, "xlsx")) { + throw new JobParametersInvalidException("The file type must be in xlsx format"); + } + } } diff --git a/src/main/java/com/springbatch/excel/tutorial/domain/Employee.java b/src/main/java/com/springbatch/excel/tutorial/domain/Employee.java index 15f5ae2..ec88f9d 100644 --- a/src/main/java/com/springbatch/excel/tutorial/domain/Employee.java +++ b/src/main/java/com/springbatch/excel/tutorial/domain/Employee.java @@ -1,37 +1,21 @@ package com.springbatch.excel.tutorial.domain; -import com.sun.istack.internal.NotNull; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.IndexDirection; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; -@Data -@AllArgsConstructor -@NoArgsConstructor -@Accessors(chain = true) @Document(collection = "employee") -public class Employee { - - @Id - private String id; - - private String firstName; - - private String lastName; - - @NotNull - @Indexed(unique = true, direction = IndexDirection.DESCENDING) - private String number; - - private String email; - - private String department; - - private double salary; -} \ No newline at end of file +public record Employee( + @Id + String id, + String firstName, + String lastName, + @Indexed(unique = true, direction = IndexDirection.DESCENDING) + String number, + String email, + String department, + double salary +) { +} diff --git a/src/main/java/com/springbatch/excel/tutorial/service/EmployeeService.java b/src/main/java/com/springbatch/excel/tutorial/service/EmployeeService.java index a36f647..6c17797 100644 --- a/src/main/java/com/springbatch/excel/tutorial/service/EmployeeService.java +++ b/src/main/java/com/springbatch/excel/tutorial/service/EmployeeService.java @@ -1,7 +1,6 @@ package com.springbatch.excel.tutorial.service; - import com.springbatch.excel.tutorial.domain.Employee; import java.util.Optional; @@ -13,4 +12,4 @@ public interface EmployeeService { * @return Optional employee */ Optional getByNumber(String number); -} \ No newline at end of file +} diff --git a/src/main/java/com/springbatch/excel/tutorial/support/poi/AbstractExcelPoi.java b/src/main/java/com/springbatch/excel/tutorial/support/poi/AbstractExcelPoi.java index d871704..0489ab8 100644 --- a/src/main/java/com/springbatch/excel/tutorial/support/poi/AbstractExcelPoi.java +++ b/src/main/java/com/springbatch/excel/tutorial/support/poi/AbstractExcelPoi.java @@ -1,5 +1,6 @@ package com.springbatch.excel.tutorial.support.poi; +import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; @@ -9,26 +10,23 @@ import java.text.ParseException; import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; /** * @param generic Class * @author aek */ +@Slf4j public abstract class AbstractExcelPoi { - private static final Logger LOGGER = Logger.getLogger(AbstractExcelPoi.class.getName()); - /** * @param filePath file path - * @param aList list of object + * @param aList list of object */ public abstract void write(String filePath, List aList); /** * @param filePathStr file path location - * @param rowMapper RowMapper object + * @param rowMapper RowMapper object * @return list of */ public List read(String filePathStr, final RowMapper rowMapper) { @@ -38,20 +36,20 @@ public List read(String filePathStr, final RowMapper rowMapper) { Sheet sheet = workbook.getSheetAt(0); - sheet.forEach(row -> { - // skip header - if (row.getRowNum() != 0){ - try { - bookList.add(rowMapper.transformerRow(row)); - } catch (ParseException exception) { - LOGGER.log(Level.WARNING, "RowMapper Parse exception"); - } + sheet.forEach(row -> { + // skip header + if (row.getRowNum() != 0) { + try { + bookList.add(rowMapper.transformerRow(row)); + } catch (ParseException exception) { + log.warn("RowMapper Parse exception"); } - }); + } + }); return bookList; } catch (IOException e) { - throw new ExcelFileException(String.format("Cannot read the file: %s",e.getMessage())); + throw new ExcelFileException(String.format("Cannot read the file: %s", e.getMessage())); } } @@ -62,7 +60,7 @@ public List read(String filePathStr, final RowMapper rowMapper) { private Workbook getWorkbook(String filePathStr) { Workbook workbook; - try{ + try { try (FileInputStream inputStream = new FileInputStream(new File(filePathStr))) { if (filePathStr.endsWith("xlsx")) { workbook = new XSSFWorkbook(inputStream); @@ -70,7 +68,7 @@ private Workbook getWorkbook(String filePathStr) { throw new ExcelFileException("The specified file is not Excel file"); } } - }catch(SecurityException | IOException e){ + } catch (SecurityException | IOException e) { throw new ExcelFileException("The specified file is not Excel file"); } @@ -78,17 +76,16 @@ private Workbook getWorkbook(String filePathStr) { } - - /** * Create header of file - * @param sheet excel sheet - * @param headers list string of header + * + * @param sheet excel sheet + * @param headers list string of header * @param rowStyle style of header row */ public void createHeaderRow(Sheet sheet, List headers, CellStyle rowStyle) { - if(!headers.isEmpty()){ + if (!headers.isEmpty()) { // Create a Row Row row = sheet.createRow(0); // Create cells @@ -101,10 +98,10 @@ public void createHeaderRow(Sheet sheet, List headers, CellStyle rowStyl } /** - * @param row file row + * @param row file row * @param columnCount index of column - * @param value the value to will set - * @param style cel row + * @param value the value to will set + * @param style cel row * @return Cell value */ public Cell createCell(Row row, int columnCount, Object value, CellStyle style) { @@ -113,14 +110,14 @@ public Cell createCell(Row row, int columnCount, Object value, CellStyle style) cell.setCellValue((Integer) value); } else if (value instanceof Boolean) { cell.setCellValue((Boolean) value); - }else if (value instanceof Double) { + } else if (value instanceof Double) { cell.setCellValue((Double) value); } else { cell.setCellValue((String) value); } - if(style != null){ + if (style != null) { cell.setCellStyle(style); } diff --git a/src/main/java/com/springbatch/excel/tutorial/support/poi/CellFactory.java b/src/main/java/com/springbatch/excel/tutorial/support/poi/CellFactory.java index 584f69a..dc1d271 100644 --- a/src/main/java/com/springbatch/excel/tutorial/support/poi/CellFactory.java +++ b/src/main/java/com/springbatch/excel/tutorial/support/poi/CellFactory.java @@ -9,11 +9,12 @@ /** * Extract cell value + * * @author aek */ public class CellFactory { - private static final EnumMap> + private static final EnumMap> EXCEL_CELL_VALUE = new EnumMap<>(CellType.class); static { @@ -37,13 +38,13 @@ public class CellFactory { * @return Object row */ public Object getCellValue(Cell cell) { - try{ - if(cell == null){ + try { + if (cell == null) { return null; } return EXCEL_CELL_VALUE.get(cell.getCellType()).apply(cell); - }catch (Exception e){ - throw new UnknownCellTypeException(String.format("Unknown cell type ( %s )",cell.getCellType())); + } catch (Exception e) { + throw new UnknownCellTypeException(String.format("Unknown cell type ( %s )", cell.getCellType())); } } diff --git a/src/main/java/com/springbatch/excel/tutorial/support/poi/package-info.java b/src/main/java/com/springbatch/excel/tutorial/support/poi/package-info.java index 4e12456..1ac6d11 100644 --- a/src/main/java/com/springbatch/excel/tutorial/support/poi/package-info.java +++ b/src/main/java/com/springbatch/excel/tutorial/support/poi/package-info.java @@ -1,5 +1,6 @@ /** * Core package for the Apache POI library. + * * @author aek */ -package com.springbatch.excel.tutorial.support.poi; \ No newline at end of file +package com.springbatch.excel.tutorial.support.poi; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7fe2c8b..a0fd8c1 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -3,9 +3,10 @@ spring: mongodb: host: localhost port: 27017 - database: <> - username: <> - password: <> + database: spring_batch_excel_mongodb_db +# username: admin +# password: pass + auto-index-creation: true jackson: default-property-inclusion: NON_NULL From 418be7a2e024b585d1366ffb9477ebcb55ca422c Mon Sep 17 00:00:00 2001 From: Raouf MAKHLOUF Date: Tue, 21 Nov 2023 21:50:23 +0100 Subject: [PATCH 2/4] test: add batch integration test --- pom.xml | 5 -- .../excel/tutorial/BachIntegrationTest.java | 61 ++++++++++++++++++ src/test/resources/application.yml | 26 ++++++++ .../resources/data/processing/employee.txt | 0 .../resources/data/processing/employee.xlsx | Bin 0 -> 16484 bytes src/test/resources/data/results/readme.txt | 0 6 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 src/test/java/com/springbatch/excel/tutorial/BachIntegrationTest.java create mode 100644 src/test/resources/application.yml create mode 100644 src/test/resources/data/processing/employee.txt create mode 100644 src/test/resources/data/processing/employee.xlsx create mode 100644 src/test/resources/data/results/readme.txt diff --git a/pom.xml b/pom.xml index 872689c..23be52a 100644 --- a/pom.xml +++ b/pom.xml @@ -50,11 +50,6 @@ spring-boot-starter-test test - - org.springframework.batch - spring-batch-test - test - diff --git a/src/test/java/com/springbatch/excel/tutorial/BachIntegrationTest.java b/src/test/java/com/springbatch/excel/tutorial/BachIntegrationTest.java new file mode 100644 index 0000000..130a434 --- /dev/null +++ b/src/test/java/com/springbatch/excel/tutorial/BachIntegrationTest.java @@ -0,0 +1,61 @@ +package com.springbatch.excel.tutorial; +import com.springbatch.excel.tutorial.batch.BatchConfiguration; +import com.springbatch.excel.tutorial.batch.listeners.JobCompletionListener; +import com.springbatch.excel.tutorial.domain.Employee; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.*; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + + + +@ExtendWith(SpringExtension.class) +@EnableBatchProcessing +@ComponentScan(basePackages = "com.springbatch.excel.tutorial") +@SpringBootTest(classes = {BatchConfiguration.class, JobCompletionListener.class}) +class BatchIntegrationTest { + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private Job jsonFileProcessingJob; + + @Autowired + private MongoTemplate mongoTemplate; + + @Test + void testBatchJob() throws Exception { + String absolutePath = Objects.requireNonNull(getClass().getResource("/data/processing/employee.xlsx")).getPath(); + + // Créez les paramètres du job + Map jobParameters = new HashMap<>(); + jobParameters.put("filePath", new JobParameter(absolutePath)); + jobParameters.put("currentTime", new JobParameter(new Date())); + + // Lancez le job avec les paramètres + JobExecution jobExecution = jobLauncher.run(jsonFileProcessingJob,new JobParameters(jobParameters)); + + // Vérifiez que le job s'est terminé avec succès + assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo("COMPLETED"); + + List couponOffers = mongoTemplate.findAll(Employee.class); + assertThat(couponOffers.size()).isEqualTo(100); + + } +} + + diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..a0fd8c1 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,26 @@ +spring: + data: + mongodb: + host: localhost + port: 27017 + database: spring_batch_excel_mongodb_db +# username: admin +# password: pass + auto-index-creation: true + + jackson: + default-property-inclusion: NON_NULL +#disabled job run at startup + batch: + job: + enabled: false + +# Enable Logging mongo queries +logging: + level: + org.springframework.data.mongodb.core.MongoTemplate: DEBUG + +employee: + excel: + processingfolder: data/processing/ + resultsfolder: data/results/ diff --git a/src/test/resources/data/processing/employee.txt b/src/test/resources/data/processing/employee.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/test/resources/data/processing/employee.xlsx b/src/test/resources/data/processing/employee.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..312ae9a43ce457aaba6ae0465bf793eed7e37fc1 GIT binary patch literal 16484 zcmeHuWmH_-vM%l(+@&G7yIXK~2@u?!;0f;T?(QzZ-Q9z`yCwvA&EEUmeNOIvZ@mBa zHe+=6V$E5rX4O|UXO}2QgF~Q$K!L!3fPj#I2yysM+JJ(9KtO_kyaRy&(-yI{aWb}X z(o=D>Gj`OWceS=6&V>M@%mx7ij{o1+|6mD}s|?%pFru`p9}9?fsDV>JMcdpML&U*4N2s@A}ClPg+HYE#_sVpl9vXbKDNSkXUf$^$;Z7e!P!T=6|i zWPR|>FIS7GiwB_+pXtA}Gb=)RUa5-tlC5Fu};-Y*6F zxpcxe+@lF5P4yYufYa4ai4Iq4UA?VMk(oseP?hFLph_SA5J81rqwuZ%kx24*WClH3 zr^XD2TZBl^yd1RHnwbcJB@h;+h6(+e*wh<}fo!d1q?sA6ciGkR(}_5COU6!R<7d4m z9^dKcaMf)2`C6B67Q0dKHz|%cr>sK-6(MvZTE?ex53nz;*v6iBwzT;-SU!`7#FL7|hp<<-Y8+UXSijq9M?dL$G%)>M={aOYa`zKgRoRToyxJhsft%D#&&aCl zMl`MS-Log1T>6j_DJ$9!=1K8E^6Wb=t$Nn0(G0gf4%ptZq03?4Frwmh;Ewg*jl_pP zKIsN1krtql;DW$_x>_;(X(ukW4weSCww7USpw(o@wFWSHT4suce=IZjYsA*tx? zx0ygziwVZh%odJQ1S3GqjMndZKl&@5R`}L8H4&#$ne4rO6Ir>3%JOw1n!dq-mE=Wq z1DQUYBcb`x{ox+wy6wqC)@{PFJMR%;55G*Bu#}C@Gth}RXh@vMiz?P}FE^!C^q~3P$pmB|XUw|p zdPVw&q9GW~WXgGk84)!YuBpq`hZbQ9&1lo=)c7B!0p)@g>ty-&bl4_!F zei|y9RA1CbmJ!VoT;V@LIxo)oFsjO;SeE2_9Sd@miMlt;5APYHG zu;6)#D(GkJ(sbCP57^7Q@vle(Ab^Lx_opqD4K0lwc*L~}pa(=A`n@Fj;F%=p=Sp5JL_#bvkJ7EG<5$ae?$ZzE z5(Lg+dU)nBGSi9H{CNz)=nLmip2N6h%pDRp9^$t*YZI(}d_;iHKeuNc?zr^wp!Y-E z=+7(&()b;zt=-g zj#y6SosAs;w?IgtBuYi(ppXMM0c6qe6{QAXblSqRR;!YJK;XqzAXiFis{Izr(R~pg2bh11MxITR~k0t$ZB^RqyLoj$Hu0&&Q@(2}E?Vk!z@wMA|dGr8L zYV6fnn{eWW#qkbXt23RXzuiwFlKpZ^$&=^w>z)&?XNT;2VvEw*{@GPi712u_CqHw$ z8I9tJS_j|P*!>?#F0U_(c!rN;<<{dXJJuT)FCGpCBNbNuu(xuJu8vi$Vz)mmo4A-- z%Y2Otk6!pdd!lO3YnU2@eUe-LQ9_13Q z$0c9S$3r~Wc{?#m(Po1j$bMy`rm3Mv6c^OwqCMostVbUSbfAt<)?U=w3^j_e^L&R~ zB3Ne(C@*M9vfh*9SaZ5l5!lunwt3ucrz66hcc`*xsA+)7r_<8jK`uZ#?R9!CISjWc zl4s!lHoZ1`TSE!nsj6=@zhYA)LnA%0Dxd55sgZAOL{30rJ6&qAg+|NxSg(Q^X6Xxb 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 l|8(4clLP_L Date: Sat, 27 Jan 2024 23:06:45 +0100 Subject: [PATCH 3/4] feat: use docker-compose.yaml --- docker-compose.yaml | 20 ++++++++++++++++++++ run-database-mongo.sh | 23 ----------------------- 2 files changed, 20 insertions(+), 23 deletions(-) create mode 100644 docker-compose.yaml delete mode 100644 run-database-mongo.sh diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..e7f9026 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,20 @@ +version: "2.2" +services: + mongo: + image: mongo:5.0 + container_name: mongo + restart: unless-stopped + ports: + - "27017:27017" + + mongo-express: + image: mongo-express:latest + container_name: mongo-express + environment: + - ME_CONFIG_MONGODB_URL=mongodb://mongo:27017/?authSource=admin + - ME_CONFIG_BASICAUTH_USERNAME=admin + - ME_CONFIG_BASICAUTH_PASSWORD=pass + links: + - mongo + ports: + - "8081:8081" diff --git a/run-database-mongo.sh b/run-database-mongo.sh deleted file mode 100644 index 3dbb690..0000000 --- a/run-database-mongo.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -# Exécuter MongoDB Container -docker run -d -p 27017:27017 \ - --name test-mongo \ - -v mongo-data:/data/db \ - -e MONGODB_INITDB_ROOT_USERNAME=admin \ - -e MONGODB_INITDB_ROOT_PASSWORD=pass \ - -e MONGODB_INITDB_DATABASE=spring_batch_excel_mongodb_db \ - mongo:latest - - -# Exécuter MongoDB Express Container -docker run --link test-mongo:mongo \ - -p 8222:8222 \ - -e ME_CONFIG_MONGODB_URL="mongodb://mongo:27017" \ - -e PORT=8222 \ - mongo-express - -# "Utilisateur MongoDB Express: admin" -# "Mot de passe MongoDB Express: pass" - - From 67dc415f1483bbd0d8942d6cc83031cab69a29db Mon Sep 17 00:00:00 2001 From: Raouf MAKHLOUF Date: Sun, 28 Jan 2024 02:27:42 +0100 Subject: [PATCH 4/4] feat: upgrade spring boot batch --- pom.xml | 15 ++++++- .../excel/tutorial/TutorialApplication.java | 3 +- .../tutorial/batch/BatchConfiguration.java | 43 ++++++++++--------- .../listeners/JobCompletionListener.java | 8 ++-- .../processors/EmployeeItemProcessor.java | 3 +- src/main/resources/application.yml | 16 +++++++ 6 files changed, 57 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 23be52a..cd7beab 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.15 + 3.2.1 com.springbatch.excel @@ -14,7 +14,7 @@ tutorial Demo project for Spring Boot - 20 + 21 5.2.4 @@ -43,6 +43,8 @@ org.projectlombok lombok + 1.18.30 + provided true @@ -50,7 +52,16 @@ spring-boot-starter-test test + + com.h2database + h2 + + + + org.springframework.boot + spring-boot-starter-data-jpa + diff --git a/src/main/java/com/springbatch/excel/tutorial/TutorialApplication.java b/src/main/java/com/springbatch/excel/tutorial/TutorialApplication.java index 60266aa..dd18e4d 100644 --- a/src/main/java/com/springbatch/excel/tutorial/TutorialApplication.java +++ b/src/main/java/com/springbatch/excel/tutorial/TutorialApplication.java @@ -2,11 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.scheduling.annotation.EnableScheduling; @EnableScheduling -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +@SpringBootApplication public class TutorialApplication { public static void main(String[] args) { diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java b/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java index 4fd0338..a009015 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/BatchConfiguration.java @@ -8,11 +8,11 @@ import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParametersValidator; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.job.CompositeJobParametersValidator; +import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.data.MongoItemWriter; @@ -20,20 +20,21 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.transaction.PlatformTransactionManager; import java.util.Collections; /** * Configuration for batch */ -@EnableBatchProcessing @Configuration @RequiredArgsConstructor public class BatchConfiguration { - public final JobBuilderFactory jobBuilderFactory; + public final JobRepository jobRepository; + public final MongoTemplate mongoTemplate; + public final PlatformTransactionManager transactionManager; - public final StepBuilderFactory stepBuilderFactory; @Bean public JobParametersValidator jobParametersValidator() { @@ -58,7 +59,7 @@ public ItemReader itemReader() { } @Bean - public MongoItemWriter writer(MongoTemplate mongoTemplate) { + public MongoItemWriter writerMongo() { return new MongoItemWriterBuilder() .template(mongoTemplate) .collection("employee") @@ -66,33 +67,33 @@ public MongoItemWriter writer(MongoTemplate mongoTemplate) { } - /** - * step declaration - * - * @return {@link Step} - */ @Bean - public Step employeeStep(MongoItemWriter itemWriter) { - return stepBuilderFactory.get("employeeStep") - .chunk(50) + public Step employeeStep() { + return new StepBuilder("employeeStep", jobRepository) + .chunk(50, transactionManager) .reader(itemReader()) .processor(itemProcessor()) - .writer(itemWriter) + .writer(writerMongo()) .build(); } + @Bean + public JobCompletionListener listener() { + return new JobCompletionListener(); + } + + /** * job declaration * - * @param listener {@link JobCompletionListener} * @return {@link Job} */ @Bean - public Job employeeJob(JobCompletionListener listener, Step employeeStep) { - return jobBuilderFactory.get("employeeJob") + public Job employeeJob() { + return new JobBuilder("employeeJob", jobRepository) .incrementer(new RunIdIncrementer()) - .listener(listener) - .flow(employeeStep) + .listener(listener()) + .flow(employeeStep()) .end() .validator(compositeJobParametersValidator()) .build(); diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java b/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java index 6035a50..5499a86 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/listeners/JobCompletionListener.java @@ -6,7 +6,7 @@ import org.springframework.batch.core.listener.JobExecutionListenerSupport; import org.springframework.stereotype.Component; -import java.util.Date; +import java.time.LocalDateTime; @Slf4j @Component @@ -15,13 +15,13 @@ public class JobCompletionListener extends JobExecutionListenerSupport { @Override public void afterJob(JobExecution jobExecution) { - String jobId = jobExecution.getJobParameters().getString("jobId"); + String jobId = jobExecution.getJobParameters().getParameter("jobId").toString(); String excelFilePath = jobExecution.getJobParameters().getString("excelPath"); // get job's start time - Date start = jobExecution.getCreateTime(); + LocalDateTime start = jobExecution.getCreateTime(); // get job's end time - Date end = jobExecution.getEndTime(); + LocalDateTime end = jobExecution.getEndTime(); if (jobExecution.getStatus() == BatchStatus.COMPLETED) { diff --git a/src/main/java/com/springbatch/excel/tutorial/batch/processors/EmployeeItemProcessor.java b/src/main/java/com/springbatch/excel/tutorial/batch/processors/EmployeeItemProcessor.java index aff6225..87f8a00 100644 --- a/src/main/java/com/springbatch/excel/tutorial/batch/processors/EmployeeItemProcessor.java +++ b/src/main/java/com/springbatch/excel/tutorial/batch/processors/EmployeeItemProcessor.java @@ -45,7 +45,6 @@ public Employee process(Employee item) { if (repository.findByNumber(item.number()).isPresent()) { existingEmployees.add(item); - return null; } @@ -60,7 +59,7 @@ public void beforeStep(StepExecution stepExecution) { // @SneakyThrows @Override public ExitStatus afterStep(StepExecution stepExecution) { - String jobId = stepExecution.getJobParameters().getString("jobId"); + String jobId = stepExecution.getJobParameters().getParameter("jobId").getValue().toString(); if (stepExecution.getStatus() == BatchStatus.COMPLETED && !CollectionUtils.isEmpty(existingEmployees)) { // create log file. if completed diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a0fd8c1..a7b8a04 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,15 @@ spring: + h2: + console: + enabled: true + datasource: + url: jdbc:h2:mem:batch-sample;MODE=Oracle;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1 + driverClassName: org.h2.Driver + username: sa + password: qaz@123 + jpa: + database-platform: org.hibernate.dialect.H2Dialect + data: mongodb: host: localhost @@ -14,6 +25,9 @@ spring: batch: job: enabled: false + initialize-schema: never + initializer: + enabled: false # Enable Logging mongo queries logging: @@ -24,3 +38,5 @@ employee: excel: processingfolder: data/processing/ resultsfolder: data/results/ +file: + input: countries.csv