JAXB Attribute Initialization Plugin

XJC plugin that adds initializes attribute values on JAXB classes that are defined with a default value for the attribute. Surprisingly, this isn't the default behavior of the XJC plugin.

License

License

GroupId

GroupId

com.massfords
ArtifactId

ArtifactId

jaxb-attr-init
Last Version

Last Version

0.1
Release Date

Release Date

Type

Type

jar
Description

Description

JAXB Attribute Initialization Plugin
XJC plugin that adds initializes attribute values on JAXB classes that are defined with a default value for the attribute. Surprisingly, this isn't the default behavior of the XJC plugin.
Project URL

Project URL

https://github.com/massfords/jaxb-attr-init
Source Code Management

Source Code Management

https://github.com/massfords/jaxb-attr-init

Download jaxb-attr-init

How to add to project

<!-- https://jarcasting.com/artifacts/com.massfords/jaxb-attr-init/ -->
<dependency>
    <groupId>com.massfords</groupId>
    <artifactId>jaxb-attr-init</artifactId>
    <version>0.1</version>
</dependency>
// https://jarcasting.com/artifacts/com.massfords/jaxb-attr-init/
implementation 'com.massfords:jaxb-attr-init:0.1'
// https://jarcasting.com/artifacts/com.massfords/jaxb-attr-init/
implementation ("com.massfords:jaxb-attr-init:0.1")
'com.massfords:jaxb-attr-init:jar:0.1'
<dependency org="com.massfords" name="jaxb-attr-init" rev="0.1">
  <artifact name="jaxb-attr-init" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.massfords', module='jaxb-attr-init', version='0.1')
)
libraryDependencies += "com.massfords" % "jaxb-attr-init" % "0.1"
[com.massfords/jaxb-attr-init "0.1"]

Dependencies

compile (1)

Group / Artifact Type Version
org.jvnet.jaxb2_commons : jaxb2-basics-tools jar 0.9.4

provided (2)

Group / Artifact Type Version
org.glassfish.jaxb : codemodel jar 2.2.11
org.glassfish.jaxb : jaxb-xjc jar 2.2.11

test (5)

Group / Artifact Type Version
org.apache.maven : maven-artifact jar 2.2.1
org.jvnet.jaxb2.maven2 : maven-jaxb2-plugin-testing jar 0.12.3
org.jvnet.jaxb2_commons : jaxb2-basics-annotate jar 1.0.1
commons-io : commons-io jar 1.4
junit : junit jar 4.11

Project Modules

There are no modules declared in this project.

Attribute Initializer Plugin

Fast and dirty JAXB plugin to add an attribute initializer to attributes that have a default value but only get the default behavior provided when you call the getter. This may be fine where you have JAXB or Schema aware parties on both ends of the wire but in cases where you're going from JAXB to JSON it's nice to provide all of the default values since the recipient may be worlds away from having access to a Schema and would instead prefer to be told what the default values for fields are.

I had assumed that this was a solved problem but here's what I found:

  • XJC behavior for default attributes is to provide the default value through the getter. This is fine but if you're marshalling via the XmlFieldAccessor then this doesn't help.
  • There's a JAXB Default Value plugin but this focuses on elements since attributes are supposedly covered.

Example Use Case

Consider the following schema and snippet:

<xs:complexType name="POP3Host">
    <xs:sequence>
        <xs:element name="foo" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="Port" type="xs:int" use="optional" default="110"/>
</xs:complexType>

// default generated getter
    public int getPort() {
        if (port == null) {
            return  110;
        } else {
            return port;
        }
    }


POP3Host host = new POP3Host();
int port = host.getPort();
marshalToJSON( host );

In the above snippet, the caller explicitly invokes the getter on the POP3Host and with the default code generated from the XJC plugin, the port field will be seen to be null and then initialized to 110 before getting returned.

However, what if the caller never invokes the getPort() method?

POP3Host host = new POP3Host();
marshalToJSON( host );

The recipient of this payload will get a structure that doesn't have a value for the port field. If they are using JAXB with the same schema then this isn't a problem. However, if they're not aware of the schema, then they won't know what the default value is.

One common scenario for the above would be a presentation layer in JSON. Perhaps there's some approach here where a JSON Schema could be derived from the XSD but having the generated code initialize with the default value is much easier.

Sample Schema

See simple.xsd in src/test/resources for an example of the annotation in play along with a test case that runs the plugin. So far there are no assertions in the test case but the generated code looks good. Again, assertions will come later if there's a second commit on this project ;)

<xs:complexType name="POP3Host">
    <xs:sequence>
        <xs:element name="foo" type="xs:string"/>
    </xs:sequence>
    <xs:attribute name="Port" type="xs:int" use="optional" default="110">
        <xs:annotation>
            <xs:appinfo>
                <mf:attrinit/>
            </xs:appinfo>
        </xs:annotation>
    </xs:attribute>
</xs:complexType>

The application fo the mf:attrinit above triggers the plugin to generate an initializer for the field.

Versions

Version
0.1