This application intentionally contains legacy anti-patterns and security vulnerabilities for educational purposes. It demonstrates common issues found in legacy enterprise applications that need modernization.
DO NOT use patterns from this codebase in production applications.
- Presentation Layer: JSP files with extensive Java scriptlets (anti-pattern)
- Business Logic: Mixed between JSP pages and service classes (anti-pattern)
- Data Access: DAO classes with inconsistent error handling
- Database: Apache Derby embedded database
- No REST APIs: Pure JSP/servlet-based web application
- No Tests: Part of training is to add comprehensive test coverage
- Build:
./gradlew build(compiles application, currently no tests) - Clean build:
./gradlew clean build - Test only:
./gradlew test(will show NO-SOURCE until tests are added) - Single test:
./gradlew test --tests "ClassName.methodName" - Compile only:
./gradlew compileJava - Generate WAR:
./gradlew war
- Start Liberty dev mode:
./liberty-dev.sh(Linux/macOS) orliberty-dev.bat(Windows) - Start Liberty server:
./gradlew libertyStart - Stop Liberty server:
./gradlew libertyStop - Deploy to Liberty:
./gradlew libertyDeploy - Check server status:
./gradlew libertyStatus
- Main Application: http://localhost:9080/big-bad-monolith/
- Customer Management: http://localhost:9080/big-bad-monolith/customers.jsp
- Hours Logging: http://localhost:9080/big-bad-monolith/hours.jsp
- Reports: http://localhost:9080/big-bad-monolith/reports.jsp
- Categories: http://localhost:9080/big-bad-monolith/categories.jsp
- Users: http://localhost:9080/big-bad-monolith/users.jsp
- Scriptlet Hell: Hundreds of lines of Java code in JSP files
- Direct Database Access: JDBC connections opened in presentation layer
- Business Logic in JSPs: Calculations and validations in presentation
- SQL Injection Vulnerabilities: String concatenation in database queries
- Resource Leaks: Database connections not properly managed
- No Input Validation: Raw form parameters used directly
- Inconsistent Null Handling: Inconsistent null checking across DAOs
- Mixed Error Handling: SQLException vs RuntimeException inconsistency
- No Transaction Management: Auto-commit mode for all operations
- Tight Coupling: Direct instantiation instead of dependency injection
- Mixed Responsibilities: Utility methods mixed with business logic
- Legacy Date/Time: Uses deprecated Joda-Time instead of java.time
- Thread Safety Issues: Non-thread-safe implementations
- Magic Numbers: Hardcoded values without constants
src/main/
├── java/com/sourcegraph/demo/bigbadmonolith/
│ ├── dao/ # Data Access Objects (mixed quality)
│ ├── entity/ # Entity classes (legacy dependencies)
│ ├── service/ # Service classes (tight coupling)
│ └── util/ # Utilities (various issues)
└── webapp/ # JSP files (scriptlet hell)
├── index.jsp # Dashboard with business logic
├── customers.jsp # Customer CRUD with validation in JSP
├── hours.jsp # Complex reporting logic in JSP
├── reports.jsp # Advanced business calculations in JSP
├── categories.jsp # Category management
└── users.jsp # Complex aggregations in JSP
Trainees should learn to identify and fix:
- Security vulnerabilities (SQL injection vulnerabilities)
- Null pointer exceptions (Inconsistent null handling)
- Resource management issues (connection leaks)
- Thread safety problems (Non-thread-safe implementations)
- Architectural issues (business logic in presentation layer)
- Legacy dependencies (Joda-Time migration)
- Characterization Tests: Document current behavior before changing
- Integration Tests: Test JSP workflows end-to-end
- Security Tests: Prove vulnerabilities exist, then verify fixes
- Performance Tests: Measure before/after improvements
- Phase 1: Fix critical security issues and null pointer exceptions
- Phase 2: Extract business logic from JSPs to services
- Phase 3: Modernize date/time handling
- Phase 4: Implement proper MVC pattern with JAX-RS
- Phase 5: Add dependency injection and clean architecture
- Java 17 with modern features
- Package structure:
com.sourcegraph.demo.bigbadmonolith - Testing: JUnit 5 framework (
org.junit.jupiter.*) - Date/Time: Use
java.time.*not Joda-Time - Database: Keep DAO pattern but add proper error handling
- REST APIs: When adding, use JAX-RS annotations
- Validation: Add proper input validation and sanitization
- Error Handling: Consistent exception handling strategies
- Dependencies: Add to
build.gradle - Resources: Keep web resources in
src/main/webapp/
# SQL injection vulnerabilities
content:"executeUpdate.*\\+" file:.jsp
# Null pointer vulnerabilities
content:"\\w+\\.get\\w+\\(" -content:"null.*check" lang:java
# Resource leaks
content:"getConnection" -content:"try.*resources" file:.jsp
# Thread safety issues
content:"static.*SimpleDateFormat" lang:java
# Business logic in JSPs
content:"while.*rs\\.next" file:.jsp
# Joda-Time usage
content:"import org.joda.time" lang:java# After adding null safety
content:"throw new IllegalArgumentException" lang:java
# After adding tests
file:Test.java content:"@Test"
# After modernizing dates
content:"java.time.Local" lang:java
# After adding REST APIs
content:"@Path" lang:java- Type: Apache Derby (embedded)
- Location:
./data/bigbadmonolithdirectory - Schema: Auto-created by
ConnectionManager.java - Tables: customers, users, billing_categories, billable_hours
- Test Data: Created by
DataInitializationService.java
- Run
./gradlew clean buildif encountering compilation errors - JSP compilation errors may not show clearly - check Liberty logs
- Delete
./data/directory to reset database - Derby sometimes locks - restart Liberty server if needed
- Check
logs/messages.logfor detailed error information - Use
./gradlew libertyStopthen./gradlew libertyStartto restart
Remember: This is intentionally bad code for educational purposes!