The general idea is same as described by Kohsuke Kawaguchi in a post of 2007, but his POM is broken with the current stage of the Maven repositories. In addition, there is a tweak with the PropertyListener customization.
So here is a little example schema:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/person/" targetNamespace="http://www.example.org/person/"> <complexType name="Person"> <sequence> <element name="firstName" type="string"></element> <element name="lastName" type="string"></element> <element name="address" type="tns:Address"></element> </sequence> </complexType> <complexType name="Address"> <sequence> <element name="street" type="string"></element> <element name="houseNumber" type="string"></element> <element name="city" type="string"></element> <element name="postalCode" type="string"></element> <element name="country" type="string"></element> </sequence> </complexType> </schema>
We use the following file bindings.xjb to customize the Java classes generated by xjc. We make all classes serializable and include support for PropertyChangeListeners.
<?xml version="1.0" encoding ="UTF-8"?> <jaxb:bindings schemaLocation="person.xsd" version="2.1" xmlns:li="http://jaxb.dev.java.net/plugin/listener-injector" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <jaxb:bindings node="/xs:schema"> <jaxb:globalBindings> <jaxb:serializable uid="1" /> </jaxb:globalBindings> <li:listener>java.beans.PropertyChangeListener</li:listener> </jaxb:bindings> </jaxb:bindings>
The following POM takes care of the code generation:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jaxb-properties</groupId> <artifactId>jaxb-properties</artifactId> <version>0.0.1-SNAPSHOT</version> <name>JAXB PropertyListener Demo</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <version>0.7.3</version> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <extension>true</extension> <generatePackage>com.example.jaxb</generatePackage> <schemaIncludes> <schemaInclude>person.xsd</schemaInclude> </schemaIncludes> <bindingIncludes> <bindingInclude>bindings.xjb</bindingInclude> </bindingIncludes> <args> <arg>-Xinject-listener-code</arg> </args> </configuration> <dependencies> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> <version>2.1.13</version> </dependency> <dependency> <groupId>org.jvnet.jaxb2-commons</groupId> <artifactId>property-listener-injector</artifactId> <version>1.1-SNAPSHOT</version> <exclusions> <exclusion> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </plugin> </plugins> </build> </project>
You do need to use the 1.1-SNAPSHOT version of the property-listener-injector, as the 1.0 release only supports VetoableChangeListeners and not the PropertyChangeListeners we want to use. The <li:listener> element in the bindings file is used to define the listener class.
It is important to exclude the jaxb-xjc dependency from the property-listener-injector, or else it will try to download an non-existing snapshot version. Looks like something is broken in the java.net repository, but then again, working with snapshot releases is always dangerous....