1404 lines
41 KiB
Markdown
1404 lines
41 KiB
Markdown
# 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
|
|
├── DOCKER_COMPOSE_GUIDE.md # Docker Compose patterns reference
|
|
├── 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 <name> - Test Hello World service
|
|
register <name> - Register regular customer
|
|
blacklist <name> - Register blacklisted customer
|
|
loan <name> <amount> <credit_score> - 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 '<?xml version="1.0" encoding="UTF-8"?>
|
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
|
|
xmlns:ser="http://service.example.com/">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<ser:getHelloWorld>
|
|
<arg0>TestUser</arg0>
|
|
</ser:getHelloWorld>
|
|
</soapenv:Body>
|
|
</soapenv:Envelope>'
|
|
```
|
|
|
|
##### 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 '<?xml version="1.0" encoding="UTF-8"?>
|
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
|
|
xmlns:ser="http://service.example.com/">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<ser:registerNewCustomer>
|
|
<arg0>
|
|
<customerName>John Doe</customerName>
|
|
<blacklisted>false</blacklisted>
|
|
</arg0>
|
|
</ser:registerNewCustomer>
|
|
</soapenv:Body>
|
|
</soapenv:Envelope>'
|
|
```
|
|
|
|
##### 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 '<?xml version="1.0" encoding="UTF-8"?>
|
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
|
|
xmlns:ser="http://service.example.com/">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<ser:processLoanApplication>
|
|
<arg0>
|
|
<applicantName>John Doe</applicantName>
|
|
<requestedAmount>50000</requestedAmount>
|
|
<creditScore>720</creditScore>
|
|
</arg0>
|
|
</ser:processLoanApplication>
|
|
</soapenv:Body>
|
|
</soapenv:Envelope>'
|
|
```
|
|
|
|
#### 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)
|