diff --git a/README.md b/README.md index bff8b39..d5f13c3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,10 @@ Simple kanban application. ## Server app Run `cd kanban_server` to go to server folder. -Run `./gradlew bootRun` to start application + +Run `sudo ./gradlew assembleDockerImage` to assemble server image. + +Run `sudo docker-compose up -d` to start docker compose # Client: Download sources. diff --git a/kanban-server/build.gradle b/kanban-server/build.gradle index 5cbd60c..5e5d607 100644 --- a/kanban-server/build.gradle +++ b/kanban-server/build.gradle @@ -68,6 +68,9 @@ dependencies { compile('org.springframework.boot:spring-boot-starter-data-jpa:1.5.8.RELEASE') runtime('com.h2database:h2') + compile("org.springframework.boot:spring-boot-starter-integration") + compile("org.springframework:spring-messaging") + // All of your normal project dependencies would be here in addition to... // liquibaseRuntime 'org.liquibase:liquibase-core:3.6.1' // liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.1' diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/BoardIntegrationConfig.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/BoardIntegrationConfig.java new file mode 100644 index 0000000..c2fa476 --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/BoardIntegrationConfig.java @@ -0,0 +1,88 @@ +package ru.otus.spring.hw.kanban; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.IntegrationComponentScan; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.channel.MessageChannels; +import ru.otus.spring.hw.kanban.domain.Board; +import ru.otus.spring.hw.kanban.dto.BoardDTO; +import ru.otus.spring.hw.kanban.repository.BoardRepository; +import ru.otus.spring.hw.kanban.service.BoardService; + +@Configuration +@IntegrationComponentScan +@EnableIntegration +public class BoardIntegrationConfig { + + @Bean(name = "createBoard.input") + public DirectChannel createBoardInputChannel() { + return MessageChannels.direct("createBoard.input").datatype(BoardDTO.class).get(); + } + + @Bean(name = "getBoards.input") + public DirectChannel getBoardsChannel() { + return MessageChannels.direct("getBoards.input").datatype(String.class).get(); + } + + @Bean(name = "updateBoard.input") + public DirectChannel updateBoardsChannel() { + return MessageChannels.direct("updateBoard.input").datatype(BoardDTO.class).get(); + } + + @Bean(name = "deleteBoard.input") + public DirectChannel deleteBoardChannel() { + return MessageChannels.direct("deleteBoard.input").datatype(Integer.class).get(); + } + + + @Bean + public IntegrationFlow createBoard(BoardService boardService, BoardRepository boardRepository) { + return f -> f + .transform(source -> source.fillBoard(new Board())) + .handle((payload, headers) -> boardRepository.save(payload)) + .transform(source -> BoardDTO.fromBoard(source)); + } + + + @Bean + public IntegrationFlow getBoards(BoardRepository boardRepository) { + return f -> f + .route(s -> s != null && s.length() > 0, + mapping -> + mapping + .subFlowMapping(true, + flow -> flow.handle((payload, headers) -> boardRepository.findBoardsByName(payload))) + .subFlowMapping(false, + flow -> flow.handle((payload, headers) -> boardRepository.findAll())) + ) + .split() + .transform(BoardDTO::fromBoard) + .aggregate(); + } + + @Bean + public IntegrationFlow updateBoard(BoardRepository boardRepository) { + return f -> f + .transform(source -> { + Board board = boardRepository.findById(source.id).orElseThrow(() -> new RuntimeException("Not found board")); + source.fillBoard(board); + return board; + } + ) + .handle((payload, headers) -> boardRepository.save(payload)) + .transform(BoardDTO::fromBoard); + } + + @Bean + public IntegrationFlow deleteBoard(BoardService boardService, BoardRepository boardRepository) { + return f -> f + .transform(source -> boardRepository.findById(source).orElseThrow(() -> new RuntimeException("Object not founded"))) + .handle((payload, headers) -> boardService.delete(payload)); + + } + + +} 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..c7d50a1 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 @@ -3,6 +3,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.security.crypto.password.PasswordEncoder; import ru.otus.spring.hw.kanban.security.UserAccount; @@ -11,8 +12,9 @@ import javax.annotation.PostConstruct; -@SpringBootApplication(scanBasePackages = "ru.otus.spring.hw.kanban") +@SpringBootApplication(scanBasePackages = {"ru.otus.spring.hw.kanban"}) @EnableJpaRepositories(basePackages = {"ru.otus.spring.hw.kanban.repository", "ru.otus.spring.hw.kanban.security"}) +@Import(BoardIntegrationConfig.class) public class KanbanApplication { public static void main(String[] args) { diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/controllers/BoardController.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/controllers/BoardController.java index 42b254d..2b284ad 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/controllers/BoardController.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/controllers/BoardController.java @@ -1,8 +1,11 @@ package ru.otus.spring.hw.kanban.controllers; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; import org.springframework.web.bind.annotation.*; import ru.otus.spring.hw.kanban.dto.BoardDTO; +import ru.otus.spring.hw.kanban.integration.BoardMessagingGateway; import ru.otus.spring.hw.kanban.service.BoardService; import java.util.List; @@ -13,19 +16,26 @@ public class BoardController { private final BoardService boardService; + private final BoardMessagingGateway boardMessagingGateway; + @Autowired - public BoardController(BoardService boardService) { + public BoardController(BoardService boardService, BoardMessagingGateway boardMessagingGateway) { this.boardService = boardService; + this.boardMessagingGateway = boardMessagingGateway; } @GetMapping(value = "/boards") public List getBoards() { - return boardService.findAll(); + return boardMessagingGateway.getBoards(MessageBuilder.withPayload("").build()); } @PostMapping("/boards") BoardDTO newBoard(@RequestBody BoardDTO newBoard) { - return boardService.create(newBoard); + Message message = MessageBuilder + .withPayload(newBoard) + .build(); + BoardDTO dto = boardMessagingGateway.createBoard(message); + return dto; } @GetMapping("/boards/{id}") @@ -35,12 +45,13 @@ public BoardDTO getBoard(@PathVariable int id) { @PutMapping("/boards/{id}") BoardDTO updateBoard(@RequestBody BoardDTO boardDTO, @PathVariable Long id) { - return boardService.update(boardDTO); + return boardMessagingGateway.updateBoard(MessageBuilder.withPayload(boardDTO).build()); } @DeleteMapping("/boards/{id}") void deleteBoard(@PathVariable int id) { - boardService.deleteById(id); + boardMessagingGateway.deleteBoard(MessageBuilder.withPayload(id).build()); + } } diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/dto/BoardDTO.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/dto/BoardDTO.java index bf53aa8..2a501e9 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/dto/BoardDTO.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/dto/BoardDTO.java @@ -32,9 +32,10 @@ public int hashCode() { return Objects.hash(name, id); } - public void fillBoard(Board board) { + public Board fillBoard(Board board) { board.setId(this.id); board.setName(this.name); + return board; } public BoardDTO() { diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/integration/BoardMessagingGateway.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/integration/BoardMessagingGateway.java new file mode 100644 index 0000000..a0b81db --- /dev/null +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/integration/BoardMessagingGateway.java @@ -0,0 +1,24 @@ +package ru.otus.spring.hw.kanban.integration; + +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.messaging.Message; +import ru.otus.spring.hw.kanban.dto.BoardDTO; + +import java.util.List; + +@MessagingGateway(name = "boardGateway") +public interface BoardMessagingGateway { + + @Gateway(requestChannel = "createBoard.input") + BoardDTO createBoard(Message message); + + @Gateway(requestChannel = "getBoards.input") + List getBoards(Message get_all); + + @Gateway(requestChannel = "updateBoard.input") + BoardDTO updateBoard(Message withPayload); + + @Gateway(requestChannel = "deleteBoard.input") + void deleteBoard(Message withPayload); +} 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..7c0562d 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 @@ -6,7 +6,7 @@ import java.util.List; public interface BoardRepository extends CrudRepository { - List findBoardsByNameLike(String name); + List findBoardsByName(String name); List findAll(); } diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardService.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardService.java index 621710a..ee57929 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardService.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardService.java @@ -1,5 +1,6 @@ package ru.otus.spring.hw.kanban.service; +import ru.otus.spring.hw.kanban.domain.Board; import ru.otus.spring.hw.kanban.dto.BoardDTO; import java.util.List; @@ -16,4 +17,6 @@ public interface BoardService { BoardDTO update(BoardDTO boardToUpdate); void deleteById(int id); + + Board delete(Board payload); } diff --git a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardServiceImpl.java b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardServiceImpl.java index 153d162..b329a2b 100644 --- a/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardServiceImpl.java +++ b/kanban-server/src/main/java/ru/otus/spring/hw/kanban/service/BoardServiceImpl.java @@ -21,6 +21,7 @@ public BoardServiceImpl(BoardRepository boardRepository) { this.boardRepository = boardRepository; } + public List findAll() { return boardRepository.findAll().stream().map(BoardDTO::fromBoard).collect(Collectors.toList()); } @@ -39,6 +40,7 @@ public BoardDTO create(BoardDTO newBoard) { return BoardDTO.fromBoard(board); } + @Transactional public BoardDTO update(BoardDTO boardToUpdate) { Board board = boardRepository.findById(boardToUpdate.id).orElseThrow(() -> new BoardNotFoundException(boardToUpdate.toString() + " not found.")); @@ -51,4 +53,11 @@ public BoardDTO update(BoardDTO boardToUpdate) { public void deleteById(int id) { boardRepository.deleteById(id); } + + @Override + @Transactional + public Board delete(Board payload) { + boardRepository.delete(payload); + return null; + } }