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