MetaObjects Examples

Learn through practical examples and real-world implementation patterns.

Quick Start Guide

1. Basic Setup

Get started with MetaObjects in your Java project. Add the dependency and create your first metadata definition.

<dependency>
    <groupId>com.metaobjects</groupId>
    <artifactId>metaobjects-core</artifactId>
    <version>6.2.5-SNAPSHOT</version>
</dependency>
implementation 'com.metaobjects:metaobjects-core:6.2.5-SNAPSHOT'

2. Create Your First Metadata

Define a simple object structure using MetaObjects JSON metadata format.

{
  "metadata": {
    "name": "user-objects",
    "version": "1.0",
    "children": [
      {
        "object": {
          "name": "User",
          "type": "pojo",
          "description": "User entity with validation",
          "children": [
            {
              "field": {
                "name": "id",
                "type": "long",
                "@required": true,
                "@primaryKey": true
              }
            },
            {
              "field": {
                "name": "username",
                "type": "string",
                "@required": true,
                "@minLength": 3,
                "@maxLength": 50,
                "@pattern": "^[a-zA-Z0-9_]+$"
              }
            },
            {
              "field": {
                "name": "email",
                "type": "string",
                "@required": true,
                "@pattern": "^[\\w._%+-]+@[\\w.-]+\\.[A-Za-z]{2,}$"
              }
            },
            {
              "field": {
                "name": "createdAt",
                "type": "datetime",
                "@required": true,
                "@default": "NOW()"
              }
            }
          ]
        }
      }
    ]
  }
}

3. Load and Use Metadata

Load your metadata and start using it in your Java application.

// Initialize MetaObjects registry
MetaDataRegistry registry = new MetaDataRegistry();

// Load metadata from JSON file
registry.loadFromFile("user-objects.json");

// Get object metadata
MetaData userMetadata = registry.getMetaData("User");

// Access field information
Field usernameField = userMetadata.getField("username");
String pattern = usernameField.getAttribute("pattern");
Integer maxLength = usernameField.getAttribute("maxLength");

// Validate data
ValidationResult result = userMetadata.validate(userData);
if (!result.isValid()) {
    result.getErrors().forEach(System.out::println);
}

Spring Boot Integration

Spring Configuration

Integrate MetaObjects with Spring Boot for automatic configuration and dependency injection.

@Configuration
@EnableMetaObjects
public class MetaObjectsConfig {

    @Bean
    public MetaDataRegistry metaDataRegistry() {
        MetaDataRegistry registry = new MetaDataRegistry();
        registry.loadFromClasspath("metadata/");
        return registry;
    }

    @Bean
    public MetaObjectValidator validator(MetaDataRegistry registry) {
        return new MetaObjectValidator(registry);
    }
}
@Service
public class UserService {

    @Autowired
    private MetaDataRegistry registry;

    @Autowired
    private MetaObjectValidator validator;

    public User createUser(UserRequest request) {
        // Get metadata for validation
        MetaData userMetadata = registry.getMetaData("User");

        // Validate input
        ValidationResult result = validator.validate(request, userMetadata);
        if (!result.isValid()) {
            throw new ValidationException(result.getErrors());
        }

        // Create and save user
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setCreatedAt(Instant.now());

        return userRepository.save(user);
    }
}
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody UserRequest request) {
        try {
            User user = userService.createUser(request);
            return ResponseEntity.ok(user);
        } catch (ValidationException e) {
            return ResponseEntity.badRequest()
                .body(new ErrorResponse(e.getErrors()));
        }
    }
}

Code Generation

Generate Multiple Language Output

Generate consistent code across multiple languages from your metadata definitions.

// Generated Java POJO
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 50)
    @Pattern(regexp = "^[a-zA-Z0-9_]+$")
    @Size(min = 3, max = 50)
    private String username;

    @Column(nullable = false)
    @Email
    private String email;

    @Column(nullable = false)
    @CreationTimestamp
    private Instant createdAt;

    // Generated getters, setters, equals, hashCode, toString
}
// Generated TypeScript interface and validation
export interface User {
  id: number;
  username: string;
  email: string;
  createdAt: string;
}

export class UserValidator {
  static validate(user: Partial<User>): ValidationResult {
    const errors: string[] = [];

    if (!user.username || user.username.length < 3 || user.username.length > 50) {
      errors.push("Username must be 3-50 characters");
    }

    if (!/^[a-zA-Z0-9_]+$/.test(user.username || '')) {
      errors.push("Username contains invalid characters");
    }

    if (!user.email || !/^[\w._%+-]+@[\w.-]+\.[A-Za-z]{2,}$/.test(user.email)) {
      errors.push("Invalid email format");
    }

    return { valid: errors.length === 0, errors };
  }
}
-- Generated SQL DDL
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(255) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

    CONSTRAINT uk_users_username UNIQUE (username),
    CONSTRAINT uk_users_email UNIQUE (email),
    CONSTRAINT ck_users_username CHECK (username REGEXP '^[a-zA-Z0-9_]+$'),
    CONSTRAINT ck_users_email CHECK (email REGEXP '^[\\w._%+-]+@[\\w.-]+\\.[A-Za-z]{2,}$')
);

-- Generated indexes
CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_users_email ON users(email);

Real-World Use Cases

🏥 Healthcare Data Management

Pharmaceutical company uses MetaObjects for clinical trial data structures that need to adapt to changing regulatory requirements.

  • Dynamic form generation for patient data
  • Compliance rule enforcement
  • Multi-language data export
  • Audit trail generation
Read Case Study

🎓 Educational Platform

Learning management system adapts course structures and assessment criteria without redeployment.

  • Dynamic course content modeling
  • Custom assessment frameworks
  • Multi-tenant data isolation
  • Real-time schema evolution
Read Case Study

💰 Financial Services

Trading platform handles complex financial instruments with varying data structures and validation rules.

  • Instrument definition management
  • Risk calculation frameworks
  • Regulatory reporting automation
  • Cross-system data consistency
Read Case Study

Advanced Patterns

Custom Field Types

Create custom field types with specialized validation and behavior.

public class CurrencyField extends PrimitiveField<BigDecimal> {

    public static void registerTypes(MetaDataRegistry registry) {
        registry.registerType(CurrencyField.class, def -> def
            .type("field").subType("currency")
            .inheritsFrom("field", "base")
            .optionalAttribute("precision", "int")
            .optionalAttribute("currencyCode", "string")
            .optionalAttribute("minValue", "decimal")
            .optionalAttribute("maxValue", "decimal")
        );
    }

    @Override
    public ValidationResult validate(BigDecimal value) {
        ValidationResult result = super.validate(value);

        if (value != null) {
            // Check precision
            Integer precision = getAttribute("precision");
            if (precision != null && value.scale() > precision) {
                result.addError("Value exceeds allowed precision of " + precision);
            }

            // Check range
            BigDecimal minValue = getAttribute("minValue");
            BigDecimal maxValue = getAttribute("maxValue");

            if (minValue != null && value.compareTo(minValue) < 0) {
                result.addError("Value below minimum: " + minValue);
            }

            if (maxValue != null && value.compareTo(maxValue) > 0) {
                result.addError("Value above maximum: " + maxValue);
            }
        }

        return result;
    }
}

Dynamic Schema Evolution

Handle schema changes at runtime without downtime.

@Component
public class SchemaEvolutionService {

    @Autowired
    private MetaDataRegistry registry;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void evolveSchema(String objectName, SchemaChange change) {
        MetaData metadata = registry.getMetaData(objectName);
        MetaData newMetadata = applyChange(metadata, change);

        // Validate the change
        ValidationResult validation = validateSchemaChange(metadata, newMetadata);
        if (!validation.isValid()) {
            throw new SchemaEvolutionException(validation.getErrors());
        }

        // Apply change atomically
        registry.updateMetaData(newMetadata);

        // Notify listeners
        eventPublisher.publishEvent(new SchemaChangedEvent(objectName, change));

        log.info("Schema evolved for {}: {}", objectName, change.getDescription());
    }

    private ValidationResult validateSchemaChange(MetaData old, MetaData updated) {
        SchemaCompatibilityChecker checker = new SchemaCompatibilityChecker();
        return checker.checkCompatibility(old, updated);
    }
}

Start Building With MetaObjects

Ready to implement these patterns in your project? Get started with our comprehensive documentation.