Automation for Java/JBoss to Spring Boot/Quarkus migration with minimal code loss.
Project description
Legacy Migration Toolkit
Python-based automation for Java/JBoss to Microservices migration with GitHub Copilot.
Goal: build a reusable migration script that helps convert JBoss code to Spring Boot with minimal code loss and minimal developer pain, especially when using Copilot or Cursor.
Solves the most redundant problem in enterprise Java: migrating complex legacy EJB/JBoss code to Spring Boot/Quarkus microservices without losing business logic.
The Problem
| Challenge | How This Toolkit Solves It |
|---|---|
| Copilot loses context on large legacy files | Chunked prompts — one method per prompt, not entire classes |
| Code loss during migration (methods, logic, validations) | Automated code loss detection — compares legacy vs migrated code |
| Tedious manual file-by-file comparison | Hash-based fingerprinting — detects body changes, missing methods, annotation drift |
| No systematic migration approach | 5-phase workflow — analyze, plan, generate, detect, repair |
| JEE annotations not properly translated | Annotation mapping — EJB→Spring, JAX-RS→Spring MVC, CDI→Spring DI |
Quick Start
# Install (pip or pipx)
pip install legacy-migration-toolkit
# or
pipx install legacy-migration-toolkit
# No external dependencies needed — pure Python 3.8+ standard library
# Run the demo (creates sample legacy + migrated files with intentional code losses)
legacy-migration --demo
# Migrate your actual legacy codebase (interactive, class-by-class)
legacy-migration --legacy /path/to/legacy/src/main/java --migrated /path/to/new/src/main/java
# Fix detected losses when you're ready
python3 fix_issues.py
The 5-Phase Workflow
┌─────────────────────────────────────────────────────────────────┐
│ │
│ Phase 1: ANALYZE │
│ ├─ Parse all legacy .java files │
│ ├─ Extract: classes, methods, fields, annotations, imports │
│ ├─ Classify: EJB, JPA, JAX-RS, CDI, Servlet, POJO │
│ └─ Fingerprint: SHA-256 hash of each method body │
│ │
│ Phase 2: PLAN │
│ ├─ Prioritize: Entities → Interfaces → Services → REST → MDB │
│ ├─ Dependency analysis: which classes are most depended-on │
│ └─ Copilot strategy: CHUNKED vs HYBRID vs FULL CLASS │
│ │
│ Phase 3: GENERATE (Copilot Prompts) │
│ ├─ Class scaffold prompt (structure + injections) │
│ ├─ Per-method prompts (one method at a time!) │
│ ├─ Test generation prompts │
│ └─ Each prompt includes verification checklist │
│ │
│ ══════ Developer uses Copilot with generated prompts ══════ │
│ │
│ Phase 4: DETECT (Code Loss Detection) │
│ ├─ Missing classes, methods, fields │
│ ├─ Signature changes (params, return types) │
│ ├─ Body changes (>50% size diff = suspicious) │
│ ├─ Annotation drift (EJB→Spring mapping validation) │
│ └─ Severity: CRITICAL / HIGH / MEDIUM / LOW │
│ │
│ Phase 5: REPAIR (Fix Prompts) │
│ ├─ Targeted Copilot prompts for each detected loss │
│ └─ Repeat Phase 4→5 until zero critical/high issues │
│ │
└─────────────────────────────────────────────────────────────────┘
How to Use with GitHub Copilot
Strategy: Chunk, Don't Dump
The #1 mistake developers make is pasting an entire 500-line EJB into Copilot and asking "convert this to Spring Boot." Copilot will:
- Lose context halfway through
- Skip methods it considers "obvious"
- Drop error handling, null checks, and edge cases
- Miss injection points
Instead, this toolkit generates focused, single-concern prompts.
Recommended Copilot Workflow
1. Run: python3 run_migration.py analyze --legacy ./src/main/java
2. Open: reports/03_copilot_prompts/{ClassName}/
3. For each class:
a. Open 01_scaffold_{ClassName}.txt → paste into Copilot Chat
b. Copilot generates the class skeleton
c. Open 02_method_{ClassName}_{methodName}_*.txt → paste one at a time
d. Copilot fills in each method with full context
e. Check off the verification checklist at the bottom of each prompt
4. Run: python3 run_migration.py detect --legacy ./old --migrated ./new
5. Open: reports/04_code_loss_report.md → review all findings
6. Start Copilot/Cursor with `reports/AGENT_MIGRATION_INSTRUCTIONS.md`, then use prompts in `reports/03_copilot_prompts/`.
7. Decide when to fix losses. You can fix immediately with reports/05_fix_prompts/ or defer and continue migrating, then run fix_issues.py later.
8. Repeat steps 4-7 until the report shows zero CRITICAL/HIGH issues
Class Mapping Overrides
If you renamed classes during migration, provide a mapping file:
{
"com.example.legacy.OrderBean": "com.example.service.OrderService",
"com.example.legacy.OrderDAOImpl": "com.example.repository.OrderRepository"
}
python3 run_migration.py detect \
--legacy ./old/src --migrated ./new/src \
--class-map ./class_mapping.json
What Gets Detected
| Detection Type | Severity | Example |
|---|---|---|
| Missing Class | CRITICAL | OrderService has no equivalent in new code |
| Missing Method | CRITICAL | cancelOrder() entirely missing |
| Signature Change | HIGH | createOrder(Request) → createOrder(Customer, List) |
| Body Change (>50% diff) | HIGH | Method went from 40 lines to 15 lines |
| Missing Injection | HIGH | @EJB InventoryService not wired in new code |
| Annotation Drift | MEDIUM | @Stateless not mapped to @Service |
| Interface Dropped | MEDIUM | implements Serializable removed |
| Body Change (minor) | LOW | Small refactoring detected |
Project Structure
legacy-migration-toolkit/
├── run_migration.py # CLI entry point
├── requirements.txt # No external deps needed
├── src/
│ ├── analyzers/
│ │ └── java_parser.py # Parses legacy Java files
│ ├── detectors/
│ │ └── code_loss_detector.py # Compares legacy vs migrated
│ ├── generators/
│ │ └── copilot_prompt_generator.py # Creates Copilot prompts
│ └── orchestrator/
│ └── migration_workflow.py # Ties everything together
├── examples/
│ ├── legacy_code/ # Sample JBoss EJB code
│ └── migrated_code/ # Sample Spring Boot code (with losses)
├── reports/ # Generated reports land here
└── templates/ # Prompt templates
Supported Migrations
| From (Legacy) | To (Target) |
|---|---|
| EJB @Stateless | Spring @Service |
| EJB @Stateful | Spring @Service + @SessionScope |
| EJB @MessageDriven | Spring @JmsListener |
| JAX-RS @Path | Spring @RestController |
| JPA @Entity | JPA @Entity (javax→jakarta) |
| CDI @Inject | Spring @Autowired / Constructor Injection |
| Servlet | Spring @Controller |
Target frameworks: Spring Boot (default), Quarkus, Micronaut
Additional Suggestions
Beyond this toolkit, consider these approaches for large-scale migrations:
-
Strangler Fig Pattern: Don't migrate everything at once. Wrap legacy services behind a facade and replace them one by one.
-
Contract-First Testing: Before migration, write integration tests against your legacy REST endpoints. After migration, run the same tests against the new code. If tests pass, the migration preserved behavior.
-
Copilot Custom Instructions: In your GitHub Copilot settings, add a custom instruction like:
"When converting Java EE code to Spring Boot, always preserve all null checks, error handling, and business validations. Never simplify or omit edge case handling. Use constructor injection instead of field injection."
-
Batch Processing with Copilot CLI: For teams, use
gh copilotCLI to script prompt execution across multiple files. -
Version Control Each Phase: Commit after each phase completes. Tag commits like
migration/phase-1-entities,migration/phase-2-services. This gives rollback points.
Packaging (pip)
Local install (dev)
# In repo root
python3 -m venv .venv
.venv/bin/python setup.py develop
legacy-migration --help
Build and publish to PyPI
python3 -m pip install build twine
python3 -m build
twine upload dist/*
Update the package
- Bump the version in
pyproject.tomlandsetup.py. - Rebuild and republish (
python3 -m build, thentwine upload dist/*).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file legacy_migration_toolkit-0.4.0.tar.gz.
File metadata
- Download URL: legacy_migration_toolkit-0.4.0.tar.gz
- Upload date:
- Size: 45.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
398bbc2781a05d799db821c3f1600efa33034fd08a3443cfd40c5754ad0f343e
|
|
| MD5 |
cc78a67591aae0f3b05ffc8a4edc44ea
|
|
| BLAKE2b-256 |
0b52745630056e49e2c2645d605c255f5effe968409966181f3a54a8ba773edd
|