diff --git a/API-Gateway/pom.xml b/API-Gateway/pom.xml index 6623607..a48a97f 100644 --- a/API-Gateway/pom.xml +++ b/API-Gateway/pom.xml @@ -34,6 +34,10 @@ org.springframework.cloud spring-cloud-starter-netflix-eureka-client + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot spring-boot-starter-test diff --git a/API-Gateway/src/main/resources/bootstrap.yml b/API-Gateway/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..fec1a91 --- /dev/null +++ b/API-Gateway/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: api-gateway + cloud: + config: + uri: http://localhost:8888 diff --git a/Account-Service/pom.xml b/Account-Service/pom.xml index 3d4401c..b192ed2 100644 --- a/Account-Service/pom.xml +++ b/Account-Service/pom.xml @@ -42,6 +42,10 @@ org.springframework.cloud spring-cloud-starter-openfeign + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot diff --git a/Account-Service/src/main/resources/bootstrap.yml b/Account-Service/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..d503a83 --- /dev/null +++ b/Account-Service/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: account-service + cloud: + config: + uri: http://localhost:8888 diff --git a/Config-Server/Dockerfile b/Config-Server/Dockerfile new file mode 100644 index 0000000..bf7d48b --- /dev/null +++ b/Config-Server/Dockerfile @@ -0,0 +1,7 @@ +FROM openjdk:17-jdk + +COPY target/configserver-0.0.1-SNAPSHOT.jar . + +EXPOSE 8888 + +ENTRYPOINT ["java", "-jar", "configserver-0.0.1-SNAPSHOT.jar"] diff --git a/Config-Server/README.md b/Config-Server/README.md new file mode 100644 index 0000000..fa49fe7 --- /dev/null +++ b/Config-Server/README.md @@ -0,0 +1,148 @@ +# Config Server + +## ๐Ÿš€ Introduction +The Config Server is a critical component in a microservices architecture, responsible for centralized configuration management. It allows microservices to externalize their configuration and retrieve it from a central location at runtime. + +## ๐Ÿ“š Table of Contents +- [๐Ÿ“‚ Project Structure](#-project-structure) +- [๐Ÿ› ๏ธ Technologies Used](#-technologies-used) + - [๐ŸŒฑ Spring Boot](#spring-boot) + - [โ˜๏ธ Spring Cloud Config](#spring-cloud-config) +- [๐Ÿ”— API Endpoints](#api-endpoints) +- [โš ๏ธ Error Handling](#error-handling) +- [๐Ÿ”’ Security](#security) +- [โš™๏ธ Configuration](#configuration) +- [๐Ÿ“ˆ Monitoring](#monitoring) +- [๐Ÿ“ Logging](#logging) +- [๐Ÿงช Testing](#testing) +- [๐Ÿš€ Build and Deployment](#build-and-deployment) + +## ๐Ÿ“‚ Project Structure +The project structure of the Config Server is as follows: +``` +Config-Server +โ”œโ”€โ”€ src +โ”‚ โ”œโ”€โ”€ main +โ”‚ โ”‚ โ”œโ”€โ”€ java +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ org +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ training +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ config +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ server +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ ConfigServerApplication.java +โ”‚ โ”‚ โ””โ”€โ”€ resources +โ”‚ โ”‚ โ”œโ”€โ”€ application.yml +โ”‚ โ”‚ โ””โ”€โ”€ config +โ”‚ โ”‚ โ”œโ”€โ”€ service-registry.yml +โ”‚ โ”‚ โ”œโ”€โ”€ api-gateway.yml +โ”‚ โ”‚ โ”œโ”€โ”€ user-service.yml +โ”‚ โ”‚ โ”œโ”€โ”€ account-service.yml +โ”‚ โ”‚ โ”œโ”€โ”€ fund-transfer-service.yml +โ”‚ โ”‚ โ”œโ”€โ”€ transaction-service.yml +โ”‚ โ”‚ โ””โ”€โ”€ sequence-generator.yml +โ”œโ”€โ”€ .gitignore +โ”œโ”€โ”€ Dockerfile +โ”œโ”€โ”€ pom.xml +โ””โ”€โ”€ README.md +``` + +## ๐Ÿ› ๏ธ Technologies Used + +### ๐ŸŒฑ Spring Boot +Spring Boot is used to create stand-alone, production-grade Spring-based applications. It simplifies the configuration and deployment process by providing a set of default configurations and a wide range of features such as embedded servers, security, and monitoring. + +### โ˜๏ธ Spring Cloud Config +Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system. With the Config Server, you have a central place to manage external properties for applications across all environments. + +## ๐Ÿ”— API Endpoints +The Config Server exposes the following endpoints: + +- `GET /{application}/{profile}[/{label}]` - Retrieve configuration for a specific application and profile +- `GET /{application}-{profile}.yml` - Retrieve configuration as YAML +- `GET /{application}-{profile}.properties` - Retrieve configuration as properties +- `GET /{label}/{application}-{profile}.yml` - Retrieve configuration from a specific label (branch/tag) + +Example: `GET http://localhost:8888/user-service/default` retrieves the configuration for user-service. + +## โš ๏ธ Error Handling +The Config Server uses standard HTTP status codes to indicate the success or failure of requests. Common status codes include: +- `200 OK` - The request was successful. +- `400 Bad Request` - The request was invalid or cannot be served. +- `404 Not Found` - The requested configuration was not found. +- `500 Internal Server Error` - An error occurred on the server. + +## ๐Ÿ”’ Security +The Config Server can be secured using Spring Security. Authentication and authorization can be configured to protect the configuration endpoints and ensure only authorized services can access configurations. + +## โš™๏ธ Configuration +The Config Server is configured to use the native profile, which stores configuration files in the classpath under `/config` directory. Each microservice has its own configuration file named `{service-name}.yml`. + +### Centralized Configurations +The Config Server manages configurations for the following services: +- **Service Registry** (service-registry.yml) - Port 8761 +- **API Gateway** (api-gateway.yml) - Port 8080 +- **User Service** (user-service.yml) - Port 8082 +- **Account Service** (account-service.yml) - Port 8081 +- **Fund Transfer Service** (fund-transfer-service.yml) - Port 8085 +- **Transaction Service** (transaction-service.yml) - Port 8084 +- **Sequence Generator** (sequence-generator.yml) - Port 8083 + +### Environment Variable Support +All database configurations support environment variable substitution: +- `MYSQL_HOST` (default: localhost) +- `MYSQL_PORT` (default: 3306) +- `MYSQL_DB_NAME` (default: service-specific database name) +- `MYSQL_USER` (default: root) +- `MYSQL_PASSWORD` (default: root) + +## ๐Ÿ“ˆ Monitoring +Spring Boot Actuator is used for monitoring and managing the application. It provides various endpoints to check the health, metrics, and other operational information of the service. + +## ๐Ÿ“ Logging +Logging is configured using Logback, which is the default logging framework in Spring Boot. It provides powerful and flexible logging capabilities. + +## ๐Ÿงช Testing +JUnit and Mockito are used for unit and integration testing. These frameworks provide a comprehensive set of tools for writing and running tests. + +## ๐Ÿš€ Build and Deployment + +### Building the Project +```bash +cd Config-Server +mvn clean install +``` + +### Running Locally +```bash +mvn spring-boot:run +``` + +The Config Server will start on port 8888. + +### Startup Sequence +The recommended startup sequence for the microservices architecture is: +1. **Service Registry** (port 8761) - Must start first for service discovery +2. **Config Server** (port 8888) - Starts second to provide centralized configuration +3. **Other services** - Can start in any order, they will connect to Config Server via bootstrap.yml + +### Docker Deployment +The service can be packaged as a Docker container for deployment in a containerized environment. + +```bash +mvn clean package -DskipTests +docker build -t config-server . +docker run -p 8888:8888 config-server +``` + +## ๐Ÿ“– Usage by Client Services +Client services connect to the Config Server by adding the `spring-cloud-starter-config` dependency and creating a `bootstrap.yml` file with the Config Server URL: + +```yaml +spring: + application: + name: {service-name} + cloud: + config: + uri: http://localhost:8888 +``` + +Client services will automatically fetch their configuration from the Config Server on startup based on their application name. diff --git a/Config-Server/pom.xml b/Config-Server/pom.xml new file mode 100644 index 0000000..68be97a --- /dev/null +++ b/Config-Server/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.14 + + + org.training + configserver + 0.0.1-SNAPSHOT + Config Server + Config Server + + 17 + 2021.0.8 + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/Config-Server/src/main/java/org/training/config/server/ConfigServerApplication.java b/Config-Server/src/main/java/org/training/config/server/ConfigServerApplication.java new file mode 100644 index 0000000..801f248 --- /dev/null +++ b/Config-Server/src/main/java/org/training/config/server/ConfigServerApplication.java @@ -0,0 +1,15 @@ +package org.training.config.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.config.server.EnableConfigServer; + +@SpringBootApplication +@EnableConfigServer +public class ConfigServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConfigServerApplication.class, args); + } + +} diff --git a/Config-Server/src/main/resources/application.yml b/Config-Server/src/main/resources/application.yml new file mode 100644 index 0000000..4633a13 --- /dev/null +++ b/Config-Server/src/main/resources/application.yml @@ -0,0 +1,13 @@ +server: + port: 8888 + +spring: + application: + name: config-server + profiles: + active: native + cloud: + config: + server: + native: + search-locations: classpath:/config diff --git a/Config-Server/src/main/resources/config/account-service.yml b/Config-Server/src/main/resources/config/account-service.yml new file mode 100644 index 0000000..0cd9e46 --- /dev/null +++ b/Config-Server/src/main/resources/config/account-service.yml @@ -0,0 +1,23 @@ +server: + port: 8081 + +spring: + application: + name: account-service + bad_request: 400 + conflict: 409 + ok: 200 + not_found: 404 + + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB_NAME:account_service} + username: ${MYSQL_USER:root} + password: ${MYSQL_PASSWORD:root} + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true diff --git a/Config-Server/src/main/resources/config/api-gateway.yml b/Config-Server/src/main/resources/config/api-gateway.yml new file mode 100644 index 0000000..d5d5bfc --- /dev/null +++ b/Config-Server/src/main/resources/config/api-gateway.yml @@ -0,0 +1,68 @@ +server: + port: 8080 + +app: + config: + keycloak: + url: http://localhost:8571/ + realm: banking-service + +eureka: + client: + service-url: + defaultZone: http://localhost:8761/eureka + +spring: + application: + name: api-gateway + + cloud: + gateway: + routes: + - id: user-service + uri: lb://user-service + predicates: + - Path=/api/users/** + - id: fund-transfer-service + uri: lb://fund-transfer-service + predicates: + - Path=/api/fund-transfers/** + - id: account-service + uri: lb://account-service + predicates: + - Path=/accounts/** + - id: sequence-generator + uri: lb://sequence-generator + predicates: + - Path=/sequence/** + - id: transaction-service + uri: lb://transaction-service + predicates: + - Path=/transactions/** + - id: fund-transfer-service-direct + uri: lb://fund-transfer-service + predicates: + - Path=/fund-transfers/** + + security: + oauth2: + client: + provider: + keycloak: + token-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/token + authorization-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/auth + user-name-attribute: preferred_username + user-info-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/userinfo + jwk-set-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/certs + user-info-authentication-method: header + registration: + banking-service-client: + provider: keycloak + client-id: banking-service-client + client-secret: ${KEYCLOAK_CLIENT_SECRET} + authorization-grant-type: authorization_code + redirect-uri: http://localhost:8571/login/oauth2/code/keycloak + scope: openid + resourceserver: + jwt: + jwk-set-uri: ${app.config.keycloak.url}/realms/${app.config.keycloak.realm}/protocol/openid-connect/certs diff --git a/Config-Server/src/main/resources/config/fund-transfer-service.yml b/Config-Server/src/main/resources/config/fund-transfer-service.yml new file mode 100644 index 0000000..a29f68e --- /dev/null +++ b/Config-Server/src/main/resources/config/fund-transfer-service.yml @@ -0,0 +1,21 @@ +server: + port: 8085 + +spring: + application: + name: fund-transfer-service + bad_request: 400 + ok: 200 + + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB_NAME:fund_transfer_service} + username: ${MYSQL_USER:root} + password: ${MYSQL_PASSWORD:root} + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true diff --git a/Config-Server/src/main/resources/config/sequence-generator.yml b/Config-Server/src/main/resources/config/sequence-generator.yml new file mode 100644 index 0000000..f39b387 --- /dev/null +++ b/Config-Server/src/main/resources/config/sequence-generator.yml @@ -0,0 +1,19 @@ +server: + port: 8083 + +spring: + application: + name: sequence-generator + + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB_NAME:sequence_generator} + username: ${MYSQL_USER:root} + password: ${MYSQL_PASSWORD:root} + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true diff --git a/Config-Server/src/main/resources/config/service-registry.yml b/Config-Server/src/main/resources/config/service-registry.yml new file mode 100644 index 0000000..b8bdc45 --- /dev/null +++ b/Config-Server/src/main/resources/config/service-registry.yml @@ -0,0 +1,13 @@ +server: + port: 8761 + +eureka: + client: + service-url: + defaultZone: http://localhost:8761/eureka + register-with-eureka: false + fetch-registry: false + +spring: + application: + name: SERVICE-REGISTRY diff --git a/Config-Server/src/main/resources/config/transaction-service.yml b/Config-Server/src/main/resources/config/transaction-service.yml new file mode 100644 index 0000000..2c19b39 --- /dev/null +++ b/Config-Server/src/main/resources/config/transaction-service.yml @@ -0,0 +1,22 @@ +server: + port: 8084 + +spring: + application: + name: transaction-service + bad_request: 400 + conflict: 409 + ok: 200 + + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB_NAME:transaction_service} + username: ${MYSQL_USER:root} + password: ${MYSQL_PASSWORD:root} + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true diff --git a/Config-Server/src/main/resources/config/user-service.yml b/Config-Server/src/main/resources/config/user-service.yml new file mode 100644 index 0000000..363a78a --- /dev/null +++ b/Config-Server/src/main/resources/config/user-service.yml @@ -0,0 +1,31 @@ +server: + port: 8082 + +spring: + application: + name: user-service + bad_request: 400 + conflict: 409 + success: 200 + not_found: 404 + + datasource: + url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB_NAME:user_service} + username: ${MYSQL_USER:root} + password: ${MYSQL_PASSWORD:root} + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true + + +app: + config: + keycloak: + server-url: http://localhost:8571 + realm: banking-service + client-id: banking-service-api-client + client-secret: ${KEYCLOAK_API_CLIENT_SECRET} diff --git a/Fund-Transfer/pom.xml b/Fund-Transfer/pom.xml index e5edb09..eb83181 100644 --- a/Fund-Transfer/pom.xml +++ b/Fund-Transfer/pom.xml @@ -63,6 +63,10 @@ org.springframework.cloud spring-cloud-starter-openfeign + + org.springframework.cloud + spring-cloud-starter-config + diff --git a/Fund-Transfer/src/main/resources/bootstrap.yml b/Fund-Transfer/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..1dec3af --- /dev/null +++ b/Fund-Transfer/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: fund-transfer-service + cloud: + config: + uri: http://localhost:8888 diff --git a/Sequence-Generator/pom.xml b/Sequence-Generator/pom.xml index 8fa1910..89d5b61 100644 --- a/Sequence-Generator/pom.xml +++ b/Sequence-Generator/pom.xml @@ -34,6 +34,10 @@ org.springframework.cloud spring-cloud-starter-netflix-eureka-client + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot diff --git a/Sequence-Generator/src/main/resources/bootstrap.yml b/Sequence-Generator/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..d384e17 --- /dev/null +++ b/Sequence-Generator/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: sequence-generator + cloud: + config: + uri: http://localhost:8888 diff --git a/Service-Registry/pom.xml b/Service-Registry/pom.xml index f236a23..a4fab06 100644 --- a/Service-Registry/pom.xml +++ b/Service-Registry/pom.xml @@ -30,6 +30,10 @@ org.springframework.cloud spring-cloud-starter-netflix-eureka-server + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot diff --git a/Service-Registry/src/main/resources/bootstrap.yml b/Service-Registry/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..3dcf0d0 --- /dev/null +++ b/Service-Registry/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: service-registry + cloud: + config: + uri: http://localhost:8888 diff --git a/Transaction-Service/pom.xml b/Transaction-Service/pom.xml index 6f70a80..091d486 100644 --- a/Transaction-Service/pom.xml +++ b/Transaction-Service/pom.xml @@ -42,6 +42,10 @@ org.springframework.cloud spring-cloud-starter-openfeign + + org.springframework.cloud + spring-cloud-starter-config + org.springframework.boot diff --git a/Transaction-Service/src/main/resources/bootstrap.yml b/Transaction-Service/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..8bf8902 --- /dev/null +++ b/Transaction-Service/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: transaction-service + cloud: + config: + uri: http://localhost:8888 diff --git a/User-Service/pom.xml b/User-Service/pom.xml index 75e9b29..0c707ea 100644 --- a/User-Service/pom.xml +++ b/User-Service/pom.xml @@ -75,6 +75,10 @@ org.springframework.cloud spring-cloud-starter-openfeign + + org.springframework.cloud + spring-cloud-starter-config + org.modelmapper modelmapper diff --git a/User-Service/src/main/resources/bootstrap.yml b/User-Service/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..7a79533 --- /dev/null +++ b/User-Service/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: user-service + cloud: + config: + uri: http://localhost:8888