GitHub

Build Status Qodana Maven Central License

Generate version-agnostic Java wrappers from multiple protobuf schema versions.

Supports both Maven and Gradle build systems.


The Problem

When protobuf schemas evolve across versions, you face:

  • Type mismatches: int32 in v1 becomes enum in v2
  • Version-specific code: Different code paths for each version
  • Maintenance burden: Changes ripple through the codebase
flowchart LR
    subgraph without["Without Proto Wrapper"]
        direction TB
        V1["v1/*.proto"]
        V2["v2/*.proto"]
        S1["ServiceV1.java"]
        S2["ServiceV2.java"]
        V1 --> S1
        V2 --> S2
    end
Loading

Result: Duplicate code, version-specific logic, maintenance nightmare.

The Solution

Proto Wrapper generates a unified API that abstracts version differences:

flowchart LR
    subgraph Input["Proto Files"]
        V1["v1/*.proto"]
        V2["v2/*.proto"]
    end
    subgraph Plugin["Proto Wrapper"]
        PW[Generate]
    end
    subgraph Output["Generated Code"]
        IF["Interface"]
        I1["ImplV1"]
        I2["ImplV2"]
    end
    subgraph App["Your Code"]
        SVC["Service.java"]
    end
    V1 --> PW
    V2 --> PW
    PW --> IF
    PW --> I1
    PW --> I2
    IF --> SVC
Loading

Usage:

// Works with v1, v2, or any future version
Order order = ctx.wrapOrder(anyVersionProto);
// Type conflicts handled automatically
PaymentType type = order.getPaymentType();  // Auto-converted from int or enum
long amount = order.getTotalAmount();        // Auto-widened from int32 or int64
// Serialize back to original version
byte[] bytes = order.toBytes();

Quick Start

Maven

1. Add the plugin:

<plugin>
    <groupId>io.alnovis</groupId>
    <artifactId>proto-wrapper-maven-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <basePackage>com.example.model</basePackage>
        <protoRoot>${basedir}/proto</protoRoot>
        <versions>
            <version><protoDir>v1</protoDir></version>
            <version><protoDir>v2</protoDir></version>
        </versions>
    </configuration>
    <executions>
        <execution><goals><goal>generate</goal></goals></execution>
    </executions>
</plugin>

2. Generate:

mvn generate-sources

Gradle

1. Apply the plugin:

plugins {
    id("io.alnovis.proto-wrapper") version "2.3.2"
}
protoWrapper {
    basePackage.set("com.example.model")
    protoRoot.set(file("proto"))
    versions {
        version("v1")
        version("v2")
    }
}

2. Generate:

./gradlew generateProtoWrapper

Features

Feature Description Since
Multi-version support Merge unlimited proto versions into unified API v1.0
Type conflict handling Automatic conversion for int/enum, int/long, string/bytes v1.0
Builder pattern Create and modify messages with fluent API v1.1
Well-known types Convert Timestamp, Duration, wrappers to Java types v1.3
Oneof support Full oneof field handling with conflict detection v1.2
Schema diff tool Compare schemas, detect breaking changes v1.5
Incremental build Skip unchanged protos, 50%+ faster rebuilds v1.6.0
Embedded protoc Auto-download protoc, no manual installation needed v1.6.5
ProtoWrapper interface Common base interface for type-safe proto access v1.6.6
Spring Boot Starter Auto-configuration for Spring Boot applications v1.6.7
Java 8 compatibility Generate Java 8 compatible code with targetJavaVersion=8 v1.6.8
ProtocolVersions class Centralized version constants with generateProtocolVersions=true v2.1.0
Per-version proto syntax Mixed proto2/proto3 projects with auto-detection v2.2.0
Field mappings Explicit mapping for renumbered fields across versions v2.2.0
Renumber detection Heuristic detection of field renumbering in diff tool v2.2.0
Validation annotations Auto-generated @NotNull, @Valid on interface getters v2.3.0
Schema metadata Runtime access to enum values, field info, and version diffs v2.3.1
Default instance for messages Unset message getters return empty wrapper (like protobuf) instead of null v2.3.2

Type Conflict Handling

Conflict Example Resolution
INT_ENUM int32enum Dual getters: getType() + getTypeEnum()
WIDENING int32int64 Unified as wider type with range validation
STRING_BYTES stringbytes Dual getters: getText() + getTextBytes()
PRIMITIVE_MESSAGE int32Money Dual getters with runtime support checks

Documentation

Document Description
Getting Started Step-by-step tutorial (15 min)
Configuration All plugin options for Maven and Gradle
Spring Boot Starter Integration with Spring Boot
Schema Metadata Runtime access to enum values and version diffs
Cookbook Practical examples and patterns
Contract Matrix Field behavior reference (getter/has for all types)
Schema Diff Compare schemas and detect breaking changes
Incremental Build Build optimization details
Known Issues Limitations and workarounds
Architecture Internal design (for contributors)
API Reference Generated code reference

Examples


Generated Code Structure

target/generated-sources/proto-wrapper/
└── com/example/model/
    ├── api/
    │   ├── Order.java              # Interface
    │   ├── PaymentType.java        # Unified enum
    │   ├── VersionContext.java     # Version factory interface
    │   ├── ProtocolVersions.java   # Version constants (optional)
    │   └── impl/
    │       └── AbstractOrder.java  # Template methods
    ├── metadata/                   # Schema metadata (optional)
    │   ├── SchemaInfoV1.java       # V1 enum/message metadata
    │   ├── SchemaInfoV2.java       # V2 enum/message metadata
    │   └── SchemaDiffV1ToV2.java   # V1→V2 schema changes
    ├── v1/
    │   ├── OrderV1.java            # V1 implementation
    │   └── VersionContextV1.java
    └── v2/
        ├── OrderV2.java            # V2 implementation
        └── VersionContextV2.java

Requirements

  • Java 17+
  • Maven 3.8+ or Gradle 8.5+

No manual protoc installation required! The plugin automatically downloads the appropriate protoc binary from Maven Central if not found in PATH.


Installation

From Maven Central

Add dependency (plugins auto-download):

<dependency>
    <groupId>io.alnovis</groupId>
    <artifactId>proto-wrapper-core</artifactId>
    <version>2.3.2</version>
</dependency>

From Source

git clone https://github.com/alnovis/proto-wrapper-plugin.git
cd proto-wrapper-plugin
mvn clean install                    # Maven modules
./gradlew publishToMavenLocal        # Gradle plugin

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

License

Apache License 2.0 - see LICENSE for details.


See Also


Acknowledgments

YourKit logo

YourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET applications. YourKit is the creator of YourKit Java Profiler, YourKit .NET Profiler, and YourKit YouMonitor.

Read the original on github.com ↗