views:

942

answers:

2

If I am using JAXB as part of Metro Web Services under Glassfish v2, how do tell JAXB to add:

 <xsd:any/> and <xsd:anyAttribute/>

tags to my generated complex types so that if I make changes in the future to add elements or attributes to my response objects then my current clients won't break.

JAXB documentation seems somewhat lacking.

A: 

Just use the java.lang.Object type. JAXB by default will then generate xsd:any. I have successfully returned a org.w3c.dom.Node instance from a web service method with java.lang.Object as the return type. I imaging there will be something similar for xsd:anyAttribute - perhaps using Object return type and the XmlAttribute JAXB annotation?

Addition: The following annotations look like they achieve your goals. Both are part of the JAXB 2.0 spec.

@XmlAnyAttribute @XmlAnyElement

kipz
Thanks for the answer. I was hoping that that there would be an annotation or system wide setting that would automatically add the tags in. It seems that maybe that isn't the case. I think I might be running into the fact that any and anyAttribute tags are frowned upon within Sun.
TiGz
Do you mean that you want xsd:any/anyAttribute tags added to the end of every type by default? JAXB specifies default behavior, so to modify those defaults would be to break the standard. Are you looking at trying to make extensible web services? I would consider versioning instead.
kipz
I didn't spot those 2 annotations because I was trying to add them at the Class level (rather than the field level), which isn't supported, and therefore my IDE, correctly, wasn't displaying them. Cheers for the help Jimbo ;-P
TiGz
A: 

Ok this is how I've made it work:

import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;


public class SchemaExtensible
{
    @XmlAnyElement(lax=true)
    private List<Element> otherElements;

    @XmlAnyAttribute
    private Map<QName,Object> otherAttributes;
}

It's not ideal because now I have to extend this class for every response class that I want to be extensible (and in some cases this stops me from extending from a request class instead). If these 2 method & field level annotations could be enhanced to allow them to be added at the class level then they could simply be saying "add the appropriate tags to the schema and just throw away the data if encountered" which would be sweet.

Any way the schema fragment ends up looking like this:

<xs:complexType name="SchemaExtensible">
  <xs:sequence>
    <xs:any processContents="lax" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:anyAttribute namespace="##other" processContents="skip"/>
 </xs:complexType>

For me, allowing this extensibility for response objects only is preferable to web service versioning as it allows you to evolve the schema bit by bit, if you so desire, without the headache of managing many different versions, and without the worry that any existing clients will break if you add a single new attribute or element to a response object.

TiGz