1. Overview
2. Hexagonal Architecture
In terms of programming (implementation), a port is an interface while an adapter is the concrete implementation of a given port.
3. Hexagonal Architecture example in Java
3.1 Define Domain layer
public class Student { private int studentId; private String name; private int age; }
public interface StudentService { public List<Student> findAll(); public void save(Student student); }
Let's implement StudentService interface now.
@Service public class StudentServiceImpl implements StudentService { private StudentDBPort studentDBPort; @Autowired public StudentServiceImpl(StudentDBPort studentDBPort) { super(); this.studentDBPort = studentDBPort; } @Override public List<Student> findAll() { return studentDBPort.findAll(); } @Override public void save(Student student) { studentDBPort.save(student); } }
3.2 Declare Ports
public interface StudentDBPort { public List<Student> findAll(); public void save(Student student); }
3.3 Implement Adapters
public class StudentControllerAdapter implements StudentRESTPort { @Autowired private StudentService studentService; @RequestMapping(method = RequestMethod.POST, value = "/register") public Student registerStudent(@RequestBody Student student) { studentService.save(student); return student; } @RequestMapping(method = RequestMethod.GET, value = "/viewAll") public List<Student> getAllStudents() { return studentService.findAll(); } }Then, we'll create the StudentServiceDBAdapter class that implements the StudentDBPort interface. So, it'll behave as an adapter to persist data in the database:
public class StudentServiceDBAdapter implements StudentDBPort { private EntityManager entityManager; @Override public List<Student> findAll() { Session currentSession = entityManager.unwrap(Session.class); Query<Student> theQuery = currentSession.createQuery("from Student", Student.class); List<Student> students = theQuery.getResultList(); return students; } @Override public void save(Student student) { Session currentSession = entityManager.unwrap(Session.class); currentSession.saveOrUpdate(student); } }That's it, we've successfully separated our App into the inside and outside components.
4. Benefits
- Independence : The core layer is independent of outer layers
- Testability : Each dependent (outer) component could be easily replaced with a stub implementation so that any component can be tested with ease
- Flexibility : Any number of ports can be added easily to serve multiple functionalities\channels
No comments:
Post a Comment