The SchemaGen feature generates Java model classes (POJOs/DTOs) from schema definitions such as JSON Schema and OpenAPI. Use it when you want types that are populated at runtime (for example via Jackson).
This is intentionally different from @Propify: @Propify generates read-only configuration accessors with compile-time embedded data, while @SchemaGen generates mutable data classes designed for binding and serialization.
| Feature | @Propify | @SchemaGen |
|---|---|---|
| Input | Config files with data | Schema files (structure only) |
| Output | Read-only classes + data | Mutable POJOs |
| Fields | private final |
private (mutable) |
| Methods | Getters only | Getters + Setters |
| Constructor | Private (singleton-style) | Public + Builder |
| Use Case | Application configuration | API data models |
| Data Source | Compile-time (fixed) | Runtime (dynamic via JSON/XML) |
- Mutable POJOs: getters and setters.
- Builder support: fluent construction for generated models.
- Jackson annotations (optional): JSON serialization/deserialization support in generated code.
- Bean Validation annotations (optional): constraints such as
@NotNull,@Email,@Size. - Multiple schema inputs: JSON Schema and OpenAPI 3.x.
- Nested object support: complex/nested types are generated as nested models.
- Compile-time generation: invalid inputs fail the build.
- Standalone output: generated code does not require SchemaGen at runtime.
Create a JSON Schema (src/main/resources/schemas/user.schema.json):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User",
"type": "object",
"properties": {
"id": { "type": "integer" },
"username": {
"type": "string",
"minLength": 3,
"maxLength": 50
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
}
},
"required": ["username", "email"]
}Annotate an interface:
@SchemaGen(
location = "classpath:schemas/user.schema.json",
type = SchemaType.JSON_SCHEMA
)
public interface UserSchema {}Use the generated class:
// Create using builder
User user = User.builder()
.id(1)
.username("johndoe")
.email("john@example.com")
.age(30)
.build();
// Or using setters
User user = new User();
user.setUsername("johndoe");
user.setEmail("john@example.com");
// Jackson serialization
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
// Deserialization
User user = mapper.readValue(json, User.class);Create OpenAPI spec (src/main/resources/schemas/api.yaml):
openapi: 3.0.0
info:
title: Pet Store API
version: 1.0.0
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
minLength: 1
maxLength: 100
status:
type: string
enum: [available, pending, sold]
price:
type: number
format: double
minimum: 0Annotate an interface:
@SchemaGen(
location = "classpath:schemas/api.yaml",
type = SchemaType.OPENAPI,
schemaRef = "Pet" // Specify which schema to generate
)
public interface PetSchema {}Use with REST APIs:
Pet pet = Pet.builder()
.id(123L)
.name("Fluffy")
.status("available")
.price(299.99)
.build();
// Spring RestTemplate
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Pet> response = restTemplate.postForEntity(
"https://api.example.com/pets",
pet,
Pet.class
);The @SchemaGen annotation provides several configuration options:
@SchemaGen(
location = "schemas/user.schema.json", // Schema file location
type = SchemaType.AUTO, // AUTO, JSON_SCHEMA, OPENAPI, XML_SCHEMA
schemaRef = "", // For OpenAPI: which schema to generate
generatedClassName = "$$", // Class name pattern ($$ = interface name)
builder = true, // Generate builder pattern
jacksonAnnotations = true, // Add Jackson annotations
jaxbAnnotations = false, // Add JAXB annotations
validationAnnotations = true, // Add Bean Validation annotations
serializable = true, // Implement Serializable
generateHelperMethods = true // Generate equals/hashCode/toString
)- Classpath:
"classpath:schemas/user.schema.json" - File System:
"file:///path/to/schema.json" - HTTP/HTTPS:
"https://example.com/api/schema.json"
SchemaType.AUTO- Auto-detect from file extension/contentSchemaType.JSON_SCHEMA- JSON Schema (draft-07+)SchemaType.OPENAPI- OpenAPI 3.x specificationSchemaType.XML_SCHEMA- XML Schema (XSD) - future support
Based on schema constraints:
@NotNull // For required fields
@Email // For email format
@Size(min=3, max=50) // For string length
@Min(0) @Max(150) // For numeric ranges
@Pattern(regexp="...")// For regex patternsFor JSON serialization:
@JsonProperty("fieldName")
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd")Fluent object construction:
User user = User.builder()
.username("john")
.email("john@example.com")
.age(30)
.build();Automatic generation of:
@Override
public boolean equals(Object o) { ... }
@Override
public int hashCode() { ... }
@Override
public String toString() { ... }Schema types are mapped to Java types:
| Schema Type | Format | Java Type |
|---|---|---|
| string | - | String |
| string | date-time | LocalDateTime |
| string | date | LocalDate |
| string | String (@Email) | |
| integer | - | Integer |
| integer | int64 | Long |
| number | - | Double |
| number | float | Float |
| boolean | - | Boolean |
| array | - | List<T> |
| object | - | Nested class |
my-project/
├── src/main/
│ ├── java/com/example/
│ │ ├── UserSchema.java # @SchemaGen annotation
│ │ └── MyService.java # Uses generated User class
│ └── resources/schemas/
│ ├── user.schema.json # JSON Schema
│ └── api.yaml # OpenAPI spec
└── pom.xml
Already included in Propify dependencies:
<dependency>
<groupId>com.vgerbot</groupId>
<artifactId>propify</artifactId>
<version>3.0.0</version>
</dependency>Runtime dependencies (if using features):
<!-- For Jackson JSON support -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.1</version>
</dependency>
<!-- For Bean Validation -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>Generate DTOs from OpenAPI specifications:
@SchemaGen(
location = "classpath:openapi/api.yaml",
type = SchemaType.OPENAPI,
schemaRef = "UserDTO"
)
public interface UserDtoSchema {}Share schema definitions across services:
@SchemaGen(
location = "https://schema-registry.example.com/user.schema.json",
type = SchemaType.JSON_SCHEMA
)
public interface UserSchema {}Generate entity classes from JSON Schema:
@SchemaGen(
location = "classpath:schemas/product.schema.json",
validationAnnotations = true,
serializable = true
)
public interface ProductSchema {}- Keep Schemas in Version Control - Track schema changes alongside code
- Use Schema Validation - Validate JSON/XML against schemas at runtime
- Separate Schema Interfaces - One schema file per interface for clarity
- Use Builder Pattern - Enabled by default, provides cleaner construction
- Enable Validation - Bean Validation catches constraint violations early
- Document Schemas - Use description fields, they become Javadoc
- Check classpath resources are in
src/main/resources/ - Verify the location path in
@SchemaGen
- Ensure
jacksonAnnotations = true(default) - Add Jackson dependencies to runtime classpath
- Ensure
validationAnnotations = true(default) - Add validation-api to runtime classpath
- Use a validation implementation (e.g., Hibernate Validator)
- Integrated with the rest of Propify.
- Compile-time generation (no separate generator step in your build).
- Builder pattern support out of the box.
- Annotation-driven workflow consistent with
@Propify.
- Annotation-based approach (no external generator CLI).
- Lightweight generated code intended to be edited/read in an IDE.
- Fits naturally into a standard Java compile/test cycle.
- XML Schema (XSD) support not yet implemented
- No support for allOf/oneOf/anyOf (planned)
- Enum types generated as Strings (planned improvement)
- Full XML Schema (XSD) support
- Support for allOf/oneOf/anyOf
- Enum type generation
- Custom type mappers
- Lombok-style generation option
- Record class generation (Java 14+)
Contributions are welcome! Please see the main CONTRIBUTING.md for guidelines.
MIT License - see LICENSE