A suite of extensible XJC (JAXB) plugins designed to streamline XML-to-Java binding, customize generated code structures, and eliminate boilerplate in modern Java projects (Java 21+).
- Modern Standards: Full support for Java 21+ and
java.time(JSR-310) date/time API mapping. - Flexible Configuration: Supports compact inline mappings (
pattern->replacement) and structured nested CLI flags. - Boilerplate Reduction: Direct Lombok integration (
-Xlombok), Jackson DTO defaults (-Xjackson), automated wrapper class flattening (-Xelement-wrapper), and getter/setter removal. - Fine-Grained Customization: Comprehensive annotation injection/removal, custom naming transformations, and namespace/prefix management.
Maps XSD date and time types to modern java.time classes.
- Timezone-aware date/time handling (
OffsetDateTime,OffsetTime). - Timezone-tolerant unmarshalling (automatically falls back to system local offset if timezone is omitted in XML).
- Custom formatting patterns.
- Automated
XmlAdaptergeneration (derived from common package prefixes).
-Xjava-time \
-type-mapping \
-xsd-type=dateTime \
-target-type=java.time.OffsetDateTime-Xjava-time \
-adapter-package=package.name \ # Optional: defaults to <common_package>.adapter
-type-mapping \ # Group marker
-xsd-type=xsdType \
-target-type=java.time.Class \
-format=dateFormat \
-adapter=custom.AdapterClass \
-field=fieldPattern \
-xsd-type=anotherType \ # Repeated child field starts next item
-target-type=java.time.LocalDate| XSD Type | Java Target Type | Notes |
|---|---|---|
xs:dateTime |
java.time.OffsetDateTime |
Timezone-tolerant |
xs:date |
java.time.LocalDate |
ISO_DATE |
xs:time |
java.time.OffsetTime |
Timezone-tolerant |
xs:gYearMonth |
java.time.YearMonth |
|
xs:gYear |
java.time.Year |
|
xs:gMonthDay |
java.time.MonthDay |
|
xs:gDay |
java.lang.Integer |
|
xs:gMonth |
java.time.Month |
|
xs:duration |
java.time.Duration |
Generates Bean Validation (JSR-380) constraint annotations on generated class fields from XSD multiplicity and simple-type facets.
The plugin picks the validation package from the XJC classpath (not the main module compile classpath):
- Prefer
jakarta.validationwhen present - Else use
javax.validationwhen present - If neither is found, XJC fails with a clear error
Add jakarta.validation:jakarta.validation-api (preferred) or javax.validation:validation-api to the jaxb-maven-plugin / XJC plugin dependencies.
| XSD | Annotation |
|---|---|
Element minOccursβ₯1 (non-nillable, non-primitive) |
@NotNull |
Element nillable="true" |
no @NotNull |
Attribute use="required" |
@NotNull |
Collection minOccurs / maxOccurs |
@NotNull + @Size |
minLength / maxLength / length (string fields) |
@Size |
pattern |
@Pattern |
minInclusive / maxInclusive |
@Min / @Max or @DecimalMin / @DecimalMax |
minExclusive / maxExclusive |
@DecimalMin / @DecimalMax(inclusive=false) |
totalDigits / fractionDigits (user-declared) |
@Digits |
Complex type / List of complex |
@Valid |
simpleContent (@XmlValue) facets |
same as simple type |
- No mapping for
enumeration,whiteSpace, orfixed. - Collection item length/pattern is not expressed (
@Sizeon a list is multiplicity only). - Facets are taken from the user restriction chain only; built-in XML Schema facets (e.g.
xs:integerfractionDigits) are ignored. - Annotations are applied to fields only (JAXB default
FIELDaccess).
-Xvalidation-Xvalidation \
-class-name=.*UserType \ # Optional regex matched against FQCN (repeatable)
-field-name=username \ # Optional regex matched against field name (repeatable)
-disable-valid=true # Optional: disable @Valid on nested/collection properties (default: false)| Option | Default | Description |
|---|---|---|
-class-name |
(all classes) | Regex matched against fully-qualified class names (repeatable) |
-field-name |
(all fields) | Regex matched against field names (repeatable) |
-disable-valid |
false |
When true, omits @Valid cascade validation annotations |
Injects Java supertypes into generated JAXB classes: interface implementations (implements) and superclasses (extends), with optional Serializable support. Similar in spirit to the jaxb-tools inheritance plugin.
- Interface Implementation: Adds
implements InterfaceFQCNvia compact or structured mapping. Accumulates multiple interfaces without duplicates. Select targets with each rule's left-hand pattern. - Superclass Extension: Adds
extends SuperClassFQCNonly when the class currently extendsObject(preserves XSD inheritance). Multiple matching rules are first-wins; further matches or existing non-Objectparents emit XJC warnings. - Serializable Shortcut: Adds
implements java.io.SerializableandserialVersionUIDwhen missing. Default UID is1L(reproducible); override with-serial-version-uid.
-serializable(+ optional-serial-version-uid)-interfacerules in declaration order (cumulative)-super-classrules in declaration order (first-wins)
-Xinheritance \
-serializable=true \
-serial-version-uid=1 \
-interface=.*Request->com.example.BaseRequest \
-super-class=.*Dto->com.example.AbstractDto-Xinheritance \
-interface=pattern->InterfaceFQCN \ # Compact interface mapping (repeatable)
-super-class=pattern->SuperClassFQCN \ # Compact superclass mapping (repeatable)
-serializable=true \ # Add Serializable + serialVersionUID when missing
-serial-version-uid=1 # UID value when -serializable is true (default: 1)Structured form is also supported:
-Xinheritance -interface -name=.*Request -to=com.example.BaseRequest| Option | Default | Description |
|---|---|---|
-interface |
(none) | Compact mapping (pattern->InterfaceFQCN) for implementing interfaces |
-super-class |
(none) | Compact mapping (pattern->SuperClassFQCN) for extending superclasses |
-serializable |
false |
When true, injects Serializable and serialVersionUID if missing |
-serial-version-uid |
1 |
serialVersionUID value used only when -serializable=true |
Adds, removes, or modifies annotations on generated classes, fields, methods, and package metadata.
- Inject arbitrary annotations (validation, framework metadata, field-level Jackson, etc.).
- For common class-level Jackson defaults (
@JsonInclude,ignoreUnknown), prefer dedicated-Xjackson. - Strip unwanted JAXB-generated annotations.
-Xannotate \
-add-to-class \
-anno=@com.example.MyAnnotation \
-target=.*Person \
-add-to-field \
-anno=@com.fasterxml.jackson.annotation.JsonProperty("value") \
-target=.*name-Xannotate \
-add-to-class \ # Target kind: class
-anno=@AnnotationClass(param="value") \
-target=pattern \
-add-to-field \ # Target kind: field
-anno=@AnnotationClass(param="value") \
-target=pattern \
-remove-from-class|-remove-from-field|-remove-from-method|-remove-from-package \
-anno=AnnotationClass \
-target=patternCustomizes how XJC maps XML element names to Java identifiers (class names, field names, method names, and package names).
- Convert
snake_caseXML definitions intocamelCaseJava properties. - Apply regular expression replacements to auto-generated class/variable names.
- Resolve conflicts with legacy naming conventions.
-Xconvert-name \
-class-name=XMLDocument->Document \
-variable-name \
-name=(.*)_ID \
-to=$1Id-Xconvert-name \
# Compact format:
-class-name=originalName->newName \
-class-name=/(.*)_ID/->$1Id \
-package-name=http://example.com/a->com.example.a \
# Structured format:
-variable-name \
-name=(.*)_ID \
-to=$1Id \
# Or exact match on original NameConverter input:
-class-name \
-input=Person \
-to=CustomPersonFlattens XML collection wrapper elements by moving @XmlElementWrapper and @XmlElement annotations directly to the collection field and optionally deleting unnecessary wrapper classes.
- Removes redundant wrapper DTO classes.
- Simplifies object graphs and cleans up API signatures.
-Xelement-wrapper \
-remove-wrapper-class=truePromotes nested static classes and enums toward package scope level by level, stopping automatically upon name collisions.
- Un-nests deeply scoped anonymous complex types and local enums.
- Avoids unsafe renames by respecting namespace boundaries.
- Executes during the
postProcessModelphase.
-Xpromote-nested-classCustomizes Java package names and XML namespace prefixes for XML namespaces.
Replaces the former -Xns-prefix plugin.
- Explicit Java package mapping per XML target namespace URI.
- Optional XML prefix on
@XmlSchemafor that namespace. - Package-scoped multi-
xmlnsprefix mappings with optional Java package regex filter. - Package bindings use
schemaLocation="*"and match bytargetNamespace(CLI schema order independent).
-Xnamespace \
-package-mapping \
-ns=http://example.com/schema \
-package=com.example.schema \
-prefix=ex-Xnamespace \
# Compact package mapping:
-package-mapping=namespaceURI->java.package.name \
-package-mapping=namespaceURI->java.package.name:xmlPrefix \
# Structured package mapping (+ optional xmlns set for that package):
-package-mapping \
-ns=namespaceURI \
-package=java.package.name \
-prefix=xmlPrefix \
-xmlns=http://other.example.com->ot \
-xmlns \
-ns=http://third.example.com \
-prefix=th \
# Prefix-only / multi-xmlns without package mapping (optional package filter):
-ns-prefix \
-package=com\.example\.* \
-xmlns=namespaceURI->xmlPrefix \
-xmlns \
-ns=http://other.example.com \
-prefix=otGenerates Lombok-annotated beans and strips default XJC getters/setters. Replaces hand-crafted -Xannotate + -Xremove-getter + -Xremove-setter pipelines.
- Replaces getter/setter boilerplate with
@Data. - Supports optional
@Builderpattern generation. - Automatically handles
@EqualsAndHashCode(callSuper = true)for non-Objectsubclasses.
-Xlombok-Xlombok \
-anno=@lombok.Data \ # Repeatable; defaults to @Data
-class-name=.*Person \ # Optional class filter
-remove-getter=true \ # Default: true
-remove-setter=true \ # Default: true
-builder # Default: false; adds @Builder + @NoArgsConstructor + @AllArgsConstructorNote: Lombok dependencies must be present on both the XJC classpath (for annotation resolution) and compile classpath.
Adds common Jackson annotations on generated classes. Zero-config replaces the usual
-Xannotate -add-to-class -anno=@JsonInclude(...) recipe for class-level defaults.
- Default
@JsonInclude(JsonInclude.Include.NON_NULL)on generated classes. - Default
@JsonIgnoreProperties(ignoreUnknown = true)for deserialization-friendly DTOs. - Optional class-name filter and
-annoescape hatch for extra class-level annotations. - Built-in annotations are skipped when already present (does not overwrite
-Xannotateor hand-written values).
-Xjackson-Xjackson \
-include=NON_NULL \ # JsonInclude.Include; default NON_NULL; use none to skip
-ignore-unknown=true \ # Default: true; false skips @JsonIgnoreProperties
-class-name=com\.example\.api\..* \ # Optional FQCN regex filter (repeatable)
-anno=@com.fasterxml.jackson.annotation.JsonPropertyOrder({"id","name"})| Option | Default | Description |
|---|---|---|
-include |
NON_NULL |
JsonInclude.Include name, or none to omit @JsonInclude |
-ignore-unknown |
true |
When true, add @JsonIgnoreProperties(ignoreUnknown = true) |
-class-name |
(all classes) | Regex matched against fully-qualified class names (repeatable) |
-anno |
(none) | Extra class-level annotation via annox syntax (repeatable) |
- Class-level only: no field
@JsonPropertyderived from@XmlElement/@XmlAttribute(planned later). - No
@JsonFormat,@JsonPropertyOrder(except via-anno),@JsonRootName, or polymorphic type info. - Does not configure
ObjectMapper.
Note:
jackson-annotationsmust be present on both the XJC classpath (for annotation resolution) and the compile classpath (same pattern as Lombok).
Removes property getter methods generated by XJC (matched against the property model rather than raw method names).
-Xremove-getterRemoves property setter methods generated by XJC to create read-only DTOs and enforce immutability.
-Xremove-setterFlattens multi-element properties (such as @XmlElements choice groups or @XmlElementRefs) into individual single-element fields.
- Splits heterogenous multi-element collection properties into distinct fields per element type.
- Preserves relative field order in generated classes.
-Xflatten-multi-element-propAdds @jakarta.annotation.Generated annotations to generated classes and package-info files.
- Automatically decorates generated classes with standard
@Generatedmarkers. - Supports optional generation date timestamp and custom comments.
-Xgenerated-anno \
-value="JAXB Generator" \
-comments="Auto-generated file" \
-date=trueRenames generated classes, enums, and element classes post-model building with simulated conflict detection.
- Rewrites short class names using regex replacement patterns.
- Safe execution: detects squeezed name collisions and rolls back conflicting renames with build warnings.
-Xrename-class \
-mapping=/(.*)Type/->$1 \
-mapping=Person->CustomPersonRenames multi-element properties produced by XJC to a short plural base name (e.g. items, items2).
- Replaces verbose generated property names (like
restorcontent) with clean plural naming conventions.
-Xrename-multi-element-prop \
-name=elementsAdd the plugin dependency to your project:
<dependency>
<groupId>io.github.rawvoid</groupId>
<artifactId>jaxb-plugins</artifactId>
<version>${latest-version}</version>
</dependency>Configure jaxb-maven-plugin with desired plugin arguments:
<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-maven-plugin</artifactId>
<version>4.0.12</version>
<configuration>
<plugins>
<plugin>
<groupId>io.github.rawvoid</groupId>
<artifactId>jaxb-plugins</artifactId>
<version>${latest-version}</version>
</plugin>
</plugins>
<args>
<arg>-Xjava-time</arg>
<arg>-Xannotate</arg>
<arg>-Xconvert-name</arg>
<arg>-Xnamespace</arg>
</args>
</configuration>
</plugin>xjc -d src -p com.example \
-extension \
-Xjava-time \
-Xannotate \
-Xconvert-name \
-Xnamespace \
schema.xsdxjc schema.xsd \
-d src/main/java \
-p com.example.api \
-extension \
-Xjava-time \
-adapter-package=com.example.adapters \
-type-mapping \
-xsd-type=dateTime \
-target-type=java.time.LocalDateTime \
-Xjackson \
-Xannotate \
-add-to-field \
-anno=@com.fasterxml.jackson.annotation.JsonProperty("value") \
-target=.*\.value \
-Xconvert-name \
-class-name \
-name=(.*)Type \
-to=$1DTO \
-variable-name \
-name=(.*)_ID \
-to=$1Id \
-Xnamespace \
-package-mapping \
-ns=http://api.example.com \
-package=com.example.apixjc schema.xsd \
-d src/main/java \
-p com.example.domain \
-extension \
-Xlombok \
-builder \
-anno=@lombok.Data \
-anno=@lombok.experimental.Accessors(chain = true)xjc schema.xsd \
-d src/main/java \
-p com.example.api \
-extension \
-Xjackson \
-include=NON_NULL \
-ignore-unknown=true \
-class-name=com\.example\.api\..* \
-Xlombok \
-builderDisable built-ins and only apply an extra annotation:
-Xjackson \
-include=none \
-ignore-unknown=false \
-anno=@com.fasterxml.jackson.annotation.JsonPropertyOrder({"id","name"})- JDK 21+
- Apache Maven 3.6+
git clone https://github.com/rawvoid/jaxb-plugins.git
cd jaxb-plugins
mvn clean installContributions are welcome! Please follow these steps:
- Fork the repository.
- Create a feature branch (
git checkout -b feat/new-plugin-feature). - Commit your changes using Conventional Commits format (
git commit -m 'feat(plugin): add feature X'). - Push to your branch (
git push origin feat/new-plugin-feature). - Submit a Pull Request.
Distributed under the Apache License 2.0. See LICENSE for details.