Customizing Bindings With Annotations In XSD
Java/XML bindings can be in-lined in the XSD schema. Binding customizations appear inside <xsd:appInfo> element which is a child of <xsd:annotation>. The following are the JBossXB-specific elements used to customize bindings:
jbxb:schemaBindings
jbxb:package
jbxb:ignoreUnresolvedFieldOrClass
jbxb:replacePropertyRefs
jbxb:class
jbxb:property
jbxb:value
jbxb:characters
jbxb:addMethod
jbxb:putMethod
jbxb:mapEntry
jbxb:mapEntryKey
jbxb:mapEntryValue
jbxb:skip
WARN: these elements are under development and their definitions are not stable yet.
Schema Diagram
jbxb:schemaBindings
This element defines default bindings for the schema, is allowed only as a child of the xsd:schema element and can appear only ones for a given schema. jbxb:schema element can have only one child (but there will be more in the future) - jbxb:package.
jbxb:package
Defines the default package for the schema which is used for searching classes when unmarshalling elements of complex types. If jbxb:package is not present, schema's namespace URI will be used as the base to generate the default package name for the schema (the mapping is defined in JAXB2.0 spec D.5.1 Mapping from a Namespace URI).
For example:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:jboss:bean-deployer" xmlns="urn:jboss:bean-deployer" xmlns:jbxb="http://www.jboss.org/xml/ns/jbxb" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0"> <xsd:annotation> <xsd:appinfo> <jbxb:schema> <jbxb:package name="org.jboss.test.xml.pojoserver.metadata"></jbxb:package> </jbxb:schema> </xsd:appinfo> </xsd:annotation>
jbxb:ignoreUnresolvedFieldOrClass
The ignoreUnresolvedFieldOrClass specifies the behavior the parser chooses when a field is not found in the parent class for a child value, or when an element does not have any class assignement. If false, an exception will be thrown when either situation is encountered. If true, the missing mapping is ignored and the parse continues.
jbxb:replacePropertyRefs
The replacePropertyRefs flag indicates whether the text content of values has $ system property references replaced during parsing. The default is true.
jbxb:class
Binds XML element or complex type to a Java class which is specified as a value of attribute 'impl'.
If jbxb:class is used inside complex type definition, all elements of this complex type will be unmarshalled into the specified Java type unless there is overriding jbxb:class in an element declaration
Example:
<xsd:complexType name="deploymentType"> <xsd:annotation> <xsd:appinfo> <jbxb:class impl="org.jboss.test.xml.pojoserver.deployment.AbstractKernelDeployment"></jbxb:class> </xsd:appinfo> </xsd:annotation> <xsd:sequence> ... </xsd:sequence> </xsd:complexType> <xsd:element name="list" type="listType"> <xsd:annotation> <xsd:appinfo> <jbxb:class impl="org.jboss.test.xml.pojoserver.metadata.AbstractListMetaData"></jbxb:class> </xsd:appinfo> </xsd:annotation> </xsd:element>
If jbxb:class is not specified for a complex type then class name is resolved based on the complex type name using "D.2 The Name to Identifier Mapping Algorithm" defined in JAXB2.0 spec.
jbxb:property
Binds an element to property/field in a class. This element can appear inside an element definition or inside jbxb:characters.
Example:
<xsd:element name="list" type="listType"> <xsd:annotation> <xsd:appinfo> <jbxb:property name="value"></jbxb:property> <jbxb:class impl="org.jboss.test.xml.pojoserver.metadata.AbstractListMetaData"></jbxb:class> </xsd:appinfo> </xsd:annotation> </xsd:element>
If jbxb:property is not specified for an element, the property name is resolved based on the element's name using "D.2 The Name to Identifier Mapping Algorithm" defined in JAXB2.0 spec.
jbxb:value
Binds text value (attribute value or text content) to a Java value. There are two attributes: unmarshalMethod which specfies a public static method that is used to unmarshal text values and marshalMethod which also a public static method that is used to marshal Java values. Both methods are defined as concatenation of fully-qualified class name, '.' and the method name.
unmarshalMethod must have two parameters: the first one of type java.lang.String and the second one is of type javax.xml.namespace.NamespaceContext.
marshalMethod must also have two parameters: the first one is of type java.lang.Object and the second one is of type javax.xml.namespace.NamespaceContext.
Example:
<xsd:simpleType name="kernelControllerState"> <xsd:annotation> <xsd:appinfo> <jbxb:value unmarshalMethod="org.jboss.test.xml.pojoserver.metadata.KernelControllerStateDatatypeConverter.unmarshal"></jbxb:value> </xsd:appinfo> </xsd:annotation> <xsd:restriction base="xsd:string"> <xsd:enumeration value="Not Installed" ></xsd:enumeration> <xsd:enumeration value="Described" ></xsd:enumeration> <xsd:enumeration value="Instantiated" ></xsd:enumeration> <xsd:enumeration value="Configured" ></xsd:enumeration> <xsd:enumeration value="Lifecycle" ></xsd:enumeration> <xsd:enumeration value="Started" ></xsd:enumeration> <xsd:enumeration value="Installed" ></xsd:enumeration> </xsd:restriction> </xsd:simpleType> public class KernelControllerStateDatatypeConverter { public static KernelControllerState unmarshal(String text, NamespaceContext nsCtx) { KernelControllerState state; if(KernelControllerState.NOT_INSTALLED.getStateString().equals(text)) { state = KernelControllerState.NOT_INSTALLED; } else ...
jbxb:value can appear inside simple type definitions, attribute declarations and jbxb:characters. If jbxb:value is not used, text values are unmarshalled using default simple types to Java bindings defained in JAXB2.0 spec. If simple type is a user-defined, by default it is not unmarshalled and passed as a string.
jbxb:characters
Binds text content of complex types. This element is just a container for jbxb:value, jbxb:property, jbxb:mapEntryKey, jbxb:mapEntryValue elements, all of them are optional. This element can only appear inside complex type definitions.
Example:
<xsd:complexType name="namedValueType" mixed="true"> <xsd:annotation> <xsd:appinfo> <jbxb:class impl="org.jboss.test.xml.pojoserver.metadata.AbstractPropertyMetaData"></jbxb:class> <jbxb:characters> <jbxb:property name="value"></jbxb:property> <jbxb:value unmarshalMethod="org.jboss.test.xml.pojoserver.metadata.DataTypeConverter.unmarshalStringValue"></jbxb:value> </jbxb:characters> </xsd:appinfo> </xsd:annotation> <xsd:complexContent> ... </xsd:complexContent> </xsd:complexType>
jbxb:addMethod
Specified on an element that should be added to its parent not with a setter (is not a property) and not with a field but with a custom method. The attributes are:
name - the name of the method. There is not default value for this attribute. It must be set.
valueType - the type of the argument. If not present, the default is java.lang.Object. And there is a special value 'child' which means the type of the child should be used as the argument's type.
Example:
<xs:element name="user"> <xsd:annotation> <xsd:appinfo> <jbxb:class impl="org.jboss.test.xml.mbeanserver.Users$User"></jbxb:class> <jbxb:addMethod name="addUser" valueType="child"></jbxb:addMethod> </xsd:appinfo> </xsd:annotation> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" ref="ur:role"></xs:element> </xs:sequence> <xs:attribute name="name" use="required" type="xs:NCName"></xs:attribute> <xs:attribute name="password" use="required" type="xs:NCName"></xs:attribute> </xs:complexType> </xs:element>
jbxb:putMethod
Specified on an element that is added to its parent as a map entry, named property, etc. The attributes are:
name - the method name in the parent object's class that adds child to to its parent object. If not present, the default is 'put'.
keyType - fully qualified type name of the key-parameter to the put-method. If not present, the default is java.lang.Object.
valueType - fully qualified type name of the value-parameter to the put-method. If not present, the default is java.lang.Object.
Note: putMethod is optional if the parent object is an instance of java.util.Map.
jbxb:mapEntry
Specified on an element or a complex type definition that is bound to a map entry. jbxb:class and jbxb:mapEntry are mutually exclusive, meanning an element or a complex type cannot be annotated with both jbxb:class and jbxb:mapEntry at the same time. Otherwise, it will result in an exception during binding.
mapEntry has following attributes:
impl - an optional element that specifies a fully qualified name of the class that will represent map entry. If absent, a special class will be used by the framework internally.
getKeyMethod - an optional element that specifies the name of the method that is used to get the key out of the object that represents a map entry. If absent, the default value is "getKey".
setKeyMethod - an optional element that specifies the name of the method that is used to set the key value on the object that represents a map entry. If absent, the default value is "setKey".
getValueMethod - an optional element that specifies the name of the method that is used to get the value out of the object that represents a map entry. If absent and impl attribute is absent too, the default value is "getValue". If absent and impl attribute is present, the value will be the object that reprents the map entry itself
setValueMethod - an optional element that specifies the name of the method that is used to set the value on the object that represents a map entry. If absent, the default value is "setValue".
valueType - an optional element that specifies the type of the map entry value. Used when map entry value should be a parent for element/type's content.
nonNullValue - can be true or false. Default value is false. If true, when a map entry is created, a non-null map entry value will also be created and set on the map entry. Otherwise, a map entry object is created with null value and the value will be created and set later when it is actually parsed. This attribute is used in combination with valueType.
jbxb:mapEntryKey
This element is a marker element that has no attributes. It is specified on an element, attribute or inside jbxb:characters to specify that the element, attribute or characters should be used as the key in map entry.
jbxb:mapEntryValue
This element is a marker element that has no attributes. It is specified on an element, attribute or inside jbxb:characters to specify that the element, attribute or characters should be used as the value in map entry.
Example:
<xsd:element name="entry1"> <xsd:annotation> <xsd:appinfo> <putMethod></putMethod> </xsd:appinfo> </xsd:annotation> <xsd:complexType> <xsd:annotation> <xsd:appinfo> <jbxb:mapEntry></jbxb:mapEntry> </xsd:appinfo> </xsd:annotation> <xsd:sequence> <xsd:element name="key1" type="xsd:string"> <xsd:annotation> <xsd:appinfo> <jbxb:mapEntryKey></jbxb:mapEntryKey> </xsd:appinfo> </xsd:annotation> </xsd:element> <xsd:element name="value1" type="xsd:string"> <xsd:annotation> <xsd:appinfo> <jbxb:mapEntryValue></jbxb:mapEntryValue> </xsd:appinfo> </xsd:annotation> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element>
jbxb:skip
This element can be used on an element declaration or a complex type definition. Unmarshaller will not try to create new objects for elements (or elements of complex types) that are annotated with jbxb:skip. Instead, the object that was created for the parent of such elements will be propagated and values of attributes, character contents and child elements of such elements will be set on their parent's object.
Example
<xs:element name="authentication"> <xsd:annotation> <xsd:appinfo> <jbxb:skip></jbxb:skip> </xsd:appinfo> </xsd:annotation> <xs:complexType> <xs:sequence> <xs:element ref="jaas:login-module"></xs:element> </xs:sequence> </xs:complexType> </xs:element>
In the example above, login-modules will be added to the parent of authentication element.
NOTE: maybe it also makes sense to add an attribute to jbxb:skip such as attributes/elementsInclusive to ignore also attributes/elements of the element's type.
Comments