From 0f260beda0c9cd96e83bfd911ae05d4b7438bb70 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 19 Nov 2018 23:37:59 +0700 Subject: [PATCH 1/3] spring batch --- kanban-server/build.gradle | 2 + .../spring/hw/kanban/KanbanApplication.java | 37 +++++++ .../kanban/conversion/BoardItemProcessor.java | 65 +++++++++++ .../NoPersistenceBatchConfigurer.java | 16 +++ .../kanban/conversion/ToMongoBatchConfig.java | 104 ++++++++++++++++++ .../spring/hw/kanban/domain/mongo/Board.java | 78 +++++++++++++ .../spring/hw/kanban/domain/mongo/Stage.java | 79 +++++++++++++ .../spring/hw/kanban/domain/mongo/Task.java | 76 +++++++++++++ .../hw/kanban/repository/BoardRepository.java | 3 + .../mongo/BoardMongoRepository.java | 15 +++ .../src/main/resources/application.properties | 9 +- 11 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/NoPersistenceBatchConfigurer.java create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Board.java create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Stage.java create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Task.java create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/mongo/BoardMongoRepository.java diff --git a/kanban-server/build.gradle b/kanban-server/build.gradle index 5cbd60c..87cd1b1 100644 --- a/kanban-server/build.gradle +++ b/kanban-server/build.gradle @@ -62,6 +62,8 @@ dependencies { compile 'org.springframework.security:spring-security-config:5.0.7.RELEASE' compile 'org.springframework:spring-context-support:5.0.7.RELEASE' compile 'net.sf.ehcache:ehcache-core:2.6.11' + compile("org.springframework.boot:spring-boot-starter-batch") + implementation('org.springframework.boot:spring-boot-starter-data-mongodb:2.0.3.RELEASE') // compile 'org.liquibase:liquibase-core:3.6.2' diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/KanbanApplication.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/KanbanApplication.java index 4f098ff..e6605b3 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/KanbanApplication.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/KanbanApplication.java @@ -1,10 +1,21 @@ package ru.otus.spring.hw.kanban; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersInvalidException; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRestartException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.security.crypto.password.PasswordEncoder; +import ru.otus.spring.hw.kanban.conversion.ToMongoBatchConfig; import ru.otus.spring.hw.kanban.security.UserAccount; import ru.otus.spring.hw.kanban.security.UserAccountRepository; @@ -13,6 +24,10 @@ @SpringBootApplication(scanBasePackages = "ru.otus.spring.hw.kanban") @EnableJpaRepositories(basePackages = {"ru.otus.spring.hw.kanban.repository", "ru.otus.spring.hw.kanban.security"}) +@EnableMongoRepositories(basePackages = {"ru.otus.spring.hw.kanban.repository.mongo"}) + +@Configuration +@Import(ToMongoBatchConfig.class) public class KanbanApplication { public static void main(String[] args) { @@ -26,6 +41,17 @@ public static void main(String[] args) { @Autowired PasswordEncoder encoder; + + @Autowired + private JobLauncher jobLauncher; + + @Autowired + private Job convertBoardsJob; + + public void start() throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException { + jobLauncher.run(convertBoardsJob, new JobParameters()); + } + @PostConstruct public void initAdmin() { if (repository.findByUsername("admin") == null) { @@ -35,5 +61,16 @@ public void initAdmin() { .build(); repository.save(acc); } + try { + start(); + } catch (JobParametersInvalidException e) { + e.printStackTrace(); + } catch (JobExecutionAlreadyRunningException e) { + e.printStackTrace(); + } catch (JobRestartException e) { + e.printStackTrace(); + } catch (JobInstanceAlreadyCompleteException e) { + e.printStackTrace(); + } } } diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java new file mode 100644 index 0000000..8adb37e --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java @@ -0,0 +1,65 @@ +package ru.otus.spring.hw.kanban.conversion; + +import org.springframework.batch.item.ItemProcessor; +import org.springframework.beans.factory.annotation.Autowired; +import ru.otus.spring.hw.kanban.domain.Board; +import ru.otus.spring.hw.kanban.domain.Stage; +import ru.otus.spring.hw.kanban.domain.Task; +import ru.otus.spring.hw.kanban.repository.StageRepository; +import ru.otus.spring.hw.kanban.repository.TaskRepository; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.springframework.stereotype.Service; + +@Service +public class BoardItemProcessor implements ItemProcessor { + + + @Autowired + StageRepository stageRepository; + + @Autowired + TaskRepository taskRepository; + + @Override + public ru.otus.spring.hw.kanban.domain.mongo.Board process(Board board) throws Exception { + ru.otus.spring.hw.kanban.domain.mongo.Board mongoBoard = new ru.otus.spring.hw.kanban.domain.mongo.Board(); + mongoBoard.setName(board.getName()); + + List stages = stageRepository.findStagesByBoard(board); + Set mongoStages = new HashSet<>(); + + Function convert = (task) -> { + ru.otus.spring.hw.kanban.domain.mongo.Task mongoTask = new ru.otus.spring.hw.kanban.domain.mongo.Task(); + mongoTask.setDescription(task.getDescription()); + mongoTask.setExecutor(task.getExecutor()); + mongoTask.setName(task.getName()); + mongoTask.setPriority(task.getPriority()); + return mongoTask; + }; + + for (Stage stage : stages) { + ru.otus.spring.hw.kanban.domain.mongo.Stage mongoStage = new ru.otus.spring.hw.kanban.domain.mongo.Stage(); + mongoStage.setDescription(stage.getDescription()); + mongoStage.setName(stage.getName()); + + + mongoStage.setTasks( + taskRepository.findAllByStage(stage) + .stream() + .map(task -> convert.apply(task)) + .collect(Collectors.toSet()) + ); + mongoStages.add(mongoStage); + + } + mongoBoard.setStages(mongoStages); + return mongoBoard; + + + } +} diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/NoPersistenceBatchConfigurer.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/NoPersistenceBatchConfigurer.java new file mode 100644 index 0000000..c85a277 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/NoPersistenceBatchConfigurer.java @@ -0,0 +1,16 @@ +package ru.otus.spring.hw.kanban.conversion; + +//public class NoPersistenceBatchConfigurer { +//} + +import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; + +@Component +public class NoPersistenceBatchConfigurer extends DefaultBatchConfigurer { + @Override + public void setDataSource(DataSource dataSource) { + } +} diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java new file mode 100644 index 0000000..0fcf778 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java @@ -0,0 +1,104 @@ +package ru.otus.spring.hw.kanban.conversion; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.batch.core.ItemReadListener; +import org.springframework.batch.core.ItemWriteListener; +import org.springframework.batch.core.Job; +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.scope.context.ChunkContext; +import org.springframework.batch.item.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.otus.spring.hw.kanban.conversion.BoardItemProcessor; +import ru.otus.spring.hw.kanban.domain.Board; +import ru.otus.spring.hw.kanban.repository.BoardRepository; +import ru.otus.spring.hw.kanban.repository.mongo.BoardMongoRepository; +import org.springframework.batch.core.*; + +import java.util.List; + +@EnableBatchProcessing +public class ToMongoBatchConfig { + + private final Logger logger = LoggerFactory.getLogger("Batch"); + + @Autowired + public JobBuilderFactory jobBuilderFactory; + + @Autowired + public StepBuilderFactory stepBuilderFactory; + + + @Autowired + BoardItemProcessor boardItemProcessor; + + @Autowired + BoardRepository boardRepository; + @Autowired + BoardMongoRepository boardMongoRepository; + + @Bean + public ItemReader reader() { + return new ItemReader() { + + private Integer currentId = 0; + + @Override + public Board read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { + Board board = boardRepository.findFirstByIdGreaterThan(currentId).orElse(null); + if (board != null) { + currentId = board.getId(); + } + + return board; + } + }; + } + + @Bean + public ItemWriter writer() { + return items -> items.forEach(o -> boardMongoRepository.save(o)); + } + + @Bean + public Step step1() { + return stepBuilderFactory.get("step1") + .chunk(5) + .reader(reader()) + .processor(boardItemProcessor) + .writer(writer()) + .listener(new ItemReadListener() { + public void beforeRead() { logger.info("Начало чтения"); } + public void afterRead(Board o) { logger.info("Конец чтения " + o.toString()); } + public void onReadError(Exception e) { logger.info("Ошибка чтения"); } + }) + .listener(new ItemWriteListener() { + public void beforeWrite(List list) { logger.info("Начало записи"); } + public void afterWrite(List list) { logger.info("Конец записи"); } + public void onWriteError(Exception e, List list) { logger.info("Ошибка записи"); } + }) + .listener(new ItemProcessListener() { + public void beforeProcess(Object o) {logger.info("Начало обработки");} + public void afterProcess(Object o, Object o2) {logger.info("Конец обработки");} + public void onProcessError(Object o, Exception e) {logger.info("Ошбка обработки");} + }) + .listener(new ChunkListener() { + public void beforeChunk(ChunkContext chunkContext) {logger.info("Начало пачки");} + public void afterChunk(ChunkContext chunkContext) {logger.info("Конец пачки");} + public void afterChunkError(ChunkContext chunkContext) {logger.info("Ошибка пачки");} + }) + .build(); + } + + @Bean + public Job convertBoardsJob() { + return jobBuilderFactory.get("convertBoardsJob") + .start(step1()) + .build(); + } +} diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Board.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Board.java new file mode 100644 index 0000000..70d6a29 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Board.java @@ -0,0 +1,78 @@ +package ru.otus.spring.hw.kanban.domain.mongo; + +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +@Document +public class Board { + + private Set stages; + private String name; + private String id; + + + public Board(String name, Set stages) { + this.stages = stages; + this.name = name; + } + + public Board(String name) { + this.name = name; + } + + public Board() { + } + + public Set getStages() { + if (stages == null) { + stages = new HashSet<>(); + } + + return stages; + } + + public void addStage(Stage stage) { + UUID uuid = UUID.randomUUID(); + stage.setId(uuid.toString()); + stage.setOrder(this.getStages().size()); + this.getStages().add(stage); + } + + + public void setStages(Set stages) { + this.stages = stages; +// this.stages.forEach(stage -> stage.setId(UUID.randomUUID().toString())); + } + + @Override + public String toString() { + return "Board{" + + "stages=" + stages + + ", name='" + name + '\'' + + ", id=" + id + + '}'; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void clearStages() { + this.getStages().clear(); + } +} diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Stage.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Stage.java new file mode 100644 index 0000000..dbd3147 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Stage.java @@ -0,0 +1,79 @@ +package ru.otus.spring.hw.kanban.domain.mongo; + +import org.springframework.data.annotation.Id; + +import java.util.HashSet; +import java.util.Set; + +public class Stage { + + private String id; + private String name; + private String description; + private Set tasks; + private int order; + + public Stage(String name, String description, Board board) { + this.name = name; + this.description = description; + } + + public Stage() { + } + + public Stage(String name, String description) { + this.name = name; + this.description = description; + } + + public Set getTasks() { + if (tasks != null) + return tasks; + return new HashSet<>(); + } + + public void setTasks(Set tasks) { + this.tasks = tasks; + } + + @Override + public String toString() { + return "Stage{" + + "id=" + id + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + '}'; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } +} diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Task.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Task.java new file mode 100644 index 0000000..dcfbf14 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/mongo/Task.java @@ -0,0 +1,76 @@ +package ru.otus.spring.hw.kanban.domain.mongo; + +public class Task { + + private String id; + + private String name; + + private String description; + + private String executor; + + private int priority; + + @Override + public String toString() { + return "Task{" + + "id=" + id + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", executor='" + executor + '\'' + + ", priority=" + priority + + '}'; + } + + public Task() { + } + + public Task(String name, String description, String executor, int priority) { + this.name = name; + this.description = description; + this.executor = executor; + this.priority = priority; + } + + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getExecutor() { + return executor; + } + + public void setExecutor(String executor) { + this.executor = executor; + } +} diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardRepository.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardRepository.java index 0b5c3bb..3653387 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardRepository.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardRepository.java @@ -4,9 +4,12 @@ import ru.otus.spring.hw.kanban.domain.Board; import java.util.List; +import java.util.Optional; public interface BoardRepository extends CrudRepository { List findBoardsByNameLike(String name); List findAll(); + Optional findFirstByIdGreaterThan(Integer id); + } diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/mongo/BoardMongoRepository.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/mongo/BoardMongoRepository.java new file mode 100644 index 0000000..cffcd84 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/mongo/BoardMongoRepository.java @@ -0,0 +1,15 @@ +package ru.otus.spring.hw.kanban.repository.mongo; + + +import org.springframework.data.mongodb.repository.MongoRepository; +import ru.otus.spring.hw.kanban.domain.mongo.Board; + +import java.util.List; + +public interface BoardMongoRepository extends MongoRepository { + List findBoardsByNameLike(String name); + + List findAll(); + + +} diff --git a/kanban-server/src/main/resources/application.properties b/kanban-server/src/main/resources/application.properties index c9e7a13..4bdaf2f 100644 --- a/kanban-server/src/main/resources/application.properties +++ b/kanban-server/src/main/resources/application.properties @@ -9,4 +9,11 @@ spring.datasource.username=sa spring.datasource.password= spring.jpa.hibernate.ddl-auto=none logging.level.org.springframework.security=DEBUG -#server.port=8090 \ No newline at end of file +#server.port=8090 + + +spring.data.mongodb.authentication-database=admin +spring.data.mongodb.port=27017 +spring.data.mongodb.host=localhost +spring.data.mongodb.database=kanban + From 1db484c7ac56676fb2d9e680750444686f8d488d Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 20 Nov 2018 22:36:19 +0700 Subject: [PATCH 2/3] fix two remarks --- .../kanban/conversion/ToMongoBatchConfig.java | 124 +++++++++++++----- .../repository/BoardPagingRepository.java | 7 + 2 files changed, 96 insertions(+), 35 deletions(-) create mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java index 0fcf778..749f333 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java @@ -1,26 +1,32 @@ package ru.otus.spring.hw.kanban.conversion; +import com.mongodb.MongoClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.batch.core.ItemReadListener; -import org.springframework.batch.core.ItemWriteListener; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; +import org.springframework.batch.core.*; 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.scope.context.ChunkContext; -import org.springframework.batch.item.*; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.data.MongoItemWriter; +import org.springframework.batch.item.data.RepositoryItemReader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.otus.spring.hw.kanban.conversion.BoardItemProcessor; +import org.springframework.data.domain.Sort; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import ru.otus.spring.hw.kanban.domain.Board; +import ru.otus.spring.hw.kanban.repository.BoardPagingRepository; import ru.otus.spring.hw.kanban.repository.BoardRepository; import ru.otus.spring.hw.kanban.repository.mongo.BoardMongoRepository; -import org.springframework.batch.core.*; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @EnableBatchProcessing public class ToMongoBatchConfig { @@ -38,33 +44,49 @@ public class ToMongoBatchConfig { BoardItemProcessor boardItemProcessor; @Autowired - BoardRepository boardRepository; + BoardPagingRepository boardPagingRepository; + + @Autowired BoardMongoRepository boardMongoRepository; - @Bean public ItemReader reader() { - return new ItemReader() { + RepositoryItemReader reader = new RepositoryItemReader<>(); + reader.setRepository(boardPagingRepository); + reader.setMethodName("findAll"); + List parameters = new ArrayList(); + reader.setArguments(parameters); + Map sort = new HashMap<>(); + sort.put("id", Sort.Direction.ASC); + reader.setSort(sort); + return reader; + } - private Integer currentId = 0; + @Bean + public ItemWriter writer() { + MongoItemWriter writer = new MongoItemWriter<>(); + try { + writer.setTemplate(mongoTemplate()); + } catch (Exception e) { + logger.error(e.toString()); + } + writer.setCollection("board"); + return writer; + } - @Override - public Board read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { - Board board = boardRepository.findFirstByIdGreaterThan(currentId).orElse(null); - if (board != null) { - currentId = board.getId(); - } - return board; - } - }; + @Bean + public MongoDbFactory mongoDbFactory() throws Exception { + return new SimpleMongoDbFactory(new MongoClient(), "kanban"); } @Bean - public ItemWriter writer() { - return items -> items.forEach(o -> boardMongoRepository.save(o)); + public MongoTemplate mongoTemplate() throws Exception { + MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory()); + return mongoTemplate; } + @Bean public Step step1() { return stepBuilderFactory.get("step1") @@ -73,24 +95,56 @@ public Step step1() { .processor(boardItemProcessor) .writer(writer()) .listener(new ItemReadListener() { - public void beforeRead() { logger.info("Начало чтения"); } - public void afterRead(Board o) { logger.info("Конец чтения " + o.toString()); } - public void onReadError(Exception e) { logger.info("Ошибка чтения"); } + public void beforeRead() { + logger.info("Начало чтения"); + } + + public void afterRead(Board o) { + logger.info("Конец чтения " + o.toString()); + } + + public void onReadError(Exception e) { + logger.info("Ошибка чтения"); + } }) .listener(new ItemWriteListener() { - public void beforeWrite(List list) { logger.info("Начало записи"); } - public void afterWrite(List list) { logger.info("Конец записи"); } - public void onWriteError(Exception e, List list) { logger.info("Ошибка записи"); } + public void beforeWrite(List list) { + logger.info("Начало записи"); + } + + public void afterWrite(List list) { + logger.info("Конец записи"); + } + + public void onWriteError(Exception e, List list) { + logger.info("Ошибка записи"); + } }) .listener(new ItemProcessListener() { - public void beforeProcess(Object o) {logger.info("Начало обработки");} - public void afterProcess(Object o, Object o2) {logger.info("Конец обработки");} - public void onProcessError(Object o, Exception e) {logger.info("Ошбка обработки");} + public void beforeProcess(Object o) { + logger.info("Начало обработки"); + } + + public void afterProcess(Object o, Object o2) { + logger.info("Конец обработки"); + } + + public void onProcessError(Object o, Exception e) { + logger.info("Ошбка обработки"); + } }) .listener(new ChunkListener() { - public void beforeChunk(ChunkContext chunkContext) {logger.info("Начало пачки");} - public void afterChunk(ChunkContext chunkContext) {logger.info("Конец пачки");} - public void afterChunkError(ChunkContext chunkContext) {logger.info("Ошибка пачки");} + public void beforeChunk(ChunkContext chunkContext) { + logger.info("Начало пачки"); + } + + public void afterChunk(ChunkContext chunkContext) { + logger.info("Конец пачки"); + } + + public void afterChunkError(ChunkContext chunkContext) { + logger.info("Ошибка пачки"); + } }) .build(); } diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java new file mode 100644 index 0000000..2970861 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java @@ -0,0 +1,7 @@ +package ru.otus.spring.hw.kanban.repository; + +import org.springframework.data.repository.PagingAndSortingRepository; +import ru.otus.spring.hw.kanban.domain.Board; + +public interface BoardPagingRepository extends PagingAndSortingRepository { +} From 22c3c8c96e079c5cb59ccbe8aebe1c52914a3e8e Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 21 Nov 2018 21:52:39 +0700 Subject: [PATCH 3/3] fix reader --- .../kanban/conversion/BoardItemProcessor.java | 24 ++------ .../kanban/conversion/ToMongoBatchConfig.java | 58 +++++++++++++------ .../otus/spring/hw/kanban/domain/Board.java | 12 ++++ .../otus/spring/hw/kanban/domain/Stage.java | 17 ++++++ .../repository/BoardPagingRepository.java | 7 --- 5 files changed, 73 insertions(+), 45 deletions(-) delete mode 100644 kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java index 8adb37e..b0ae0d6 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/BoardItemProcessor.java @@ -1,36 +1,24 @@ package ru.otus.spring.hw.kanban.conversion; import org.springframework.batch.item.ItemProcessor; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import ru.otus.spring.hw.kanban.domain.Board; import ru.otus.spring.hw.kanban.domain.Stage; import ru.otus.spring.hw.kanban.domain.Task; -import ru.otus.spring.hw.kanban.repository.StageRepository; -import ru.otus.spring.hw.kanban.repository.TaskRepository; import java.util.HashSet; -import java.util.List; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; -import org.springframework.stereotype.Service; @Service -public class BoardItemProcessor implements ItemProcessor { - - - @Autowired - StageRepository stageRepository; - - @Autowired - TaskRepository taskRepository; +public class BoardItemProcessor implements ItemProcessor { @Override public ru.otus.spring.hw.kanban.domain.mongo.Board process(Board board) throws Exception { ru.otus.spring.hw.kanban.domain.mongo.Board mongoBoard = new ru.otus.spring.hw.kanban.domain.mongo.Board(); mongoBoard.setName(board.getName()); - List stages = stageRepository.findStagesByBoard(board); Set mongoStages = new HashSet<>(); Function convert = (task) -> { @@ -39,17 +27,15 @@ public ru.otus.spring.hw.kanban.domain.mongo.Board process(Board board) throws E mongoTask.setExecutor(task.getExecutor()); mongoTask.setName(task.getName()); mongoTask.setPriority(task.getPriority()); - return mongoTask; + return mongoTask; }; - for (Stage stage : stages) { + for (Stage stage : board.getStages()) { ru.otus.spring.hw.kanban.domain.mongo.Stage mongoStage = new ru.otus.spring.hw.kanban.domain.mongo.Stage(); mongoStage.setDescription(stage.getDescription()); mongoStage.setName(stage.getName()); - - mongoStage.setTasks( - taskRepository.findAllByStage(stage) + stage.getTasks() .stream() .map(task -> convert.apply(task)) .collect(Collectors.toSet()) diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java index 749f333..36420da 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/conversion/ToMongoBatchConfig.java @@ -8,25 +8,22 @@ import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.item.ItemReader; -import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.*; import org.springframework.batch.item.data.MongoItemWriter; -import org.springframework.batch.item.data.RepositoryItemReader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; -import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; import ru.otus.spring.hw.kanban.domain.Board; -import ru.otus.spring.hw.kanban.repository.BoardPagingRepository; +import ru.otus.spring.hw.kanban.domain.Stage; import ru.otus.spring.hw.kanban.repository.BoardRepository; +import ru.otus.spring.hw.kanban.repository.StageRepository; +import ru.otus.spring.hw.kanban.repository.TaskRepository; import ru.otus.spring.hw.kanban.repository.mongo.BoardMongoRepository; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; @EnableBatchProcessing public class ToMongoBatchConfig { @@ -44,24 +41,47 @@ public class ToMongoBatchConfig { BoardItemProcessor boardItemProcessor; @Autowired - BoardPagingRepository boardPagingRepository; + BoardRepository boardRepository; @Autowired BoardMongoRepository boardMongoRepository; + @Autowired + StageRepository stageRepository; + + @Autowired + TaskRepository taskRepository; + + @Bean public ItemReader reader() { - RepositoryItemReader reader = new RepositoryItemReader<>(); - reader.setRepository(boardPagingRepository); - reader.setMethodName("findAll"); - List parameters = new ArrayList(); - reader.setArguments(parameters); - Map sort = new HashMap<>(); - sort.put("id", Sort.Direction.ASC); - reader.setSort(sort); - return reader; + return new ItemReader() { + + private Integer currentId = 0; + + @Override + public Board read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { + Board board = boardRepository.findFirstByIdGreaterThan(currentId).orElse(null); + if (board != null) { + Set stagesSet = new HashSet<>(); + List stages = stageRepository.findStagesByBoard(board); + + for (Stage stage : stages) { + stage.setTasks(taskRepository.findAllByStage(stage) + .stream() + .collect(Collectors.toSet())); + stagesSet.add(stage); + } + board.setStages(stagesSet); + currentId = board.getId(); + } + + return board; + } + }; } + @Bean public ItemWriter writer() { MongoItemWriter writer = new MongoItemWriter<>(); diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Board.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Board.java index ac3acd7..9163c42 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Board.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Board.java @@ -1,10 +1,22 @@ package ru.otus.spring.hw.kanban.domain; import javax.persistence.*; +import java.util.HashSet; import java.util.Set; @Entity public class Board { + public Set getStages() { + if (stages == null) { + stages = new HashSet<>(); + } + return stages; + } + + public void setStages(Set stages) { + this.stages = stages; + } + @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY) private Set stages; @Column(length = 500) diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Stage.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Stage.java index e1c2bb8..4ab1d86 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Stage.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/domain/Stage.java @@ -1,6 +1,8 @@ package ru.otus.spring.hw.kanban.domain; import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; @Entity public class Stage { @@ -16,6 +18,21 @@ public class Stage { @ManyToOne(fetch = FetchType.LAZY) private Board board; + public Set getTasks() { + if (tasks == null) { + tasks = new HashSet<>(); + } + return tasks; + } + + public void setTasks(Set tasks) { + this.tasks = tasks; + } + + @OneToMany(fetch = FetchType.LAZY) + private Set tasks; + + public Stage(String name, String description, Board board) { this.name = name; this.description = description; diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java deleted file mode 100644 index 2970861..0000000 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/repository/BoardPagingRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.otus.spring.hw.kanban.repository; - -import org.springframework.data.repository.PagingAndSortingRepository; -import ru.otus.spring.hw.kanban.domain.Board; - -public interface BoardPagingRepository extends PagingAndSortingRepository { -}