# JAX-WS Loan Approval System A complete JAX-WS SOAP web services application for loan processing, featuring customer registration, credit score evaluation, and loan approval workflows with SQLite database persistence. ## Quick Reference Card ### πŸš€ Three Ways to Use This Project | Task | Command | Result | |------|---------|--------| | **Run Tests** | `docker-compose -f docker-compose.test.yml up --build` | Tests run, results in `./target/surefire-reports/` | | **Generate Coverage** | `docker-compose -f docker-compose.coverage.yml up --build` | Coverage report in `./target/site/jacoco/index.html` | | **Start Server** | `docker-compose up -d` | Server running at http://localhost:8080 | ### πŸ“ Convenience Scripts | Platform | Run Tests | Generate Coverage | |----------|-----------|-------------------| | **Windows** | `run-tests.bat` | `run-coverage.bat` | | **Linux/Mac** | `./run-tests.sh` | `./run-coverage.sh` | --- ## Project Details ### Overview This project demonstrates a production-ready JAX-WS web service implementation using Java 8, Maven, and Apache Tomcat. The system provides three main SOAP services: 1. **Hello World Service** - A simple demonstration service for testing SOAP connectivity 2. **Loan Approval Service** - Complete loan processing system with: - Customer registration with blacklist management - Automated credit score evaluation - Risk-based interest rate calculation - Loan application processing and approval workflows ### Technology Stack - **Java**: 1.8 (JDK 8) - **Web Services**: JAX-WS 2.3.1 (SOAP) - **Build Tool**: Apache Maven 3.x - **Application Server**: Apache Tomcat 9+ - **Database**: SQLite 3.43.0 - **Containerization**: Docker & Docker Compose - **Unit Testing**: JUnit 5 (Jupiter), Mockito, JaCoCo - **Integration Testing**: Python 3 with requests library ### Key Features - **RESTful SOAP Services**: Industry-standard JAX-WS implementation - **Database Persistence**: SQLite database with automatic schema initialization - **Credit Risk Assessment**: Tiered approval logic based on credit scores - **Blacklist Management**: Customer screening and rejection system - **Docker Support**: Fully containerized with one-command deployment - **Unit Testing**: JUnit 5 tests with JaCoCo code coverage - **Integration Testing**: Python test clients for all services - **Production-Ready**: Singleton patterns, prepared statements, error handling --- ## How to Run and Rebuild Using Docker Compose ### Prerequisites - [Docker Desktop](https://www.docker.com/products/docker-desktop/) (Windows/Mac) or [Docker Engine](https://docs.docker.com/engine/install/) (Linux) - Docker Compose (included with Docker Desktop) ### Quick Start #### Three Docker Compose Configurations This project provides three Docker Compose files for different purposes: | Purpose | File | Command | Output Location | |---------|------|---------|----------------| | **πŸš€ Start Server** | `docker-compose.yml` | `docker-compose up -d` | http://localhost:8080 | | **βœ… Run Tests** | `docker-compose.test.yml` | `docker-compose -f docker-compose.test.yml up --build` | `./target/surefire-reports/` | | **πŸ“Š Coverage Report** | `docker-compose.coverage.yml` | `docker-compose -f docker-compose.coverage.yml up --build` | `./target/site/jacoco/index.html` | **Visual Workflow:** ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Development Workflow β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ 1. Write Code β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Run Unit Tests β”‚ ──► docker-compose -f docker-compose.test.yml up --build β”‚ (docker-compose.test) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ Tests Pass βœ“ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Generate Coverage β”‚ ──► docker-compose -f docker-compose.coverage.yml up --build β”‚ (docker-compose.coverageβ”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Open: ./target/site/jacoco/index.html β”‚ Coverage OK βœ“ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Deploy Application β”‚ ──► docker-compose up -d β”‚ (docker-compose.yml) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ Access: http://localhost:8080 β”‚ β–Ό Production Ready! ``` **Quick Commands:** ```bash # Run all tests docker-compose -f docker-compose.test.yml up --build && docker-compose -f docker-compose.test.yml down # Generate coverage report docker-compose -f docker-compose.coverage.yml up --build && docker-compose -f docker-compose.coverage.yml down # Start application server docker-compose up -d ``` **Or use convenience scripts:** ```cmd REM Windows run-tests.bat run-coverage.bat docker-compose up -d ``` ```bash # Linux/Mac ./run-tests.sh ./run-coverage.sh docker-compose up -d ``` --- #### 1. Start the Application ```bash docker-compose up -d ``` This command will: - Build the Docker image with Maven multi-stage build - Compile the Java application - Package it as a WAR file - Deploy to Tomcat - Start the container in detached mode **Wait 30-40 seconds for Tomcat to fully start** #### 2. Verify the Deployment Access the following URLs in your browser: - **Hello World WSDL**: http://localhost:8080/jaxws-hello-world/hello?wsdl - **Loan Service WSDL**: http://localhost:8080/jaxws-hello-world/loan?wsdl - **Tomcat Manager**: http://localhost:8080/manager (username: `admin`, password: `admin123`) #### 3. View Application Logs ```bash # Follow logs in real-time docker-compose logs -f # View recent logs docker-compose logs --tail=100 # View logs for specific service docker-compose logs jaxws-service ``` #### 4. Stop the Application ```bash docker-compose down ``` --- ### Docker Compose Patterns This project includes three Docker Compose configurations for different purposes: #### Pattern 1: Start Application Server **File**: `docker-compose.yml` **Purpose**: Deploy and run the JAX-WS application on Tomcat ```bash # Start the server in detached mode docker-compose up -d # Start with build (after code changes) docker-compose up -d --build # View logs in real-time docker-compose logs -f # Stop the server docker-compose down ``` **What happens:** 1. Runs unit tests (Stage 1: tester) 2. Builds WAR file (Stage 2: builder) 3. Deploys to Tomcat (Stage 3) 4. Exposes port 8080 5. Creates/persists SQLite database **Access points:** - Hello World Service: http://localhost:8080/jaxws-hello-world/hello?wsdl - Loan Service: http://localhost:8080/jaxws-hello-world/loan?wsdl - Tomcat Manager: http://localhost:8080/manager (admin/admin123) --- #### Pattern 2: Run Unit Tests **File**: `docker-compose.test.yml` **Purpose**: Execute JUnit tests and export results to `./target` ```bash # Run tests docker-compose -f docker-compose.test.yml up --build # Run tests in background docker-compose -f docker-compose.test.yml up -d # View test output docker-compose -f docker-compose.test.yml logs # Clean up docker-compose -f docker-compose.test.yml down ``` **What happens:** 1. Builds test environment (tester stage) 2. Runs `mvn test` 3. Executes all *Test.java files 4. Exports test reports to `./target/surefire-reports/` 5. Exports coverage data to `./target/jacoco.exec` **Test results location:** - Console output: Test summary with pass/fail counts - Reports: `./target/surefire-reports/` (text and XML) **Example output:** ``` Tests run: 10, Failures: 0, Errors: 0, Skipped: 0 BUILD SUCCESS ``` --- #### Pattern 3: Generate Code Coverage Report **File**: `docker-compose.coverage.yml` **Purpose**: Run tests and generate JaCoCo coverage reports in `./target/site/jacoco/` ```bash # Generate coverage reports docker-compose -f docker-compose.coverage.yml up --build # Generate coverage in background docker-compose -f docker-compose.coverage.yml up -d # View coverage generation logs docker-compose -f docker-compose.coverage.yml logs # Clean up docker-compose -f docker-compose.coverage.yml down ``` **What happens:** 1. Builds test environment 2. Runs `mvn test` with JaCoCo agent 3. Generates coverage reports in multiple formats 4. Exports to `./target/site/jacoco/` **Coverage reports location:** - **HTML Report**: `./target/site/jacoco/index.html` ← **Open this in browser** - **XML Report**: `./target/site/jacoco/jacoco.xml` (for CI/CD) - **CSV Report**: `./target/site/jacoco/jacoco.csv` (for spreadsheets) **Example output:** ``` ================================================================================= Coverage report generated successfully! ================================================================================= HTML Report: ./target/site/jacoco/index.html XML Report: ./target/site/jacoco/jacoco.xml CSV Report: ./target/site/jacoco/jacoco.csv ================================================================================= ``` --- ### Complete Workflow Example Here's a typical development workflow using all three patterns: ```bash # 1. Run tests to ensure code works docker-compose -f docker-compose.test.yml up --build docker-compose -f docker-compose.test.yml down # 2. Generate coverage report to check test quality docker-compose -f docker-compose.coverage.yml up --build docker-compose -f docker-compose.coverage.yml down # 3. View coverage report # Open target/site/jacoco/index.html in browser # 4. Deploy application if tests pass docker-compose up -d --build # 5. Verify deployment curl http://localhost:8080/jaxws-hello-world/hello?wsdl # 6. View application logs docker-compose logs -f # 7. Stop when done docker-compose down ``` --- ### Quick Reference Scripts For convenience, use the provided scripts instead of typing full commands: | Task | Windows | Linux/Mac | Docker Compose Equivalent | |------|---------|-----------|--------------------------| | Run Tests | `run-tests.bat` | `./run-tests.sh` | `docker-compose -f docker-compose.test.yml up --build` | | Generate Coverage | `run-coverage.bat` | `./run-coverage.sh` | `docker-compose -f docker-compose.coverage.yml up --build` | | Start Server | N/A | N/A | `docker-compose up -d` | **Example:** ```cmd REM Windows run-tests.bat run-coverage.bat REM Then start server docker-compose up -d ``` ```bash # Linux/Mac ./run-tests.sh ./run-coverage.sh # Then start server docker-compose up -d ``` --- ### Rebuild After Code Changes When you modify the source code, rebuild and restart: ```bash # Rebuild and restart docker-compose up -d --build # Or rebuild without cache (clean build) docker-compose build --no-cache docker-compose up -d ``` ### Docker Commands Reference #### Application Server Commands | Command | Description | |---------|-------------| | `docker-compose up -d` | Start application server in detached mode | | `docker-compose up -d --build` | Rebuild and start application server | | `docker-compose down` | Stop and remove application containers | | `docker-compose logs -f` | Follow application logs in real-time | | `docker-compose ps` | List running containers | | `docker-compose restart` | Restart application services | | `docker-compose exec jaxws-service bash` | Access application container shell | #### Test Commands | Command | Description | |---------|-------------| | `docker-compose -f docker-compose.test.yml up --build` | Run unit tests | | `docker-compose -f docker-compose.test.yml logs` | View test output | | `docker-compose -f docker-compose.test.yml down` | Clean up test containers | #### Coverage Commands | Command | Description | |---------|-------------| | `docker-compose -f docker-compose.coverage.yml up --build` | Generate coverage reports | | `docker-compose -f docker-compose.coverage.yml logs` | View coverage generation logs | | `docker-compose -f docker-compose.coverage.yml down` | Clean up coverage containers | ### Accessing the Database The SQLite database is mounted to the host machine and persists between container restarts: ```bash # Access database from host sqlite3 loan_app.db "SELECT * FROM customers;" # Or access from within container docker-compose exec jaxws-service sqlite3 /usr/local/tomcat/loan_app.db ``` ### Environment Configuration The `docker-compose.yml` includes these configurations: - **Port Mapping**: `8080:8080` (host:container) - **Memory Settings**: Xms256m, Xmx512m - **Health Check**: Automatic WSDL availability check every 30s - **Auto Restart**: Container restarts unless manually stopped - **Volume Mounts**: - `./logs:/usr/local/tomcat/logs` - Log persistence - `./loan_app.db:/usr/local/tomcat/loan_app.db` - Database persistence --- ## File Structure ``` jaxws-hello-world/ β”‚ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ main/ β”‚ β”‚ β”œβ”€β”€ java/ β”‚ β”‚ β”‚ └── com/ β”‚ β”‚ β”‚ └── example/ β”‚ β”‚ β”‚ β”œβ”€β”€ listener/ β”‚ β”‚ β”‚ β”‚ └── DatabaseInitializationListener.java # Application startup initialization β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ model/ # Data models (POJOs) β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ CustomerRegistrationRequest.java # Customer registration request β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ LoanRequest.java # Loan application request β”‚ β”‚ β”‚ β”‚ └── LoanResponse.java # Loan application response β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ repository/ # Data access layer β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ CustomerRepository.java # Customer DAO interface β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ LoanHistoryRepository.java # Loan history DAO interface β”‚ β”‚ β”‚ β”‚ └── impl/ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ CustomerRepositoryImpl.java # Customer DAO implementation β”‚ β”‚ β”‚ β”‚ └── LoanHistoryRepositoryImpl.java # Loan history DAO implementation β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ service/ # Web service layer β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ HelloWorldService.java # Hello World interface β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ HelloWorldServiceImpl.java # Hello World implementation β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ LoanApprovalService.java # Loan service (interface + impl) β”‚ β”‚ β”‚ β”‚ └── CreditScoreService.java # Credit score evaluation β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └── util/ β”‚ β”‚ β”‚ └── DatabaseManager.java # Singleton DB connection manager β”‚ β”‚ β”‚ β”‚ β”‚ └── webapp/ β”‚ β”‚ └── WEB-INF/ β”‚ β”‚ β”œβ”€β”€ web.xml # Web application descriptor β”‚ β”‚ └── sun-jaxws.xml # JAX-WS endpoint configuration β”‚ β”‚ β”‚ └── test/ β”‚ └── java/ β”‚ └── com/ β”‚ └── example/ β”‚ └── service/ β”‚ └── HelloWorldServiceImplTest.java # Unit tests for Hello World service β”‚ β”œβ”€β”€ scripts/ # Python test clients β”‚ β”œβ”€β”€ test_all_services.py # Comprehensive test suite β”‚ β”œβ”€β”€ test_hello_world.py # Hello World service tests β”‚ β”œβ”€β”€ test_register_customer.py # Customer registration tests β”‚ β”œβ”€β”€ simple_test.py # Quick smoke test β”‚ └── README.md # Test scripts documentation β”‚ β”œβ”€β”€ logs/ # Tomcat logs (Docker volume) β”œβ”€β”€ target/ # Build output (generated) β”‚ β”œβ”€β”€ site/jacoco/ # Code coverage reports β”‚ β”‚ β”œβ”€β”€ index.html # HTML coverage report β”‚ β”‚ β”œβ”€β”€ jacoco.xml # XML coverage report β”‚ β”‚ └── jacoco.csv # CSV coverage report β”‚ └── surefire-reports/ # Test execution reports β”‚ β”œβ”€β”€ pom.xml # Maven project configuration β”œβ”€β”€ docker-compose.yml # Docker Compose orchestration β”œβ”€β”€ docker-compose.test.yml # Docker Compose for unit tests β”œβ”€β”€ docker-compose.coverage.yml # Docker Compose for coverage β”œβ”€β”€ Dockerfile # Multi-stage Docker build β”œβ”€β”€ Dockerfile.coverage.simple # Dockerfile for coverage β”œβ”€β”€ tomcat-users.xml # Tomcat manager users β”œβ”€β”€ loan_app.db # SQLite database (created on first run) β”œβ”€β”€ run-tests.bat # Windows test runner script β”œβ”€β”€ run-tests.sh # Linux/Mac test runner script β”œβ”€β”€ run-coverage.bat # Windows coverage script β”œβ”€β”€ run-coverage.sh # Linux/Mac coverage script β”œβ”€β”€ README.md # This file β”œβ”€β”€ apidoc.md # Complete API documentation β”œβ”€β”€ requirements.md # Project requirements specification β”œβ”€β”€ .dockerignore # Docker build exclusions └── .gitignore # Git exclusions ``` ### Architecture Layers #### 1. **Listener Layer** (`listener/`) - Application lifecycle management - Database schema initialization on startup - Connection validation #### 2. **Model Layer** (`model/`) - Plain Old Java Objects (POJOs) - Request/Response DTOs for web services - JAX-WS annotated data structures #### 3. **Repository Layer** (`repository/`) - Data access objects (DAO pattern) - Database CRUD operations - SQL query execution with prepared statements #### 4. **Service Layer** (`service/`) - JAX-WS web service endpoints - Business logic implementation - Credit score evaluation - Loan approval decision engine #### 5. **Utility Layer** (`util/`) - Singleton database connection manager - Reusable helper classes - Schema initialization and reset utilities --- ## Database Structure The application uses SQLite with the following schema: ### Database File - **Location**: `loan_app.db` (project root) - **Type**: SQLite 3 - **JDBC URL**: `jdbc:sqlite:loan_app.db` - **Initialization**: Automatic on application startup via `DatabaseInitializationListener` ### Schema #### Table: `customers` Stores registered customer information with blacklist status. ```sql CREATE TABLE customers ( customer_name TEXT PRIMARY KEY, is_blacklisted INTEGER DEFAULT 0, registered_at TEXT ); ``` **Column Details:** | Column | Type | Constraints | Description | |--------|------|-------------|-------------| | `customer_name` | TEXT | PRIMARY KEY | Customer's unique name identifier | | `is_blacklisted` | INTEGER | DEFAULT 0 | Blacklist flag (0 = not blacklisted, 1 = blacklisted) | | `registered_at` | TEXT | NOT NULL | Registration timestamp (ISO 8601 format) | **Indexes:** - Primary key index on `customer_name` (automatic) **Business Rules:** - Customer names must be unique - Blacklisted customers cannot get loan approvals - Registration timestamp is automatically set during registration #### Table: `loan_history` Stores all loan application records for audit and reporting. ```sql CREATE TABLE loan_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, applicant_name TEXT, requested_amount INTEGER, approved INTEGER, approved_rate REAL, rejection_reason TEXT, processed_at TEXT ); ``` **Column Details:** | Column | Type | Constraints | Description | |--------|------|-------------|-------------| | `id` | INTEGER | PRIMARY KEY AUTOINCREMENT | Unique record identifier | | `applicant_name` | TEXT | | Applicant's name (may not be registered customer) | | `requested_amount` | INTEGER | | Loan amount requested in currency units | | `approved` | INTEGER | | Approval status (0 = rejected, 1 = approved) | | `approved_rate` | REAL | | Interest rate if approved (0.0 if rejected) | | `rejection_reason` | TEXT | NULL | Reason for rejection (NULL if approved) | | `processed_at` | TEXT | NOT NULL | Processing timestamp (ISO 8601 format) | **Indexes:** - Primary key index on `id` (automatic) **Business Rules:** - Every loan application is logged regardless of approval status - Approved loans have `approved=1` and `rejection_reason=NULL` - Rejected loans have `approved=0` and populated `rejection_reason` - Timestamp is automatically set during processing ### Credit Score Tiers & Interest Rates The loan approval logic uses the following credit score tiers: | Credit Score Range | Approval Status | Interest Rate | Rejection Reason | |-------------------|-----------------|---------------|------------------| | **>= 700** | βœ… Approved | 3.5% | - | | **600 - 699** | βœ… Approved | 5.5% | - | | **500 - 599** | βœ… Approved | 8.5% | - | | **< 500** | ❌ Rejected | - | "Credit score too low" | | **Blacklisted** | ❌ Rejected | - | "Applicant is blacklisted" | ### Database Operations #### Manual Database Access ```bash # View all customers sqlite3 loan_app.db "SELECT * FROM customers;" # View all loan applications sqlite3 loan_app.db "SELECT * FROM loan_history;" # View approved loans only sqlite3 loan_app.db "SELECT * FROM loan_history WHERE approved = 1;" # View rejected loans with reasons sqlite3 loan_app.db "SELECT applicant_name, rejection_reason FROM loan_history WHERE approved = 0;" # Count customers by blacklist status sqlite3 loan_app.db "SELECT is_blacklisted, COUNT(*) FROM customers GROUP BY is_blacklisted;" # View loan approval rate sqlite3 loan_app.db "SELECT COUNT(*) as total, SUM(approved) as approved, ROUND(CAST(SUM(approved) AS FLOAT) / COUNT(*) * 100, 2) as approval_rate FROM loan_history;" ``` #### Database Reset (Testing) The `DatabaseManager` class provides a reset method for testing: ```java DatabaseManager.getInstance().resetDatabase(); ``` This will: 1. Drop all tables 2. Recreate the schema 3. Clear all data --- ## How to Run Tests ### Prerequisites Before running tests, ensure: 1. **Service is Running** ```bash # Start the service docker-compose up -d # Wait 30-40 seconds, then verify curl http://localhost:8080/jaxws-hello-world/hello?wsdl ``` 2. **Python Environment** - Python 3.6 or higher - pip (Python package installer) ### Step 1: Install Test Dependencies Navigate to the scripts directory and install dependencies: **Windows:** ```cmd cd scripts pip install -r requirements.txt ``` **Linux/Mac:** ```bash cd scripts pip3 install -r requirements.txt ``` **Required Python Package:** - `requests>=2.31.0` - HTTP library for SOAP requests ### Step 2: Choose Your Test Approach #### Option 1: Comprehensive Test Suite (Recommended) Run all tests in one go with the unified test script: ```bash # Windows python test_all_services.py # Linux/Mac python3 test_all_services.py ``` **What it tests:** - βœ… Hello World Service (2 test cases) - βœ… Customer Registration (4 test cases with validation) - βœ… Loan Application Processing (14 test cases covering all scenarios) - βœ… WSDL availability checks - βœ… Error handling and edge cases **Expected Output:** ``` ================================================================================ JAX-WS UNIFIED TEST CLIENT ================================================================================ Testing all services and operations Checking services availability... Hello World Service: Service is accessible Loan Approval Service: Service is accessible ================================================================================ AUTOMATED TEST SUITE ================================================================================ -------------------------------------------------------------------------------- 1. Testing Hello World Service -------------------------------------------------------------------------------- βœ“ PASS | getHelloWorld('John') - Should return greeting Hello World, John! βœ“ PASS | getHelloWorld('Alice') - Should return greeting Hello World, Alice! -------------------------------------------------------------------------------- 2. Testing Customer Registration Service -------------------------------------------------------------------------------- βœ“ PASS | registerNewCustomer('Alice Johnson', blacklisted=False) Registration Successful βœ“ PASS | registerNewCustomer('Bob Smith', blacklisted=False) Registration Successful βœ“ PASS | registerNewCustomer('Charlie Brown', blacklisted=True) Registration Successful βœ“ PASS | registerNewCustomer('Alice Johnson', blacklisted=False) - Duplicate Error: Customer already exists -------------------------------------------------------------------------------- 3. Testing Loan Application Processing Service -------------------------------------------------------------------------------- βœ“ PASS | processLoanApplication('Alice Johnson', $50000, score=750) approved: True | rate: 3.5% | Loan approved with excellent rate βœ“ PASS | processLoanApplication('Bob Smith', $30000, score=650) approved: True | rate: 5.5% | Loan approved with standard rate βœ“ PASS | processLoanApplication('New Customer', $25000, score=550) approved: True | rate: 8.5% | Loan approved with high risk rate βœ“ PASS | processLoanApplication('Poor Credit', $20000, score=450) approved: False | Credit score too low βœ“ PASS | processLoanApplication('Charlie Brown', $40000, score=700) approved: False | Applicant is blacklisted ================================================================================ TEST SUMMARY ================================================================================ Total Tests: 20 Passed: 20 Failed: 0 Success Rate: 100.0% Would you like to enter interactive mode? (y/n): ``` **Interactive Mode:** After automated tests, you can enter interactive mode for manual testing: ``` Available commands: hello - Test Hello World service register - Register regular customer blacklist - Register blacklisted customer loan - Process loan application quit - Exit > hello TestUser Response: Hello World, TestUser! > register John Doe Result: Registration Successful > loan John Doe 50000 720 Result: approved: True approvedRate: 3.5 message: Loan approved with excellent rate > quit ``` #### Option 2: Individual Test Scripts Test specific services individually: ##### A. Hello World Service Test ```bash # Windows python test_hello_world.py # Linux/Mac python3 test_hello_world.py ``` Tests the basic Hello World SOAP service with predefined test cases and interactive mode. ##### B. Customer Registration Test ```bash # Windows python test_register_customer.py # Linux/Mac python3 test_register_customer.py ``` Tests customer registration including: - Regular customer registration - Blacklisted customer registration - Duplicate registration handling - Interactive registration mode ##### C. Simple Smoke Test Quick test for CI/CD pipelines: ```bash # Windows python simple_test.py "Test Name" # Linux/Mac python3 simple_test.py "Test Name" ``` Returns exit code 0 on success, 1 on failure. #### Option 3: Manual Testing with cURL Test services directly using cURL commands: ##### Test Hello World Service ```bash curl -X POST http://localhost:8080/jaxws-hello-world/hello \ -H "Content-Type: text/xml; charset=utf-8" \ -H "SOAPAction: " \ -d ' TestUser ' ``` ##### Test Customer Registration ```bash curl -X POST http://localhost:8080/jaxws-hello-world/loan \ -H "Content-Type: text/xml; charset=utf-8" \ -H "SOAPAction: " \ -d ' John Doe false ' ``` ##### Test Loan Application ```bash curl -X POST http://localhost:8080/jaxws-hello-world/loan \ -H "Content-Type: text/xml; charset=utf-8" \ -H "SOAPAction: " \ -d ' John Doe 50000 720 ' ``` #### Option 4: Testing with SoapUI 1. Download and install [SoapUI](https://www.soapui.org/downloads/soapui/) 2. Create a new SOAP project 3. Import WSDL URLs: - **Hello World**: `http://localhost:8080/jaxws-hello-world/hello?wsdl` - **Loan Approval**: `http://localhost:8080/jaxws-hello-world/loan?wsdl` 4. SoapUI automatically generates request templates 5. Fill in parameters and execute requests ### Step 3: Verify Database Records After running tests, verify data was persisted: ```bash # View registered customers sqlite3 loan_app.db "SELECT * FROM customers;" # View loan application history sqlite3 loan_app.db "SELECT * FROM loan_history;" # View approved loans with rates sqlite3 loan_app.db " SELECT applicant_name, requested_amount, approved_rate FROM loan_history WHERE approved = 1;" # View rejection reasons sqlite3 loan_app.db " SELECT applicant_name, rejection_reason FROM loan_history WHERE approved = 0;" ``` ### Troubleshooting Tests #### Service Not Available **Error:** `Connection refused` or `Failed to establish connection` **Solutions:** ```bash # Check if container is running docker-compose ps # Check container logs docker-compose logs -f # Restart the service docker-compose restart # Verify WSDL is accessible curl http://localhost:8080/jaxws-hello-world/hello?wsdl ``` #### Python Command Not Found **Error:** `python: command not found` **Solutions:** - **Windows**: Try `py` or `python3` - **Linux/Mac**: Use `python3` instead of `python` - **Check installation**: `python --version` or `python3 --version` #### Dependencies Installation Failed **Error:** `Could not install packages` **Solutions:** ```bash # Upgrade pip python -m pip install --upgrade pip # Use virtual environment (recommended) python -m venv venv # Windows venv\Scripts\activate # Linux/Mac source venv/bin/activate # Install dependencies in venv pip install -r requirements.txt ``` #### Port Already in Use **Error:** `Port 8080 already in use` **Solutions:** ```bash # Windows - Find process using port netstat -ano | findstr :8080 # Linux/Mac - Find process using port lsof -i :8080 # Kill the process or change docker-compose port mapping ``` #### Database Locked **Error:** `database is locked` **Solutions:** ```bash # Stop all running tests # Restart the service docker-compose restart # If persists, reset database rm loan_app.db docker-compose restart ``` ### Test Coverage The comprehensive test suite covers: | Category | Test Cases | Coverage | |----------|-----------|----------| | Hello World Service | 2 | Basic functionality, edge cases | | Customer Registration | 4 | Regular, blacklisted, duplicates, validation | | Loan Processing - Approvals | 7 | All credit score tiers (3.5%, 5.5%, 8.5%) | | Loan Processing - Rejections | 5 | Low credit, blacklisted, validation errors | | WSDL Availability | 2 | Both service endpoints | | **Total** | **20** | **Full workflow coverage** | ### API Documentation For detailed API documentation including: - Complete SOAP request/response examples - All service operations and parameters - Error handling and SOAP faults - Business logic and validation rules - Production testing considerations See [apidoc.md](apidoc.md) For detailed test script documentation: - Script usage and options - Python client class examples - Advanced testing scenarios See [scripts/README.md](scripts/README.md) --- ## Unit Tests and Code Coverage ### Overview This project includes comprehensive unit testing with JUnit 5 and code coverage analysis with JaCoCo. All test results and coverage reports are automatically exported to the `./target` directory for easy access. ### Quick Start #### Run Unit Tests **Windows:** ```cmd run-tests.bat ``` **Linux/Mac:** ```bash ./run-tests.sh ``` **Docker Compose:** ```bash docker-compose -f docker-compose.test.yml up --build docker-compose -f docker-compose.test.yml down ``` #### Generate Code Coverage Reports **Windows:** ```cmd run-coverage.bat ``` **Linux/Mac:** ```bash ./run-coverage.sh ``` **Docker Compose:** ```bash docker-compose -f docker-compose.coverage.yml up --build docker-compose -f docker-compose.coverage.yml down ``` ### Coverage Reports All coverage reports are generated in `./target/site/jacoco/`: - **HTML Report**: `target/site/jacoco/index.html` (open in browser) - **XML Report**: `target/site/jacoco/jacoco.xml` (for CI/CD tools) - **CSV Report**: `target/site/jacoco/jacoco.csv` (for spreadsheets) ### Test Framework The project uses: - **JUnit 5 (Jupiter)** - Modern testing framework with annotations - **Mockito** - Mocking framework for complex test scenarios - **JaCoCo** - Code coverage analysis and reporting - **Maven Surefire** - Test execution plugin ### Current Test Coverage | Service | Test Class | Test Cases | Status | |---------|-----------|------------|--------| | Hello World Service | HelloWorldServiceImplTest | 10 | βœ… Passing | ### Understanding Coverage Reports **Coverage Metrics:** - **Line Coverage**: Percentage of executable lines tested - **Branch Coverage**: Percentage of decision points (if/else) tested - **Method Coverage**: Percentage of methods invoked during tests - **Class Coverage**: Percentage of classes with at least one test **Coverage Goals:** - Line Coverage: > 80% - Branch Coverage: > 70% - Method Coverage: > 85% ### Running Tests with Maven (Local) If you have Maven installed locally: ```bash # Run tests only mvn test # Run tests with coverage mvn clean test # View coverage report # Open target/site/jacoco/index.html in your browser ``` ### CI/CD Integration #### GitHub Actions Example ```yaml - name: Run tests with coverage run: mvn clean test - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: files: ./target/site/jacoco/jacoco.xml ``` #### Jenkins Example ```groovy stage('Test') { steps { sh 'mvn clean test' jacoco( execPattern: 'target/jacoco.exec', classPattern: 'target/classes', sourcePattern: 'src/main/java' ) } } ``` ### Writing New Tests Create test classes in `src/test/java/` following this pattern: ```java package com.example.service; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.DisplayName; import static org.junit.jupiter.api.Assertions.*; @DisplayName("Your Service Tests") class YourServiceTest { private YourService service; @BeforeEach void setUp() { service = new YourServiceImpl(); } @Test @DisplayName("Should do something") void testSomething() { // Arrange String input = "test"; String expected = "result"; // Act String result = service.doSomething(input); // Assert assertEquals(expected, result); } } ``` ### Troubleshooting #### Tests Not Running ```bash # Ensure test files end with Test.java # Verify directory: src/test/java/ # Check pom.xml includes maven-surefire-plugin ``` #### Coverage Reports Not Generated ```bash # Ensure JaCoCo plugin is in pom.xml mvn clean test # Or use Docker docker-compose -f docker-compose.coverage.yml up --build ``` #### Permission Issues (Linux/Mac) ```bash chmod +x run-tests.sh chmod +x run-coverage.sh ``` --- ## Service Endpoints Once running, the following endpoints are available: | Service | Endpoint | WSDL | |---------|----------|------| | Hello World | http://localhost:8080/jaxws-hello-world/hello | [WSDL](http://localhost:8080/jaxws-hello-world/hello?wsdl) | | Loan Approval | http://localhost:8080/jaxws-hello-world/loan | [WSDL](http://localhost:8080/jaxws-hello-world/loan?wsdl) | | Tomcat Manager | http://localhost:8080/manager | admin/admin123 | --- ## Development ### Building Locally (without Docker) **Prerequisites:** - Java JDK 8+ - Apache Maven 3.6+ - Apache Tomcat 9+ **Build Commands:** ```bash # Clean and build mvn clean package # The WAR file will be created at: # target/jaxws-hello-world.war # Deploy to Tomcat webapps directory cp target/jaxws-hello-world.war $CATALINA_HOME/webapps/ ``` ### Project Dependencies See [pom.xml](pom.xml) for complete dependency list: - `javax.xml.ws:jaxws-api:2.3.1` - JAX-WS API - `com.sun.xml.ws:jaxws-rt:2.3.3` - JAX-WS Runtime - `javax.servlet:javax.servlet-api:4.0.1` - Servlet API - `org.xerial:sqlite-jdbc:3.43.0.0` - SQLite JDBC Driver --- ## Production Considerations ### Security ⚠️ **This is a demonstration project. For production use:** - Implement WS-Security for authentication - Use HTTPS/TLS for all communications - Add input sanitization beyond current validation - Implement rate limiting - Add audit logging for sensitive operations - Store credentials in secure vault (not in `tomcat-users.xml`) ### Database - Consider PostgreSQL or MySQL for production workloads - Implement connection pooling (HikariCP, c3p0) - Add database backup strategy - Implement database migration tool (Flyway, Liquibase) ### Performance - The current `CreditScoreService` returns a fixed value (700) - Integrate with real credit bureau APIs for production - Add caching layer for credit scores - Implement request/response logging - Add monitoring and metrics (Prometheus, Grafana) --- ## Troubleshooting ### Container won't start ```bash # Check container logs docker-compose logs # Check if port 8080 is already in use netstat -ano | findstr :8080 # Windows lsof -i :8080 # Linux/Mac # Remove and rebuild docker-compose down docker-compose up -d --build ``` ### Database errors ```bash # Check database file permissions ls -la loan_app.db # Reset database (will delete all data) rm loan_app.db docker-compose restart ``` ### WSDL not accessible - Wait 30-40 seconds for Tomcat to fully start - Check logs: `docker-compose logs -f` - Verify container is running: `docker-compose ps` --- ## License This is a demonstration project for educational purposes. --- ## Support For issues, questions, or contributions: - Review the [API Documentation](apidoc.md) - Check the [Requirements Specification](requirements.md) - Review test scripts in [scripts/README.md](scripts/README.md)