diff --git a/architecture/README.md b/architecture/README.md new file mode 100644 index 000000000000..c7cd61828574 --- /dev/null +++ b/architecture/README.md @@ -0,0 +1,5 @@ +## Architecture + +This module contains articles about software architecture. + +### Relevant articles diff --git a/architecture/pom.xml b/architecture/pom.xml new file mode 100644 index 000000000000..c9c32aedb0bc --- /dev/null +++ b/architecture/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + com.baeldung.architecture + architecture + architecture + jar + Architecture-related articles + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-devtools + true + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-core + test + + + + + + + \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/BookAppConfiguration.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/BookAppConfiguration.java new file mode 100644 index 000000000000..46b5c3101ad2 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/BookAppConfiguration.java @@ -0,0 +1,24 @@ +package com.baeldung.hexagonalarchitecture; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.hexagonalarchitecture.domain.BookService; +import com.baeldung.hexagonalarchitecture.domain.IBookRepository; +import com.baeldung.hexagonalarchitecture.domain.IBookService; +import com.baeldung.hexagonalarchitecture.infrastructure.DatabaseBookRepository; +import com.baeldung.hexagonalarchitecture.infrastructure.JpaBookRepository; + +@Configuration +public class BookAppConfiguration { + + @Bean + IBookRepository bookRepository(JpaBookRepository jpaBookRepository) { + return new DatabaseBookRepository(jpaBookRepository); + } + + @Bean + IBookService bookService(IBookRepository bookRepository) { + return new BookService(bookRepository); + } +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/BookApplication.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/BookApplication.java new file mode 100644 index 000000000000..301c7fa09664 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/BookApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.hexagonalarchitecture; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@PropertySource(value = { "classpath:hexagonal-architecture.properties" }) +public class BookApplication { + + public static void main(final String[] args) { + SpringApplication.run(BookApplication.class, args); + } +} diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/application/BookController.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/application/BookController.java new file mode 100644 index 000000000000..aaf4cde19b17 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/application/BookController.java @@ -0,0 +1,23 @@ +package com.baeldung.hexagonalarchitecture.application; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.hexagonalarchitecture.domain.Book; +import com.baeldung.hexagonalarchitecture.domain.IBookService; + +@RestController +public class BookController { + + @Autowired + private IBookService bookService; + + @GetMapping("/books") + ResponseEntity> listAllBooks() { + return ResponseEntity.ok(bookService.listAllBooks()); + } +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/Book.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/Book.java new file mode 100644 index 000000000000..4d13f875677b --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/Book.java @@ -0,0 +1,31 @@ +package com.baeldung.hexagonalarchitecture.domain; + +public class Book { + private String isbn; + private String title; + + public Book() { + + } + + public Book(String isbn, String title) { + this.isbn = isbn; + this.title = title; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/BookService.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/BookService.java new file mode 100644 index 000000000000..74519d978b83 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/BookService.java @@ -0,0 +1,17 @@ +package com.baeldung.hexagonalarchitecture.domain; + +import java.util.List; + +public class BookService implements IBookService { + + private IBookRepository bookRepository; + + public BookService(IBookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + @Override + public List listAllBooks() { + return bookRepository.findAllBooks(); + } +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/IBookRepository.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/IBookRepository.java new file mode 100644 index 000000000000..55ade300f0c3 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/IBookRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.hexagonalarchitecture.domain; + +import java.util.List; + +public interface IBookRepository { + List findAllBooks(); +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/IBookService.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/IBookService.java new file mode 100644 index 000000000000..aabb61cc158a --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/domain/IBookService.java @@ -0,0 +1,7 @@ +package com.baeldung.hexagonalarchitecture.domain; + +import java.util.List; + +public interface IBookService { + List listAllBooks(); +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/BasicBookRepository.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/BasicBookRepository.java new file mode 100644 index 000000000000..2ff0a7cb0704 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/BasicBookRepository.java @@ -0,0 +1,16 @@ +package com.baeldung.hexagonalarchitecture.infrastructure; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.hexagonalarchitecture.domain.Book; +import com.baeldung.hexagonalarchitecture.domain.IBookRepository; + +public class BasicBookRepository implements IBookRepository { + @Override + public List findAllBooks() { + List books = new ArrayList(); + books.add(new Book("9780136083238", "Clean Code: A Handbook of Agile Software Craftsmanship")); + return books; + } +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/DatabaseBookRepository.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/DatabaseBookRepository.java new file mode 100644 index 000000000000..84a63261f964 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/DatabaseBookRepository.java @@ -0,0 +1,24 @@ +package com.baeldung.hexagonalarchitecture.infrastructure; + +import java.util.List; +import java.util.stream.Collectors; + +import com.baeldung.hexagonalarchitecture.domain.Book; +import com.baeldung.hexagonalarchitecture.domain.IBookRepository; + +public class DatabaseBookRepository implements IBookRepository { + + private JpaBookRepository jpaBookRepository; + + public DatabaseBookRepository(JpaBookRepository jpaBookRepository) { + this.jpaBookRepository = jpaBookRepository; + } + + @Override + public List findAllBooks() { + return jpaBookRepository.findAll() + .stream() + .map(bookEntity -> new Book(bookEntity.getIsbn(), bookEntity.getTitle())) + .collect(Collectors.toList()); + } +} diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/JpaBookEntity.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/JpaBookEntity.java new file mode 100644 index 000000000000..6324ab0decb4 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/JpaBookEntity.java @@ -0,0 +1,27 @@ +package com.baeldung.hexagonalarchitecture.infrastructure; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class JpaBookEntity { + @Id + private String isbn; + private String title; + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String iSBN) { + isbn = iSBN; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} \ No newline at end of file diff --git a/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/JpaBookRepository.java b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/JpaBookRepository.java new file mode 100644 index 000000000000..fae39de963f5 --- /dev/null +++ b/architecture/src/main/java/com/baeldung/hexagonalarchitecture/infrastructure/JpaBookRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.hexagonalarchitecture.infrastructure; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface JpaBookRepository extends JpaRepository { +} \ No newline at end of file diff --git a/architecture/src/main/resources/hexagonal-architecture.properties b/architecture/src/main/resources/hexagonal-architecture.properties new file mode 100644 index 000000000000..e1c730d50fcf --- /dev/null +++ b/architecture/src/main/resources/hexagonal-architecture.properties @@ -0,0 +1,5 @@ +spring.datasource.url=jdbc:h2:mem:db +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/architecture/src/test/java/com/baeldung/hexagonalarchitecture/BookServiceUnitTest.java b/architecture/src/test/java/com/baeldung/hexagonalarchitecture/BookServiceUnitTest.java new file mode 100644 index 000000000000..8bc7f24c9c4d --- /dev/null +++ b/architecture/src/test/java/com/baeldung/hexagonalarchitecture/BookServiceUnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.hexagonalarchitecture; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.baeldung.hexagonalarchitecture.domain.Book; +import com.baeldung.hexagonalarchitecture.domain.BookService; +import com.baeldung.hexagonalarchitecture.domain.IBookRepository; +import com.baeldung.hexagonalarchitecture.domain.IBookService; + +@DisplayName("Book service") +@ExtendWith(MockitoExtension.class) +public class BookServiceUnitTest { + + private IBookService bookService; + + @Mock + private IBookRepository bookRepository; + + @BeforeEach + void init() { + bookService = new BookService(bookRepository); + } + + @Test + @DisplayName("When listing all books then it should use repository") + void whenListingAllBooks_thenItShouldUseRepository() { + List booksFromRepository = new ArrayList<>(); + booksFromRepository.add(new Book("testIsbn", "testTitle")); + when(bookRepository.findAllBooks()).thenReturn(booksFromRepository); + + List booksFromService = bookService.listAllBooks(); + + verify(bookRepository).findAllBooks(); + assertThat(booksFromService).containsExactlyElementsOf(booksFromRepository); + } +} diff --git a/pom.xml b/pom.xml index b7c4efa4215e..6e595a8bb443 100644 --- a/pom.xml +++ b/pom.xml @@ -363,6 +363,8 @@ apache-tika apache-velocity + architecture + asciidoctor asm @@ -842,6 +844,8 @@ apache-thrift apache-tika apache-velocity + + architecture asciidoctor asm