users@jaxb.java.net

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

From: Sekhar Vajjhala <Sekhar.Vajjhala_at_Sun.COM>
Date: Tue, 24 Jan 2006 11:23:58 -0500

Mark Hansen wrote:

> OK - thanks. I entered that bug report (#117). Do you have any idea
> when the 2.0 spec will be finalized?

April 2006.

Sekhar

>
>
> Sekhar Vajjhala wrote:
>
>> mark_at_javector.com wrote:
>>
>>> 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?
>>
>>
>>
>> Sorry for my delayed reply.
>>
>> There is already a bug report:
>> https://jaxb.dev.java.net/issues/show_bug.cgi?id=117
>> which seems to contain the text below.
>>
>>
>>>
>>> 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 {
>>
>>
>>
>> The annotation is not correct. MyFooAdapter adapts
>> MyFoo -> Foo but what you are trying to do is
>> adapt Foo->MyFoo. This requires a new annotation.
>> Furthermore, it might be desirable to ensure that this solution
>> works well when the use cases involve interfaces as opposed
>> to concrete classes.
>>
>> So we will address this in a future version of the spec.
>> We will use the defect report 117 to track this request.
>> For now, as Kohsuke suggested, you can invoke the adapter
>> yourself.
>>
>> Thanks for bringing up the issue.
>>
>> regards
>> Sekhar Vajjhala
>>
>>>
>>>
>>> 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
>>>>
>>>>
>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jaxb.dev.java.net
>> For additional commands, e-mail: users-help_at_jaxb.dev.java.net
>>