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