Skip to content

Commit

Permalink
It works!
Browse files Browse the repository at this point in the history
  • Loading branch information
gianluca-sabena committed Nov 29, 2023
1 parent 8dfff5f commit 594b648
Show file tree
Hide file tree
Showing 41 changed files with 2,238,226 additions and 1 deletion.
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
__DEL
.vscode
.gradle
**/build/
!src/**/build/

# Ignore Gradle GUI config
gradle-app.setting

# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties

# Cache of project
.gradletasknamecache

# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
# Compiled class file
*.class

Expand Down
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,35 @@
# spring-clean-architecture
# Spring clean

An opinionated spring template based on a "clean architecture". (See credits)

## Architecture

## Folder

## Configure



## Gradle

-


## Source

- Generate spring servlet from spring boot initializr
- Add example from official guide <https://github.com/spring-guides/tut-rest>

## Credits

This project was inspired by:

- Anatomy of a Spring Boot App with Clean Architecture Spring I/O 2023 - [Video](https://www.youtube.com/watch?v=mbNzUkNjrnA) - [Slide](https://www.slideshare.net/StevePember/anatomy-of-a-spring-boot-app-with-clean-architecture-spring-io-2023) - [ Kotlin code](https://github.com/spember/spring-shoestore)
- Spring boot example - Baeldung <https://www.baeldung.com/spring-boot-clean-architecture>
- Spring example with multi-module gradle <https://github.com/carlphilipp/clean-architecture-example/tree/master>
- Spring example with multi-module gradle - Thombergs <https://github.com/thombergs/buckpal>
- Blog <https://medium.com/@viniciusromualdobusiness/clean-architecture-with-spring-boot-a-good-idea-d6f97e450130>
- Red Hat <https://developers.redhat.com/articles/2023/08/08/implementing-clean-architecture-solutions-practical-example>
- Example with ArchUnit <https://reflectoring.io/java-components-clean-boundaries/>
- Blog <https://www.arhohuttunen.com/hexagonal-architecture-spring-boot/>
- Blog <https://betterprogramming.pub/hexagonal-architecture-with-spring-boot-74e93030eba3>
33 changes: 33 additions & 0 deletions adapters/jdbc/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
plugins {
id 'org.springframework.boot' version '3.1.5' apply false
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
sourceCompatibility = '17'
}

repositories {
mavenCentral()
}

dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}

dependencies {
implementation project(':entities:user')
implementation project(':usecases:user')
//implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
implementation 'org.liquibase:liquibase-core'
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.example.clean.adapter;

import com.example.clean.entities.user.User;
import com.example.clean.usecase.port.UserRepository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class DbUserRepository implements UserRepository {
Logger logger = LoggerFactory.getLogger(DbUserRepository.class);

// @Autowired
private JdbcTemplate jdbcTemplate;

private final Map<String, User> inMemoryDb = new HashMap<>();

@Autowired
public DbUserRepository(JdbcTemplate jdbcTemplate) {
logger.info("-------> DbUserRepository JDBC - {}", jdbcTemplate.toString());
this.jdbcTemplate = jdbcTemplate;
}

@Override
public Optional<User> findByEmail(final String email) {
return inMemoryDb.values().stream()
.filter(user -> user.getEmail().equals(email))
.findAny();
}

@Override
public User create(final User user) {
logger.info("JDBC adapter - Create user: {}", user.getId());
jdbcTemplate.update("INSERT INTO person(id, email, password, lastName, firstName) VALUES (?,?,?,?,?)", user.getId(), user.getEmail(), user.getPassword(), user.getLastName(), user.getFirstName());
//inMemoryDb.put(user.getId(), user);
return user;
}

@Override
public Optional<User> findById(final String id) {
return Optional.ofNullable(inMemoryDb.get(id));
}

@Override
public List<User> findAllUsers() {
return jdbcTemplate.query(
"SELECT id, email, password, lastName, firstName FROM person",
(rs, rowNum) -> User.builder().id(rs.getString("id")).email(rs.getString("email"))
.password(rs.getString("password")).lastName(rs.getString("lastName"))
.firstName(rs.getString("firstName")).build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
databaseChangeLog:
- changeSet:
id: "1"
author: default
changes:
- createTable:
tableName: person
columns:
- column:
name: id
type: uuid
constraints:
primaryKey: true
nullable: false
- column:
name: email
type: varchar(50)
- column:
name: password
type: varchar(50)
- column:
name: lastName
type: varchar(50)
- column:
name: firstName
type: varchar(50)
- changeSet:
id: "2"
author: default
changes:
- insert:
tableName: person
columns:
- column:
name: id
value: 00000000-0000-0000-0000-000000000000
- column:
name: email
value: [email protected]
- column:
name: firstName
value: First Name
- column:
name: lastName
value: Last Name
28 changes: 28 additions & 0 deletions adapters/memory/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
plugins {
id 'org.springframework.boot' version '3.1.5' apply false
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
sourceCompatibility = '17'
}

repositories {
mavenCentral()
}

dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}

dependencies {
implementation project(':entities:user')
implementation project(':usecases:user')
implementation 'org.springframework.boot:spring-boot-starter'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.example.clean.adapter;

import com.example.clean.entities.user.User;
import com.example.clean.usecase.port.UserRepository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class DbUserRepository implements UserRepository {
Logger logger = LoggerFactory.getLogger(DbUserRepository.class);
private final Map<String, User> inMemoryDb = new HashMap<>();

public DbUserRepository() {
logger.info("-------> DbUserRepository MEMORY");
}

@Override
public User create(final User user) {
inMemoryDb.put(user.getId(), user);
return user;
}
@Override
public Optional<User> findByEmail(final String email) {
return inMemoryDb.values().stream()
.filter(user -> user.getEmail().equals(email))
.findAny();
}
@Override
public Optional<User> findById(final String id) {
return Optional.ofNullable(inMemoryDb.get(id));
}

@Override
public List<User> findAllUsers() {
return new ArrayList<>(inMemoryDb.values());
}
}
Empty file added build.gradle
Empty file.
9 changes: 9 additions & 0 deletions entities/user/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apply plugin: 'java-library'
archivesBaseName = 'entities-user'
java {
sourceCompatibility = '17'
}

repositories {
mavenCentral()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.example.clean.entities.user;

public class User {

private String id;
private String email;
private String password;
private String lastName;
private String firstName;

// required for mvc servlet json deserialization
User() {

}

private User(final String id, final String email, final String password, final String lastName, final String firstName) {
this.id = id;
this.email = email;
this.password = password;
this.lastName = lastName;
this.firstName = firstName;
}

public static UserBuilder builder() {
return new UserBuilder();
}

public static class UserBuilder {
private String id;
private String email;
private String password;
private String lastName;
private String firstName;

UserBuilder() {
}

public UserBuilder id(final String id) {
this.id = id;
return this;
}

public UserBuilder email(final String email) {
this.email = email;
return this;
}

public UserBuilder password(final String password) {
this.password = password;
return this;
}

public UserBuilder lastName(final String lastName) {
this.lastName = lastName;
return this;
}

public UserBuilder firstName(final String firstName) {
this.firstName = firstName;
return this;
}

public User build() {
return new User(id, email, password, lastName, firstName);
}
}

public String getId() {
return id;
}

public String getEmail() {
return email;
}

public String getPassword() {
return password;
}

public String getLastName() {
return lastName;
}

public String getFirstName() {
return firstName;
}

@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
", lastName='" + lastName + '\'' +
", firstName='" + firstName + '\'' +
'}';
}
}
Loading

0 comments on commit 594b648

Please sign in to comment.