You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Nikolay Aleksiev <ni...@alexiev.net> on 2012/05/22 17:52:04 UTC

Missing xsi:type in derrived types

Hello,

I have a REST service which returns a com.foo.Base class. This class is 
part of a complex domain hierarchy which looks like this:

/com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and 
Base3 is extended by multiple Concrete implementors.

What I want to achieve is to have "xsi:type" set in the returned XML 
when a concrete class instance is used. I went through the documentation 
and added "JaxbElementClassNames" to my JAXBProvider. Here is my config:

<bean id="jaxbProvider" 
class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
<property name="marshallerProperties" ref="marshallerPropertiesMap" />
<property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
</bean>

<util:map id="marshallerPropertiesMap">
<entry key="jaxb.encoding">
<value type="java.lang.String">UTF-8</value>
</entry>
</util:map>

<util:list id="myJaxbElementClassNames">
<value>/com.foo.Base/</value>
<value>/com.foo.Base/1</value>
<value>/com.foo.Base/2</value>
<value>/com.foo.Base/3</value>
<value>/com.foo.Concrete1/</value>
<value>/com.foo.Concrete2/</value>
<value>/com.foo.Concrete3/</value>
<value>/com.foo.Concrete4/</value>
</util:list>

<jaxrs:server id="clientServer" address="/">
<jaxrs:providers>
<ref bean="systemExceptionMapper" />
<ref bean="jaxbProvider" />
<ref bean="jsonProvider"/>
<ref bean="followUpFilter" />
</jaxrs:providers>
             ...
</jaxrs:server>

The result is that the xsi:type attribute is not added. All the concrete 
classes and com.foo.Base have @XMLRootElement annotation (the other base 
ones DO NOT). @XMLSeeAlso is added in all the classes.

I'm using apache 2.4.7.

Thanks for the help. Any ideas are welcome!

Cheers,
Nikolay




Re: Missing xsi:type in derrived types

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 08/06/12 08:53, Nikolay Aleksiev wrote:
> Hi Sergey,
>
> I test the fix both in 2.4.7 and 2.6.1 and everything is OK!
>
Great, thanks for your help in getting this fixed too
Cheers, Sergey
> Thank you very much for the support!
>
> Cheers,
> Nikolay
>
> On 05/29/2012 08:46 PM, Sergey Beryozkin wrote:
>> Hi Nikolay,
>>
>> I fixed it on all the branches except 2.3.x as the changes were a bit
>> sensitive
>>
>> Thanks for the help
>> Sergey
>>
>> https://issues.apache.org/jira/browse/CXF-4349
>>
>> On 29/05/12 08:25, Nikolay Aleksiev wrote:
>>> Hi Sergey,
>>>
>>> I tried your test and created a test app. There are two issues I
>>> noticed:
>>>
>>> 1. In 2.4.7 JAXBElementProvider is not generic. Anyway the test works
>>> with the one available.
>>>
>>> 2. The actual call to writeTo is:
>>>
>>> provider.writeTo(b, Item.class, Base.class, ...);
>>>
>>> The second param value is retrieved in
>>> JAXRSOutInterceptor.getRawResponseClass and it returns the real class of
>>> the object.
>>>
>>> When the test is run with /provider.writeTo(b, Item.class, Base.class,
>>> ...); /it behaves exactly as in the container and returns:
>>>
>>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>>> <base/>
>>>
>>> Thanks for the help!
>>> Cheers,
>>> Nikolay
>>>
>>>
>>> On 05/28/2012 08:03 PM, Sergey Beryozkin wrote:
>>>> Hi
>>>>
>>>> The following:
>>>>
>>>> @Test
>>>> public void testWriteDerivedType() throws Exception {
>>>> JAXBElementProvider<Base> provider = new JAXBElementProvider<Base>();
>>>>
>>>> provider.setJaxbElementClassNames(Collections.singletonList(Base.class.getName()));
>>>>
>>>>
>>>> Base b = new Item();
>>>>
>>>> ByteArrayOutputStream bos = new ByteArrayOutputStream();
>>>> provider.writeTo(b, Base.class, Base.class,
>>>> new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String,
>>>> Object>(), bos);
>>>> System.out.println(bos.toString());
>>>> }
>>>>
>>>> public static abstract class Base0 {
>>>> }
>>>>
>>>> @XmlType(name = "content")
>>>> @XmlRootElement
>>>> @XmlSeeAlso({ Item.class })
>>>> public static abstract class Base extends Base0 {
>>>> }
>>>>
>>>> @XmlRootElement(name = "content")
>>>> @XmlType(name = "item")
>>>> public static class Item extends Base {
>>>> }
>>>>
>>>> produces
>>>>
>>>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>>>> <base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>>> xsi:type="item"/>
>>>>
>>>> You are confirming that the code branch to do with wrapping the
>>>> response type in JAXBElement is executed, so I'm not really sure what
>>>> is missing in your case.
>>>>
>>>> Perhaps some of JAXB annotations are not even visible to
>>>> JAXBElementProvider and hence to JAXB Marshaller ? Are you working
>>>> with WebSphere or WebLogic ? I vaguely remember that someone had few
>>>> problems with getting the JAX-RS annotations recognized in one of
>>>> those containers.
>>>>
>>>> If you can provider a sample test project or just a war then it would
>>>> help me to investigate further.
>>>>
>>>> Please keep me updated,
>>>>
>>>> thanks, Sergey
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On 28/05/12 16:12, Nikolay Aleksiev wrote:
>>>>> Hi,
>>>>>
>>>>> I'm already working with the latest 2.4.7. Here is the information:
>>>>>
>>>>> @MappedSuperclass
>>>>> @XmlType(name = "content")
>>>>> @XmlRootElement
>>>>> @XmlSeeAlso({ Item.class })
>>>>> public abstract class Base extends OtherBase implements
>>>>> Comparable<Base> {
>>>>> ...
>>>>> ...
>>>>> }
>>>>>
>>>>> @Entity
>>>>> @Table(name = "CONTENT")
>>>>> @AttributeOverrides({
>>>>> ...
>>>>> ...
>>>>> ...
>>>>> })
>>>>> @ObjectTypeConverter(name = "charCodeToBooleanConverter", dataType =
>>>>> String.class, objectType = Boolean.class, conversionValues = {
>>>>> @ConversionValue(dataValue = "Y", objectValue = "TRUE"),
>>>>> @ConversionValue(dataValue = "N", objectValue = "FALSE") })
>>>>> @XmlRootElement(name = "content")
>>>>> @XmlType(name = "item")
>>>>> @Cacheable(false)
>>>>> public class Item extends Base {
>>>>> ...
>>>>> }
>>>>>
>>>>> @WebMethod
>>>>> @GET
>>>>> @Path("/item/{contentType}/{id}")
>>>>> @Secured("ROLE_RESTCLIENT")
>>>>> public Base get(@PathParam("id") String contentId,
>>>>> @PathParam("contentType") ContentType contentType)
>>>>> throws WSException;
>>>>>
>>>>> Cheers,
>>>>> Nikolay
>>>>>
>>>>>
>>>>>
>>>>> On 05/28/2012 05:44 PM, Sergey Beryozkin wrote:
>>>>>> Hi
>>>>>> On 28/05/12 15:18, Nikolay Aleksiev wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> one more thing. I debugged the JAXBElementProvider. What I
>>>>>>> noticed is
>>>>>>> that my object is converted to JAXBElement but xsi:type is still
>>>>>>> missing.
>>>>>>>
>>>>>>> When I create JAXB context, marshaller manually and construct a
>>>>>>> JAXBElement, the xsi:type is added.
>>>>>>>
>>>>>>> It seems I'm missing something, but I can't find what.
>>>>>>>
>>>>>>
>>>>>> Can you try the latest 2.4.7 on the 2.4.x branch ?
>>>>>> Or send me the following info:
>>>>>>
>>>>>> - the sample pair of Base and Base1 classes, with all the annotations
>>>>>> which are used on the actual classes that you work with
>>>>>>
>>>>>> - sample JAX-RS method signature, example
>>>>>> @GET
>>>>>> public Base getBase() {
>>>>>> return new Base1();
>>>>>> }
>>>>>>
>>>>>> Cheers, Sergey
>>>>>>
>>>>>>> Thanks for your help!
>>>>>>>
>>>>>>> Regards,
>>>>>>> Nikolay
>>>>>>>
>>>>>>> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>>>>>>>> Hi Nikolay
>>>>>>>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>>>>>>>> Hi Sergey,
>>>>>>>>>
>>>>>>>>> basically - yes. I return a child of com.foo.Base and all the
>>>>>>>>> parents
>>>>>>>>> have @XMLRootElement. The resource returns the child without
>>>>>>>>> xsi:type.
>>>>>>>>>
>>>>>>>>> I don't know if this is useful, but when I return collection, the
>>>>>>>>> elements in the collection have xsi:type.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Here is the code I wrote:
>>>>>>>>
>>>>>>>> JAXBElementProvider<Book> provider = new
>>>>>>>> JAXBElementProvider<Book>();
>>>>>>>>
>>>>>>>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> provider.setExtraClass(new Class[]{SuperBook.class});
>>>>>>>>
>>>>>>>> Book is the base class, SuperBook extends it. For xsi:type to
>>>>>>>> appear
>>>>>>>> one should have either @XmlSeeAlso({SuperBook.class }) on Book
>>>>>>>> class or
>>>>>>>> configure the provider as in the code above.
>>>>>>>>
>>>>>>>> Having a jaxb.index package resource will probably do it too.
>>>>>>>>
>>>>>>>> So the jaxbElementClassNames property should only list the return
>>>>>>>> types of various resource methods and subclasses should be listed
>>>>>>>> using one of the options mentioned above.
>>>>>>>>
>>>>>>>> How many base classes like Base.class do you have ? I think if one
>>>>>>>> has
>>>>>>>> to list more than 3-5 base classes then it will probably make
>>>>>>>> sense to
>>>>>>>> add wildcard jaxbElementClassNames property
>>>>>>>>
>>>>>>>> Cheers, Sergey
>>>>>>>>
>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Nikolay
>>>>>>>>>
>>>>>>>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> So, for example, you have
>>>>>>>>>>
>>>>>>>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>>>>>>>> XMLRootElement on both classes ? The resource method returns
>>>>>>>>>> com.foo.Base, when Base1 is returned no xsi:type is added,
>>>>>>>>>> right ?
>>>>>>>>>>
>>>>>>>>>> Cheers, Sergey
>>>>>>>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>>>>>>>> Hello,
>>>>>>>>>>>
>>>>>>>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>>>>>>>> class is
>>>>>>>>>>> part of a complex domain hierarchy which looks like this:
>>>>>>>>>>>
>>>>>>>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 ->
>>>>>>>>>>> com.foo.Base3/
>>>>>>>>>>> and
>>>>>>>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>>>>>>>
>>>>>>>>>>> What I want to achieve is to have "xsi:type" set in the
>>>>>>>>>>> returned XML
>>>>>>>>>>> when a concrete class instance is used. I went through the
>>>>>>>>>>> documentation
>>>>>>>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>>>>>>>> config:
>>>>>>>>>>>
>>>>>>>>>>> <bean id="jaxbProvider"
>>>>>>>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>>>>>>>> <property name="marshallerProperties"
>>>>>>>>>>> ref="marshallerPropertiesMap" />
>>>>>>>>>>> <property name="jaxbElementClassNames"
>>>>>>>>>>> ref="myJaxbElementClassNames"/>
>>>>>>>>>>> </bean>
>>>>>>>>>>>
>>>>>>>>>>> <util:map id="marshallerPropertiesMap">
>>>>>>>>>>> <entry key="jaxb.encoding">
>>>>>>>>>>> <value type="java.lang.String">UTF-8</value>
>>>>>>>>>>> </entry>
>>>>>>>>>>> </util:map>
>>>>>>>>>>>
>>>>>>>>>>> <util:list id="myJaxbElementClassNames">
>>>>>>>>>>> <value>/com.foo.Base/</value>
>>>>>>>>>>> <value>/com.foo.Base/1</value>
>>>>>>>>>>> <value>/com.foo.Base/2</value>
>>>>>>>>>>> <value>/com.foo.Base/3</value>
>>>>>>>>>>> <value>/com.foo.Concrete1/</value>
>>>>>>>>>>> <value>/com.foo.Concrete2/</value>
>>>>>>>>>>> <value>/com.foo.Concrete3/</value>
>>>>>>>>>>> <value>/com.foo.Concrete4/</value>
>>>>>>>>>>> </util:list>
>>>>>>>>>>>
>>>>>>>>>>> <jaxrs:server id="clientServer" address="/">
>>>>>>>>>>> <jaxrs:providers>
>>>>>>>>>>> <ref bean="systemExceptionMapper" />
>>>>>>>>>>> <ref bean="jaxbProvider" />
>>>>>>>>>>> <ref bean="jsonProvider"/>
>>>>>>>>>>> <ref bean="followUpFilter" />
>>>>>>>>>>> </jaxrs:providers>
>>>>>>>>>>> ...
>>>>>>>>>>> </jaxrs:server>
>>>>>>>>>>>
>>>>>>>>>>> The result is that the xsi:type attribute is not added. All the
>>>>>>>>>>> concrete
>>>>>>>>>>> classes and com.foo.Base have @XMLRootElement annotation (the
>>>>>>>>>>> other
>>>>>>>>>>> base
>>>>>>>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>>>>>>>
>>>>>>>>>>> I'm using apache 2.4.7.
>>>>>>>>>>>
>>>>>>>>>>> Thanks for the help. Any ideas are welcome!
>>>>>>>>>>>
>>>>>>>>>>> Cheers,
>>>>>>>>>>> Nikolay
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>



Re: Missing xsi:type in derrived types

Posted by Nikolay Aleksiev <ni...@alexiev.net>.
Hi Sergey,

I test the fix both in 2.4.7 and 2.6.1 and everything is OK!

Thank you very much for the support!

Cheers,
Nikolay

On 05/29/2012 08:46 PM, Sergey Beryozkin wrote:
> Hi Nikolay,
>
> I fixed it on all the branches except 2.3.x as the changes were a bit 
> sensitive
>
> Thanks for the help
> Sergey
>
> https://issues.apache.org/jira/browse/CXF-4349
>
> On 29/05/12 08:25, Nikolay Aleksiev wrote:
>> Hi Sergey,
>>
>> I tried your test and created a test app. There are two issues I 
>> noticed:
>>
>> 1. In 2.4.7 JAXBElementProvider is not generic. Anyway the test works
>> with the one available.
>>
>> 2. The actual call to writeTo is:
>>
>> provider.writeTo(b, Item.class, Base.class, ...);
>>
>> The second param value is retrieved in
>> JAXRSOutInterceptor.getRawResponseClass and it returns the real class of
>> the object.
>>
>> When the test is run with /provider.writeTo(b, Item.class, Base.class,
>> ...); /it behaves exactly as in the container and returns:
>>
>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>> <base/>
>>
>> Thanks for the help!
>> Cheers,
>> Nikolay
>>
>>
>> On 05/28/2012 08:03 PM, Sergey Beryozkin wrote:
>>> Hi
>>>
>>> The following:
>>>
>>> @Test
>>> public void testWriteDerivedType() throws Exception {
>>> JAXBElementProvider<Base> provider = new JAXBElementProvider<Base>();
>>>
>>> provider.setJaxbElementClassNames(Collections.singletonList(Base.class.getName())); 
>>>
>>>
>>> Base b = new Item();
>>>
>>> ByteArrayOutputStream bos = new ByteArrayOutputStream();
>>> provider.writeTo(b, Base.class, Base.class,
>>> new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String,
>>> Object>(), bos);
>>> System.out.println(bos.toString());
>>> }
>>>
>>> public static abstract class Base0 {
>>> }
>>>
>>> @XmlType(name = "content")
>>> @XmlRootElement
>>> @XmlSeeAlso({ Item.class })
>>> public static abstract class Base extends Base0 {
>>> }
>>>
>>> @XmlRootElement(name = "content")
>>> @XmlType(name = "item")
>>> public static class Item extends Base {
>>> }
>>>
>>> produces
>>>
>>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>>> <base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>>> xsi:type="item"/>
>>>
>>> You are confirming that the code branch to do with wrapping the
>>> response type in JAXBElement is executed, so I'm not really sure what
>>> is missing in your case.
>>>
>>> Perhaps some of JAXB annotations are not even visible to
>>> JAXBElementProvider and hence to JAXB Marshaller ? Are you working
>>> with WebSphere or WebLogic ? I vaguely remember that someone had few
>>> problems with getting the JAX-RS annotations recognized in one of
>>> those containers.
>>>
>>> If you can provider a sample test project or just a war then it would
>>> help me to investigate further.
>>>
>>> Please keep me updated,
>>>
>>> thanks, Sergey
>>>
>>>
>>>
>>>
>>>
>>> On 28/05/12 16:12, Nikolay Aleksiev wrote:
>>>> Hi,
>>>>
>>>> I'm already working with the latest 2.4.7. Here is the information:
>>>>
>>>> @MappedSuperclass
>>>> @XmlType(name = "content")
>>>> @XmlRootElement
>>>> @XmlSeeAlso({ Item.class })
>>>> public abstract class Base extends OtherBase implements
>>>> Comparable<Base> {
>>>> ...
>>>> ...
>>>> }
>>>>
>>>> @Entity
>>>> @Table(name = "CONTENT")
>>>> @AttributeOverrides({
>>>> ...
>>>> ...
>>>> ...
>>>> })
>>>> @ObjectTypeConverter(name = "charCodeToBooleanConverter", dataType =
>>>> String.class, objectType = Boolean.class, conversionValues = {
>>>> @ConversionValue(dataValue = "Y", objectValue = "TRUE"),
>>>> @ConversionValue(dataValue = "N", objectValue = "FALSE") })
>>>> @XmlRootElement(name = "content")
>>>> @XmlType(name = "item")
>>>> @Cacheable(false)
>>>> public class Item extends Base {
>>>> ...
>>>> }
>>>>
>>>> @WebMethod
>>>> @GET
>>>> @Path("/item/{contentType}/{id}")
>>>> @Secured("ROLE_RESTCLIENT")
>>>> public Base get(@PathParam("id") String contentId,
>>>> @PathParam("contentType") ContentType contentType)
>>>> throws WSException;
>>>>
>>>> Cheers,
>>>> Nikolay
>>>>
>>>>
>>>>
>>>> On 05/28/2012 05:44 PM, Sergey Beryozkin wrote:
>>>>> Hi
>>>>> On 28/05/12 15:18, Nikolay Aleksiev wrote:
>>>>>> Hi,
>>>>>>
>>>>>> one more thing. I debugged the JAXBElementProvider. What I 
>>>>>> noticed is
>>>>>> that my object is converted to JAXBElement but xsi:type is still
>>>>>> missing.
>>>>>>
>>>>>> When I create JAXB context, marshaller manually and construct a
>>>>>> JAXBElement, the xsi:type is added.
>>>>>>
>>>>>> It seems I'm missing something, but I can't find what.
>>>>>>
>>>>>
>>>>> Can you try the latest 2.4.7 on the 2.4.x branch ?
>>>>> Or send me the following info:
>>>>>
>>>>> - the sample pair of Base and Base1 classes, with all the annotations
>>>>> which are used on the actual classes that you work with
>>>>>
>>>>> - sample JAX-RS method signature, example
>>>>> @GET
>>>>> public Base getBase() {
>>>>> return new Base1();
>>>>> }
>>>>>
>>>>> Cheers, Sergey
>>>>>
>>>>>> Thanks for your help!
>>>>>>
>>>>>> Regards,
>>>>>> Nikolay
>>>>>>
>>>>>> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>>>>>>> Hi Nikolay
>>>>>>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>>>>>>> Hi Sergey,
>>>>>>>>
>>>>>>>> basically - yes. I return a child of com.foo.Base and all the
>>>>>>>> parents
>>>>>>>> have @XMLRootElement. The resource returns the child without
>>>>>>>> xsi:type.
>>>>>>>>
>>>>>>>> I don't know if this is useful, but when I return collection, the
>>>>>>>> elements in the collection have xsi:type.
>>>>>>>>
>>>>>>>
>>>>>>> Here is the code I wrote:
>>>>>>>
>>>>>>> JAXBElementProvider<Book> provider = new 
>>>>>>> JAXBElementProvider<Book>();
>>>>>>>
>>>>>>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName())); 
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> provider.setExtraClass(new Class[]{SuperBook.class});
>>>>>>>
>>>>>>> Book is the base class, SuperBook extends it. For xsi:type to 
>>>>>>> appear
>>>>>>> one should have either @XmlSeeAlso({SuperBook.class }) on Book
>>>>>>> class or
>>>>>>> configure the provider as in the code above.
>>>>>>>
>>>>>>> Having a jaxb.index package resource will probably do it too.
>>>>>>>
>>>>>>> So the jaxbElementClassNames property should only list the return
>>>>>>> types of various resource methods and subclasses should be listed
>>>>>>> using one of the options mentioned above.
>>>>>>>
>>>>>>> How many base classes like Base.class do you have ? I think if one
>>>>>>> has
>>>>>>> to list more than 3-5 base classes then it will probably make
>>>>>>> sense to
>>>>>>> add wildcard jaxbElementClassNames property
>>>>>>>
>>>>>>> Cheers, Sergey
>>>>>>>
>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Nikolay
>>>>>>>>
>>>>>>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> So, for example, you have
>>>>>>>>>
>>>>>>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>>>>>>> XMLRootElement on both classes ? The resource method returns
>>>>>>>>> com.foo.Base, when Base1 is returned no xsi:type is added, 
>>>>>>>>> right ?
>>>>>>>>>
>>>>>>>>> Cheers, Sergey
>>>>>>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>>>>>>> Hello,
>>>>>>>>>>
>>>>>>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>>>>>>> class is
>>>>>>>>>> part of a complex domain hierarchy which looks like this:
>>>>>>>>>>
>>>>>>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> 
>>>>>>>>>> com.foo.Base3/
>>>>>>>>>> and
>>>>>>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>>>>>>
>>>>>>>>>> What I want to achieve is to have "xsi:type" set in the
>>>>>>>>>> returned XML
>>>>>>>>>> when a concrete class instance is used. I went through the
>>>>>>>>>> documentation
>>>>>>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>>>>>>> config:
>>>>>>>>>>
>>>>>>>>>> <bean id="jaxbProvider"
>>>>>>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>>>>>>> <property name="marshallerProperties"
>>>>>>>>>> ref="marshallerPropertiesMap" />
>>>>>>>>>> <property name="jaxbElementClassNames"
>>>>>>>>>> ref="myJaxbElementClassNames"/>
>>>>>>>>>> </bean>
>>>>>>>>>>
>>>>>>>>>> <util:map id="marshallerPropertiesMap">
>>>>>>>>>> <entry key="jaxb.encoding">
>>>>>>>>>> <value type="java.lang.String">UTF-8</value>
>>>>>>>>>> </entry>
>>>>>>>>>> </util:map>
>>>>>>>>>>
>>>>>>>>>> <util:list id="myJaxbElementClassNames">
>>>>>>>>>> <value>/com.foo.Base/</value>
>>>>>>>>>> <value>/com.foo.Base/1</value>
>>>>>>>>>> <value>/com.foo.Base/2</value>
>>>>>>>>>> <value>/com.foo.Base/3</value>
>>>>>>>>>> <value>/com.foo.Concrete1/</value>
>>>>>>>>>> <value>/com.foo.Concrete2/</value>
>>>>>>>>>> <value>/com.foo.Concrete3/</value>
>>>>>>>>>> <value>/com.foo.Concrete4/</value>
>>>>>>>>>> </util:list>
>>>>>>>>>>
>>>>>>>>>> <jaxrs:server id="clientServer" address="/">
>>>>>>>>>> <jaxrs:providers>
>>>>>>>>>> <ref bean="systemExceptionMapper" />
>>>>>>>>>> <ref bean="jaxbProvider" />
>>>>>>>>>> <ref bean="jsonProvider"/>
>>>>>>>>>> <ref bean="followUpFilter" />
>>>>>>>>>> </jaxrs:providers>
>>>>>>>>>> ...
>>>>>>>>>> </jaxrs:server>
>>>>>>>>>>
>>>>>>>>>> The result is that the xsi:type attribute is not added. All the
>>>>>>>>>> concrete
>>>>>>>>>> classes and com.foo.Base have @XMLRootElement annotation (the
>>>>>>>>>> other
>>>>>>>>>> base
>>>>>>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>>>>>>
>>>>>>>>>> I'm using apache 2.4.7.
>>>>>>>>>>
>>>>>>>>>> Thanks for the help. Any ideas are welcome!
>>>>>>>>>>
>>>>>>>>>> Cheers,
>>>>>>>>>> Nikolay
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>

Re: Missing xsi:type in derrived types

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Nikolay,

I fixed it on all the branches except 2.3.x as the changes were a bit 
sensitive

Thanks for the help
Sergey

https://issues.apache.org/jira/browse/CXF-4349

On 29/05/12 08:25, Nikolay Aleksiev wrote:
> Hi Sergey,
>
> I tried your test and created a test app. There are two issues I noticed:
>
> 1. In 2.4.7 JAXBElementProvider is not generic. Anyway the test works
> with the one available.
>
> 2. The actual call to writeTo is:
>
> provider.writeTo(b, Item.class, Base.class, ...);
>
> The second param value is retrieved in
> JAXRSOutInterceptor.getRawResponseClass and it returns the real class of
> the object.
>
> When the test is run with /provider.writeTo(b, Item.class, Base.class,
> ...); /it behaves exactly as in the container and returns:
>
> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
> <base/>
>
> Thanks for the help!
> Cheers,
> Nikolay
>
>
> On 05/28/2012 08:03 PM, Sergey Beryozkin wrote:
>> Hi
>>
>> The following:
>>
>> @Test
>> public void testWriteDerivedType() throws Exception {
>> JAXBElementProvider<Base> provider = new JAXBElementProvider<Base>();
>>
>> provider.setJaxbElementClassNames(Collections.singletonList(Base.class.getName()));
>>
>> Base b = new Item();
>>
>> ByteArrayOutputStream bos = new ByteArrayOutputStream();
>> provider.writeTo(b, Base.class, Base.class,
>> new Annotation[0], MediaType.TEXT_XML_TYPE, new MetadataMap<String,
>> Object>(), bos);
>> System.out.println(bos.toString());
>> }
>>
>> public static abstract class Base0 {
>> }
>>
>> @XmlType(name = "content")
>> @XmlRootElement
>> @XmlSeeAlso({ Item.class })
>> public static abstract class Base extends Base0 {
>> }
>>
>> @XmlRootElement(name = "content")
>> @XmlType(name = "item")
>> public static class Item extends Base {
>> }
>>
>> produces
>>
>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
>> <base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xsi:type="item"/>
>>
>> You are confirming that the code branch to do with wrapping the
>> response type in JAXBElement is executed, so I'm not really sure what
>> is missing in your case.
>>
>> Perhaps some of JAXB annotations are not even visible to
>> JAXBElementProvider and hence to JAXB Marshaller ? Are you working
>> with WebSphere or WebLogic ? I vaguely remember that someone had few
>> problems with getting the JAX-RS annotations recognized in one of
>> those containers.
>>
>> If you can provider a sample test project or just a war then it would
>> help me to investigate further.
>>
>> Please keep me updated,
>>
>> thanks, Sergey
>>
>>
>>
>>
>>
>> On 28/05/12 16:12, Nikolay Aleksiev wrote:
>>> Hi,
>>>
>>> I'm already working with the latest 2.4.7. Here is the information:
>>>
>>> @MappedSuperclass
>>> @XmlType(name = "content")
>>> @XmlRootElement
>>> @XmlSeeAlso({ Item.class })
>>> public abstract class Base extends OtherBase implements
>>> Comparable<Base> {
>>> ...
>>> ...
>>> }
>>>
>>> @Entity
>>> @Table(name = "CONTENT")
>>> @AttributeOverrides({
>>> ...
>>> ...
>>> ...
>>> })
>>> @ObjectTypeConverter(name = "charCodeToBooleanConverter", dataType =
>>> String.class, objectType = Boolean.class, conversionValues = {
>>> @ConversionValue(dataValue = "Y", objectValue = "TRUE"),
>>> @ConversionValue(dataValue = "N", objectValue = "FALSE") })
>>> @XmlRootElement(name = "content")
>>> @XmlType(name = "item")
>>> @Cacheable(false)
>>> public class Item extends Base {
>>> ...
>>> }
>>>
>>> @WebMethod
>>> @GET
>>> @Path("/item/{contentType}/{id}")
>>> @Secured("ROLE_RESTCLIENT")
>>> public Base get(@PathParam("id") String contentId,
>>> @PathParam("contentType") ContentType contentType)
>>> throws WSException;
>>>
>>> Cheers,
>>> Nikolay
>>>
>>>
>>>
>>> On 05/28/2012 05:44 PM, Sergey Beryozkin wrote:
>>>> Hi
>>>> On 28/05/12 15:18, Nikolay Aleksiev wrote:
>>>>> Hi,
>>>>>
>>>>> one more thing. I debugged the JAXBElementProvider. What I noticed is
>>>>> that my object is converted to JAXBElement but xsi:type is still
>>>>> missing.
>>>>>
>>>>> When I create JAXB context, marshaller manually and construct a
>>>>> JAXBElement, the xsi:type is added.
>>>>>
>>>>> It seems I'm missing something, but I can't find what.
>>>>>
>>>>
>>>> Can you try the latest 2.4.7 on the 2.4.x branch ?
>>>> Or send me the following info:
>>>>
>>>> - the sample pair of Base and Base1 classes, with all the annotations
>>>> which are used on the actual classes that you work with
>>>>
>>>> - sample JAX-RS method signature, example
>>>> @GET
>>>> public Base getBase() {
>>>> return new Base1();
>>>> }
>>>>
>>>> Cheers, Sergey
>>>>
>>>>> Thanks for your help!
>>>>>
>>>>> Regards,
>>>>> Nikolay
>>>>>
>>>>> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>>>>>> Hi Nikolay
>>>>>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>>>>>> Hi Sergey,
>>>>>>>
>>>>>>> basically - yes. I return a child of com.foo.Base and all the
>>>>>>> parents
>>>>>>> have @XMLRootElement. The resource returns the child without
>>>>>>> xsi:type.
>>>>>>>
>>>>>>> I don't know if this is useful, but when I return collection, the
>>>>>>> elements in the collection have xsi:type.
>>>>>>>
>>>>>>
>>>>>> Here is the code I wrote:
>>>>>>
>>>>>> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>>>>>>
>>>>>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
>>>>>>
>>>>>>
>>>>>>
>>>>>> provider.setExtraClass(new Class[]{SuperBook.class});
>>>>>>
>>>>>> Book is the base class, SuperBook extends it. For xsi:type to appear
>>>>>> one should have either @XmlSeeAlso({SuperBook.class }) on Book
>>>>>> class or
>>>>>> configure the provider as in the code above.
>>>>>>
>>>>>> Having a jaxb.index package resource will probably do it too.
>>>>>>
>>>>>> So the jaxbElementClassNames property should only list the return
>>>>>> types of various resource methods and subclasses should be listed
>>>>>> using one of the options mentioned above.
>>>>>>
>>>>>> How many base classes like Base.class do you have ? I think if one
>>>>>> has
>>>>>> to list more than 3-5 base classes then it will probably make
>>>>>> sense to
>>>>>> add wildcard jaxbElementClassNames property
>>>>>>
>>>>>> Cheers, Sergey
>>>>>>
>>>>>>
>>>>>>> Thanks,
>>>>>>> Nikolay
>>>>>>>
>>>>>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> So, for example, you have
>>>>>>>>
>>>>>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>>>>>> XMLRootElement on both classes ? The resource method returns
>>>>>>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>>>>>>
>>>>>>>> Cheers, Sergey
>>>>>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>>>>>> Hello,
>>>>>>>>>
>>>>>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>>>>>> class is
>>>>>>>>> part of a complex domain hierarchy which looks like this:
>>>>>>>>>
>>>>>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/
>>>>>>>>> and
>>>>>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>>>>>
>>>>>>>>> What I want to achieve is to have "xsi:type" set in the
>>>>>>>>> returned XML
>>>>>>>>> when a concrete class instance is used. I went through the
>>>>>>>>> documentation
>>>>>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>>>>>> config:
>>>>>>>>>
>>>>>>>>> <bean id="jaxbProvider"
>>>>>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>>>>>> <property name="marshallerProperties"
>>>>>>>>> ref="marshallerPropertiesMap" />
>>>>>>>>> <property name="jaxbElementClassNames"
>>>>>>>>> ref="myJaxbElementClassNames"/>
>>>>>>>>> </bean>
>>>>>>>>>
>>>>>>>>> <util:map id="marshallerPropertiesMap">
>>>>>>>>> <entry key="jaxb.encoding">
>>>>>>>>> <value type="java.lang.String">UTF-8</value>
>>>>>>>>> </entry>
>>>>>>>>> </util:map>
>>>>>>>>>
>>>>>>>>> <util:list id="myJaxbElementClassNames">
>>>>>>>>> <value>/com.foo.Base/</value>
>>>>>>>>> <value>/com.foo.Base/1</value>
>>>>>>>>> <value>/com.foo.Base/2</value>
>>>>>>>>> <value>/com.foo.Base/3</value>
>>>>>>>>> <value>/com.foo.Concrete1/</value>
>>>>>>>>> <value>/com.foo.Concrete2/</value>
>>>>>>>>> <value>/com.foo.Concrete3/</value>
>>>>>>>>> <value>/com.foo.Concrete4/</value>
>>>>>>>>> </util:list>
>>>>>>>>>
>>>>>>>>> <jaxrs:server id="clientServer" address="/">
>>>>>>>>> <jaxrs:providers>
>>>>>>>>> <ref bean="systemExceptionMapper" />
>>>>>>>>> <ref bean="jaxbProvider" />
>>>>>>>>> <ref bean="jsonProvider"/>
>>>>>>>>> <ref bean="followUpFilter" />
>>>>>>>>> </jaxrs:providers>
>>>>>>>>> ...
>>>>>>>>> </jaxrs:server>
>>>>>>>>>
>>>>>>>>> The result is that the xsi:type attribute is not added. All the
>>>>>>>>> concrete
>>>>>>>>> classes and com.foo.Base have @XMLRootElement annotation (the
>>>>>>>>> other
>>>>>>>>> base
>>>>>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>>>>>
>>>>>>>>> I'm using apache 2.4.7.
>>>>>>>>>
>>>>>>>>> Thanks for the help. Any ideas are welcome!
>>>>>>>>>
>>>>>>>>> Cheers,
>>>>>>>>> Nikolay
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Missing xsi:type in derrived types

Posted by Nikolay Aleksiev <ni...@alexiev.net>.
Hi Sergey,

I tried your test and created a test app. There are two issues I noticed:

1. In 2.4.7 JAXBElementProvider is not generic. Anyway the test works 
with the one available.

2. The actual call to writeTo is:

     provider.writeTo(b, Item.class, Base.class, ...);

The second param value is retrieved in 
JAXRSOutInterceptor.getRawResponseClass and it returns the real class of 
the object.

When the test is run with /provider.writeTo(b, Item.class, Base.class, 
...); /it behaves exactly as in the container and returns:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<base/>

Thanks for the help!
Cheers,
Nikolay


On 05/28/2012 08:03 PM, Sergey Beryozkin wrote:
> Hi
>
> The following:
>
> @Test
>     public void testWriteDerivedType() throws Exception {
>         JAXBElementProvider<Base> provider = new 
> JAXBElementProvider<Base>();
>
> provider.setJaxbElementClassNames(Collections.singletonList(Base.class.getName())); 
>
>         Base b = new Item();
>
>         ByteArrayOutputStream bos = new ByteArrayOutputStream();
>         provider.writeTo(b, Base.class, Base.class,
>                        new Annotation[0], MediaType.TEXT_XML_TYPE, new 
> MetadataMap<String, Object>(), bos);
>         System.out.println(bos.toString());
>     }
>
>     public static abstract class Base0 {
>     }
>
>     @XmlType(name = "content")
>     @XmlRootElement
>     @XmlSeeAlso({ Item.class })
>     public static abstract class Base extends Base0 {
>     }
>
>     @XmlRootElement(name = "content")
>     @XmlType(name = "item")
>     public static class Item extends Base {
>     }
>
> produces
>
> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
> <base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
> xsi:type="item"/>
>
> You are confirming that the code branch to do with wrapping the 
> response type in JAXBElement is executed, so I'm not really sure what 
> is missing in your case.
>
> Perhaps some of JAXB annotations are not even visible to 
> JAXBElementProvider and hence to JAXB Marshaller ? Are you working 
> with WebSphere or WebLogic ? I vaguely remember that someone had few 
> problems with getting the JAX-RS annotations recognized in one of 
> those containers.
>
> If you can provider a sample test project or just a war then it would 
> help me to investigate further.
>
> Please keep me updated,
>
> thanks, Sergey
>
>
>
>
>
> On 28/05/12 16:12, Nikolay Aleksiev wrote:
>> Hi,
>>
>> I'm already working with the latest 2.4.7. Here is the information:
>>
>> @MappedSuperclass
>> @XmlType(name = "content")
>> @XmlRootElement
>> @XmlSeeAlso({ Item.class })
>> public abstract class Base extends OtherBase implements 
>> Comparable<Base> {
>> ...
>> ...
>> }
>>
>> @Entity
>> @Table(name = "CONTENT")
>> @AttributeOverrides({
>> ...
>> ...
>> ...
>> })
>> @ObjectTypeConverter(name = "charCodeToBooleanConverter", dataType =
>> String.class, objectType = Boolean.class, conversionValues = {
>> @ConversionValue(dataValue = "Y", objectValue = "TRUE"),
>> @ConversionValue(dataValue = "N", objectValue = "FALSE") })
>> @XmlRootElement(name = "content")
>> @XmlType(name = "item")
>> @Cacheable(false)
>> public class Item extends Base {
>> ...
>> }
>>
>> @WebMethod
>> @GET
>> @Path("/item/{contentType}/{id}")
>> @Secured("ROLE_RESTCLIENT")
>> public Base get(@PathParam("id") String contentId,
>> @PathParam("contentType") ContentType contentType)
>> throws WSException;
>>
>> Cheers,
>> Nikolay
>>
>>
>>
>> On 05/28/2012 05:44 PM, Sergey Beryozkin wrote:
>>> Hi
>>> On 28/05/12 15:18, Nikolay Aleksiev wrote:
>>>> Hi,
>>>>
>>>> one more thing. I debugged the JAXBElementProvider. What I noticed is
>>>> that my object is converted to JAXBElement but xsi:type is still
>>>> missing.
>>>>
>>>> When I create JAXB context, marshaller manually and construct a
>>>> JAXBElement, the xsi:type is added.
>>>>
>>>> It seems I'm missing something, but I can't find what.
>>>>
>>>
>>> Can you try the latest 2.4.7 on the 2.4.x branch ?
>>> Or send me the following info:
>>>
>>> - the sample pair of Base and Base1 classes, with all the annotations
>>> which are used on the actual classes that you work with
>>>
>>> - sample JAX-RS method signature, example
>>> @GET
>>> public Base getBase() {
>>> return new Base1();
>>> }
>>>
>>> Cheers, Sergey
>>>
>>>> Thanks for your help!
>>>>
>>>> Regards,
>>>> Nikolay
>>>>
>>>> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>>>>> Hi Nikolay
>>>>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>>>>> Hi Sergey,
>>>>>>
>>>>>> basically - yes. I return a child of com.foo.Base and all the 
>>>>>> parents
>>>>>> have @XMLRootElement. The resource returns the child without 
>>>>>> xsi:type.
>>>>>>
>>>>>> I don't know if this is useful, but when I return collection, the
>>>>>> elements in the collection have xsi:type.
>>>>>>
>>>>>
>>>>> Here is the code I wrote:
>>>>>
>>>>> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>>>>>
>>>>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName())); 
>>>>>
>>>>>
>>>>>
>>>>> provider.setExtraClass(new Class[]{SuperBook.class});
>>>>>
>>>>> Book is the base class, SuperBook extends it. For xsi:type to appear
>>>>> one should have either @XmlSeeAlso({SuperBook.class }) on Book 
>>>>> class or
>>>>> configure the provider as in the code above.
>>>>>
>>>>> Having a jaxb.index package resource will probably do it too.
>>>>>
>>>>> So the jaxbElementClassNames property should only list the return
>>>>> types of various resource methods and subclasses should be listed
>>>>> using one of the options mentioned above.
>>>>>
>>>>> How many base classes like Base.class do you have ? I think if one 
>>>>> has
>>>>> to list more than 3-5 base classes then it will probably make 
>>>>> sense to
>>>>> add wildcard jaxbElementClassNames property
>>>>>
>>>>> Cheers, Sergey
>>>>>
>>>>>
>>>>>> Thanks,
>>>>>> Nikolay
>>>>>>
>>>>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> So, for example, you have
>>>>>>>
>>>>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>>>>> XMLRootElement on both classes ? The resource method returns
>>>>>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>>>>>
>>>>>>> Cheers, Sergey
>>>>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>>>>> Hello,
>>>>>>>>
>>>>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>>>>> class is
>>>>>>>> part of a complex domain hierarchy which looks like this:
>>>>>>>>
>>>>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/
>>>>>>>> and
>>>>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>>>>
>>>>>>>> What I want to achieve is to have "xsi:type" set in the 
>>>>>>>> returned XML
>>>>>>>> when a concrete class instance is used. I went through the
>>>>>>>> documentation
>>>>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>>>>> config:
>>>>>>>>
>>>>>>>> <bean id="jaxbProvider"
>>>>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>>>>> <property name="marshallerProperties"
>>>>>>>> ref="marshallerPropertiesMap" />
>>>>>>>> <property name="jaxbElementClassNames"
>>>>>>>> ref="myJaxbElementClassNames"/>
>>>>>>>> </bean>
>>>>>>>>
>>>>>>>> <util:map id="marshallerPropertiesMap">
>>>>>>>> <entry key="jaxb.encoding">
>>>>>>>> <value type="java.lang.String">UTF-8</value>
>>>>>>>> </entry>
>>>>>>>> </util:map>
>>>>>>>>
>>>>>>>> <util:list id="myJaxbElementClassNames">
>>>>>>>> <value>/com.foo.Base/</value>
>>>>>>>> <value>/com.foo.Base/1</value>
>>>>>>>> <value>/com.foo.Base/2</value>
>>>>>>>> <value>/com.foo.Base/3</value>
>>>>>>>> <value>/com.foo.Concrete1/</value>
>>>>>>>> <value>/com.foo.Concrete2/</value>
>>>>>>>> <value>/com.foo.Concrete3/</value>
>>>>>>>> <value>/com.foo.Concrete4/</value>
>>>>>>>> </util:list>
>>>>>>>>
>>>>>>>> <jaxrs:server id="clientServer" address="/">
>>>>>>>> <jaxrs:providers>
>>>>>>>> <ref bean="systemExceptionMapper" />
>>>>>>>> <ref bean="jaxbProvider" />
>>>>>>>> <ref bean="jsonProvider"/>
>>>>>>>> <ref bean="followUpFilter" />
>>>>>>>> </jaxrs:providers>
>>>>>>>> ...
>>>>>>>> </jaxrs:server>
>>>>>>>>
>>>>>>>> The result is that the xsi:type attribute is not added. All the
>>>>>>>> concrete
>>>>>>>> classes and com.foo.Base have @XMLRootElement annotation (the 
>>>>>>>> other
>>>>>>>> base
>>>>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>>>>
>>>>>>>> I'm using apache 2.4.7.
>>>>>>>>
>>>>>>>> Thanks for the help. Any ideas are welcome!
>>>>>>>>
>>>>>>>> Cheers,
>>>>>>>> Nikolay
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>

Re: Missing xsi:type in derrived types

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi

The following:

@Test
     public void testWriteDerivedType() throws Exception {
         JAXBElementProvider<Base> provider = new 
JAXBElementProvider<Base>();
 
provider.setJaxbElementClassNames(Collections.singletonList(Base.class.getName()));
         Base b = new Item();

         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         provider.writeTo(b, Base.class, Base.class,
                        new Annotation[0], MediaType.TEXT_XML_TYPE, new 
MetadataMap<String, Object>(), bos);
         System.out.println(bos.toString());
     }

     public static abstract class Base0 {
     }

     @XmlType(name = "content")
     @XmlRootElement
     @XmlSeeAlso({ Item.class })
     public static abstract class Base extends Base0 {
     }

     @XmlRootElement(name = "content")
     @XmlType(name = "item")
     public static class Item extends Base {
     }

produces

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:type="item"/>

You are confirming that the code branch to do with wrapping the response 
type in JAXBElement is executed, so I'm not really sure what is missing 
in your case.

Perhaps some of JAXB annotations are not even visible to 
JAXBElementProvider and hence to JAXB Marshaller ? Are you working with 
WebSphere or WebLogic ? I vaguely remember that someone had few problems 
with getting the JAX-RS annotations recognized in one of those containers.

If you can provider a sample test project or just a war then it would 
help me to investigate further.

Please keep me updated,

thanks, Sergey





On 28/05/12 16:12, Nikolay Aleksiev wrote:
> Hi,
>
> I'm already working with the latest 2.4.7. Here is the information:
>
> @MappedSuperclass
> @XmlType(name = "content")
> @XmlRootElement
> @XmlSeeAlso({ Item.class })
> public abstract class Base extends OtherBase implements Comparable<Base> {
> ...
> ...
> }
>
> @Entity
> @Table(name = "CONTENT")
> @AttributeOverrides({
> ...
> ...
> ...
> })
> @ObjectTypeConverter(name = "charCodeToBooleanConverter", dataType =
> String.class, objectType = Boolean.class, conversionValues = {
> @ConversionValue(dataValue = "Y", objectValue = "TRUE"),
> @ConversionValue(dataValue = "N", objectValue = "FALSE") })
> @XmlRootElement(name = "content")
> @XmlType(name = "item")
> @Cacheable(false)
> public class Item extends Base {
> ...
> }
>
> @WebMethod
> @GET
> @Path("/item/{contentType}/{id}")
> @Secured("ROLE_RESTCLIENT")
> public Base get(@PathParam("id") String contentId,
> @PathParam("contentType") ContentType contentType)
> throws WSException;
>
> Cheers,
> Nikolay
>
>
>
> On 05/28/2012 05:44 PM, Sergey Beryozkin wrote:
>> Hi
>> On 28/05/12 15:18, Nikolay Aleksiev wrote:
>>> Hi,
>>>
>>> one more thing. I debugged the JAXBElementProvider. What I noticed is
>>> that my object is converted to JAXBElement but xsi:type is still
>>> missing.
>>>
>>> When I create JAXB context, marshaller manually and construct a
>>> JAXBElement, the xsi:type is added.
>>>
>>> It seems I'm missing something, but I can't find what.
>>>
>>
>> Can you try the latest 2.4.7 on the 2.4.x branch ?
>> Or send me the following info:
>>
>> - the sample pair of Base and Base1 classes, with all the annotations
>> which are used on the actual classes that you work with
>>
>> - sample JAX-RS method signature, example
>> @GET
>> public Base getBase() {
>> return new Base1();
>> }
>>
>> Cheers, Sergey
>>
>>> Thanks for your help!
>>>
>>> Regards,
>>> Nikolay
>>>
>>> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>>>> Hi Nikolay
>>>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>>>> Hi Sergey,
>>>>>
>>>>> basically - yes. I return a child of com.foo.Base and all the parents
>>>>> have @XMLRootElement. The resource returns the child without xsi:type.
>>>>>
>>>>> I don't know if this is useful, but when I return collection, the
>>>>> elements in the collection have xsi:type.
>>>>>
>>>>
>>>> Here is the code I wrote:
>>>>
>>>> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>>>>
>>>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
>>>>
>>>>
>>>> provider.setExtraClass(new Class[]{SuperBook.class});
>>>>
>>>> Book is the base class, SuperBook extends it. For xsi:type to appear
>>>> one should have either @XmlSeeAlso({SuperBook.class }) on Book class or
>>>> configure the provider as in the code above.
>>>>
>>>> Having a jaxb.index package resource will probably do it too.
>>>>
>>>> So the jaxbElementClassNames property should only list the return
>>>> types of various resource methods and subclasses should be listed
>>>> using one of the options mentioned above.
>>>>
>>>> How many base classes like Base.class do you have ? I think if one has
>>>> to list more than 3-5 base classes then it will probably make sense to
>>>> add wildcard jaxbElementClassNames property
>>>>
>>>> Cheers, Sergey
>>>>
>>>>
>>>>> Thanks,
>>>>> Nikolay
>>>>>
>>>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>>>> Hi,
>>>>>>
>>>>>> So, for example, you have
>>>>>>
>>>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>>>> XMLRootElement on both classes ? The resource method returns
>>>>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>>>>
>>>>>> Cheers, Sergey
>>>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>>>> Hello,
>>>>>>>
>>>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>>>> class is
>>>>>>> part of a complex domain hierarchy which looks like this:
>>>>>>>
>>>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/
>>>>>>> and
>>>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>>>
>>>>>>> What I want to achieve is to have "xsi:type" set in the returned XML
>>>>>>> when a concrete class instance is used. I went through the
>>>>>>> documentation
>>>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>>>> config:
>>>>>>>
>>>>>>> <bean id="jaxbProvider"
>>>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>>>> <property name="marshallerProperties"
>>>>>>> ref="marshallerPropertiesMap" />
>>>>>>> <property name="jaxbElementClassNames"
>>>>>>> ref="myJaxbElementClassNames"/>
>>>>>>> </bean>
>>>>>>>
>>>>>>> <util:map id="marshallerPropertiesMap">
>>>>>>> <entry key="jaxb.encoding">
>>>>>>> <value type="java.lang.String">UTF-8</value>
>>>>>>> </entry>
>>>>>>> </util:map>
>>>>>>>
>>>>>>> <util:list id="myJaxbElementClassNames">
>>>>>>> <value>/com.foo.Base/</value>
>>>>>>> <value>/com.foo.Base/1</value>
>>>>>>> <value>/com.foo.Base/2</value>
>>>>>>> <value>/com.foo.Base/3</value>
>>>>>>> <value>/com.foo.Concrete1/</value>
>>>>>>> <value>/com.foo.Concrete2/</value>
>>>>>>> <value>/com.foo.Concrete3/</value>
>>>>>>> <value>/com.foo.Concrete4/</value>
>>>>>>> </util:list>
>>>>>>>
>>>>>>> <jaxrs:server id="clientServer" address="/">
>>>>>>> <jaxrs:providers>
>>>>>>> <ref bean="systemExceptionMapper" />
>>>>>>> <ref bean="jaxbProvider" />
>>>>>>> <ref bean="jsonProvider"/>
>>>>>>> <ref bean="followUpFilter" />
>>>>>>> </jaxrs:providers>
>>>>>>> ...
>>>>>>> </jaxrs:server>
>>>>>>>
>>>>>>> The result is that the xsi:type attribute is not added. All the
>>>>>>> concrete
>>>>>>> classes and com.foo.Base have @XMLRootElement annotation (the other
>>>>>>> base
>>>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>>>
>>>>>>> I'm using apache 2.4.7.
>>>>>>>
>>>>>>> Thanks for the help. Any ideas are welcome!
>>>>>>>
>>>>>>> Cheers,
>>>>>>> Nikolay
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>



Re: Missing xsi:type in derrived types

Posted by Nikolay Aleksiev <ni...@alexiev.net>.
Hi,

I'm already working with the latest 2.4.7. Here is the information:

@MappedSuperclass
@XmlType(name = "content")
@XmlRootElement
@XmlSeeAlso({ Item.class })
public abstract class Base extends OtherBase implements Comparable<Base> {
...
...
}

@Entity
@Table(name = "CONTENT")
@AttributeOverrides({
        ...
        ...
        ...
})
@ObjectTypeConverter(name = "charCodeToBooleanConverter", dataType = 
String.class, objectType = Boolean.class, conversionValues = {
         @ConversionValue(dataValue = "Y", objectValue = "TRUE"),
         @ConversionValue(dataValue = "N", objectValue = "FALSE") })
@XmlRootElement(name = "content")
@XmlType(name = "item")
@Cacheable(false)
public class Item extends Base {
...
}

@WebMethod
     @GET
     @Path("/item/{contentType}/{id}")
     @Secured("ROLE_RESTCLIENT")
     public Base get(@PathParam("id") String contentId, 
@PathParam("contentType") ContentType contentType)
             throws WSException;

Cheers,
Nikolay



On 05/28/2012 05:44 PM, Sergey Beryozkin wrote:
> Hi
> On 28/05/12 15:18, Nikolay Aleksiev wrote:
>> Hi,
>>
>> one more thing. I debugged the JAXBElementProvider. What I noticed is
>> that my object is converted to JAXBElement but xsi:type is still 
>> missing.
>>
>> When I create JAXB context, marshaller manually and construct a
>> JAXBElement, the xsi:type is added.
>>
>> It seems I'm missing something, but I can't find what.
>>
>
> Can you try the latest 2.4.7 on the 2.4.x branch ?
> Or send me the following info:
>
> - the sample pair of Base and Base1 classes, with all the annotations 
> which are used on the actual classes that you work with
>
> - sample JAX-RS method signature, example
> @GET
> public Base getBase() {
>    return new Base1();
> }
>
> Cheers, Sergey
>
>> Thanks for your help!
>>
>> Regards,
>> Nikolay
>>
>> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>>> Hi Nikolay
>>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>>> Hi Sergey,
>>>>
>>>> basically - yes. I return a child of com.foo.Base and all the parents
>>>> have @XMLRootElement. The resource returns the child without xsi:type.
>>>>
>>>> I don't know if this is useful, but when I return collection, the
>>>> elements in the collection have xsi:type.
>>>>
>>>
>>> Here is the code I wrote:
>>>
>>> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>>>
>>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName())); 
>>>
>>>
>>> provider.setExtraClass(new Class[]{SuperBook.class});
>>>
>>> Book is the base class, SuperBook extends it. For xsi:type to appear
>>> one should have either @XmlSeeAlso({SuperBook.class }) on Book class or
>>> configure the provider as in the code above.
>>>
>>> Having a jaxb.index package resource will probably do it too.
>>>
>>> So the jaxbElementClassNames property should only list the return
>>> types of various resource methods and subclasses should be listed
>>> using one of the options mentioned above.
>>>
>>> How many base classes like Base.class do you have ? I think if one has
>>> to list more than 3-5 base classes then it will probably make sense to
>>> add wildcard jaxbElementClassNames property
>>>
>>> Cheers, Sergey
>>>
>>>
>>>> Thanks,
>>>> Nikolay
>>>>
>>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>>> Hi,
>>>>>
>>>>> So, for example, you have
>>>>>
>>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>>> XMLRootElement on both classes ? The resource method returns
>>>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>>>
>>>>> Cheers, Sergey
>>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>>> Hello,
>>>>>>
>>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>>> class is
>>>>>> part of a complex domain hierarchy which looks like this:
>>>>>>
>>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ 
>>>>>> and
>>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>>
>>>>>> What I want to achieve is to have "xsi:type" set in the returned XML
>>>>>> when a concrete class instance is used. I went through the
>>>>>> documentation
>>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>>> config:
>>>>>>
>>>>>> <bean id="jaxbProvider"
>>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>>> <property name="marshallerProperties" 
>>>>>> ref="marshallerPropertiesMap" />
>>>>>> <property name="jaxbElementClassNames" 
>>>>>> ref="myJaxbElementClassNames"/>
>>>>>> </bean>
>>>>>>
>>>>>> <util:map id="marshallerPropertiesMap">
>>>>>> <entry key="jaxb.encoding">
>>>>>> <value type="java.lang.String">UTF-8</value>
>>>>>> </entry>
>>>>>> </util:map>
>>>>>>
>>>>>> <util:list id="myJaxbElementClassNames">
>>>>>> <value>/com.foo.Base/</value>
>>>>>> <value>/com.foo.Base/1</value>
>>>>>> <value>/com.foo.Base/2</value>
>>>>>> <value>/com.foo.Base/3</value>
>>>>>> <value>/com.foo.Concrete1/</value>
>>>>>> <value>/com.foo.Concrete2/</value>
>>>>>> <value>/com.foo.Concrete3/</value>
>>>>>> <value>/com.foo.Concrete4/</value>
>>>>>> </util:list>
>>>>>>
>>>>>> <jaxrs:server id="clientServer" address="/">
>>>>>> <jaxrs:providers>
>>>>>> <ref bean="systemExceptionMapper" />
>>>>>> <ref bean="jaxbProvider" />
>>>>>> <ref bean="jsonProvider"/>
>>>>>> <ref bean="followUpFilter" />
>>>>>> </jaxrs:providers>
>>>>>> ...
>>>>>> </jaxrs:server>
>>>>>>
>>>>>> The result is that the xsi:type attribute is not added. All the
>>>>>> concrete
>>>>>> classes and com.foo.Base have @XMLRootElement annotation (the other
>>>>>> base
>>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>>
>>>>>> I'm using apache 2.4.7.
>>>>>>
>>>>>> Thanks for the help. Any ideas are welcome!
>>>>>>
>>>>>> Cheers,
>>>>>> Nikolay
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>

Re: Missing xsi:type in derrived types

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 28/05/12 15:18, Nikolay Aleksiev wrote:
> Hi,
>
> one more thing. I debugged the JAXBElementProvider. What I noticed is
> that my object is converted to JAXBElement but xsi:type is still missing.
>
> When I create JAXB context, marshaller manually and construct a
> JAXBElement, the xsi:type is added.
>
> It seems I'm missing something, but I can't find what.
>

Can you try the latest 2.4.7 on the 2.4.x branch ?
Or send me the following info:

- the sample pair of Base and Base1 classes, with all the annotations 
which are used on the actual classes that you work with

- sample JAX-RS method signature, example
@GET
public Base getBase() {
    return new Base1();
}

Cheers, Sergey

> Thanks for your help!
>
> Regards,
> Nikolay
>
> On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
>> Hi Nikolay
>> On 23/05/12 09:16, Nikolay Alexiev wrote:
>>> Hi Sergey,
>>>
>>> basically - yes. I return a child of com.foo.Base and all the parents
>>> have @XMLRootElement. The resource returns the child without xsi:type.
>>>
>>> I don't know if this is useful, but when I return collection, the
>>> elements in the collection have xsi:type.
>>>
>>
>> Here is the code I wrote:
>>
>> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>>
>> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
>>
>> provider.setExtraClass(new Class[]{SuperBook.class});
>>
>> Book is the base class, SuperBook extends it. For xsi:type to appear
>> one should have either @XmlSeeAlso({SuperBook.class }) on Book class or
>> configure the provider as in the code above.
>>
>> Having a jaxb.index package resource will probably do it too.
>>
>> So the jaxbElementClassNames property should only list the return
>> types of various resource methods and subclasses should be listed
>> using one of the options mentioned above.
>>
>> How many base classes like Base.class do you have ? I think if one has
>> to list more than 3-5 base classes then it will probably make sense to
>> add wildcard jaxbElementClassNames property
>>
>> Cheers, Sergey
>>
>>
>>> Thanks,
>>> Nikolay
>>>
>>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>>> Hi,
>>>>
>>>> So, for example, you have
>>>>
>>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>>> XMLRootElement on both classes ? The resource method returns
>>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>>
>>>> Cheers, Sergey
>>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>>> Hello,
>>>>>
>>>>> I have a REST service which returns a com.foo.Base class. This
>>>>> class is
>>>>> part of a complex domain hierarchy which looks like this:
>>>>>
>>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and
>>>>> Base3 is extended by multiple Concrete implementors.
>>>>>
>>>>> What I want to achieve is to have "xsi:type" set in the returned XML
>>>>> when a concrete class instance is used. I went through the
>>>>> documentation
>>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my
>>>>> config:
>>>>>
>>>>> <bean id="jaxbProvider"
>>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>>> <property name="marshallerProperties" ref="marshallerPropertiesMap" />
>>>>> <property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
>>>>> </bean>
>>>>>
>>>>> <util:map id="marshallerPropertiesMap">
>>>>> <entry key="jaxb.encoding">
>>>>> <value type="java.lang.String">UTF-8</value>
>>>>> </entry>
>>>>> </util:map>
>>>>>
>>>>> <util:list id="myJaxbElementClassNames">
>>>>> <value>/com.foo.Base/</value>
>>>>> <value>/com.foo.Base/1</value>
>>>>> <value>/com.foo.Base/2</value>
>>>>> <value>/com.foo.Base/3</value>
>>>>> <value>/com.foo.Concrete1/</value>
>>>>> <value>/com.foo.Concrete2/</value>
>>>>> <value>/com.foo.Concrete3/</value>
>>>>> <value>/com.foo.Concrete4/</value>
>>>>> </util:list>
>>>>>
>>>>> <jaxrs:server id="clientServer" address="/">
>>>>> <jaxrs:providers>
>>>>> <ref bean="systemExceptionMapper" />
>>>>> <ref bean="jaxbProvider" />
>>>>> <ref bean="jsonProvider"/>
>>>>> <ref bean="followUpFilter" />
>>>>> </jaxrs:providers>
>>>>> ...
>>>>> </jaxrs:server>
>>>>>
>>>>> The result is that the xsi:type attribute is not added. All the
>>>>> concrete
>>>>> classes and com.foo.Base have @XMLRootElement annotation (the other
>>>>> base
>>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>>
>>>>> I'm using apache 2.4.7.
>>>>>
>>>>> Thanks for the help. Any ideas are welcome!
>>>>>
>>>>> Cheers,
>>>>> Nikolay
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>
>>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Missing xsi:type in derrived types

Posted by Nikolay Aleksiev <ni...@alexiev.net>.
Hi,

one more thing. I debugged the JAXBElementProvider. What I noticed is 
that my object is converted to JAXBElement but xsi:type is still missing.

When I create JAXB context, marshaller manually and construct a 
JAXBElement, the xsi:type is added.

It seems I'm missing something, but I can't find what.

Thanks for your help!

Regards,
Nikolay

On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
> Hi Nikolay
> On 23/05/12 09:16, Nikolay Alexiev wrote:
>> Hi Sergey,
>>
>> basically - yes. I return a child of com.foo.Base and all the parents
>> have @XMLRootElement. The resource returns the child without xsi:type.
>>
>> I don't know if this is useful, but when I return collection, the
>> elements in the collection have xsi:type.
>>
>
> Here is the code I wrote:
>
> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>
> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName())); 
>
> provider.setExtraClass(new Class[]{SuperBook.class});
>
> Book is the base class, SuperBook extends it. For xsi:type to appear 
> one should have either @XmlSeeAlso({SuperBook.class }) on Book class or
> configure the provider as in the code above.
>
> Having a jaxb.index package resource will probably do it too.
>
> So the jaxbElementClassNames property should only list the return 
> types of various resource methods and subclasses should be listed 
> using one of the options mentioned above.
>
> How many base classes like Base.class do you have ? I think if one has 
> to list more than 3-5 base classes then it will probably make sense to 
> add wildcard jaxbElementClassNames property
>
> Cheers, Sergey
>
>
>> Thanks,
>> Nikolay
>>
>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>> Hi,
>>>
>>> So, for example, you have
>>>
>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>> XMLRootElement on both classes ? The resource method returns
>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>
>>> Cheers, Sergey
>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>> Hello,
>>>>
>>>> I have a REST service which returns a com.foo.Base class. This 
>>>> class is
>>>> part of a complex domain hierarchy which looks like this:
>>>>
>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and
>>>> Base3 is extended by multiple Concrete implementors.
>>>>
>>>> What I want to achieve is to have "xsi:type" set in the returned XML
>>>> when a concrete class instance is used. I went through the 
>>>> documentation
>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my 
>>>> config:
>>>>
>>>> <bean id="jaxbProvider"
>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>> <property name="marshallerProperties" ref="marshallerPropertiesMap" />
>>>> <property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
>>>> </bean>
>>>>
>>>> <util:map id="marshallerPropertiesMap">
>>>> <entry key="jaxb.encoding">
>>>> <value type="java.lang.String">UTF-8</value>
>>>> </entry>
>>>> </util:map>
>>>>
>>>> <util:list id="myJaxbElementClassNames">
>>>> <value>/com.foo.Base/</value>
>>>> <value>/com.foo.Base/1</value>
>>>> <value>/com.foo.Base/2</value>
>>>> <value>/com.foo.Base/3</value>
>>>> <value>/com.foo.Concrete1/</value>
>>>> <value>/com.foo.Concrete2/</value>
>>>> <value>/com.foo.Concrete3/</value>
>>>> <value>/com.foo.Concrete4/</value>
>>>> </util:list>
>>>>
>>>> <jaxrs:server id="clientServer" address="/">
>>>> <jaxrs:providers>
>>>> <ref bean="systemExceptionMapper" />
>>>> <ref bean="jaxbProvider" />
>>>> <ref bean="jsonProvider"/>
>>>> <ref bean="followUpFilter" />
>>>> </jaxrs:providers>
>>>> ...
>>>> </jaxrs:server>
>>>>
>>>> The result is that the xsi:type attribute is not added. All the 
>>>> concrete
>>>> classes and com.foo.Base have @XMLRootElement annotation (the other 
>>>> base
>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>
>>>> I'm using apache 2.4.7.
>>>>
>>>> Thanks for the help. Any ideas are welcome!
>>>>
>>>> Cheers,
>>>> Nikolay
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>
>

Re: Missing xsi:type in derrived types

Posted by Nikolay Aleksiev <ni...@alexiev.net>.
Hi Sergey,

I simplified my code. Now I have only two class Base and Item (Item 
extends Base). My resource method returns base and base has both 
@XMLRootElement and @XMLSeeAlso({Item.class}). I added jaxb.index and 
modified my config so that only Base is in JaxbElementClassNames.

And.. still no success.

Any ideas?

Regards,
Nikolay

On 05/23/2012 01:20 PM, Sergey Beryozkin wrote:
> Hi Nikolay
> On 23/05/12 09:16, Nikolay Alexiev wrote:
>> Hi Sergey,
>>
>> basically - yes. I return a child of com.foo.Base and all the parents
>> have @XMLRootElement. The resource returns the child without xsi:type.
>>
>> I don't know if this is useful, but when I return collection, the
>> elements in the collection have xsi:type.
>>
>
> Here is the code I wrote:
>
> JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
>
> provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName())); 
>
> provider.setExtraClass(new Class[]{SuperBook.class});
>
> Book is the base class, SuperBook extends it. For xsi:type to appear 
> one should have either @XmlSeeAlso({SuperBook.class }) on Book class or
> configure the provider as in the code above.
>
> Having a jaxb.index package resource will probably do it too.
>
> So the jaxbElementClassNames property should only list the return 
> types of various resource methods and subclasses should be listed 
> using one of the options mentioned above.
>
> How many base classes like Base.class do you have ? I think if one has 
> to list more than 3-5 base classes then it will probably make sense to 
> add wildcard jaxbElementClassNames property
>
> Cheers, Sergey
>
>
>> Thanks,
>> Nikolay
>>
>> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>>> Hi,
>>>
>>> So, for example, you have
>>>
>>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>>> XMLRootElement on both classes ? The resource method returns
>>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>>
>>> Cheers, Sergey
>>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>>> Hello,
>>>>
>>>> I have a REST service which returns a com.foo.Base class. This 
>>>> class is
>>>> part of a complex domain hierarchy which looks like this:
>>>>
>>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and
>>>> Base3 is extended by multiple Concrete implementors.
>>>>
>>>> What I want to achieve is to have "xsi:type" set in the returned XML
>>>> when a concrete class instance is used. I went through the 
>>>> documentation
>>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my 
>>>> config:
>>>>
>>>> <bean id="jaxbProvider"
>>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>>> <property name="marshallerProperties" ref="marshallerPropertiesMap" />
>>>> <property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
>>>> </bean>
>>>>
>>>> <util:map id="marshallerPropertiesMap">
>>>> <entry key="jaxb.encoding">
>>>> <value type="java.lang.String">UTF-8</value>
>>>> </entry>
>>>> </util:map>
>>>>
>>>> <util:list id="myJaxbElementClassNames">
>>>> <value>/com.foo.Base/</value>
>>>> <value>/com.foo.Base/1</value>
>>>> <value>/com.foo.Base/2</value>
>>>> <value>/com.foo.Base/3</value>
>>>> <value>/com.foo.Concrete1/</value>
>>>> <value>/com.foo.Concrete2/</value>
>>>> <value>/com.foo.Concrete3/</value>
>>>> <value>/com.foo.Concrete4/</value>
>>>> </util:list>
>>>>
>>>> <jaxrs:server id="clientServer" address="/">
>>>> <jaxrs:providers>
>>>> <ref bean="systemExceptionMapper" />
>>>> <ref bean="jaxbProvider" />
>>>> <ref bean="jsonProvider"/>
>>>> <ref bean="followUpFilter" />
>>>> </jaxrs:providers>
>>>> ...
>>>> </jaxrs:server>
>>>>
>>>> The result is that the xsi:type attribute is not added. All the 
>>>> concrete
>>>> classes and com.foo.Base have @XMLRootElement annotation (the other 
>>>> base
>>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>>
>>>> I'm using apache 2.4.7.
>>>>
>>>> Thanks for the help. Any ideas are welcome!
>>>>
>>>> Cheers,
>>>> Nikolay
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>
>

Re: Missing xsi:type in derrived types

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Nikolay
On 23/05/12 09:16, Nikolay Alexiev wrote:
> Hi Sergey,
>
> basically - yes. I return a child of com.foo.Base and all the parents
> have @XMLRootElement. The resource returns the child without xsi:type.
>
> I don't know if this is useful, but when I return collection, the
> elements in the collection have xsi:type.
>

Here is the code I wrote:

JAXBElementProvider<Book> provider = new JAXBElementProvider<Book>();
 
provider.setJaxbElementClassNames(Collections.singletonList(Book.class.getName()));
provider.setExtraClass(new Class[]{SuperBook.class});

Book is the base class, SuperBook extends it. For xsi:type to appear one 
should have either @XmlSeeAlso({SuperBook.class }) on Book class or
configure the provider as in the code above.

Having a jaxb.index package resource will probably do it too.

So the jaxbElementClassNames property should only list the return types 
of various resource methods and subclasses should be listed using one of 
the options mentioned above.

How many base classes like Base.class do you have ? I think if one has 
to list more than 3-5 base classes then it will probably make sense to 
add wildcard jaxbElementClassNames property

Cheers, Sergey


> Thanks,
> Nikolay
>
> On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
>> Hi,
>>
>> So, for example, you have
>>
>> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with
>> XMLRootElement on both classes ? The resource method returns
>> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>>
>> Cheers, Sergey
>> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>>> Hello,
>>>
>>> I have a REST service which returns a com.foo.Base class. This class is
>>> part of a complex domain hierarchy which looks like this:
>>>
>>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and
>>> Base3 is extended by multiple Concrete implementors.
>>>
>>> What I want to achieve is to have "xsi:type" set in the returned XML
>>> when a concrete class instance is used. I went through the documentation
>>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my config:
>>>
>>> <bean id="jaxbProvider"
>>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>>> <property name="marshallerProperties" ref="marshallerPropertiesMap" />
>>> <property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
>>> </bean>
>>>
>>> <util:map id="marshallerPropertiesMap">
>>> <entry key="jaxb.encoding">
>>> <value type="java.lang.String">UTF-8</value>
>>> </entry>
>>> </util:map>
>>>
>>> <util:list id="myJaxbElementClassNames">
>>> <value>/com.foo.Base/</value>
>>> <value>/com.foo.Base/1</value>
>>> <value>/com.foo.Base/2</value>
>>> <value>/com.foo.Base/3</value>
>>> <value>/com.foo.Concrete1/</value>
>>> <value>/com.foo.Concrete2/</value>
>>> <value>/com.foo.Concrete3/</value>
>>> <value>/com.foo.Concrete4/</value>
>>> </util:list>
>>>
>>> <jaxrs:server id="clientServer" address="/">
>>> <jaxrs:providers>
>>> <ref bean="systemExceptionMapper" />
>>> <ref bean="jaxbProvider" />
>>> <ref bean="jsonProvider"/>
>>> <ref bean="followUpFilter" />
>>> </jaxrs:providers>
>>> ...
>>> </jaxrs:server>
>>>
>>> The result is that the xsi:type attribute is not added. All the concrete
>>> classes and com.foo.Base have @XMLRootElement annotation (the other base
>>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>>
>>> I'm using apache 2.4.7.
>>>
>>> Thanks for the help. Any ideas are welcome!
>>>
>>> Cheers,
>>> Nikolay
>>>
>>>
>>>
>>>
>>
>>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: Missing xsi:type in derrived types

Posted by Nikolay Alexiev <ni...@alexiev.net>.
Hi Sergey,

basically - yes. I return a child of com.foo.Base and all the parents 
have @XMLRootElement. The resource returns the child without xsi:type.

I don't know if this is useful, but when I return collection, the 
elements in the collection have xsi:type.

Thanks,
Nikolay

On 05/23/2012 12:09 AM, Sergey Beryozkin wrote:
> Hi,
>
> So, for example, you have
>
> com.foo.Base and com.foo.Base1 (extending com.foo.Base) with 
> XMLRootElement on both classes ? The resource method returns
> com.foo.Base, when Base1 is returned no xsi:type is added, right ?
>
> Cheers, Sergey
> On 22/05/12 16:52, Nikolay Aleksiev wrote:
>> Hello,
>>
>> I have a REST service which returns a com.foo.Base class. This class is
>> part of a complex domain hierarchy which looks like this:
>>
>> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and
>> Base3 is extended by multiple Concrete implementors.
>>
>> What I want to achieve is to have "xsi:type" set in the returned XML
>> when a concrete class instance is used. I went through the documentation
>> and added "JaxbElementClassNames" to my JAXBProvider. Here is my config:
>>
>> <bean id="jaxbProvider"
>> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
>> <property name="marshallerProperties" ref="marshallerPropertiesMap" />
>> <property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
>> </bean>
>>
>> <util:map id="marshallerPropertiesMap">
>> <entry key="jaxb.encoding">
>> <value type="java.lang.String">UTF-8</value>
>> </entry>
>> </util:map>
>>
>> <util:list id="myJaxbElementClassNames">
>> <value>/com.foo.Base/</value>
>> <value>/com.foo.Base/1</value>
>> <value>/com.foo.Base/2</value>
>> <value>/com.foo.Base/3</value>
>> <value>/com.foo.Concrete1/</value>
>> <value>/com.foo.Concrete2/</value>
>> <value>/com.foo.Concrete3/</value>
>> <value>/com.foo.Concrete4/</value>
>> </util:list>
>>
>> <jaxrs:server id="clientServer" address="/">
>> <jaxrs:providers>
>> <ref bean="systemExceptionMapper" />
>> <ref bean="jaxbProvider" />
>> <ref bean="jsonProvider"/>
>> <ref bean="followUpFilter" />
>> </jaxrs:providers>
>> ...
>> </jaxrs:server>
>>
>> The result is that the xsi:type attribute is not added. All the concrete
>> classes and com.foo.Base have @XMLRootElement annotation (the other base
>> ones DO NOT). @XMLSeeAlso is added in all the classes.
>>
>> I'm using apache 2.4.7.
>>
>> Thanks for the help. Any ideas are welcome!
>>
>> Cheers,
>> Nikolay
>>
>>
>>
>>
>
>

Re: Missing xsi:type in derrived types

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi,

So, for example, you have

com.foo.Base and com.foo.Base1 (extending com.foo.Base) with 
XMLRootElement on both classes ? The resource method returns
com.foo.Base, when Base1 is returned no xsi:type is added, right ?

Cheers, Sergey
On 22/05/12 16:52, Nikolay Aleksiev wrote:
> Hello,
>
> I have a REST service which returns a com.foo.Base class. This class is
> part of a complex domain hierarchy which looks like this:
>
> /com.foo.Base -> com.foo.Base1 -> com.foo.Base2 -> com.foo.Base3/ and
> Base3 is extended by multiple Concrete implementors.
>
> What I want to achieve is to have "xsi:type" set in the returned XML
> when a concrete class instance is used. I went through the documentation
> and added "JaxbElementClassNames" to my JAXBProvider. Here is my config:
>
> <bean id="jaxbProvider"
> class="org.apache.cxf.jaxrs.provider.JAXBElementProvider">
> <property name="marshallerProperties" ref="marshallerPropertiesMap" />
> <property name="jaxbElementClassNames" ref="myJaxbElementClassNames"/>
> </bean>
>
> <util:map id="marshallerPropertiesMap">
> <entry key="jaxb.encoding">
> <value type="java.lang.String">UTF-8</value>
> </entry>
> </util:map>
>
> <util:list id="myJaxbElementClassNames">
> <value>/com.foo.Base/</value>
> <value>/com.foo.Base/1</value>
> <value>/com.foo.Base/2</value>
> <value>/com.foo.Base/3</value>
> <value>/com.foo.Concrete1/</value>
> <value>/com.foo.Concrete2/</value>
> <value>/com.foo.Concrete3/</value>
> <value>/com.foo.Concrete4/</value>
> </util:list>
>
> <jaxrs:server id="clientServer" address="/">
> <jaxrs:providers>
> <ref bean="systemExceptionMapper" />
> <ref bean="jaxbProvider" />
> <ref bean="jsonProvider"/>
> <ref bean="followUpFilter" />
> </jaxrs:providers>
> ...
> </jaxrs:server>
>
> The result is that the xsi:type attribute is not added. All the concrete
> classes and com.foo.Base have @XMLRootElement annotation (the other base
> ones DO NOT). @XMLSeeAlso is added in all the classes.
>
> I'm using apache 2.4.7.
>
> Thanks for the help. Any ideas are welcome!
>
> Cheers,
> Nikolay
>
>
>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com