diff --git a/patterns/hexagonal-design-pattern/.gitignore b/patterns/hexagonal-design-pattern/.gitignore
new file mode 100644
index 0000000000..aceea512a2
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/.gitignore
@@ -0,0 +1,5 @@
+/target/
+.settings/
+.classpath
+.project
+/bin/
diff --git a/patterns/hexagonal-design-pattern/pom.xml b/patterns/hexagonal-design-pattern/pom.xml
new file mode 100644
index 0000000000..1552859a65
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/pom.xml
@@ -0,0 +1,80 @@
+
+ 4.0.0
+ com.baeldung
+ hexagonal-design-pattern
+ 0.0.1-SNAPSHOT
+ hexagonal-design-pattern
+ war
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.3.RELEASE
+
+
+
+
+ ma.glasnost.orika
+ orika-core
+ 1.4.6
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+
+
+
+ maven-compiler-plugin
+
+
+ maven-war-plugin
+
+ WebContent
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+ com.baeldung.hexagonal.Application
+ ${project.basedir}/docker
+
+
+
+
+
+
+
+
+
+ 8.0.43
+ UTF-8
+ 1.8
+
+
+
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/Application.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/Application.java
new file mode 100644
index 0000000000..772a8ad9fd
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/Application.java
@@ -0,0 +1,13 @@
+package com.baeldung.hexagonal;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/controller/UserController.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/controller/UserController.java
new file mode 100644
index 0000000000..1d4dda510e
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/controller/UserController.java
@@ -0,0 +1,31 @@
+package com.baeldung.hexagonal.adapter.controller;
+
+import java.util.List;
+
+import com.baeldung.hexagonal.core.contract.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.http.HttpStatus;
+import com.baeldung.hexagonal.core.contract.User;
+
+@RestController
+public class UserController {
+
+ @Autowired
+ private UserService userService;
+
+ @PostMapping("/users")
+ @ResponseStatus(HttpStatus.CREATED)
+ public void addUser(@RequestBody User user) {
+ userService.addUser(user);
+ }
+
+ @GetMapping("/users")
+ public List getUsers() {
+ return userService.getUsers();
+ }
+}
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/UserDataAdapter.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/UserDataAdapter.java
new file mode 100644
index 0000000000..38a0e08468
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/UserDataAdapter.java
@@ -0,0 +1,11 @@
+package com.baeldung.hexagonal.adapter.data;
+
+import com.baeldung.hexagonal.core.contract.dto.UserDTO;
+import java.util.List;
+
+public interface UserDataAdapter {
+
+ void addUser(UserDTO user);
+
+ List getUsers();
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/UserDataAdapterImpl.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/UserDataAdapterImpl.java
new file mode 100644
index 0000000000..fe100b1ce0
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/UserDataAdapterImpl.java
@@ -0,0 +1,27 @@
+package com.baeldung.hexagonal.adapter.data;
+
+import com.baeldung.hexagonal.adapter.data.entity.UserEntity;
+import com.baeldung.hexagonal.adapter.data.mapper.ModelMapper;
+import com.baeldung.hexagonal.adapter.data.repository.UserRepository;
+import com.baeldung.hexagonal.core.contract.dto.UserDTO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import java.util.List;
+
+@Component
+public class UserDataAdapterImpl implements UserDataAdapter {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private ModelMapper modelMapper;
+
+ public void addUser(UserDTO user) {
+ userRepository.save(modelMapper.map(user, UserEntity.class));
+ }
+
+ public List getUsers() {
+ return modelMapper.mapAsList(userRepository.findAll(), UserDTO.class);
+ }
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/entity/UserEntity.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/entity/UserEntity.java
new file mode 100644
index 0000000000..91f80efa90
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/entity/UserEntity.java
@@ -0,0 +1,39 @@
+package com.baeldung.hexagonal.adapter.data.entity;
+
+import javax.persistence.*;
+
+@Entity(name = "user")
+@Table(name = "user")
+public class UserEntity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ private String name;
+
+ public UserEntity() {
+ }
+
+ public UserEntity(long id, String name) {
+ super();
+ this.id = id;
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/mapper/ModelMapper.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/mapper/ModelMapper.java
new file mode 100644
index 0000000000..f451781b06
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/mapper/ModelMapper.java
@@ -0,0 +1,41 @@
+package com.baeldung.hexagonal.adapter.data.mapper;
+
+import com.baeldung.hexagonal.adapter.data.entity.UserEntity;
+import com.baeldung.hexagonal.core.contract.dto.UserDTO;
+import ma.glasnost.orika.CustomMapper;
+import ma.glasnost.orika.MapperFactory;
+import ma.glasnost.orika.MappingContext;
+import ma.glasnost.orika.impl.ConfigurableMapper;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ModelMapper extends ConfigurableMapper {
+
+ public void configure(MapperFactory factory) {
+ super.configure(factory);
+
+ factory.registerClassMap(factory.classMap(UserDTO.class, UserEntity.class)
+ .customize(new CustomMapper() {
+ @Override
+ public void mapAtoB(UserDTO userDTO, UserEntity userEntity, MappingContext context) {
+ userEntity.setId(userDTO.getId());
+ userEntity.setName(userDTO.getName());
+ }
+ })
+ .byDefault()
+ .toClassMap());
+
+ factory.registerClassMap(factory.classMap(UserEntity.class, UserDTO.class)
+ .customize(new CustomMapper() {
+ @Override
+ public void mapAtoB(UserEntity userEntity, UserDTO userDTO, MappingContext context) {
+ userDTO.setId(userEntity.getId());
+ userDTO.setName(userEntity.getName());
+ }
+ })
+ .byDefault()
+ .toClassMap());
+
+ }
+
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/repository/UserRepository.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/repository/UserRepository.java
new file mode 100644
index 0000000000..937be19056
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/adapter/data/repository/UserRepository.java
@@ -0,0 +1,8 @@
+package com.baeldung.hexagonal.adapter.data.repository;
+
+import com.baeldung.hexagonal.adapter.data.entity.UserEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserRepository extends JpaRepository {
+
+}
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/config/PersistenceConfig.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/config/PersistenceConfig.java
new file mode 100644
index 0000000000..b9a5f9d556
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/config/PersistenceConfig.java
@@ -0,0 +1,24 @@
+package com.baeldung.hexagonal.config;
+
+import javax.sql.DataSource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
+
+@Configuration
+public class PersistenceConfig {
+
+ @Bean
+ public DataSource dataSource() {
+ EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
+ EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2)
+ .addScript("mySchema.sql")
+ .addScript("myData.sql")
+ .build();
+ return db;
+ }
+
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/User.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/User.java
new file mode 100644
index 0000000000..2013c2a88e
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/User.java
@@ -0,0 +1,34 @@
+package com.baeldung.hexagonal.core.contract;
+
+public class User {
+
+ private long id;
+
+ private String name;
+
+ public User() {
+ }
+
+ public User(long id, String name) {
+ super();
+ this.id = id;
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/UserService.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/UserService.java
new file mode 100644
index 0000000000..2b0867872a
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/UserService.java
@@ -0,0 +1,10 @@
+package com.baeldung.hexagonal.core.contract;
+
+import java.util.List;
+
+public interface UserService {
+
+ void addUser(User user);
+
+ List getUsers();
+}
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/dto/UserDTO.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/dto/UserDTO.java
new file mode 100644
index 0000000000..a92851310b
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/contract/dto/UserDTO.java
@@ -0,0 +1,24 @@
+package com.baeldung.hexagonal.core.contract.dto;
+
+public class UserDTO {
+
+ private long id;
+
+ private String name;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/mapper/CoreModelMapper.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/mapper/CoreModelMapper.java
new file mode 100644
index 0000000000..1cb569d109
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/mapper/CoreModelMapper.java
@@ -0,0 +1,41 @@
+package com.baeldung.hexagonal.core.mapper;
+
+import com.baeldung.hexagonal.core.contract.dto.UserDTO;
+import com.baeldung.hexagonal.core.contract.User;
+import ma.glasnost.orika.CustomMapper;
+import ma.glasnost.orika.MapperFactory;
+import ma.glasnost.orika.MappingContext;
+import ma.glasnost.orika.impl.ConfigurableMapper;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CoreModelMapper extends ConfigurableMapper {
+
+ public void configure(MapperFactory factory) {
+ super.configure(factory);
+
+ factory.registerClassMap(factory.classMap(UserDTO.class, User.class)
+ .customize(new CustomMapper() {
+ @Override
+ public void mapAtoB(UserDTO userDTO, User user, MappingContext context) {
+ user.setId(userDTO.getId());
+ user.setName(userDTO.getName());
+ }
+ })
+ .byDefault()
+ .toClassMap());
+
+ factory.registerClassMap(factory.classMap(User.class, UserDTO.class)
+ .customize(new CustomMapper() {
+ @Override
+ public void mapAtoB(User user, UserDTO userDTO, MappingContext context) {
+ userDTO.setId(user.getId());
+ userDTO.setName(user.getName());
+ }
+ })
+ .byDefault()
+ .toClassMap());
+
+ }
+
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/service/UserServiceImpl.java b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/service/UserServiceImpl.java
new file mode 100644
index 0000000000..3b4800cffc
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/java/com/baeldung/hexagonal/core/service/UserServiceImpl.java
@@ -0,0 +1,28 @@
+package com.baeldung.hexagonal.core.service;
+
+import com.baeldung.hexagonal.adapter.data.UserDataAdapter;
+import com.baeldung.hexagonal.core.contract.UserService;
+import com.baeldung.hexagonal.core.contract.dto.UserDTO;
+import com.baeldung.hexagonal.core.mapper.CoreModelMapper;
+import com.baeldung.hexagonal.core.contract.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import java.util.List;
+
+@Service
+public class UserServiceImpl implements UserService {
+
+ @Autowired
+ private UserDataAdapter userDataAdapter;
+
+ @Autowired
+ private CoreModelMapper coreModelMapper;
+
+ public void addUser(User user) {
+ userDataAdapter.addUser(coreModelMapper.map(user, UserDTO.class));
+ }
+
+ public List getUsers() {
+ return coreModelMapper.mapAsList(userDataAdapter.getUsers(), User.class);
+ }
+}
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/resources/application.properties b/patterns/hexagonal-design-pattern/src/main/resources/application.properties
new file mode 100644
index 0000000000..4420285967
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+server.port=8081
+server.contextPath=/hexagonaldesignapp
+logging.level.org.springframework.web: INFO
+
+spring.jpa.hibernate.ddl-auto=update
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/resources/logback.xml b/patterns/hexagonal-design-pattern/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/resources/myData.sql b/patterns/hexagonal-design-pattern/src/main/resources/myData.sql
new file mode 100644
index 0000000000..21353649ba
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/resources/myData.sql
@@ -0,0 +1 @@
+insert into user(name) values ('ana');
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/main/resources/mySchema.sql b/patterns/hexagonal-design-pattern/src/main/resources/mySchema.sql
new file mode 100644
index 0000000000..d561e4f8b2
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/main/resources/mySchema.sql
@@ -0,0 +1 @@
+create table user(id int identity primary key, name varchar(30));
\ No newline at end of file
diff --git a/patterns/hexagonal-design-pattern/src/test/java/com/baeldung/hexagonal/test/UserControllerTest.java b/patterns/hexagonal-design-pattern/src/test/java/com/baeldung/hexagonal/test/UserControllerTest.java
new file mode 100644
index 0000000000..3b0c849e3b
--- /dev/null
+++ b/patterns/hexagonal-design-pattern/src/test/java/com/baeldung/hexagonal/test/UserControllerTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.hexagonal.test;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import static org.hamcrest.Matchers.*;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+import com.baeldung.hexagonal.Application;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+@WebAppConfiguration
+public class UserControllerTest {
+
+ private static final String CONTENT_TYPE = "application/json;charset=UTF-8";
+
+ private MockMvc mockMvc;
+
+ @Autowired
+ private WebApplicationContext webApplicationContext;
+
+ @Before
+ public void setup() throws Exception {
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
+ .build();
+ }
+
+ @Test
+ public void whenCreateGetUser_thenOk() throws Exception {
+ String userJson = "{\"name\":\"john\"}";
+
+ this.mockMvc.perform(post("/users").contentType(CONTENT_TYPE)
+ .content(userJson))
+ .andExpect(status().isCreated());
+
+ this.mockMvc.perform(get("/users"))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(CONTENT_TYPE))
+ .andExpect(jsonPath("$", hasSize(2)))
+ .andExpect(jsonPath("$[0].name", is("ana")))
+ .andExpect(jsonPath("$[1].name", is("john")));
+ }
+}
diff --git a/patterns/pom.xml b/patterns/pom.xml
index bc1f5173e2..795b4c64db 100644
--- a/patterns/pom.xml
+++ b/patterns/pom.xml
@@ -17,6 +17,7 @@
front-controller
intercepting-filter
design-patterns
+ hexagonal-design-pattern