Propify is a Java annotation processor that generates typed APIs from configuration files (YAML, INI, .properties), i18n bundles, and schema definitions (JSON Schema, OpenAPI).
If a config key, message key, or schema shape changes, the generated API changes with it and mismatches show up during compilation rather than as runtime lookups.
It supports nested properties, custom lookup providers (env/system/custom), ICU4J message formatting, and schema-based POJO generation. Generated code is regular Java; you call it from your application code.
- Why Propify?
- Features
- Requirements
- Installation
- Quick Start
- Internationalization (i18n)
- Schema-Based Generation
- How It Works
- Examples
- Documentation
- 📖 @Propify Guide - Complete guide to type-safe configuration
- 📖 @I18n Guide - Comprehensive internationalization guide
- 📖 @SchemaGen Guide - Schema-based POJO generation guide
- Getting Help
- Contributing
- License
- Acknowledgments
- Typed access: use generated getters/methods instead of
config.get("a.b.c")-style lookups. - Earlier failures: missing keys and invalid formats fail the build, not production.
- Less glue code: no hand-written parsing/mapping for common cases.
- Extensible resolution: plug in custom lookup providers for env vars, system properties, or your own sources.
- Type-safe config: generate APIs from YAML, INI, or
.properties. - Type-safe i18n: generate resource bundle accessors; ICU4J MessageFormat support.
- Schema-based POJOs: generate mutable DTOs from JSON Schema or OpenAPI specs.
- Compile-time validation: syntax and schema checks happen during the build.
- Nested keys: hierarchical configs map to nested types.
- Custom lookups: resolve values from env/system/custom providers.
- Compile-time generation: no runtime parsing step required for the generated accessors.
- Java: 8 or higher
- Build: Maven or Gradle
Add dependency and annotation processor:
<dependencies>
<dependency>
<groupId>com.vgerbot</groupId>
<artifactId>propify</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>com.vgerbot</groupId>
<artifactId>propify</artifactId>
<version>3.0.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>dependencies {
implementation 'com.vgerbot:propify:3.0.0'
annotationProcessor 'com.vgerbot:propify:3.0.0'
}plugins {
id 'net.ltgt.apt' version '0.21'
}
dependencies {
compile 'com.vgerbot:propify:3.0.0'
apt 'com.vgerbot:propify:3.0.0'
}For other tools, configure your build to include
propifyas an annotation processor.
-
Create
src/main/resources/application.yml:server: host: localhost port: 8080 database: url: jdbc:mysql://localhost:3306/mydb username: root password: secret
-
Annotate an interface:
@Propify(location = "application.yml") public interface AppConfig {}
-
Use the generated API:
public class Main { public static void main(String[] args) { AppConfigPropify cfg = AppConfigPropify.getInstance(); System.out.println(cfg.getServer().getHost()); System.out.println(cfg.getDatabase().getUrl()); } }
📖 Full @Propify Documentation - Learn about custom lookups, media types, advanced configuration options, and more.
Generate type-safe resource bundles using ICU4J:
-
Create message files in
resources/:# messages.properties (default) welcome=Welcome greeting=Hello, {0}! # messages_zh_CN.properties welcome=欢迎 greeting=你好, {0}!
-
Annotate a class:
@I18n(baseName = "messages", defaultLocale = "en") public class Messages {}
-
Access messages:
String hi = MessageResource.getDefault().greeting("Alice"); String hiZh = MessageResource.get(Locale.CHINESE).greeting("张三");
📖 Full @I18n Documentation - Explore ICU MessageFormat, pluralization, date/time formatting, and multi-locale support.
Generate mutable POJO/DTO classes from schema definitions for REST APIs and data modeling:
// 1. Create a JSON Schema or OpenAPI spec
@SchemaGen(location = "schemas/user.schema.json")
public interface UserSchema {}
// 2. Use the generated POJO
User user = User.builder()
.username("johndoe")
.email("john@example.com")
.build();
// 3. Serialize/deserialize with Jackson
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
User deserializedUser = mapper.readValue(json, User.class);Key points:
- Mutable POJOs with getters/setters
- Builder pattern for fluent construction
- Optional Jackson annotations for JSON serialization
- Optional Bean Validation annotations (
@NotNull,@Email,@Size, etc.) - JSON Schema and OpenAPI 3.x inputs
📖 Full @SchemaGen Documentation - Learn about OpenAPI support, type mapping, validation annotations, and more.
- Scan for
@Propify,@I18n, and@SchemaGenannotations - Parse configuration files, message bundles, and schema definitions
- Generate Java implementation classes and POJOs
- Compile everything together—fail-fast on errors
Check the example/ directory for complete working examples:
- Basic Configuration - Simple YAML/Properties configuration
- Advanced Configuration - Custom lookups and nested structures
- INI Configuration - INI format support
- Internationalization - Multi-locale messages with ICU formatting
- Schema Generation - JSON Schema and OpenAPI POJO generation
If you encounter any issues or have questions about using Propify:
- GitHub Issues: Submit a new issue on our GitHub repository
- Documentation: Check the Wiki for detailed documentation
- Examples: Browse the example directory for sample projects
- Fork the repo
- Create a feature branch (
git checkout -b feature/xyz) - Implement and test your changes
- Submit a Pull Request
Please follow the existing coding style and update tests.
MIT © 2024 vgerbot-libraries
- JavaPoet - Java source file generation
- Jackson YAML - YAML parsing
- Apache Commons Configuration - Configuration management
- ICU4J - Internationalization support