Skip to content

Commit

Permalink
Merge pull request #10 from tomoyane/add-di-db
Browse files Browse the repository at this point in the history
Add di db
  • Loading branch information
tomoyane authored Feb 4, 2024
2 parents 7e929d0 + 09c9d6b commit 40170d2
Show file tree
Hide file tree
Showing 98 changed files with 2,683 additions and 1,479 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
out/
build/
credentials.yml
.java-version
.java-version
docker/Cassandra/*
295 changes: 148 additions & 147 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,179 +4,180 @@

About Spring Boot architecture.

## Environment variable
This repository support multiple database by SPRING_PROFILES_ACTIVE
* RDBMS
* MongoDB
* Cassandra
* Redis

|Name|Description|
|---|---|
|SPRING_PROFILES_ACTIVE|Spring runtime environment|
|MYSQL_DB_HOST|Database host|
|MYSQL_DB_NAME|Database name|
|MYSQL_DB_USER|Database username|
|MYSQL_DB_PASS|Database password|
|REDIS_DB_HOST|Redis host|
|REDIS_DB_PORT|Redis port|
|REDIS_DB_PASS|Redis password|
## Requirements
* Docker engine
* Docker Compose
* OpenJDK 17
* Spring Boot 2

### Spring Active Profiles (Local)
### Docker database
MySQL8
* **Standalone**

Local development property file is application-local.yml.
MongoDB
* **Standalone**

Cassandra cluster.
* **3 Nodes**

## Architecture
The "app" package holds controllers for API endpoints and provides interception. The "app" package can depend on the "domain" package.

The "domain" package provides business logic and holds Spring Component Beans or Service Beans. It cannot depend on the "app" package but relies on the "infrastructure" package.

The "infrastructure" package provides data storage by holding Spring Repository Beans. It is independent and cannot depend on the "app" and "domain" packages.

The "common" package offers generic functions.

Initialization processes during server startup depend on "SPRING_PROFILES_ACTIVE" and assume the specified data store's Bean as a prerequisite for the initial startup.


### Directory structure

```bash
$ export SPRING_PROFILES_ACTIVE="local"
java
│   │   └── com
│   │   └── bestpractice
│   │   └── api
│   │   ├── Application.java
│   │   ├── app
│   │   │   ├── AdviceController.java
│   │   │   ├── AppBean.java
│   │   │   ├── InterceptorController.java
│   │   │   ├── v1
│   │   │   │   ├── AuthController.java
│   │   │   │   ├── HelloController.java
│   │   │   │   ├── RdbmsController.java
│   │   │   │   └── UserController.java
│   │   │   └── v2
│   │   │   └── AuthorizationController.java
│   │   ├── common
│   │   │   ├── exception
│   │   │   │   ├── BadRequest.java
│   │   │   │   ├── Conflict.java
│   │   │   │   ├── Forbidden.java
│   │   │   │   ├── InternalServerError.java
│   │   │   │   ├── NotFound.java
│   │   │   │   ├── RequestTimeout.java
│   │   │   │   ├── ServiceUnavailable.java
│   │   │   │   └── UnAuthorized.java
│   │   │   ├── property
│   │   │   │   └── CredentialProperty.java
│   │   │   └── util
│   │   │   └── Util.java
│   │   ├── domain
│   │   │   ├── DomainBean.java
│   │   │   ├── component
│   │   │   │   ├── AuthComponent.java
│   │   │   │   ├── BCryptPasswordEncryptionComponent.java
│   │   │   │   └── RequestInfoComponent.java
│   │   │   ├── model
│   │   │   │   ├── AuthByEmailRequest.java
│   │   │   │   ├── AuthByRefreshTokenRequest.java
│   │   │   │   ├── AuthResponse.java
│   │   │   │   ├── Credential.java
│   │   │   │   ├── ErrorResponse.java
│   │   │   │   ├── InfoRequest.java
│   │   │   │   ├── InfoResponse.java
│   │   │   │   ├── UserRequest.java
│   │   │   │   └── UserResponse.java
│   │   │   └── service
│   │   │   ├── AuthService.java
│   │   │   ├── AuthServiceImpl.java
│   │   │   ├── InfoService.java
│   │   │   ├── InfoServiceImpl.java
│   │   │   ├── UserService.java
│   │   │   └── UserServiceImpl.java
│   │   └── infrastrucuture
│   │   ├── InfrastructureBean.java
│   │   ├── cache
│   │   │   ├── CacheRepository.java
│   │   │   ├── local
│   │   │   │   └── LocalCacheRepository.java
│   │   │   └── redis
│   │   │   ├── RedisCacheRepository.java
│   │   │   └── RedisProperty.java
│   │   ├── entity
│   │   │   ├── Info.java
│   │   │   ├── SharedData.java
│   │   │   └── User.java
│   │   └── persistent
│   │   ├── InfoPersistentRepository.java
│   │   ├── UserPersistentRepository.java
│   │   ├── cassandra
│   │   │   ├── CassandraInfoPersistentRepository.java
│   │   │   ├── CassandraUserPersistentRepository.java
│   │   │   └── property
│   │   │   └── CassandraProperty.java
│   │   ├── local
│   │   │   ├── LocalInfoPersistentRepository.java
│   │   │   └── LocalUserPersistentRepository.java
│   │   ├── mongo
│   │   │   ├── MongoInfoPersistentRepository.java
│   │   │   ├── MongoUserPersistentRepository.java
│   │   │   ├── entity
│   │   │   │   ├── MongoInfoEntity.java
│   │   │   │   └── MongoUserEntity.java
│   │   │   └── property
│   │   │   └── MongoProperty.java
│   │   └── rdbms
│   │   ├── RdbmsInfoPersistentRepository.java
│   │   └── RdbmsUserPersistentRepository.java
```

You can check start server for local.
### Interceptor JWT verification

```bash
# Data store
$ cd docker
$ docker-compose up
* app/InterceptorController.java

# Application
$ cd scripts
$ ./start_local_server.sh
```
### MySQL Repository injection

Working on docker container.
* Docker Image
* MySQL
* Redis
* OpenJDK 17
* infrastructure/persistent/rdbms/RdbmsUserPersistentRepository.java
* infrastructure/persistent/rdbms/RdbmsInfoPersistentRepository.java

Cassandra cluster.
* CentOS7 virtual machine
* 3 nodes
### MongoDB Repository injection

#### MySQL (8)
* infrastructure/persistent/mongo/RdbmsUserPersistentRepository.java
* infrastructure/persistent/mongo/RdbmsInfoPersistentRepository.java

Sample Class
* UserRepository.java
* InfoRepository.java

#### Redis
Sample Class
* UserService
### Cassandra Repository injection

### Spring Active Profiles (Develop)
Develop development property file is application-dev.yml.
* infrastructure/persistent/cassandra/RdbmsUserPersistentRepository.java
* infrastructure/persistent/cassandra/RdbmsInfoPersistentRepository.java

```bash
$ export SPRING_PROFILES_ACTIVE="dev"
```
### Redis Repository injection

## Build
Git clone.
```bash
$ git clone https://github.com/tomoyane/springboot-bestpractice.git
```
* infrastructure/cache/redis/RedisCacheRepository.java

Run test.
```bash
./gradlew test
```
## Getting Started

Rub build.
Start database process
```bash
./gradlew build
```
# RDBMS
docker-compose run -p 3306:3306 mysql_db

### Using docker container
Docker image build
* Build SpringBoot best practice application.
* Use docker for local development.
* MySQL
* Redis
* OpenJDK
# Mongo
docker-compose run -p 27017:27017 mongo_db

```bash
$ docker-compose build
# Cassandra
docker-compose up cassandra_01 cassandra_02 cassandra_03
```

Run container
Start api server via script
```bash
$ docker-compose up -d
```
# RDBMS
./scripts/start_server.sh --spring_profile=local,db_rdbms

## Authentication and Authorization
Spring security.
# Mongo
./scripts/start_server.sh --spring_profile=local,db_mongo

JWT.

## Architecture
```bash
spring-boot-bestpracite
├── LICENSE
├── README.md
├── build
│   ├── bootRunMainClassName
│   ├── classes
│   │   └── java
│   │   └── main
│   │   └── com
│   │   └── bestpractice
│   │   └── api
│   │   ├── Application.class
│   │   ├── app
│   │   │   ├── Advice.class
│   │   │   ├── AppBean$SwaggerConfig.class
│   │   │   ├── AppBean.class
│   │   │   ├── v1
│   │   │   │   ├── AuthenticationController.class
│   │   │   │   ├── HelloController.class
│   │   │   │   └── RdbmsController.class
│   │   │   └── v2
│   │   │   └── AuthorizationController.class
│   │   ├── common
│   │   │   ├── exception
│   │   │   │   ├── BadRequest.class
│   │   │   │   ├── Conflict.class
│   │   │   │   ├── Forbidden.class
│   │   │   │   ├── InternalServerError.class
│   │   │   │   ├── NotFound.class
│   │   │   │   ├── RequestTimeout.class
│   │   │   │   ├── ServiceUnavailable.class
│   │   │   │   └── UnAuthorized.class
│   │   │   ├── property
│   │   │   │   ├── CredentialProperty.class
│   │   │   │   └── RedisProperty.class
│   │   │   └── util
│   │   │   └── Util.class
│   │   ├── domain
│   │   │   ├── DomainBean.class
│   │   │   ├── model
│   │   │   │   ├── AuthRequest.class
│   │   │   │   ├── AuthResponse.class
│   │   │   │   ├── Credential.class
│   │   │   │   ├── Exception.class
│   │   │   │   ├── InfoRequest.class
│   │   │   │   ├── InfoResponse.class
│   │   │   │   ├── UserRequest.class
│   │   │   │   └── UserResponse.class
│   │   │   └── service
│   │   │   ├── AuthenticationService.class
│   │   │   ├── InfoService.class
│   │   │   ├── InfoServiceImpl.class
│   │   │   ├── JsonWebTokenService.class
│   │   │   ├── UserService.class
│   │   │   └── UserServiceImpl.class
│   │   ├── infrastrucuture
│   │   │   ├── InfrastructureBean.class
│   │   │   ├── entity
│   │   │   │   ├── Info.class
│   │   │   │   ├── SharedAbstract.class
│   │   │   │   ├── SignatureKey.class
│   │   │   │   └── User.class
│   │   │   └── repository
│   │   │   ├── InfoRepository.class
│   │   │   └── UserRepository.class
│   │   └── security
│   │   ├── SecurityBean.class
│   │   ├── filter
│   │   │   ├── AuthEntryPoint.class
│   │   │   └── PreAuthenticatedProcessingFilter.class
│   │   └── role
│   │   ├── AdminAuthority.class
│   │   └── UserAuthority.class```
# Cassandra
./scripts/start_server.sh --spring_profile=local,db_cassandra
```

## License
Expand Down
15 changes: 11 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {

def pkgName = 'com.bestpractice.api'
def pkgVersion = "1.1.0"
def javaVersion = project.hasProperty('javaVersion') ? project.getProperty('javaVersion') : '17'
def javaVersion = !project.hasProperty('javaVersion') ? '17' : project.getProperty('javaVersion')
def artifactId = 'spring-boot-bestpractice'

sourceCompatibility = javaVersion
Expand All @@ -15,9 +15,13 @@ repositories {
mavenCentral()
}

configurations.all {
exclude group: 'org.slf4j', module: 'slf4j-nop'
}

dependencies {
// Spring
implementation "org.springframework.boot:spring-boot-starter-web"
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springframework.boot:spring-boot-starter-data-jpa"
implementation "org.springframework.boot:spring-boot-configuration-processor"
implementation "org.springframework.boot:spring-boot-starter-security"
Expand All @@ -26,12 +30,15 @@ dependencies {
implementation "io.springfox:springfox-swagger-ui:2.8.0"

// Token
implementation "io.jsonwebtoken:jjwt:0.9.0"
implementation 'com.auth0:java-jwt:4.4.0'

// Database
implementation "mysql:mysql-connector-java"
implementation "org.postgresql:postgresql"
implementation 'redis.clients:jedis:3.7.0'
implementation 'org.mongodb:mongo-java-driver:3.12.14'
implementation 'com.datastax.oss:java-driver-core:4.17.0'
implementation 'com.datastax.oss:java-driver-query-builder:4.17.0'

// Third party
implementation 'javax.validation:validation-api:2.0.1.Final'
Expand All @@ -54,4 +61,4 @@ sourceSets {

processResources {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}
Loading

0 comments on commit 40170d2

Please sign in to comment.