users@jaxb.java.net

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

From: Sekhar Vajjhala <Sekhar.Vajjhala_at_Sun.COM>
Date: Fri, 20 Jan 2006 19:02:28 -0500

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
>>
>>
>
>