initial implementation of loan approval service
This commit is contained in:
@ -0,0 +1,47 @@
|
||||
package com.example.listener;
|
||||
|
||||
import com.example.util.DatabaseManager;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
/**
|
||||
* DatabaseInitializationListener - Initializes database schema when application starts
|
||||
*/
|
||||
public class DatabaseInitializationListener implements ServletContextListener {
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
System.out.println("===========================================");
|
||||
System.out.println("Starting Database Initialization...");
|
||||
System.out.println("===========================================");
|
||||
|
||||
try {
|
||||
DatabaseManager dbManager = DatabaseManager.getInstance();
|
||||
|
||||
// Test connection
|
||||
if (dbManager.testConnection()) {
|
||||
System.out.println("Database connection test: PASSED");
|
||||
} else {
|
||||
System.err.println("Database connection test: FAILED");
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize schema (create tables if they don't exist)
|
||||
dbManager.initializeSchema();
|
||||
|
||||
System.out.println("Database initialization completed successfully");
|
||||
System.out.println("===========================================");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("FATAL: Database initialization failed!");
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to initialize database", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
System.out.println("Application shutdown - Database cleanup completed");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package com.example.model;
|
||||
|
||||
/**
|
||||
* CustomerRegistrationRequest - Input model for customer registration
|
||||
*/
|
||||
public class CustomerRegistrationRequest {
|
||||
|
||||
private String customerName;
|
||||
private boolean blacklisted;
|
||||
|
||||
public CustomerRegistrationRequest() {
|
||||
}
|
||||
|
||||
public CustomerRegistrationRequest(String customerName, boolean blacklisted) {
|
||||
this.customerName = customerName;
|
||||
this.blacklisted = blacklisted;
|
||||
}
|
||||
|
||||
public String getCustomerName() {
|
||||
return customerName;
|
||||
}
|
||||
|
||||
public void setCustomerName(String customerName) {
|
||||
this.customerName = customerName;
|
||||
}
|
||||
|
||||
public boolean isBlacklisted() {
|
||||
return blacklisted;
|
||||
}
|
||||
|
||||
public void setBlacklisted(boolean blacklisted) {
|
||||
this.blacklisted = blacklisted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CustomerRegistrationRequest{" +
|
||||
"customerName='" + customerName + '\'' +
|
||||
", blacklisted=" + blacklisted +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
53
src/main/java/com/example/model/LoanRequest.java
Normal file
53
src/main/java/com/example/model/LoanRequest.java
Normal file
@ -0,0 +1,53 @@
|
||||
package com.example.model;
|
||||
|
||||
/**
|
||||
* LoanRequest - Input model for loan application processing
|
||||
*/
|
||||
public class LoanRequest {
|
||||
|
||||
private String applicantName;
|
||||
private int requestedAmount;
|
||||
private int creditScore;
|
||||
|
||||
public LoanRequest() {
|
||||
}
|
||||
|
||||
public LoanRequest(String applicantName, int requestedAmount, int creditScore) {
|
||||
this.applicantName = applicantName;
|
||||
this.requestedAmount = requestedAmount;
|
||||
this.creditScore = creditScore;
|
||||
}
|
||||
|
||||
public String getApplicantName() {
|
||||
return applicantName;
|
||||
}
|
||||
|
||||
public void setApplicantName(String applicantName) {
|
||||
this.applicantName = applicantName;
|
||||
}
|
||||
|
||||
public int getRequestedAmount() {
|
||||
return requestedAmount;
|
||||
}
|
||||
|
||||
public void setRequestedAmount(int requestedAmount) {
|
||||
this.requestedAmount = requestedAmount;
|
||||
}
|
||||
|
||||
public int getCreditScore() {
|
||||
return creditScore;
|
||||
}
|
||||
|
||||
public void setCreditScore(int creditScore) {
|
||||
this.creditScore = creditScore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoanRequest{" +
|
||||
"applicantName='" + applicantName + '\'' +
|
||||
", requestedAmount=" + requestedAmount +
|
||||
", creditScore=" + creditScore +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
64
src/main/java/com/example/model/LoanResponse.java
Normal file
64
src/main/java/com/example/model/LoanResponse.java
Normal file
@ -0,0 +1,64 @@
|
||||
package com.example.model;
|
||||
|
||||
/**
|
||||
* LoanResponse - Output model for loan application result
|
||||
*/
|
||||
public class LoanResponse {
|
||||
|
||||
private boolean approved;
|
||||
private double approvedRate;
|
||||
private String rejectionReason;
|
||||
private String message;
|
||||
|
||||
public LoanResponse() {
|
||||
}
|
||||
|
||||
public LoanResponse(boolean approved, double approvedRate, String rejectionReason, String message) {
|
||||
this.approved = approved;
|
||||
this.approvedRate = approvedRate;
|
||||
this.rejectionReason = rejectionReason;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public boolean isApproved() {
|
||||
return approved;
|
||||
}
|
||||
|
||||
public void setApproved(boolean approved) {
|
||||
this.approved = approved;
|
||||
}
|
||||
|
||||
public double getApprovedRate() {
|
||||
return approvedRate;
|
||||
}
|
||||
|
||||
public void setApprovedRate(double approvedRate) {
|
||||
this.approvedRate = approvedRate;
|
||||
}
|
||||
|
||||
public String getRejectionReason() {
|
||||
return rejectionReason;
|
||||
}
|
||||
|
||||
public void setRejectionReason(String rejectionReason) {
|
||||
this.rejectionReason = rejectionReason;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoanResponse{" +
|
||||
"approved=" + approved +
|
||||
", approvedRate=" + approvedRate +
|
||||
", rejectionReason='" + rejectionReason + '\'' +
|
||||
", message='" + message + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
22
src/main/java/com/example/repository/CustomerRepository.java
Normal file
22
src/main/java/com/example/repository/CustomerRepository.java
Normal file
@ -0,0 +1,22 @@
|
||||
package com.example.repository;
|
||||
|
||||
/**
|
||||
* CustomerRepository - Interface for customer data access
|
||||
*/
|
||||
public interface CustomerRepository {
|
||||
|
||||
/**
|
||||
* Checks if the customer is on the blacklist
|
||||
* @param name Customer name
|
||||
* @return true if blacklisted, false otherwise
|
||||
*/
|
||||
boolean isBlacklisted(String name);
|
||||
|
||||
/**
|
||||
* Registers a new customer into the database
|
||||
* @param name Customer name
|
||||
* @param isBlacklisted Blacklist status
|
||||
* @return true if registered successfully, false if customer already exists
|
||||
*/
|
||||
boolean registerCustomer(String name, boolean isBlacklisted);
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.example.repository;
|
||||
|
||||
/**
|
||||
* LoanHistoryRepository - Interface for loan history data access
|
||||
*/
|
||||
public interface LoanHistoryRepository {
|
||||
|
||||
/**
|
||||
* Saves loan application history to the database
|
||||
* @param applicantName Name of the applicant
|
||||
* @param requestedAmount Requested loan amount
|
||||
* @param approved Whether the loan was approved
|
||||
* @param approvedRate Interest rate if approved
|
||||
* @param rejectionReason Reason for rejection if declined
|
||||
*/
|
||||
void saveHistory(String applicantName, int requestedAmount, boolean approved,
|
||||
double approvedRate, String rejectionReason);
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package com.example.repository.impl;
|
||||
|
||||
import com.example.repository.CustomerRepository;
|
||||
import com.example.util.DatabaseManager;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* CustomerRepositoryImpl - SQLite implementation of CustomerRepository
|
||||
*/
|
||||
public class CustomerRepositoryImpl implements CustomerRepository {
|
||||
|
||||
private final DatabaseManager dbManager;
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public CustomerRepositoryImpl() {
|
||||
this.dbManager = DatabaseManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlacklisted(String name) {
|
||||
String query = "SELECT is_blacklisted FROM customers WHERE customer_name = ?";
|
||||
|
||||
try (Connection conn = dbManager.getConnection();
|
||||
PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||
|
||||
pstmt.setString(1, name);
|
||||
|
||||
try (ResultSet rs = pstmt.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
int blacklisted = rs.getInt("is_blacklisted");
|
||||
return blacklisted == 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Customer not found, not blacklisted by default
|
||||
return false;
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Error checking blacklist status for: " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerCustomer(String name, boolean isBlacklisted) {
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("Customer name cannot be null or empty");
|
||||
}
|
||||
|
||||
// Check if customer already exists
|
||||
if (customerExists(name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String insert = "INSERT INTO customers (customer_name, is_blacklisted, registered_at) VALUES (?, ?, ?)";
|
||||
|
||||
try (Connection conn = dbManager.getConnection();
|
||||
PreparedStatement pstmt = conn.prepareStatement(insert)) {
|
||||
|
||||
pstmt.setString(1, name);
|
||||
pstmt.setInt(2, isBlacklisted ? 1 : 0);
|
||||
pstmt.setString(3, LocalDateTime.now().format(DATE_FORMATTER));
|
||||
|
||||
int rowsAffected = pstmt.executeUpdate();
|
||||
return rowsAffected > 0;
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Error registering customer: " + name, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check if customer already exists
|
||||
* @param name Customer name
|
||||
* @return true if exists, false otherwise
|
||||
*/
|
||||
private boolean customerExists(String name) {
|
||||
String query = "SELECT COUNT(*) as count FROM customers WHERE customer_name = ?";
|
||||
|
||||
try (Connection conn = dbManager.getConnection();
|
||||
PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||
|
||||
pstmt.setString(1, name);
|
||||
|
||||
try (ResultSet rs = pstmt.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
return rs.getInt("count") > 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Error checking customer existence: " + name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.example.repository.impl;
|
||||
|
||||
import com.example.repository.LoanHistoryRepository;
|
||||
import com.example.util.DatabaseManager;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* LoanHistoryRepositoryImpl - SQLite implementation of LoanHistoryRepository
|
||||
*/
|
||||
public class LoanHistoryRepositoryImpl implements LoanHistoryRepository {
|
||||
|
||||
private final DatabaseManager dbManager;
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public LoanHistoryRepositoryImpl() {
|
||||
this.dbManager = DatabaseManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveHistory(String applicantName, int requestedAmount, boolean approved,
|
||||
double approvedRate, String rejectionReason) {
|
||||
|
||||
String insert = "INSERT INTO loan_history " +
|
||||
"(applicant_name, requested_amount, approved, approved_rate, rejection_reason, processed_at) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?)";
|
||||
|
||||
try (Connection conn = dbManager.getConnection();
|
||||
PreparedStatement pstmt = conn.prepareStatement(insert)) {
|
||||
|
||||
pstmt.setString(1, applicantName);
|
||||
pstmt.setInt(2, requestedAmount);
|
||||
pstmt.setInt(3, approved ? 1 : 0);
|
||||
pstmt.setDouble(4, approvedRate);
|
||||
pstmt.setString(5, rejectionReason);
|
||||
pstmt.setString(6, LocalDateTime.now().format(DATE_FORMATTER));
|
||||
|
||||
pstmt.executeUpdate();
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Error saving loan history for: " + applicantName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/main/java/com/example/service/CreditScoreService.java
Normal file
15
src/main/java/com/example/service/CreditScoreService.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.example.service;
|
||||
|
||||
/**
|
||||
* CreditScoreService - Interface for external credit score checking
|
||||
* This interface is designed to be mocked in unit tests
|
||||
*/
|
||||
public interface CreditScoreService {
|
||||
|
||||
/**
|
||||
* Get credit score for an applicant
|
||||
* @param applicantName Name of the applicant
|
||||
* @return Credit score (0-850)
|
||||
*/
|
||||
int getCreditScore(String applicantName);
|
||||
}
|
||||
193
src/main/java/com/example/service/LoanApprovalService.java
Normal file
193
src/main/java/com/example/service/LoanApprovalService.java
Normal file
@ -0,0 +1,193 @@
|
||||
package com.example.service;
|
||||
|
||||
import com.example.model.CustomerRegistrationRequest;
|
||||
import com.example.model.LoanRequest;
|
||||
import com.example.model.LoanResponse;
|
||||
import com.example.repository.CustomerRepository;
|
||||
import com.example.repository.LoanHistoryRepository;
|
||||
import com.example.repository.impl.CustomerRepositoryImpl;
|
||||
import com.example.repository.impl.LoanHistoryRepositoryImpl;
|
||||
|
||||
import javax.jws.WebMethod;
|
||||
import javax.jws.WebService;
|
||||
import javax.xml.ws.soap.SOAPFaultException;
|
||||
import javax.xml.soap.SOAPFactory;
|
||||
import javax.xml.soap.SOAPFault;
|
||||
|
||||
/**
|
||||
* LoanApprovalService - Main JAX-WS service for loan processing and customer management
|
||||
*/
|
||||
@WebService(
|
||||
serviceName = "LoanApprovalService",
|
||||
portName = "LoanApprovalPort"
|
||||
)
|
||||
public class LoanApprovalService {
|
||||
|
||||
private CustomerRepository customerRepository;
|
||||
private LoanHistoryRepository loanHistoryRepository;
|
||||
private CreditScoreService creditScoreService;
|
||||
|
||||
/**
|
||||
* Default constructor - initializes with real implementations
|
||||
*/
|
||||
public LoanApprovalService() {
|
||||
this.customerRepository = new CustomerRepositoryImpl();
|
||||
this.loanHistoryRepository = new LoanHistoryRepositoryImpl();
|
||||
// Default credit score service (can be overridden for testing)
|
||||
this.creditScoreService = new CreditScoreService() {
|
||||
@Override
|
||||
public int getCreditScore(String applicantName) {
|
||||
// Simple mock implementation - returns a fixed score
|
||||
// In production, this would call an external API
|
||||
return 700;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for CustomerRepository (for dependency injection in tests)
|
||||
*/
|
||||
@WebMethod(exclude = true)
|
||||
public void setCustomerRepository(CustomerRepository customerRepository) {
|
||||
this.customerRepository = customerRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for LoanHistoryRepository (for dependency injection in tests)
|
||||
*/
|
||||
@WebMethod(exclude = true)
|
||||
public void setLoanHistoryRepository(LoanHistoryRepository loanHistoryRepository) {
|
||||
this.loanHistoryRepository = loanHistoryRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for CreditScoreService (for dependency injection in tests)
|
||||
*/
|
||||
@WebMethod(exclude = true)
|
||||
public void setCreditScoreService(CreditScoreService creditScoreService) {
|
||||
this.creditScoreService = creditScoreService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new customer
|
||||
* @param request Customer registration request
|
||||
* @return Success or error message
|
||||
*/
|
||||
@WebMethod
|
||||
public String registerNewCustomer(CustomerRegistrationRequest request) {
|
||||
// Input validation
|
||||
if (request == null || request.getCustomerName() == null ||
|
||||
request.getCustomerName().trim().isEmpty()) {
|
||||
throw createSOAPFault("Customer name cannot be null or empty");
|
||||
}
|
||||
|
||||
// Register customer
|
||||
boolean registered = customerRepository.registerCustomer(
|
||||
request.getCustomerName(),
|
||||
request.isBlacklisted()
|
||||
);
|
||||
|
||||
if (registered) {
|
||||
return "Registration Successful";
|
||||
} else {
|
||||
return "Error: Customer already exists";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process loan application
|
||||
* @param request Loan application request
|
||||
* @return Loan decision response
|
||||
*/
|
||||
@WebMethod
|
||||
public LoanResponse processLoanApplication(LoanRequest request) {
|
||||
// Input validation
|
||||
if (request == null || request.getApplicantName() == null ||
|
||||
request.getApplicantName().trim().isEmpty()) {
|
||||
throw createSOAPFault("Applicant name cannot be null or empty");
|
||||
}
|
||||
|
||||
if (request.getRequestedAmount() <= 0) {
|
||||
throw createSOAPFault("Requested amount must be greater than 0");
|
||||
}
|
||||
|
||||
// Check blacklist
|
||||
if (customerRepository.isBlacklisted(request.getApplicantName())) {
|
||||
LoanResponse response = new LoanResponse(
|
||||
false,
|
||||
0.0,
|
||||
"Applicant is blacklisted",
|
||||
"Loan application rejected"
|
||||
);
|
||||
|
||||
// Save history
|
||||
loanHistoryRepository.saveHistory(
|
||||
request.getApplicantName(),
|
||||
request.getRequestedAmount(),
|
||||
false,
|
||||
0.0,
|
||||
"Applicant is blacklisted"
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// Get credit score
|
||||
int creditScore = creditScoreService.getCreditScore(request.getApplicantName());
|
||||
|
||||
// Loan approval logic
|
||||
boolean approved;
|
||||
double approvedRate;
|
||||
String rejectionReason = null;
|
||||
String message;
|
||||
|
||||
if (creditScore >= 700) {
|
||||
// Good credit - approved with low rate
|
||||
approved = true;
|
||||
approvedRate = 3.5;
|
||||
message = "Loan approved with excellent rate";
|
||||
} else if (creditScore >= 600) {
|
||||
// Fair credit - approved with standard rate
|
||||
approved = true;
|
||||
approvedRate = 5.5;
|
||||
message = "Loan approved with standard rate";
|
||||
} else if (creditScore >= 500) {
|
||||
// Poor credit - approved with high rate
|
||||
approved = true;
|
||||
approvedRate = 8.5;
|
||||
message = "Loan approved with high risk rate";
|
||||
} else {
|
||||
// Very poor credit - rejected
|
||||
approved = false;
|
||||
approvedRate = 0.0;
|
||||
rejectionReason = "Credit score too low";
|
||||
message = "Loan application rejected";
|
||||
}
|
||||
|
||||
// Save history
|
||||
loanHistoryRepository.saveHistory(
|
||||
request.getApplicantName(),
|
||||
request.getRequestedAmount(),
|
||||
approved,
|
||||
approvedRate,
|
||||
rejectionReason
|
||||
);
|
||||
|
||||
// Create response
|
||||
return new LoanResponse(approved, approvedRate, rejectionReason, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create SOAP fault
|
||||
*/
|
||||
private SOAPFaultException createSOAPFault(String message) {
|
||||
try {
|
||||
SOAPFactory soapFactory = SOAPFactory.newInstance();
|
||||
SOAPFault soapFault = soapFactory.createFault();
|
||||
soapFault.setFaultString(message);
|
||||
return new SOAPFaultException(soapFault);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error creating SOAP fault", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
137
src/main/java/com/example/util/DatabaseManager.java
Normal file
137
src/main/java/com/example/util/DatabaseManager.java
Normal file
@ -0,0 +1,137 @@
|
||||
package com.example.util;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
/**
|
||||
* DatabaseManager - Utility class for managing SQLite database connections and schema initialization.
|
||||
* This class provides methods to:
|
||||
* - Get database connections
|
||||
* - Initialize database schema (create tables)
|
||||
* - Reset database (drop and recreate tables)
|
||||
*/
|
||||
public class DatabaseManager {
|
||||
|
||||
private static final String DB_URL = "jdbc:sqlite:loan_app.db";
|
||||
private static DatabaseManager instance;
|
||||
|
||||
// Private constructor for singleton pattern
|
||||
private DatabaseManager() {
|
||||
try {
|
||||
// Load SQLite JDBC driver
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Failed to load SQLite JDBC driver", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get singleton instance of DatabaseManager
|
||||
* @return DatabaseManager instance
|
||||
*/
|
||||
public static synchronized DatabaseManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DatabaseManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new database connection
|
||||
* @return Connection object
|
||||
* @throws SQLException if connection fails
|
||||
*/
|
||||
public Connection getConnection() throws SQLException {
|
||||
return DriverManager.getConnection(DB_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize database schema - create tables if they don't exist
|
||||
*/
|
||||
public void initializeSchema() {
|
||||
String createCustomersTable =
|
||||
"CREATE TABLE IF NOT EXISTS customers (" +
|
||||
" customer_name TEXT PRIMARY KEY," +
|
||||
" is_blacklisted INTEGER DEFAULT 0," +
|
||||
" registered_at TEXT" +
|
||||
")";
|
||||
|
||||
String createLoanHistoryTable =
|
||||
"CREATE TABLE IF NOT EXISTS loan_history (" +
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT," +
|
||||
" applicant_name TEXT," +
|
||||
" requested_amount INTEGER," +
|
||||
" approved INTEGER," +
|
||||
" approved_rate REAL," +
|
||||
" rejection_reason TEXT," +
|
||||
" processed_at TEXT" +
|
||||
")";
|
||||
|
||||
try (Connection conn = getConnection();
|
||||
Statement stmt = conn.createStatement()) {
|
||||
|
||||
// Create tables
|
||||
stmt.execute(createCustomersTable);
|
||||
stmt.execute(createLoanHistoryTable);
|
||||
|
||||
System.out.println("Database schema initialized successfully");
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Failed to initialize database schema", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset database - drop all tables and recreate them
|
||||
* Useful for testing scenarios
|
||||
*/
|
||||
public void resetDatabase() {
|
||||
String dropCustomers = "DROP TABLE IF EXISTS customers";
|
||||
String dropLoanHistory = "DROP TABLE IF EXISTS loan_history";
|
||||
|
||||
try (Connection conn = getConnection();
|
||||
Statement stmt = conn.createStatement()) {
|
||||
|
||||
// Drop tables
|
||||
stmt.execute(dropCustomers);
|
||||
stmt.execute(dropLoanHistory);
|
||||
|
||||
System.out.println("Database tables dropped");
|
||||
|
||||
// Recreate tables
|
||||
initializeSchema();
|
||||
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Failed to reset database", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test database connection
|
||||
* @return true if connection is successful
|
||||
*/
|
||||
public boolean testConnection() {
|
||||
try (Connection conn = getConnection()) {
|
||||
return conn != null && !conn.isClosed();
|
||||
} catch (SQLException e) {
|
||||
System.err.println("Database connection test failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close connection safely
|
||||
* @param conn Connection to close
|
||||
*/
|
||||
public static void closeConnection(Connection conn) {
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException e) {
|
||||
System.err.println("Error closing connection: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,4 +6,9 @@
|
||||
implementation="com.example.service.HelloWorldServiceImpl"
|
||||
url-pattern="/hello"/>
|
||||
|
||||
<endpoint
|
||||
name="LoanApprovalService"
|
||||
implementation="com.example.service.LoanApprovalService"
|
||||
url-pattern="/loan"/>
|
||||
|
||||
</endpoints>
|
||||
|
||||
@ -5,12 +5,19 @@
|
||||
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
|
||||
version="4.0">
|
||||
|
||||
<display-name>JAX-WS Hello World Service</display-name>
|
||||
<display-name>JAX-WS Loan Approval Service</display-name>
|
||||
|
||||
<!-- Database Initialization Listener -->
|
||||
<listener>
|
||||
<listener-class>com.example.listener.DatabaseInitializationListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- JAX-WS Context Listener -->
|
||||
<listener>
|
||||
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- Hello World Service Servlet -->
|
||||
<servlet>
|
||||
<servlet-name>HelloWorldService</servlet-name>
|
||||
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
|
||||
@ -22,4 +29,16 @@
|
||||
<url-pattern>/hello</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Loan Approval Service Servlet -->
|
||||
<servlet>
|
||||
<servlet-name>LoanApprovalService</servlet-name>
|
||||
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>LoanApprovalService</servlet-name>
|
||||
<url-pattern>/loan</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
Reference in New Issue
Block a user