This file provides guidance to WARP (warp.dev) when working with code in this repository.
MetaObjects is a comprehensive Java suite for metadata-driven development, featuring a completely modular architecture (v5.2.0+) designed for modern enterprise software development. It provides sophisticated control over applications beyond traditional model-driven development techniques.
Key Facts:
- Current Version: 5.2.0-SNAPSHOT (Modular Architecture)
- Java Version: Java 17 LTS (Production Ready)
- Build Tool: Maven 3.9+
- License: Apache License 2.0
# Clean build of all modules
mvn clean compile
# Run all tests across modules
mvn test
# Package all modules
mvn package
# Full clean build with packaging
mvn clean package# Build specific module (respect dependency order)
mvn -pl metadata clean compile
mvn -pl core clean compile
mvn -pl web clean compile
# Build with dependencies
mvn -pl core -am clean compile# Run all tests
mvn test
# Run tests for specific module
mvn -pl metadata test
mvn -pl core test
# Run single test class
mvn -Dtest=VehicleMetadataTest test
# Run with detailed output
mvn test -X# Navigate to web module
cd web
# Install dependencies
npm install
# Development mode with TypeScript watch
npm run dev
# Build TypeScript and CSS
npm run build
# Run Jest tests
npm run test
# Lint TypeScript/React code
npm run lint
npm run lint:fix# Generate code using Maven plugin
mvn com.draagon:metaobjects-maven-plugin:generate
# Clean and regenerate
mvn clean compile com.draagon:metaobjects-maven-plugin:generate# Run basic example (core functionality)
cd examples/basic-example && mvn compile exec:java
# Run Spring integration example
cd examples/spring-example && mvn compile exec:java
# Run OSGi example
cd examples/osgi-example && mvn compile exec:javaMetaObjects follows a READ-OPTIMIZED WITH CONTROLLED MUTABILITY design pattern, analogous to Java's Class/Field reflection system with dynamic class loading.
- Loading Phase vs Runtime Phase: MetaData objects are loaded once during application startup and optimized for heavy read access
- Permanent Memory Residence: Like Java Class objects, MetaData stays in memory for the application lifetime
- Thread-Safe Reads: No synchronization needed for read operations (99.9% of use cases)
- Copy-on-Write Updates: Infrequent updates use atomic reference swapping to maintain read performance
metadata/- Core metadata definitions and constraint systemcore/- File-based metadata loading and core functionality
codegen-base/- Base code generation frameworkcodegen-mustache/- Mustache template-based code generationcodegen-plantuml/- PlantUML diagram generationmaven-plugin/- Maven integration for build-time code generation
core-spring/- Spring Framework integrationweb-spring/- Spring Web integration with REST controllers
om/- Object Manager for metadata-driven object persistenceomdb/- Database Object Manager (SQL databases)omnosql/- NoSQL Object Manager
web/- React TypeScript components and web utilitiesdemo/- Demo applications with complete examplesexamples/- Comprehensive usage examples for all scenarios
metadata → codegen-* → core → *-spring → om → web → demo → examples
The framework uses a service-based type registry with these key components:
// LOADING PHASE - Once at startup
MetaDataLoader loader = new SimpleLoader("myLoader");
loader.setSourceURIs(Arrays.asList(URI.create("metadata.json")));
loader.init(); // Loads ALL metadata into permanent memory
// RUNTIME PHASE - Read-only operations
MetaObject userMeta = loader.getMetaObjectByName("User"); // O(1) lookup
MetaField field = userMeta.getMetaField("email"); // Cached access- ConcurrentHashMap: Permanent cache for core metadata lookups
- WeakHashMap: Computed cache for derived calculations (OSGi-compatible)
- Dual Strategy: Balances performance with memory cleanup in long-running applications
Constraints are self-registered programmatically via static initializers in MetaData classes:
@MetaDataType(type = "field", subType = "string")
public class StringField extends PrimitiveField<String> {
static {
// Self-registration with constraint setup
MetaDataTypeRegistry registry = new MetaDataTypeRegistry();
registry.registerHandler(
new MetaDataTypeId(TYPE_FIELD, SUBTYPE_STRING),
StringField.class
);
setupStringFieldConstraints();
}
}- Loading Phase: Use synchronization for writes/construction
- Runtime Phase: No synchronization needed for reads (immutable after loading)
- Update Phase: Copy-on-write for infrequent metadata updates
- DO NOT treat MetaData as frequently mutable domain objects
- DO NOT replace WeakHashMap with strong references (breaks OSGi compatibility)
- DO NOT create new MetaDataLoader instances frequently
- DO follow ClassLoader patterns for caching and lifecycle management
All tests inherit from SharedRegistryTestBase to prevent registry conflicts:
@IsolatedTest // For tests that must manipulate registry directly
public class MyTest extends SharedRegistryTestBase {
// Test implementation
}@Bean
@Singleton
public MetaDataLoader applicationMetaDataLoader() {
SimpleLoader loader = new SimpleLoader("app-metadata");
loader.setSourceURIs(getMetadataSourceURIs());
loader.init(); // Heavy one-time cost
return loader; // Permanent application bean
}- Backend serves metadata as JSON via Spring REST controllers
- Frontend uses TypeScript MetaView components for automatic form generation
- State management with Redux Toolkit and React Query
Reduce metadata verbosity with inline attributes:
JSON Format (@ prefixed):
{
"field": {
"name": "email",
"type": "string",
"@required": true,
"@maxLength": 255
}
}XML Format (no prefix):
<field name="email" type="string" required="true" maxLength="255" />The framework is designed for OSGi environments with dynamic bundle loading/unloading:
- Service discovery uses ServiceLoader pattern
- WeakReference patterns prevent memory leaks
- Bundle classloader cleanup supported
- Service registrations cleaned up automatically
Comprehensive modernization completed:
- ✅ Security: CVE-2015-7501 & CVE-2015-6420 vulnerabilities eliminated
- ✅ Java 17 LTS: Production-ready migration from Java 21
- ✅ Dependencies: Updated to secure versions (Spring 5.3.39, Commons Lang3 3.18.0)
- ✅ Code Quality: 341 lines of deprecated/vulnerable code removed
- ✅ CI/CD: GitHub Actions modernized with security improvements
- ✅ Test Success: 117+ tests passing with 100% success rate
When working with this codebase, remember:
- Read-Optimized Architecture: This is NOT a typical data access pattern - optimize for heavy reads, rare updates
- ClassLoader Analogy: MetaDataLoader operates like Java's ClassLoader with permanent memory residence
- Constraint System Integration: Constraints are programmatically self-registered, no external JSON files
- Shared Registry Pattern: Tests use static shared registry to prevent conflicts
- OSGi Bundle Management: WeakHashMap design is intentional for bundle lifecycle support
- Performance Expectations:
- Loading Phase: 100ms-1s (one-time cost)
- Runtime Reads: 1-10μs (cached, lock-free)
- Concurrent Readers: Unlimited (no lock contention)
The architecture is sophisticated and follows enterprise patterns for metadata-driven development with high-performance read characteristics.
These universally applicable principles should be followed for any software development:
- Apply "THINK HARD THROUGH THIS STEP BY STEP" approach to complex problems
- Break down problems into logical phases with clear objectives
- Identify root causes before applying solutions
- Use incremental validation at each step
- Maintain zero-regression policy during major changes
- Address CVE vulnerabilities immediately using dependency exclusion + secure replacement
- Never use unsafe generic casting - use stream-based conversion instead
- Prefer Optional-based APIs for null-safe programming
- Use modern exception patterns with rich context and suggestions
- Use shared registry patterns to prevent test conflicts
- Achieve 100% test success rate before considering features complete
- Validate incrementally: Unit → Integration → Build → Regression → Performance
- Create
@IsolatedTestannotations for tests that manipulate shared state
- Design for enterprise publishing with proper dependency management
- Use service discovery over hard-coding with META-INF/services patterns
- Preserve APIs through deprecation - never break backward compatibility
- Keep architecture documentation current with every major change
- Categorize enhancements systematically: HIGH/MEDIUM/LOW priority with clear success criteria
- Optimize for the primary use case (99% case, accommodate 1%)
- Use appropriate data structures for access patterns
- Implement lock-free algorithms where possible
- Support unlimited concurrent readers when appropriate
These rules are specific to MetaObjects architecture and should NOT be applied to other projects:
- MetaData objects follow ClassLoader pattern: Load once, permanent in memory, thread-safe reads
- Optimize for 99.9% reads, 0.1% updates - this is NOT a mutable domain model
- Use Copy-on-Write patterns for infrequent metadata updates
- Performance expectations: Loading 100ms-1s, Runtime reads 1-10μs, Unlimited concurrent readers
- Use WeakHashMap for computed caches - allows cleanup when bundles unload
- Implement ServiceReference leak prevention with proper cleanup patterns
- Use WeakReference patterns for ClassLoader cleanup
- Never use global static state that breaks modularization
- Respect dual cache strategy: ConcurrentHashMap (permanent) + WeakHashMap (computed)
- Never replace WeakHashMap with strong references - breaks OSGI compatibility
- Cache computed values can be GC'd and recomputed during memory pressure
- Permanent cache for core metadata lookups never gets GC'd
- Use service discovery for type registration via META-INF/services
- Implement priority-based provider loading: 0=base, 10=concrete, 50+=extensions
- Enable extensibility without modifying parent classes
- Support dynamic registration and cleanup
- Use programmatic self-registration - no external JSON constraint files
- Check constraint system before adding validation anywhere in codebase
- Use PlacementConstraint for "X CAN be placed under Y" rules
- Use ValidationConstraint for value validation rules
- Never add validation to type definitions, annotations, or constructors
- Constants live with classes that create the need for them
- Core MetaData constants go in owning classes (MetaData.java, MetaField.java)
- Service-specific constants go in service modules (DatabaseAttributeConstants, JpaConstants)
- Never create centralized constant files that violate dependency relationships
- ❌ DON'T treat MetaData as mutable domain objects - they're like Java Class objects
- ❌ DON'T create MetaDataLoader instances frequently - one per application context
- ❌ DON'T add rigid validation to core types - use constraint system instead
- ❌ DON'T synchronize read operations after loading - kills concurrent performance
- ❌ DON'T add service-specific attributes to core types - violates separation of concerns
- Use single static MetaDataRegistry shared across ALL tests
- Don't tear down registry between tests - creates conflicts
- All tests inherit from SharedRegistryTestBase
- Use @IsolatedTest for tests that manipulate registry directly
- Field names must follow pattern:
^[a-zA-Z][a-zA-Z0-9_]*$(no :: allowed)
- Use existing Optional-based APIs:
findString(),requireString(),getFieldsStream() - Use ObjectManager API correctly:
om.createObject(connection, object) - Use MetaObjects exception constructors:
new MetaDataNotFoundException("msg", name) - Prefer inline attributes in JSON:
"@required": true, "@maxLength": 255
Before making ANY changes to MetaObjects code, verify:
- Does it respect READ-OPTIMIZED WITH CONTROLLED MUTABILITY pattern?
- Does it maintain OSGI compatibility with WeakHashMap design?
- Does it optimize for read-heavy workloads (99.9% reads, 0.1% updates)?
- Does it support future dynamic metadata updates without blocking readers?
- Does it preserve extensibility without breaking existing functionality?
- ✅ 100% test success rate: All 199+ tests must pass consistently
- ✅ Registry health: 33-35+ types properly registered without conflicts
- ✅ Architecture compliance: READ-OPTIMIZED pattern maintained
- ✅ OSGI compatibility: WeakHashMap patterns and service discovery working
- ✅ Constraint system: Programmatic constraints enforcing without external files
- ✅ Provider registration: Service-based type discovery functioning correctly