users@jaxb.java.net

Re: [jaxb-20-comments] cannot adapt an XmlRootElement ?

From: <mark_at_javector.com>
Date: Fri, 13 Jan 2006 21:10:09 -0700

Thank you for the detailed explanation. I do not think the Sun RI implements
either the marshalling or the unmarshalling case. Details below. Should I
enter this as a bug report?

The following code example should work. However, can you confirm thatI
need the
@XmlJavaTypeAdapter on *both* the value-type class (so the unmarshaller knows
what to do) and the bound-type class (so the marshaller knows what do to)?

Value-Type = Foo
Bound-Type = MyFoo

@XmlRootElement
@XmlJavaTypeAdapter(MyFooAdapter.class)
public class Foo {

  String x;

}

@XmlJavaTypeAdapter(MyFooAdapter.class)
public class MyFoo {

  String y;

}

public class MyFooAdapter extends XmlAdapter<Foo, MyFoo> { ... }

Then, this marshalling / unmarshalling should work:

    MyFoo myFoo = new MyFoo();
    myFoo.y = "Hello World";
    m.marshal(myFoo, System.out)

should print a serializer instance of Foo like this:

    <foo><x>Hello World</x></foo>

And if I do this:

    MyFoo myFoo = u.unmarshal(
      new StringReader("<foo><x>Hello World</x></foo>");

That should work also - right?

But with the Sun RI, I get the following errors:

Marshalling ...
    [java] javax.xml.bind.MarshalException
    [java] - with linked exception:
    [java] [org.xml.sax.SAXException: unable to marshal type "samples.MyFoo" as
an element because it is missing an @XmlRootElement annotation]


Unmarshalling ...
    [java] java.lang.ClassCastException: samples.Foo
    [java] at samples.MyFooSerializer.main(MyFooSerializer.java:34)






Quoting Sekhar Vajjhala <Sekhar.Vajjhala_at_Sun.COM>:

> Mark Hansen wrote:
>
>> It appears that you cannot get JAXB to adapt a root element class.
>> So, there is no way to marshal a bound type to a global element.
>
> Thanks for the feedback and interest in JAXB 2.0.
>
> I agree this case needs to be supported.
>
> The spec already supports this case but requires a partial
> fix. Details below
>
>>
>>
>> The spec requires a "point of reference" for the bound type. And
>> when the bound type is the root element class, then there is no
>> point of reference. This seems like a problem with the
>> specification.
>
> You are correct that there is no "point of reference" in the bound
> type, MyFoo i.e. there is no property/field that reference
> MyFoo. However, marshalling and unmarshalling is still required to
> adapt the class using MyFooAdapter. This is required by the runtime
> processing model specified in Appendix B, "Runtime Processing", that
> deals with marshalling/unmarshalling of XML instances. Referenced
> below are sections from Appendix B which shows the requirements for
> the adapter to be used.
>
> Unmarshalling:
> =============
>
> The use of adapter for unmarshalling is required by section B.3.1,
> "Gobally Declared Root Element", page 305 , bullet item b. of the
> Proposed Final Draft which contains the following:
>
> ------- begin excerpt from the JAXB 2.0 spec ---------
> b. if a type annotated with @XmlRootElement is found and is not
> annotated with @XmlJavaTypeAdapter, then the valueType is type that
> has been annotated. For e.g.
>
> @XmlRootElement(...)
> public class Foo { ... }
>
> The valueType is Foo.
>
> if a type annotated with @XmlRootElement is found and is annotated
> with @XmlJavaTypeAdapter, then the valueType is the type that has
> been specified in @XmlJavaTypeAdapter.value().
> ------- end excerpt from the JAXB 2.0 spec ---------
>
> Marshalling:
> ============
> Marshalling is covered by section, Section B.4,
> "Marshalling". Sub section b.4.2.1, "JAXBElement" requires the use of
> adapter when a JAXBElement instance is being marshalled. From Bullet
> item 6.
>
> -------- begin excerpt from Appendix B ---------
> 6. determine the valueType to be marshalled. If the program element
> being processed is associated with @XmlJavaTypeAdapter then
> boundType is valueType =
> @XmlJavaTypeAdapter.value().marshal(boundType)
> otherwise valueType is boundType.
> -------- end excerpt from Appendix B ---------
>
> However, the requirement on the use of an adapter is missing from
> section section B.4.2, "Class" when a type annotated with
> XmlRootElement is marshalled. This was an omission, which I will
> correct.
>
>>
>>
>> I.e., you should be able to do this (Foo is the value type and MyFoo
>> is the bound type):
>>
>> @XmlRootElement
>> @XmlJavaTypeAdapter(MyFooAdapter.class)
>> public class MyFoo {
>> ....
>> }
>>
>>
>> @XmlRootElement
>> public class Foo {
>> ....
>> }
>>
>>
>> Given the above, when you marshal an instance of MyFoo, it should
>> produce the XML that is mapped from Foo. But, the Sun RI does not
>> work like this. It seems to ignore the adapter. It seems that this
>> behavior is consistent with the specification - since there is not
>> "point of reference" for MyFoo in the actual class definition of
>> MyFoo. However, the upshot is that you can't marshal a boutn type
>> to a global element. That seems like a common use case that JAXB
>> 2.0 should handle.
>>
>> Pleasse let me know if I am missing something.
>>
>> -- Mark
>
>
> regards
> Sekhar Vajjhala
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jaxb.dev.java.net
> For additional commands, e-mail: users-help_at_jaxb.dev.java.net
>
>