Skip to content

sergeykad/jaxb2-fixed-value

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 

Repository files navigation

JAXB 2 Fixed Value Plugin Build Status

Introduction

This plugin is highly inspired by the JAXB 2 Default Value Plugin, and share a lot of common code. This is an XJC plugin to set fixed values in the XJC generated classes based on the fixed attribute to xs:element. The fixed attribute is documented here. Note that JAXB handles fixed values for xs:attribute natively, so this plugin is not necessary for an attribute fixed.

The plugin is particularly useful while generating Value Objects for a user interface from an XML schema. User interface tags such as the Struts HTML tags use reflection on bean properties to render themselves, so it is often useful to have a set of sensible fixed values set in the Java Beans mapping to the user interface themselves.

The XML schema below describes a generic product and some subclasses, like books, clothes and groceries. It also uses a string to indicate the product group, and it's unit type. Since we already know the product classification and unit type for the subclasses, it will great to enforce the correct value. The XML schema "fixed" attribute is used to achieve this.

        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
        <xs:element name="product" type="Product" />
        
        <xs:complexType name="Product" abstract="true">
            <xs:sequence>
                <xs:element name="price" type="Money"/>
            </xs:sequence>
        </xs:complexType>
        
        <xs:complexType name="Book">
            <xs:complexContent>
                <xs:extension base="Product">
                    <xs:sequence>
                        <xs:element name="unit" type="UnitOfMeasurement" fixed="unit" />
                        <xs:element name="group" type="ProductGroup" fixed="Books"/>
                        <xs:element name="isbn" type="xs:string" />
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
                
        </xs:schema>

The XJC generated code for the schema (comments removed for brevity):

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Book", propOrder = {
        "unit",
        "group",
        "isbn"
    })
    public class Book
        extends Product
    {
    
        @XmlElement(required = true)
        protected UnitOfMeasurement unit;
        @XmlElement(required = true)
        protected ProductGroup group;
        @XmlElement(required = true)
        protected String isbn;
    
        public UnitOfMeasurement getUnit() {
            return unit;
        }
    
        public void setUnit(UnitOfMeasurement value) {
            this.unit = value;
        }
    
        public ProductGroup getGroup() {
            return group;
        }
    
        public void setGroup(ProductGroup value) {
            this.group = value;
        }
    
        public String getIsbn() {
            return isbn;
        }
    
        public void setIsbn(String value) {
            this.isbn = value;
        }
    
    }

Note that the group property's does not map to the variable declaration - which, being a ProductGroup, defaults to null. Wouldn't it be nice to have the declaration reflect this as well? Enter the fixed value plugin. Here's the declaration section of Book.java with the fixed value plugin enabled:

    @XmlElement(required = true)
    protected UnitOfMeasurement unit = UnitOfMeasurement.UNIT;
    @XmlElement(required = true)
    protected ProductGroup group = ProductGroup.BOOKS;
    @XmlElement(required = true)
    protected String isbn;

Usage

For information about how to use XJC plugins in general, see here.

This is a sample build.xml that shows how the plugin is used. It's used to build the sample classes in the samples/ directory:

    <?xml version="1.0" ?>
    
    <project name="samples" default="compile" basedir=".">
      <description>Builds the default value plugin sample</description>
    
      <property file="../build.properties"/>
    
      <!-- Remove an earlier build by deleting the "build" directory -->
      <target name="clean">
        <delete dir="gen-src"/>
      </target>
    
      <!-- Compile classes generated by XJC compiler -->
      <target name="compile" depends="gen-src">
        <javac compiler="javac1.5" srcdir="gen-src/generated" includes="*.java">
          <classpath>
    	<fileset dir="${jaxb.lib.dir}" includes="*.jar"/>
          </classpath>
        </javac>
      </target>
    
      <!-- Use XJC task to compile schema to Java code -->
      <target name="gen-src">
        <mkdir dir="gen-src"/>
        <xjc removeOldOutput="yes" schema="sample.xsd" target="gen-src">
          <arg value="-extension"/>
          <arg value="-Xfixed-value"/>
        </xjc>
      </target>
      
      <!-- Defines XJC task -->
      <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
        <classpath>
          <fileset dir="${jaxb.lib.dir}" includes="*.jar"/>
          <pathelement location="../build/jaxb2-fixed-value-1.2.jar"/>
        </classpath>
      </taskdef>
    
    </project>

A sample for using this plugin with Maven can be found on the source code (see this pom.xml). Here a small snippet:

    <build>
          <plugins>
              <plugin>
                  <groupId>org.jvnet.jaxb2.maven2</groupId>
                  <artifactId>maven-jaxb2-plugin</artifactId>
                  <executions>
                      <execution>
                          <goals>
                              <goal>generate</goal>
                          </goals>
                      </execution>
                  </executions>
                  <configuration>
                      <args>
                          <arg>-Xfixed-value</arg>
                      </args>
                      <plugins>
                          <plugin>
                              <groupId>com.github.fbdo</groupId>
                              <artifactId>jaxb2-fixed-value</artifactId>
                              <version>1.2</version>
                          </plugin>
                      </plugins>
                  </configuration>
              </plugin>
              <plugin>
                  <inherited>true</inherited>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <configuration>
                      <source>1.5</source>
                      <target>1.5</target>
                  </configuration>
              </plugin>
          </plugins>
    </build>

Fixed values for attributes

The xjc compiler is completely capable of generating classes with pre-populated fields if in this case the field map to an attribute. In this case, the only thing needed is a in place or a global binding with the directive, for example:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
               jaxb:version="2.0">
  <jaxb:bindings schemaLocation="sample.xsd">
    <jaxb:globalBindings fixedAttributeAsConstantProperty="true" />
  </jaxb:bindings>
</jaxb:bindings>

I added a small sample in the integration tests, take a look in the src/it/fixedvalue-it/src/main/resources/binding.xjb, and the generated Product.java.

About

JAXB2 Fixed Value Plugin

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 94.4%
  • Groovy 5.6%