JAXB 2.1 Propsoed Change List ============================= Tue Oct 17 14:39:55 PDT 2006 Proposed Change: EaseOfUseAPI221 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=221 Background ---------- Today, it just takes too many lines to do a simple stuff with JAXB. One typical example is the following code for reading XML from a file: File in = new File("FamilyData.xml"); JAXBContext jc = JAXBContext.newInstance("kgh.geneology.xml"); Unmarshaller u = jc.createUnmarshaller(); JAXBElement junk = (JAXBElement)u.unmarshal(fin); DataFile df = (DataFile) junk.getValue(); (and if you count exception handling, add at least 4 lines for that.) Think of the DataFile class as the top-level class generated by a schema compiler. We need convenience methods that focus on typical simple use case. Proposed Solution ----------------- Define the JAXB class and the unmarshal/marshal methods on them. Those methods generally look like this: public static T unmarshal( SOMETHING xml, Class type ); public static void marshal( Object jaxbObject, SOMETHING xml ); These methods do not throw checked exceptions. Spec Changes ------------ None, except in the API javadoc and source files. See the javadoc for more details about this change. Proposed Change: ExternalCustomization144 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=144 Background ---------- The most common customization that people specifies is the globalBindings customization, and probably the schemaBindings customization. But the current syntax for doing this is somewhat verbose. For example, to specify a global customization, you need to do this: The @schemaLocation and @node is pointless given that this is a globalBindings. A similar problem applies to schemaBindings, where @node is pointless. This change rectifies this situation by not requiring those attributes for globalBindings and schemaBindings. The user will be able to write the same customization as follows: This also allows those customizations to be applied to other schemas without any changes, as customization files no longer hard-code any path names. Spec Changes ------------ Change section 7.1.3 External Binding Declaration to - In the example, show that @schemaLocation and @node are optional - Insert the following sentence before the paragraph that follows the exmple: "The schemaLocation attribute is optional for specifying , and The node attribute is optional for specifying ." Change section E.2 - A sentence in 3.b will be "Then the target element will be the document element of the schema document identified by the absolutized URI. If there's no such schema document in the current input, it is an error." - A sentence at the end of 3 will be "We define the target element of a binding declaration to be the target element of its parent element. The only exception to this is binding declaraiton, in which case the target element will be the document element of any one of the schema documents being compiled (such choice is undeterministic, but the semantics of is not affected by this choice, so the end result will be the same.) It is an error if ..." Proposed Change: MiscBugFixes222 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=222 Background ---------- This is an umbrella issue to fix miscellaneous typos and corrections in the spec Section 3.5.2.1 Change the first sentence: The detection of complex schema constraint violations has been redesigned to have a JAXB 2.0 implementation delegate to the validation API in JAXP 1.3. This is to address the feedback from the TCK team. Section 7.6.1.1 Remove the following constraints: If one source schema includes (via the include mechanism specified by XSD PART 1) a second source schema, then the declaration must be declared in the first including source schema. This is based on the implementation feedback. This restriction doesn't seem to be buying us anything. Proposed Change: NoJAXBElementCustomization220 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=220 Background ---------- We discovered that the XML serialization technology in Microsoft .NET often generates types like the following: The use of minOccurs="0", when combined with nillable="true", causes JAXB to generate a property that uses JAXBElement: class Foo { JAXBElement name; } This was done so that we can correctly round-trip the absence of and as distinctive states, but when users use JAXB to consume .NET services, this causes JAXBElement to be everywhere, and significantly reduce the usability. A similar issue, however on much smaller scale, can be seen with Java-only use of JAXB. Some schema authors define this kind of grammar, yet often application developers find such distinction useless. So it is desirable to define a customization to allow users to eliminate JAXBElements. Because of the compatibility reasons, we cannot make such mode default. Proposed Solution ----------------- Define one more attribute inside as follows: This @generateElementProperty is a three-state variable. It can be true, false, or absent (The default is absent.) When false, nillable and minOccurs=0 property generates a property that doesn't use JAXBElement, as if . If true, a property is always generated as a JAXBElement property, as if was specified. If absent, the current behavior is retained. The same attribute will be defined on customization. The scoping rule applies between them. The non-absent generateElementProperty customization on would override the generateElementProperty customization on The 'true' value at the globalBindings level is almost useless, but it improves the symmetry of the two cases, and simplifies the explanation. This customization has been successfully implemented in the JAXB RI, and we received feedback that it helped our users. Spec Changes ------------ Section 7.5.1 "Usage": Add the following line into the synopsis: [ generateElementProperty = "true" | "false" | "1" | "0" ] Add the following bullet item to the list: - generateElementProperty if specified, controls the generation of JAXBElement property. The value must be one of "true", "false", "1", or "0". The default is absence of the value. Add Section 7.5.7 "@generateElementProperty" Some schemas use both minOccurs="0" on element as well as nillable="true", causing the generation of JAXBElement. This customization lets you control this behavior. This attribute may take two values: true: Always generate properties to use JAXBElement, unless overriden by on individual property. false: When generating properties from , generate a property not to use JAXBElement, as if the element declaration were just , unless overriden by on individual property. It is an error to specify this customization, when the property is required to be JAXBElement (such as when a property contains multiple elements with different names but of the same type.) Section 7.8.1 "Usage" Add the following line into the synopsis: [ generateElementProperty = "true" | "false" | "1" | "0" ] Add the following bullet item to the list: - generateElementProperty if specified, controls the generation of JAXBElement property. The value must be one of "true", "false", "1", or "0". The default is absence of the value. It is an error for this attribute to be present if this customization is attached to local or global attribute declarations. This customization affects the binding as follows: true: Always generate properties to use JAXBElement. false: When generating properties from , generate a property not to use JAXBElement, as if the element declaration were just . It is an error to specify this customization, when the property is required to be JAXBElement (such as when a property contains multiple elements with different names but of the same type.) Proposed Change: OptimizePointlessChoice219 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=219 Background ---------- The current schema generation rules in the specification occasionally require a generation of pointless elements that only have one child element. This makes the output unnecessarily ugly, and shall be removed. Spec Changes ------------ Section 8.9.2.2 "Mapping" Table 8-15 will be: {term} If Table 8-16 {particles} row results in single particle, then that single particle. Otherwise mapped as specified in Table 8-16. Section 8.9.3.2 "Mapping" Table 8-19 will be: {term} If Table 8-20 {particles} row results in single particle, then that single particle. Otherwise mapped as specified in Table 8-20. Section 8.9.4.2 "Mapping" Table 8-21 will be: {term} If Table 8-22 {particles} row results in a single particle, then that single particle. Otherwise mapped as specified in Table 8-22. Proposed Change: SeparateCompilation38 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=38 Background ---------- It is a fairly common for a schema to be developed as a 'module', to be used by other schemas. The idea is for the party X to develop a 'core' schema, then the party Y will develop additional schema on top of the core. Examples of this can be seen in many places, including W3C XML Schema itself, WSDL, WS-Addressing, SOAP, UBL, ... When people develop corresponding Java libraries for these schemas, there's often a need to compile the core schema and the additional schema separately. That is, the party X generates (or even hand-write) Java classes for the core schema, then the party Y compiles the additional schema, in such a way that the generated classes refer to the classes generated earlier (or hand-written) by X. A similar problem applies to schema generation. Sometimes your Java classes refer to other classes, which already have pre-generated (or hand-written) corresponding schemas somewhere. In this case, it's desirable to simply refer to that schema, as opposed to generate definitions. It is desirable for JAXB to support this notion. This feature has been repeatedly asked from our users, and the JAX-WS 2.1 is planning to rely on this feature, too. Proposed Solution ----------------- On the schema compiler side, we'll expand the customization so that the references to the existing classes can be specified. When such customizations are seen, a schema compiler must not generate a class, and instead simply refer to the referenced classes. So for example, given the following schema: a schema compiler will simply assume that there's already such a class called "org.acme.foo.Foo", and will not generate another class. All the generated classes that reference this type will refer to "org.acme.foo.Foo". The same annotation can be applied on simple types. We'll also define the map attribute on customization, to disallow the code generation for the entire namespace (unless otherwise overriden by ). While we can conceptually define such attributes on smaller units (such as on customization), given that a common use case of separate compilation happens at the namespace level, it's unlikely to be useful. This allows a library to "hide" certain definitions that are globally defined in XSD. (In schema, it's a common practice to define almost everything as global types, which restricts Java library designer's ability to design classes. With this, one could write a schema like the following: The schemaBindings statement prevents any class generation from this package, reference to the complex type "foo" will become a reference to "org.acme.foo.Foo" type, and reference to the complex type "bar" will be an error. On the schema generator side, we'll add a new 'location' annotation element to @XmlSchema annotation. When this attribute is present, it points to the URI of the existing schema document that defines the namespace. For example, @XmlSchema(namespace="foo") package foo; @XmlType class Foo { @XmlElement Bar zot; } @XmlSchema(namespace="bar",location="http://example.org/test.xsd") package bar; @XmlType class Bar { ... } Spec Changes ------------ Section 6.2.2.2 "Bind to a JAXB mapped class" Change the 2nd paragraph as follows: The binding of a named simple type definition to a Java value class is based on the abstract model properties in Section F.1.1, "Simple Type Definition Schema Component," on page 347. The Java value class must be defined as specified here, unless the ref attribute is specified on the declaration, in which case the schema compiler will simply assume that the nominated class is already bound to this simple type. Section 6.3.2 "Java value class": Change the first paragraph: The binding of a complex type definition to a Java value class is based on the abstract model properties in Section F.1.3, "Complex Type Definition Schema Component," on page 348. The Java value class must be defined as specified here, unless the ref attribute is specified on the declaration, in which case the schema compiler will simply assume that the nominated class is already bound to this complex type. Section 7.6.1 Usage: Add the following to the synopsis: Add the following paragraph after the synopsis: The following customizations are defined in the schema scope: * map : if specified, prevents the classes from being generated from this schema. When the value is "0" or "false", then no class/interface/enum will be generated from this package. map defaults to true. The semantics of the customization values, if not specified above, are specified when they are actually used in the binding declarations. Section 7.7.1 Usage: Add the following to the synopsis and the bullet list that follows: [ref="className"] * ref if specified, is the name of the value class that is provided outside the schema compiler. This customization causes a schema compiler to refer to this external enum, as opposed to generate a definition. It must include the complete package name. This attribute is mutually exclusive with the className attribute and the implClass attribute. Section 7.10.1 Usage: Add the following to the synopsis and the bullet list that follows: [ref="className"] * ref if specified, is the name of the enum class that is provided outside the schema compiler. This customization causes a schema compiler to refer to this external enum, as opposed to generate a definition. It must include the complete package name. This attribute is mutually exclusive with the className attribute and the map attribute. Section 7.10.1 Usage: Add the following to the synopsis and the bullet list that follows: [ref="className"] * ref if specified, is the name of the enum class that is provided outside the schema compiler. This customization causes a schema compiler to refer to this external enum, as opposed to generate a definition. It must include the complete package name. This attribute is mutually exclusive with the className attribute and the map attribute. Section 8.6.1.1 will be: @Retention(RUNTIME) @Target({PACKAGE}) public @interface XmlSchema { XmlNs[] xmlns() default {}; String namespace() default ""; String location() default ""; XmlNsForm elementFormDefault() default XmlNsForm.UNSET; XmlNsForm attributeFormDefault() default XmlNsForm.UNSET; } Section 8.6.1.2 will be: If location() is "", a package annotated with @XmlSchema must be mapped as specified in Table 8-3, "Mapping: Package to XML target namespace," on page 234. Otherwise a package will not produce any schema document. Add another design note in 8.6.1.2: Note: When location() is present, this specification only guarantees that no schema is generated for the namespace. Implementations should generate statements accordingly with the schemaLocation attribute pointing to the value of the @XmlSchema.location(), but statements do not have corresponding schema components, and they are anyway just hints, so it's not possible to enforce such constraints. Implementations are also allowed to use values other than @XmlSchema.location() in for example so that the reference points to a copy of the resource that's preferrable for the user. Proposed Change: XmlElementWrapperRequired192 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=192 Background ---------- Currently there is no way to enforce the presence of an @XmlElementWrapper, the wrapper is always generated with minOccurs=0. So let's add @XmlElementWrapper.required(). This defaults to false to be backward compatible, and when true, it will cause the wrapper element to be generated minOccurs=1. Spec Changes ------------ Modify Section 8.9.5.1 and add the required() element. @Retention(RUNTIME) @Target({FIELD, METHOD} public @interface XmlElementWrapper { String name() default "##default" ; // name for XML element String namespace() default "##default" ; boolean nillable() default false; boolean required() default false; } Modify Section 8.9.5.2 Table 8-23 first row as follows: {minOccurs} if @XmlElementWrapper.nillable() is true or @XmlElementWrapper.required() is true, then 1; otherwise 0 Proposed Change: XmlSeeAlso201 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=201 Background ---------- For JAXB to operate, it needs to know a list of classes that it's going to handle up front. This is the list of classes that are passed to JAXBContext.newInstance(). While the implementation of this method does a transitive type reference analysis, this analysis is unable to find subclasses due to the way Java works. At the runtime, the list of classes that JAX-WS knows to be bound by JAXB is primarily those types that appear in the SEI. Any types that are not transitively reachable from these classes will not be a part of JAXBContext, and as such they'll fail to marshal/unmarshal. What's needed here is for a portable way for the WSDL compiler tool to pass a list of additional classes to the runtime. If such a mechanism exist, then wscompile can capture all the generated types (by communicating with xjc) to be used by runtime. Since the JAX-WS implementation used at the development time and the JAX-WS implementation at runtime might differ, any mechanism that captures the list of classes need to be portable. That means this requires a spec change. Proposed Solution ----------------- Define an annotation in JAXB that instructs JAXB runtime to bind other classes. The feature is intended so that classes that are not otherwise statically reachable will become reachable for the JAXB runtime. @XmlSeeAlso({FooBeanEx.class,FooBean2.class,...}) class FooBean { ... } The semantics is that this would extend the transitive reference closure computation. When the closure includes FooBean, this annotation will add all the referenced classes into this closure. To make this work with JAX-WS, JAX-WS spec will allow this annotation to be placed on the web service class, and JAX-WS implementation needs to be involved in passing this information to JAXB implementation (as JAXB won't see the web service class itself as a bindable class.) So for example, this can be used like this: @XmlSeeAlso({Bar.class,Zot.class}) abstract class Foo {} class Bar extends Foo {} class Zot extends Foo {} and "JAXBContext.newInstance(Foo.class)" will include all three classes. (Without @XmlSeeAlso annotation on Foo, "JAXBContext.newInstance(Foo.class)" will include only Foo.) The JAX-WS 2.1 spec proposes to allow @XmlSeeAlso on the SEI or endpoint implementation, like this: @XmlSeeAlso(Foo.class) interface SEI { Object echo(Object o); } JAX-WS implementation will be responsible for making sure that the JAXBContext it creates includes all the classes listed in @XmlSeeAlso. This annotaion is allowed but not required. Spec Changes ------------ Add the following to the spec. 8.7.3 @XmlSeeAlso @XmlSeeAlso is an optional annotation that can be placed on a class to instruct the JAXB runtime and the schema generator to also bind classes listed in @XmlSeeAlso, when it binds the class that @XmlSeeAlso is on. 8.7.3.1 Synopsis @Rentention(RUNTIME) @Target({TYPE}) public @interface XmlSeeAlso { Class[] value(); } Proposed Change: XmlTransientOnClass216 ------------------------------------------------------------ See https://jaxb.dev.java.net/issues/show_bug.cgi?id=216 Background ---------- Java type hierarchy and XML type hierarchy may not always match one to one. One such example is where you define a common base class between various classes to share some utility code, yet such a base class should be considered as an implementation detail. class AbstractModelObject { public void toString() { // use commons-lang to define a toString() for all return ToStringBuilder.reflectionToString(this); } } class Person extends AbstractModelObject { ... } class Computer extends AbstractModelObject { ... } The user do not wish to create a complex type that corresponds to the 'abstractModelObject', since it's pointless. It's often even actively harmful, because such a base class blocks the use of @XmlValue annotation on Person and Computer classes. Proposed Solution ----------------- Allow @XmlTransient to be placed on a class, to indicate that it doesn't have the corresponding XML representation. So in the above example, one can do as follows to achieve the desired effect of not defining 'abstractModelObject' complex type: @XmlTransient class AbstractModelObject { public void toString() { // use commons-lang to define a toString() for all return ToStringBuilder.reflectionToString(this); } } class Person extends AbstractModelObject { } class Computer extends AbstractModelObject { } The following example illustrates more general case: class Foo { @XmlElement String a; } @XmlTransient class Bar extends Foo { @XmlElement String b; } @XmlType(propOrder={"c","b"}) class Zot extends Bar { @XmlElement String c; } A few things to note: - Even if a class is marked as transient, you can still use JAXB annotations on its members, and they are bound as a part of the derived class. This is in accordance with the similar Java persistence API annotation @MappedSuperclass. - Since property 'b' is bound by Zot, you can freely change its order among other properties defined in Zot, as seen in this example. Spec Changes ------------ Section 8.7.1.2 "Mapping" bullet 7: if the class, subClass, derives from another XML-bound class, baseClass directly or indirectly (other than java.lang.Object), then the subClass must not contain a mapped property or field annotated with @XmlValue annotation. Section 8.7.1.2 Table 8-4 "Mapping: Class to Complex Type Definition" {base type definition} "otherwise schema type to which the nearest XML-bound ancestor class is mapped" Also add the following text at the note: When class X with @XmlType derives from another class Y with @XmlTransient, which in turn derives from class X with @XmlType, then the above wording causes complex type X to derive from complex type Z, causing Y to skip. Add Section 8.7.3 @XmlTransient @XmlTransient is used to prevent the mapping of a class. 8.7.3.1 Synopsis @Retention(RUNTIME) @Target({FIELD,METHOD,TYPE}) public @interface XmlTransient {} 8.7.3.2 Mapping The class must not be mapped. Any reference to this class from the other XML-bound classes will treated as if they are refering to the nearest XML-bound ancestor of this class (which could be java.lang.Object, which guarantees that there always exists such a class.) For the effect that this annotation causes on derived classes, see Table 8-4. Note that a class with @XmlTransient may still have properties and fields with JAXB annotations. Those are mapped to XML when a derived class is mapped to XML. See section 8.9 for more details. The following mapping constraints must be enforced: - @XmlTransient is mutually exclusive with all other mapping annotations. Modify Section 8.9 - read/write property as identified by java.beans.Introspector.getBeanInfo, where the stopClass is the nearest XML-bound super class. - non static, non transient field of all the ancestors up to the stopClass (but excluding itself); if ... A mapped property is a property found as above and mapped either by default or using a JAXB annotation. A mapped field is a field found as above and mapped either by default or using a JAXB annotation. A property or field that has been annotated with @XmlTransient is not mapped. Modify Section 8.9.9.1 Synopsis @Retention(RUNTIME) @Target({FIELD,METHOD,TYPE}) Modify Section 8.12.3 Unless @XmlTransient annotation is present, a class with a public or protected ...