Autogenerator_ipynb_2_
Prerequisites
Before using the auto-generator, make sure you have:
- Java 21+ installed
- Spring Boot project running on port
8585 - Admin credentials set up (from
.envfile) - A JPA Entity you want to create a table for
- A JPA Repository for that entity
Example Entity Structure:
@Entity
@Table(name = "games")
public class Game {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String type;
private Long personId;
private Double amount;
// ... more fields
}
Example Repository:
public interface GameJPARepository extends JpaRepository<Game, Long> {
// Your custom queries
}
How It Works: The Magic of Reflection
The auto-generator uses Java Reflection to inspect your entity class at runtime and automatically discover all its fields.
What is Reflection?
Reflection is Java’s ability to examine and manipulate classes, methods, and fields at runtime. Instead of hardcoding each field name, the system asks the entity class: “What fields do you have?”
The Core Components
- TableConfigBuilder - Uses reflection to scan entity fields
- Skips: static fields, transients, collections
- Detects: String, Number, Boolean, Date types
- Auto-generates: column labels (camelCase → Title Case)
- auto-table.html - Generic Thymeleaf fragment
- Renders ANY entity table
- Dynamic columns based on
TableConfig - Type-aware rendering (TEXT, CHECKBOX, LINK, etc.)
- GenerateTablePage.java - One-file automation script
- Creates controller with all CRUD endpoints
- Generates
read.html(table view) - Generates
edit.html(create/update form)
Step 1: Configure the Generator
Open GenerateTablePage.java in your project root and edit 3 lines:
// ═══════════════════════════════════════════════════════════════════
// ✏️ EDIT THESE LINES - Everything else is automatic!
// ═══════════════════════════════════════════════════════════════════
static final String ENTITY_NAME = "Game"; // ← Your entity class name
static final String ENTITY_PACKAGE = "com.open.spring.mvc.rpg.games"; // ← Where your entity class is
static final String PAGE_NAME = "Games"; // ← Creates /mvc/games/read
// ═══════════════════════════════════════════════════════════════════
Configuration Guide
| Field | Example | Purpose |
|---|---|---|
ENTITY_NAME |
"Game" |
Name of your JPA entity class |
ENTITY_PACKAGE |
"com.open.spring.mvc.rpg.games" |
Full package path to entity |
PAGE_NAME |
"Games" |
Controls URL and file paths |
Result:
- Controller:
src/main/java/com/open/spring/mvc/games/GamesMvcController.java - Views:
src/main/resources/templates/games/read.html+edit.html - URL:
http://localhost:8585/mvc/games/read
Step 2: Run the Generator
Execute the generator from your project root:
java GenerateTablePage.java
Expected Output:
╔════════════════════════════════════════════════════════════╗
║ AUTO TABLE PAGE GENERATOR ║
╚════════════════════════════════════════════════════════════╝
Entity: Game
Entity Package: com.open.spring.mvc.rpg.games
Controller Pkg: com.open.spring.mvc.games
URL Path: /mvc/games/read
Generating files...
════════════════════════════════════════════════════════════
✓ Created: src/main/java/com/open/spring/mvc/games/GamesMvcController.java
✓ Created: src/main/resources/templates/games/read.html
✓ Created: src/main/resources/templates/games/edit.html
════════════════════════════════════════════════════════════
╔════════════════════════════════════════════════════════════╗
║ ✓ SUCCESS! Everything ready to use. ║
╚════════════════════════════════════════════════════════════╝
What Just Happened?
- ✅ Controller with 5 CRUD endpoints created
- ✅ Table view with column toggles generated
- ✅ Edit form with auto-discovered fields created
- ✅ All endpoints secured with admin-only access
Step 3: Restart Spring Boot
Since we generated new Java files, restart your Spring Boot application:
# Stop the current server (Ctrl+C in terminal)
./mvnw spring-boot:run
Or use VSCode:
- Stop the running application
- Click Run on
Main.java
Wait for:
Tomcat started on port(s): 8585 (http)
Started Main in X.XXX seconds
Step 4: Test Your New Admin Table!
Open the Table View
Navigate to: http://localhost:8585/mvc/games/read
Login Required:
- Username:
toby(or your admin username) - Password: From your
.envfile (ADMIN_PASSWORD)
What You Should See
Column Toggle Buttons at the top:
- Click any button to show/hide that column
- Active (green) = visible, Inactive (gray) = hidden
The Table:
- All entity fields automatically displayed
- Update/Delete buttons for each row
- “Create New Game” button at bottom
Import/Export Controls:
- Export All → Download as JSON
- Import JSON → Upload data
Step 5: Test CRUD Operations
Create a New Record
- Click “Create New Game” button
- Fill out the auto-generated form:
- All entity fields shown as form inputs
- Textareas for fields with “details”, “description”, “summary”
- Checkboxes for Boolean fields
- Regular inputs for everything else
- Click Save
- Redirected to table → new record appears!
Update an Existing Record
- Click Update button on any row
- Form pre-filled with current values
- Modify fields
- Click Save
- Changes reflected in table
Delete a Record
- Click Delete button on any row
- Record removed immediately
- Table refreshes
All operations are admin-only! Non-admin users see “Access denied” message.
Verification: Is It Actually Working?
Check 1: Controller Exists
Look for generated controller:
ls src/main/java/com/open/spring/mvc/games/GamesMvcController.java
Check 2: Views Exist
ls src/main/resources/templates/games/read.html
ls src/main/resources/templates/games/edit.html
Check 3: Database Has Data
If table shows 0 rows, check SQLite database:
# From project root
sqlite3 volumes/sqlite.db
# In SQLite shell
SELECT COUNT(*) FROM games;
SELECT * FROM games LIMIT 5;
If count is 0:
- Entity’s
init()method may not be called - Check
ModelInit.javafor seeding logic - Create test records via the UI
Check 4: Endpoints Are Accessible
Test URLs (while logged in as admin):
- ✅
http://localhost:8585/mvc/games/read - ✅
http://localhost:8585/mvc/games/new - ✅
http://localhost:8585/mvc/games/edit/1
Understanding the Generated Code
The Controller (5 Endpoints)
@Controller
@RequestMapping("/mvc/games")
public class GamesMvcController {
@Autowired
private GameJPARepository gameJPARepository;
// Checks if user is admin
private boolean isAdmin(Authentication authentication) { ... }
// Builds table config via reflection
private TableConfig buildTableConfig() {
return TableConfigBuilder.fromEntity(Game.class)
.withEntityName("games")
.withPaths("/mvc/games/edit", "/mvc/games/delete")
.build();
}
@GetMapping("/read") // List all records
@GetMapping("/new") // Show create form
@GetMapping("/edit/{id}") // Show edit form
@PostMapping("/save") // Create or update
@GetMapping("/delete/{id}") // Delete record
}
The Read View
One line renders the entire table using the auto-table fragment with dynamic columns!
The Edit View
Form fields auto-generated from tableConfig.columns:
- Loops through discovered fields
- Skips
id,ACTIONS,IMPORT_EXPORT - Renders appropriate input type based on field type
Troubleshooting Common Issues
❌ Error: “Ambiguous mapping”
Symptom:
Ambiguous mapping. Cannot map 'gamesMvcController' method
to {GET [/mvc/games/read]}: There is already 'gameMvcController'
Cause: Two controllers mapping to the same URL
Fix:
- Find old controller (e.g.,
GameMvcController.java) - Either delete it or change its
@RequestMappingpath:@RequestMapping("/mvc/games-old") // Rename to avoid conflict
❌ Page Loads Forever (ERR_INCOMPLETE_CHUNKED_ENCODING)
Symptom: Browser shows “Loading…” indefinitely
Possible Causes:
- Template syntax error - Check Spring Boot console for Thymeleaf errors
- Missing fragment - Ensure
fragments/auto-table.htmlexists - Repository not found - Check repository naming matches
REPO_NAME
Fix: Check console logs for specific error, restart Spring Boot
❌ Table Shows 0 Rows (But Entity Exists)
Symptom: Table renders but shows empty
Cause: Database table empty
Fix:
// Check ModelInit.java - entity seeding may be disabled
// Example:
Game[] games = Game.init();
for (Game g : games) {
gameJPARepository.save(g);
}
Or create records via UI: Click “Create New”
❌ Repository Not Found Error
Symptom:
Could not autowire. No beans of 'GameJPARepository' type found.
Cause: Repository naming doesn’t match REPO_NAME assumption
Fix: Generator assumes ENTITY_NAME + "JPARepository". If your repo has a different name (e.g., UnifiedGameRepository), manually edit generated controller to use correct repo name.
Advanced: How Reflection Works
Let’s peek under the hood at TableConfigBuilder.java:
Field Discovery
private List<Field> getAllFields(Class<?> clazz) {
List<Field> fields = new ArrayList<>();
// Add fields from current class
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
// Add fields from superclass (inheritance support)
if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) {
fields.addAll(getAllFields(clazz.getSuperclass()));
}
return fields;
}
Field Filtering
private boolean shouldSkipField(Field field) {
// Skip static fields
if (Modifier.isStatic(field.getModifiers())) return true;
// Skip @Transient fields
if (field.isAnnotationPresent(Transient.class)) return true;
// Skip collections/maps (avoid complex recursion)
if (Collection.class.isAssignableFrom(field.getType())) return true;
return false;
}
Type Detection
private TableColumn.ColumnType determineColumnType(Field field) {
Class<?> type = field.getType();
if (type == Boolean.class || type == boolean.class) {
return TableColumn.ColumnType.CHECKBOX;
}
if (type == String.class || Number.class.isAssignableFrom(type)) {
return TableColumn.ColumnType.TEXT;
}
return TableColumn.ColumnType.TEXT; // Default
}
Reflection Benefits:
- ✅ No hardcoding field names
- ✅ Automatically adapts to entity changes
- ✅ Works with ANY entity structure
- ✅ Supports inheritance
Try It Yourself: Generate a Resume Table
Let’s practice by generating a CRUD table for the Resume entity!
Exercise Instructions
-
Open
GenerateTablePage.java - Edit the configuration:
static final String ENTITY_NAME = "Resume"; static final String ENTITY_PACKAGE = "com.open.spring.mvc.resume"; static final String PAGE_NAME = "Resumes"; - Run the generator:
java GenerateTablePage.java -
Restart Spring Boot
-
Visit:
http://localhost:8585/mvc/resumes/read - Test CRUD:
- Create a resume record
- View it in the table
- Edit it
- Delete it
Expected Result
You should see a table showing Resume fields:
idusernameprofessionalSummaryexperiences
With full CRUD functionality, all auto-generated in 10 seconds!
Summary: What You Learned
The Power of Automation
- ✅ 97% code reduction: From ~100 lines → 3 configuration lines
- ✅ 180-360x faster: From 60 minutes → 10 seconds
- ✅ Works with ANY entity: Unlimited scalability
Key Concepts
- Java Reflection - Runtime type inspection
- Generic Templates - One template, infinite entities
- Builder Pattern - Fluent configuration API
- Admin Security - All endpoints protected
Architecture Components
TableConfigBuilder- Reflection engineauto-table.html- Generic Thymeleaf fragmentGenerateTablePage.java- Code generator- Generated Controllers - Full CRUD endpoints
- Generated Views - Table + Form pages
Real-World Impact
Instead of manually writing controllers, views, and forms for every entity, you can now:
- Configure 3 lines
- Run 1 command
- Get complete admin CRUD in seconds
This is the power of meta-programming and automation in modern software development!
Challenge: Extend the System
Want to go further? Try these enhancements:
Easy Challenges
- Add Custom Field Labels
- Modify
TableConfigBuilderto read@Column(name=...)annotations - Use annotation names as display labels
- Modify
- Add Data Validation
- Generate form validation based on entity constraints
- Show error messages for invalid inputs
- Custom Styling
- Modify
auto-table.htmlto use your own CSS classes - Add custom Bootstrap themes
- Modify
Medium Challenges
- Support @ManyToOne Relationships
- Detect relationship fields via reflection
- Render as dropdown selects in edit form
- Load options from related repository
- Add Pagination
- Modify generated controller to accept page parameters
- Update template to show pagination controls
- Export to CSV/Excel
- Add export format options beyond JSON
- Use Apache POI for Excel generation
Hard Challenges
- Generate REST API Controllers
- Extend generator to create REST endpoints
- Auto-generate
@RestControllerwith GET/POST/PUT/DELETE
- Add Search/Filter UI
- Generate search fields based on entity types
- Build dynamic SQL queries from user input
- Create Admin Dashboard
- Auto-generate cards showing entity statistics
- Link to all generated CRUD pages
Pick a challenge and level up your automation skills! 🚀