diff --git a/hexagonal-architecture/.gitignore b/hexagonal-architecture/.gitignore new file mode 100644 index 0000000000..ae3c172604 --- /dev/null +++ b/hexagonal-architecture/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/hexagonal-architecture/pom.xml b/hexagonal-architecture/pom.xml new file mode 100644 index 0000000000..c8eceae21a --- /dev/null +++ b/hexagonal-architecture/pom.xml @@ -0,0 +1,14 @@ + + 4.0.0 + com.baeldung.hexagonal + hexagonal-architecture + jar + hexagonal-architecture + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + \ No newline at end of file diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/Application.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/Application.java new file mode 100644 index 0000000000..4691d498f4 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/Application.java @@ -0,0 +1,27 @@ +package com.baeldung.hexagonal; + +import java.io.File; + +import com.baeldung.hexagonal.domain.EmployeeService; +import com.baeldung.hexagonal.output.EmployeeCsvWriter; +import com.baeldung.hexagonal.output.EmployeeLogger; +import com.baeldung.hexagonal.output.EmployeeOutput; +import com.baeldung.hexagonal.storage.EmployeeRepository; +import com.baeldung.hexagonal.storage.InMemoryEmployeeRepository; +import com.baeldung.hexagonal.ui.EmployeeConsoleInputImpl; +import com.baeldung.hexagonal.ui.EmployeeInput; + +public class Application { + + public static void main(String[] args) { + EmployeeRepository repository = new InMemoryEmployeeRepository(); + EmployeeOutput output = new EmployeeLogger(); + EmployeeOutput csvOutput = new EmployeeCsvWriter(new File(".").getAbsolutePath(), "output.csv"); + EmployeeService service = new EmployeeService(repository, csvOutput); + EmployeeInput ui = new EmployeeConsoleInputImpl(); + ui.collectData(service); + service.generateOutput(); + + } + +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/domain/Employee.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/domain/Employee.java new file mode 100644 index 0000000000..91b22d0d11 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/domain/Employee.java @@ -0,0 +1,70 @@ +package com.baeldung.hexagonal.domain; + +import java.math.BigDecimal; + +public class Employee { + private Long id; + private String firstName; + private String lastName; + private String employeeId; + private BigDecimal salary; + + public Employee( + Long id, + String firstName, + String lastName, + String employeeId, + BigDecimal salary) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.employeeId = employeeId; + this.salary = salary; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmployeeId() { + return employeeId; + } + + public void setEmployeeId(String employeeId) { + this.employeeId = employeeId; + } + + public BigDecimal getSalary() { + return salary; + } + + public void setSalary(BigDecimal salary) { + this.salary = salary; + } + + @Override + public String toString() { + return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", employeeId=" + employeeId + ", salary=" + salary + "]"; + } + +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/domain/EmployeeService.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/domain/EmployeeService.java new file mode 100644 index 0000000000..12b2028035 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/domain/EmployeeService.java @@ -0,0 +1,26 @@ +package com.baeldung.hexagonal.domain; + + +import java.util.List; + +import com.baeldung.hexagonal.output.EmployeeOutput; +import com.baeldung.hexagonal.storage.EmployeeRepository; + +public class EmployeeService { + private EmployeeRepository employeeRepository; + private EmployeeOutput employeeOutput; + + public EmployeeService(EmployeeRepository employeeRepository, EmployeeOutput employeeOutput) { + this.employeeRepository = employeeRepository; + this.employeeOutput = employeeOutput; + } + + public Long add(Employee employee) { + return employeeRepository.save(employee); + } + + public void generateOutput() { + List employees = employeeRepository.findAll(); + employeeOutput.writeAll(employees); + } +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeCsvWriter.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeCsvWriter.java new file mode 100644 index 0000000000..c434d19525 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeCsvWriter.java @@ -0,0 +1,64 @@ +package com.baeldung.hexagonal.output; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +import com.baeldung.hexagonal.domain.Employee; + +public class EmployeeCsvWriter implements EmployeeOutput { + private File outputFile; + + public EmployeeCsvWriter(String path, String fileName) throws IllegalArgumentException { + if (fileName == null || path == null || fileName.length() == 0 || path.length() == 0) { + throw new IllegalArgumentException("Path and FileName are required"); + } else if (!fileName.endsWith(".csv")) { + throw new IllegalArgumentException("File name must be a .csv file"); + } + + System.out.println(path); + if (!path.endsWith("/")) path += "/"; + + outputFile = new File(path, fileName); + } + + @Override + public void writeAll(List employees) { + BufferedWriter writer = null; + + try { + writer = new BufferedWriter(new FileWriter(outputFile)); + for (Iterator it = employees.iterator(); it.hasNext();) { + Employee emp = it.next(); + StringBuffer empLine = new StringBuffer(); + empLine.append(emp.getId()); + empLine.append(","); + empLine.append(emp.getFirstName()); + empLine.append(","); + empLine.append(emp.getLastName()); + empLine.append(","); + empLine.append(emp.getEmployeeId()); + empLine.append(","); + empLine.append(emp.getSalary()); + writer.write(empLine.toString()); + writer.newLine(); + } + writer.flush(); + } catch (IOException ioe) { + //handle the exception + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + //handle the exception + } + } + } + + } + +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeLogger.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeLogger.java new file mode 100644 index 0000000000..681e631012 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeLogger.java @@ -0,0 +1,17 @@ +package com.baeldung.hexagonal.output; + +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.hexagonal.domain.Employee; + +public class EmployeeLogger implements EmployeeOutput { + private static final Logger LOG = LoggerFactory.getLogger(EmployeeLogger.class); + + @Override + public void writeAll(List employees) { + employees.forEach(employee -> LOG.info(employee.toString())); + } + +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeOutput.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeOutput.java new file mode 100644 index 0000000000..979c06e1f4 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/output/EmployeeOutput.java @@ -0,0 +1,9 @@ +package com.baeldung.hexagonal.output; + +import java.util.List; + +import com.baeldung.hexagonal.domain.Employee; + +public interface EmployeeOutput { + public void writeAll(List employees); +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/storage/EmployeeRepository.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/storage/EmployeeRepository.java new file mode 100644 index 0000000000..f12584f8e1 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/storage/EmployeeRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.hexagonal.storage; + +import java.util.List; + +import com.baeldung.hexagonal.domain.Employee; + +public interface EmployeeRepository { + public Long save(Employee employee); + public Employee findById(Long id); + public List findAll(); +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/storage/InMemoryEmployeeRepository.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/storage/InMemoryEmployeeRepository.java new file mode 100644 index 0000000000..e860c16462 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/storage/InMemoryEmployeeRepository.java @@ -0,0 +1,31 @@ +package com.baeldung.hexagonal.storage; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.baeldung.hexagonal.domain.Employee; + +public class InMemoryEmployeeRepository implements EmployeeRepository { + private static Map employees = new HashMap<>(); + + @Override + public Long save(Employee employee) { + Long id = employee.getId(); + employees.put(id, employee); + return id; + } + + @Override + public Employee findById(Long id) { + return employees.get(id); + } + + @Override + public List findAll() { + List all = new ArrayList(employees.values()); + return all; + } + +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/ui/EmployeeConsoleInputImpl.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/ui/EmployeeConsoleInputImpl.java new file mode 100644 index 0000000000..5f613f7bf9 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/ui/EmployeeConsoleInputImpl.java @@ -0,0 +1,53 @@ +package com.baeldung.hexagonal.ui; + +import java.math.BigDecimal; +import java.util.Scanner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.baeldung.hexagonal.domain.Employee; +import com.baeldung.hexagonal.domain.EmployeeService; + +public class EmployeeConsoleInputImpl implements EmployeeInput { + private static final Logger LOG = LoggerFactory.getLogger(EmployeeConsoleInputImpl.class); + + public void enterEmployee(EmployeeService service, Scanner scanner) { + + LOG.info("ID: "); + System.out.print("> "); + Long id = scanner.nextLong(); + LOG.info("First Name: "); + System.out.print("> "); + String firstName = scanner.next(); + LOG.info("Last Name: "); + System.out.print("> "); + String lastName = scanner.next(); + LOG.info("Employee ID: "); + System.out.print("> "); + String employeeId = scanner.next(); + LOG.info("Salary: " ); + System.out.print("> "); + BigDecimal salary = scanner.nextBigDecimal(); + + Employee employee = new Employee(id, firstName, lastName, employeeId, salary); + service.add(employee); + + } + + @Override + public void collectData(EmployeeService service) { + try (final Scanner scanner = new Scanner(System.in)) { + String keepGoing = "Y"; + do { + LOG.info("Enter information for an employee"); + enterEmployee(service, scanner); + LOG.info("Do you want to enter another employee? (Y/N)"); + System.out.print("> "); + keepGoing = scanner.next(); + if (keepGoing.length() > 1) keepGoing = keepGoing.substring(0, 1); + } while (keepGoing.equalsIgnoreCase("Y")); + } + } + +} diff --git a/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/ui/EmployeeInput.java b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/ui/EmployeeInput.java new file mode 100644 index 0000000000..62156fc6d9 --- /dev/null +++ b/hexagonal-architecture/src/main/java/com/baeldung/hexagonal/ui/EmployeeInput.java @@ -0,0 +1,7 @@ +package com.baeldung.hexagonal.ui; + +import com.baeldung.hexagonal.domain.EmployeeService; + +public interface EmployeeInput { + void collectData(EmployeeService service); +}