diff --git a/README.md b/README.md
index c36fb16..6a1e0f9 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,10 @@ To maintain a clean and professional structure, all deep-dive documentation has
- [**Deployment & Environments**](./docs/DEPLOYMENT_GUIDE.md): How to run the app in Local, Docker, and Cloud.
- [**Tax Engine Standards**](./docs/TAX_ENGINE_STANDARDS.md): Logical breakdown of Indian Tax laws and our Strategy implementation.
- [**Quality Standards**](./docs/QUALITY_STANDARDS.md): Guide to Checkstyle, PMD, and SpotBugs integration.
+- [**API Test Plan**](./docs/API_TEST_PLAN.md): Manual verification steps and Postman payloads.
- [**Java 21 Migration Guide**](./docs/JAVA_21_MIGRATION_GUIDE.md): Technical checklist of features migrated (Records, Switch Expressions, etc.).
+
---
## ๐ Quick Start
@@ -17,8 +19,9 @@ To maintain a clean and professional structure, all deep-dive documentation has
cd docker
docker-compose up -d --build
```
-- People Service: `http://localhost:8080`
- Tax Engine Service: `http://localhost:8081`
+> **Note**: If you face database errors like `database "peopledb" does not exist`, run `docker-compose down -v` to reset the volumes and restart.
+
### Running Locally (Individual Services)
```bash
@@ -53,8 +56,9 @@ Current Phase: **Phase 2 - Intelligent Orchestration** (Completed โ
)
- [ ] **Internal Research**: Explore `RestClient` vs `OpenFeign`.
- [ ] **Observability & Ops**
- - [ ] Add Spring Boot Actuator to all services.
- - [ ] Standardize structured logging and Correlation IDs.
+ - [x] Add Spring Boot Actuator to all services.
+ - [x] Standardize structured logging and Correlation IDs.
+
- [ ] **Infrastructure**
- [x] GitHub Actions CI/CD Pipeline integration.
diff --git a/common-lib/pom.xml b/common-lib/pom.xml
index 2fd5df9..0add339 100644
--- a/common-lib/pom.xml
+++ b/common-lib/pom.xml
@@ -27,5 +27,36 @@
lombok
true
+
+ org.springframework.boot
+ spring-boot-starter-web
+ provided
+
+
+ net.logstash.logback
+ logstash-logback-encoder
+ 9.0
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ 4.1.0
+ provided
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 3.0.1
+ provided
+
+
+
+
+
diff --git a/common-lib/src/main/java/com/example/common/config/OpenApiConfig.java b/common-lib/src/main/java/com/example/common/config/OpenApiConfig.java
new file mode 100644
index 0000000..60fa3fc
--- /dev/null
+++ b/common-lib/src/main/java/com/example/common/config/OpenApiConfig.java
@@ -0,0 +1,21 @@
+package com.example.common.config;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.annotation.Bean;
+
+@AutoConfiguration
+public class OpenApiConfig {
+
+ @Bean
+ public OpenAPI customOpenAPI() {
+ return new OpenAPI()
+ .info(new Info()
+ .title("People & Tax Ecosystem API")
+ .version("0.0.1-SNAPSHOT")
+ .description("API for managing people and calculating tax in the Indian context.")
+ .license(new License().name("Apache 2.0").url("http://springdoc.org")));
+ }
+}
diff --git a/common-lib/src/main/java/com/example/common/exception/ErrorResponse.java b/common-lib/src/main/java/com/example/common/exception/ErrorResponse.java
new file mode 100644
index 0000000..1525004
--- /dev/null
+++ b/common-lib/src/main/java/com/example/common/exception/ErrorResponse.java
@@ -0,0 +1,10 @@
+package com.example.common.exception;
+
+import java.time.LocalDateTime;
+
+public record ErrorResponse(
+ String message,
+ String correlationId,
+ int status,
+ LocalDateTime timestamp) {
+}
diff --git a/common-lib/src/main/java/com/example/common/exception/GlobalExceptionHandler.java b/common-lib/src/main/java/com/example/common/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..9d64a75
--- /dev/null
+++ b/common-lib/src/main/java/com/example/common/exception/GlobalExceptionHandler.java
@@ -0,0 +1,53 @@
+package com.example.common.exception;
+
+import com.example.common.logging.CorrelationIdFilter;
+import org.slf4j.MDC;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+import java.time.LocalDateTime;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity handleAllExceptions(Exception ex) {
+ if (logger.isErrorEnabled()) {
+ logger.error("Unhandled exception occurred: {}", ex.getMessage(), ex);
+ }
+ return buildErrorResponse(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ @ExceptionHandler(IllegalArgumentException.class)
+ public ResponseEntity handleIllegalArgumentException(IllegalArgumentException ex) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("Invalid argument: {}", ex.getMessage());
+ }
+ return buildErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST);
+ }
+
+ @ExceptionHandler(IllegalStateException.class)
+ public ResponseEntity handleIllegalStateException(IllegalStateException ex) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("Illegal state: {}", ex.getMessage());
+ }
+ return buildErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST);
+ }
+
+ private ResponseEntity buildErrorResponse(String message, HttpStatus status) {
+ String correlationId = MDC.get(CorrelationIdFilter.CORRELATION_ID_LOG_VAR);
+ ErrorResponse error = new ErrorResponse(
+ message,
+ correlationId,
+ status.value(),
+ LocalDateTime.now());
+ return new ResponseEntity<>(error, status);
+ }
+}
diff --git a/common-lib/src/main/java/com/example/common/logging/CorrelationIdFilter.java b/common-lib/src/main/java/com/example/common/logging/CorrelationIdFilter.java
new file mode 100644
index 0000000..ae30ec6
--- /dev/null
+++ b/common-lib/src/main/java/com/example/common/logging/CorrelationIdFilter.java
@@ -0,0 +1,39 @@
+package com.example.common.logging;
+
+import jakarta.servlet.*;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.UUID;
+
+@Component
+public class CorrelationIdFilter implements Filter {
+
+ public static final String CORRELATION_ID_HEADER = "X-Correlation-ID";
+ public static final String CORRELATION_ID_LOG_VAR = "correlationId";
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+ String correlationId = httpRequest.getHeader(CORRELATION_ID_HEADER);
+ if (correlationId == null || correlationId.isEmpty()) {
+ correlationId = UUID.randomUUID().toString();
+ }
+
+ MDC.put(CORRELATION_ID_LOG_VAR, correlationId);
+ httpResponse.setHeader(CORRELATION_ID_HEADER, correlationId);
+
+ try {
+ chain.doFilter(request, response);
+ } finally {
+ MDC.remove(CORRELATION_ID_LOG_VAR);
+ }
+ }
+}
diff --git a/common-lib/src/main/java/com/example/common/logging/CorrelationIdInterceptor.java b/common-lib/src/main/java/com/example/common/logging/CorrelationIdInterceptor.java
new file mode 100644
index 0000000..ae9c1ae
--- /dev/null
+++ b/common-lib/src/main/java/com/example/common/logging/CorrelationIdInterceptor.java
@@ -0,0 +1,18 @@
+package com.example.common.logging;
+
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.slf4j.MDC;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CorrelationIdInterceptor implements RequestInterceptor {
+
+ @Override
+ public void apply(RequestTemplate template) {
+ String correlationId = MDC.get(CorrelationIdFilter.CORRELATION_ID_LOG_VAR);
+ if (correlationId != null) {
+ template.header(CorrelationIdFilter.CORRELATION_ID_HEADER, correlationId);
+ }
+ }
+}
diff --git a/common-lib/src/main/java/com/example/common/logging/ObservabilityAutoConfiguration.java b/common-lib/src/main/java/com/example/common/logging/ObservabilityAutoConfiguration.java
new file mode 100644
index 0000000..d115405
--- /dev/null
+++ b/common-lib/src/main/java/com/example/common/logging/ObservabilityAutoConfiguration.java
@@ -0,0 +1,17 @@
+package com.example.common.logging;
+
+import com.example.common.exception.GlobalExceptionHandler;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.context.annotation.Import;
+
+@AutoConfiguration
+@ConditionalOnWebApplication
+@Import({
+ CorrelationIdFilter.class,
+ CorrelationIdInterceptor.class,
+ GlobalExceptionHandler.class,
+ com.example.common.config.OpenApiConfig.class
+})
+public class ObservabilityAutoConfiguration {
+}
diff --git a/common-lib/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/common-lib/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..ca6d378
--- /dev/null
+++ b/common-lib/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.example.common.logging.ObservabilityAutoConfiguration
diff --git a/docs/API_TEST_PLAN.md b/docs/API_TEST_PLAN.md
new file mode 100644
index 0000000..83d8316
--- /dev/null
+++ b/docs/API_TEST_PLAN.md
@@ -0,0 +1,87 @@
+# API Test Plan & Manual Verification
+
+This document outlines the steps to verify the stability of the People & Tax Ecosystem APIs.
+
+## ๐ Swagger / OpenAPI Documentation
+Once the services are running, you can access the interactive API docs at:
+- **People Service**: [http://localhost:8080/swagger-ui/index.html](http://localhost:8080/swagger-ui/index.html)
+- **Tax Engine Service**: [http://localhost:8081/swagger-ui/index.html](http://localhost:8081/swagger-ui/index.html)
+
+## ๐งช 1. People Management Service
+**Base URL**: `http://localhost:8080`
+
+### 1.1 Create Person (Full Time Employee)
+**Endpoint**: `POST /people`
+**Headers**:
+- `Content-Type`: `application/json`
+
+**Body**:
+```json
+{
+ "personType": "EMPLOYEE_FULL_TIME",
+ "id": 101,
+ "name": "Rahul Dravid",
+ "email": "rahul.dravid@example.com",
+ "annualSalary": 1200000
+}
+```
+**Expected Response**: `201 Created`
+
+### 1.2 Create Person (Contractor)
+**Endpoint**: `POST /people`
+**Body**:
+```json
+{
+ "personType": "EMPLOYEE_CONTRACTOR",
+ "id": 102,
+ "name": "Hardik Pandya",
+ "email": "hardik@example.com",
+ "hourlyRate": 2000,
+ "hoursWorked": 160
+}
+```
+
+### 1.3 Get Person by ID
+**Endpoint**: `GET /people/101`
+**Expected Response**: JSON object of Rahul Dravid.
+
+### 1.4 Get Monthly Income
+**Endpoint**: `GET /people/101/income`
+**Expected Response**: `100000.00` (12,00,000 / 12)
+
+---
+
+## ๐ฐ 2. Tax Engine Service
+**Base URL**: `http://localhost:8081`
+
+### 2.1 Calculate Tax (Standalone)
+**Endpoint**: `POST /tax/calculate`
+**Body**:
+```json
+{
+ "person": {
+ "personType": "EMPLOYEE_FULL_TIME",
+ "id": 999,
+ "name": "Richie Rich",
+ "email": "richie@example.com",
+ "annualSalary": 1500000
+ },
+ "regime": "NEW"
+}
+```
+**Expected Response**: JSON with calculated tax breakdown.
+
+### 2.2 Calculate Tax for Existing Person (Orchestrated)
+**Endpoint**: `GET /tax/calculate/101?regime=NEW`
+**Description**: Fetches Rahul Dravid (101) from People Service and calculates tax.
+**Verification**: Check logs for `X-Correlation-ID` to ensure it matches across both services.
+
+---
+
+## ๐ ๏ธ Verification Checklist
+- [x] Swagger UI loads for both services.
+- [x] `POST /people` creates data successfully.
+- [x] `GET /people/{id}` retrieves correct data.
+- [x] `POST /tax/calculate` returns valid tax computation.
+- [x] `GET /tax/calculate/{id}` works and shows orchestration success.
+- [x] Logs show matching `X-Correlation-ID` for the orchestrated call.
diff --git a/docs/ARCHITECTURAL_BLUEPRINT.md b/docs/ARCHITECTURAL_BLUEPRINT.md
index d77ba56..0150763 100644
--- a/docs/ARCHITECTURAL_BLUEPRINT.md
+++ b/docs/ARCHITECTURAL_BLUEPRINT.md
@@ -66,6 +66,78 @@ graph TD
4. **Computation**: The Tax Engine applies Java 21 `switch` expressions to determine the tax liability based on the latest Indian Budget slabs.
5. **Output**: Returns a detailed breakdown of Tax, Cess, Surcharge, and Savings Tips.
+### 3.1 Interaction Flow (Orchestration)
+The following sequence explains how a tax calculation request is enriched with live person data.
+
+```mermaid
+sequenceDiagram
+ participant User
+ participant TaxApp as Tax Engine Service
+ participant PeopleApp as People Service
+ participant DB as PostgreSQL
+
+ User->>TaxApp: GET /tax/calculate/{personId} (Regime: NEW)
+ activate TaxApp
+
+ Note right of TaxApp: Generated Correlation ID
+
+ TaxApp->>PeopleApp: GET /people/{id}
+ activate PeopleApp
+ PeopleApp->>DB: Fetch Person Entity
+ DB-->>PeopleApp: Person Data
+ PeopleApp-->>TaxApp: Return Person (JSON Record)
+ deactivate PeopleApp
+
+ Note right of TaxApp: Orchestrator selects Strategy
+ TaxApp->>TaxApp: Apply Deductions (Pattern Matching)
+ TaxApp->>TaxApp: Calculate Tax & Cess
+
+ TaxApp-->>User: Return TaxResult (Breakdown)
+ deactivate TaxApp
+```
+
+### 3.2 Domain Model (Sealed Hierarchy)
+The core `Person` model uses Java 21 advanced features to ensure type safety and exhaustive pattern matching.
+
+```mermaid
+classDiagram
+ class Person {
+ <>
+ +Long id
+ +String name
+ +String email
+ +BigDecimal income()
+ }
+
+ class FullTimeEmployee {
+ <>
+ +BigDecimal annualSalary
+ }
+
+ class Contractor {
+ <>
+ +BigDecimal hourlyRate
+ +int hoursWorked
+ }
+
+ class SelfEmployed {
+ <>
+ +BigDecimal annualTurnover
+ +String profession
+ }
+
+ class BusinessOwner {
+ <>
+ +BigDecimal annualBusinessTurnover
+ +String businessType
+ }
+
+ Person <|-- FullTimeEmployee
+ Person <|-- Contractor
+ Person <|-- SelfEmployed
+ Person <|-- BusinessOwner
+```
+
---
## 4. Java 21 Showcase Features
diff --git a/DOCKER_SETUP_SUMMARY.md b/docs/DOCKER_SETUP_SUMMARY.md
similarity index 100%
rename from DOCKER_SETUP_SUMMARY.md
rename to docs/DOCKER_SETUP_SUMMARY.md
diff --git a/people-management-service/pom.xml b/people-management-service/pom.xml
index f583ea9..3dd2d5a 100644
--- a/people-management-service/pom.xml
+++ b/people-management-service/pom.xml
@@ -37,11 +37,23 @@
spring-boot-starter-actuator
-
+
com.h2database
h2
runtime
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 3.0.1
+
+
+
org.postgresql
postgresql
diff --git a/people-management-service/src/main/java/com/example/javamigrationlab/exception/GlobalExceptionHandler.java b/people-management-service/src/main/java/com/example/javamigrationlab/exception/GlobalExceptionHandler.java
deleted file mode 100644
index fdd581a..0000000
--- a/people-management-service/src/main/java/com/example/javamigrationlab/exception/GlobalExceptionHandler.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.example.javamigrationlab.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.ControllerAdvice;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-
-@ControllerAdvice
-public class GlobalExceptionHandler {
-
- @ExceptionHandler(RuntimeException.class)
- public ResponseEntity handleRuntimeException(RuntimeException ex) {
- return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
- }
-}
diff --git a/people-management-service/src/main/java/com/example/javamigrationlab/modern/service/PersonService.java b/people-management-service/src/main/java/com/example/javamigrationlab/modern/service/PersonService.java
index aa31531..0aa8573 100644
--- a/people-management-service/src/main/java/com/example/javamigrationlab/modern/service/PersonService.java
+++ b/people-management-service/src/main/java/com/example/javamigrationlab/modern/service/PersonService.java
@@ -3,6 +3,7 @@
import com.example.common.domain.*;
import com.example.javamigrationlab.entity.PersonEntity;
import com.example.javamigrationlab.repository.PersonRepository;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
@@ -10,6 +11,7 @@
import java.util.List;
import java.util.stream.Collectors;
+@Slf4j
@Service
public class PersonService {
@@ -26,6 +28,7 @@ public Person createPerson(Person person) {
}
public Person getPerson(Long id) {
+ log.info("Fetching person with ID: {}", id);
return personRepository.findById(id)
.map(this::mapToDomain)
.orElseThrow(() -> new RuntimeException("Person not found with id: " + id));
diff --git a/people-management-service/src/main/resources/application-docker.properties b/people-management-service/src/main/resources/application-docker.properties
index f12785f..c435e82 100644
--- a/people-management-service/src/main/resources/application-docker.properties
+++ b/people-management-service/src/main/resources/application-docker.properties
@@ -1,34 +1,7 @@
-# Docker profile configuration
-# This profile is activated when running in Docker containers
-
-# PostgreSQL Database Configuration
spring.datasource.url=jdbc:postgresql://postgres:5432/peopledb
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
-
-# JPA/Hibernate
spring.jpa.hibernate.ddl-auto=update
-spring.jpa.show-sql=false
-spring.jpa.properties.hibernate.format_sql=true
-
-# Virtual Threads
-spring.threads.virtual.enabled=true
-
-# Hikari Connection Pool
-spring.datasource.hikari.maximum-pool-size=50
-spring.datasource.hikari.minimum-idle=10
-spring.datasource.hikari.connection-timeout=20000
-spring.datasource.hikari.idle-timeout=300000
-spring.datasource.hikari.max-lifetime=1200000
-
-# Actuator endpoints
-management.endpoints.web.exposure.include=health,info,metrics
-management.endpoint.health.show-details=always
-management.health.defaults.enabled=true
-
-# Logging
-logging.level.root=INFO
-logging.level.com.example.javamigrationlab=DEBUG
-logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
+spring.sql.init.mode=always
diff --git a/people-management-service/src/main/resources/logback-spring.xml b/people-management-service/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..4b3d0a4
--- /dev/null
+++ b/people-management-service/src/main/resources/logback-spring.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ UTC
+
+
+
+ {
+ "timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
+ "level": "%level",
+ "service": "people-management-service",
+ "correlationId": "%X{correlationId:-undefined}",
+ "thread": "%thread",
+ "logger": "%logger{36}",
+ "message": "%message",
+ "exception": "%ex"
+ }
+
+
+
+
+
+
+
+
+
+
diff --git a/tax-engine-service/pom.xml b/tax-engine-service/pom.xml
index 2fddb56..d97d587 100644
--- a/tax-engine-service/pom.xml
+++ b/tax-engine-service/pom.xml
@@ -40,6 +40,17 @@
spotbugs-annotations
provided
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 3.0.1
+
+
+
+ org.projectlombok
+ lombok
+ true
+
diff --git a/tax-engine-service/src/main/java/com/example/tax/service/TaxCalculationService.java b/tax-engine-service/src/main/java/com/example/tax/service/TaxCalculationService.java
index 6aca147..4775487 100644
--- a/tax-engine-service/src/main/java/com/example/tax/service/TaxCalculationService.java
+++ b/tax-engine-service/src/main/java/com/example/tax/service/TaxCalculationService.java
@@ -5,6 +5,7 @@
import com.example.tax.constants.TaxConstants;
import com.example.tax.strategy.TaxRegimeStrategy;
import com.example.tax.strategy.TaxStrategyFactory;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -13,6 +14,7 @@
* Smart Tax Calculation Orchestrator.
* USES Strategy Pattern and Java 21 Record Patterns for maximum flexibility.
*/
+@Slf4j
@Service
public class TaxCalculationService {
@@ -23,6 +25,9 @@ public TaxCalculationService(TaxStrategyFactory strategyFactory) {
}
public TaxResult calculateTax(Person person, TaxRegime regime) {
+ if (log.isInfoEnabled()) {
+ log.info("Calculating tax for person ID: {}", person.id());
+ }
TaxRegimeStrategy strategy = strategyFactory.getStrategy(regime);
BigDecimal grossIncome = person.income();
diff --git a/tax-engine-service/src/main/resources/application-docker.properties b/tax-engine-service/src/main/resources/application-docker.properties
index 6f38044..8cd1ce1 100644
--- a/tax-engine-service/src/main/resources/application-docker.properties
+++ b/tax-engine-service/src/main/resources/application-docker.properties
@@ -5,3 +5,8 @@ spring.threads.virtual.enabled=true
# Service endpoints in Docker (use container name of People service)
app.services.people-service.url=http://people-service:8080
+
+# Restricted Actuator for Docker
+management.endpoints.web.exposure.include=health,info
+management.endpoint.health.show-details=when-authorized
+management.info.env.enabled=false
diff --git a/tax-engine-service/src/main/resources/application-test.properties b/tax-engine-service/src/main/resources/application-test.properties
new file mode 100644
index 0000000..fbfce32
--- /dev/null
+++ b/tax-engine-service/src/main/resources/application-test.properties
@@ -0,0 +1,4 @@
+# Test profile for Tax Engine
+management.endpoints.web.exposure.include=health,info
+management.endpoint.health.show-details=always
+management.info.env.enabled=true
diff --git a/tax-engine-service/src/main/resources/application.properties b/tax-engine-service/src/main/resources/application.properties
index bf0f584..2c5e130 100644
--- a/tax-engine-service/src/main/resources/application.properties
+++ b/tax-engine-service/src/main/resources/application.properties
@@ -4,3 +4,6 @@ spring.threads.virtual.enabled=true
# Service endpoints
app.services.people-service.url=http://localhost:8080
+
+
+
diff --git a/tax-engine-service/src/main/resources/logback-spring.xml b/tax-engine-service/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..6d65640
--- /dev/null
+++ b/tax-engine-service/src/main/resources/logback-spring.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+ UTC
+
+
+
+ {
+ "timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
+ "level": "%level",
+ "service": "tax-engine-service",
+ "correlationId": "%X{correlationId:-undefined}",
+ "thread": "%thread",
+ "logger": "%logger{36}",
+ "message": "%message",
+ "exception": "%ex"
+ }
+
+
+
+
+
+
+
+
+
+