It has been a few dreadful days :-(

I eventually get everything working. The first thing I did was to get
rid of the interfaces in EMF genmodel. Essentially, you can change a
flag to suppress separating interfaces and implementation classes.

In addition to that, using @XmlSeeAlso helps not only in marshalling
but also unmarshalling.

Finally, do not use @XmlMixed together with @XmlElement and
@XmlElements. I added this flag accidentally, and it causes my program
to crash without meaningful debug/output messages --- took me at least
a full day to realize...

Haven't got a chance to try XmlJavaTypeAdapters, will do so later...

Thanks everyone!
-Simon

On Tue, Apr 19, 2011 at 7:15 AM, Sergey Beryozkin <[email protected]> wrote:
> HI Simon
>
> On Tue, Apr 19, 2011 at 1:26 AM, Simon Chen <[email protected]> wrote:
>> (Sorry Sergey for the dup message, I forgot to reply to all last time...)
>>
>
> No problems, we'd just update the list aftewards otherwise:-)
>
>> It seems that I get all sorts of weird issues with EMF+JAXB.
>>
>> For example, if I have a base class of Customer and two inherited
>> classes of GoodCustomer and BadCustomer.
>> Then I have a WebStore as a
>> container for a list of Customer objects. The mind-twisting (for me at
>> least) problem is that if Customer is not defined as abstract in the
>> ecore model, I cannot even create the JAXBContext for WebStore (well,
>> actually WebStoreImpl for EMF), with a NoSuchElementException. If I
>> change Customer to be abstract, then at least it works in this aspect.
>>
>> I tried plain java classes (hand-written, without interface/impl,
>> without proxy), it works no matter Customer is abstract or not...
>
> What is WebStore, is it a root resource class or JAXB bean which your
> JAX-RS service returns/updates ?
> May be you have to add @XmlJavaTypeAdapter to WebStore field which
> keeps the list of Customer interface impls...
>
> Cheers, Sergey
>
>>
>> -Simon
>>
>> On Mon, Apr 18, 2011 at 11:02 AM, Sergey Beryozkin <[email protected]> 
>> wrote:
>>> Sorry for the noise, I think I've got totally confused - no @XmlSeeAlso has
>>> to be added to subclasses. But, I have a test where
>>>
>>> SuperBook extends Book, Book has @XmlSeeAlso pointing to SuperBook, and
>>> without using JAXBElement (internally), xsi:type is not written when Book is
>>> returned, however, no extra classes or jaxb.index is used, so that might
>>> explain why...
>>>
>>> Cheers, Sergey
>>>
>>>
>>>
>>> On Mon, Apr 18, 2011 at 3:57 PM, Sergey Beryozkin <[email protected]>
>>> wrote:
>>>>
>>>> That should work with adapters too, with @XmlSeeAlso.
>>>>
>>>> Actually, I remember now what adding a jaxbElementClassNames property
>>>> (containing a CustomerImpl full class name only in this particular 
>>>> case) can
>>>> do, it may help with avoiding adding @XmlSeeAlso to subclasses, I see a 
>>>> test
>>>> where only a base class has @XmlSeeAlso - somehow JAXBElement figures it 
>>>> out
>>>> that xsi:type has to be added...
>>>> Adding jaxb.index  extra classes for JAXBContext to include them should
>>>> also help...
>>>>
>>>> thanks, Sergey
>>>>
>>>> On Mon, Apr 18, 2011 at 3:36 PM, Daniel Kulp <[email protected]> wrote:
>>>>>
>>>>> When dealing with polymorphism with JAXB, one thing that is often
>>>>> required is
>>>>> to add XmlSeeAlso annotations all over the place.  In particular, on the
>>>>> base
>>>>> class, it's  useful to have XmlSeeAlso point at the potential subclasses.
>>>>> This allows the jaxb runtime to find the subclasses to instantiate and
>>>>> will
>>>>> usually result in the proper xsi:type attributes written out and such.
>>>>>
>>>>> If you haven't already tried it, I'd definitely suggest adding the
>>>>> annotation
>>>>> and seeing if that helps.
>>>>>
>>>>> Dan
>>>>>
>>>>>
>>>>> On Friday 15 April 2011 4:02:17 PM Simon Chen wrote:
>>>>> > Hi all,
>>>>> >
>>>>> > I've been playing with building a REST web service to handle
>>>>> > polymorphism... It's a long post, but bear with me :-)
>>>>> >
>>>>> > In particular, I may have:
>>>>> >
>>>>> > @Path("/")
>>>>> > class WebStore {
>>>>> >   @POST
>>>>> >   @Path("/customers/")
>>>>> >   Response addCustomer(Customer c) {
>>>>> >     ...
>>>>> >   }
>>>>> > }
>>>>> >
>>>>> > But I have a base class of Customer, but also inherited classes of
>>>>> > AwesomeCustomer, and SuperAwesomeCustomer. Things get more complicated
>>>>> > when EMF kicks in, where I actually have a Customer interface and
>>>>> > CustomerImpl class.
>>>>> >
>>>>> > The previous declaration doesn't work when I post a customer XML
>>>>> > snippet,
>>>>> > say: <customer><name>simon</name></customer>
>>>>> >
>>>>> > Because Customer is an interface, so cannot be annotated with
>>>>> > @XmlRootElement. As a result, the error of "no message body reader can
>>>>> > be found" is raised...
>>>>> >
>>>>> > If we change the POST function this way, it can work:
>>>>> >   @POST
>>>>> >   @Path("/customers/")
>>>>> >   Response addCustomer(CustomerImpl c) {
>>>>> >     ...
>>>>> >   }
>>>>> >
>>>>> > But, this breaks again, when I add the following:
>>>>> >   @POST
>>>>> >   @Path("/customers/")
>>>>> >   Response addCustomer(CustomerImpl c) {
>>>>> >     ...
>>>>> >   }
>>>>> >   @POST
>>>>> >   @Path("/customers/")
>>>>> >   Response addCustomer(AwesomeCustomerImpl c) {
>>>>> >     ...
>>>>> >   }
>>>>> >   @POST
>>>>> >   @Path("/customers/")
>>>>> >   Response addCustomer(SuperAwesomeCustomerImpl c) {
>>>>> >     ...
>>>>> >   }
>>>>> >
>>>>> > Here, if I post a SuperAwesomeCustomerImpl object to "/customers", the
>>>>> > ws would find all the functions that can handle "POST to /customers",
>>>>> > which will include all three functions above. However, in
>>>>> >
>>>>> > "src/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.
>>>>> > java", public static OperationResourceInfo findTargetMethod(), we have:
>>>>> >
>>>>> >         if (!candidateList.isEmpty()) {
>>>>> >             Map.Entry<OperationResourceInfo, MultivaluedMap<String,
>>>>> > String>> firstEntry =
>>>>> >                 candidateList.entrySet().iterator().next();
>>>>> >             //---------> This only looks at the first function that
>>>>> > matches, while not look at the class hierarchy...
>>>>> >             values.clear();
>>>>> >             values.putAll(firstEntry.getValue());
>>>>> >             OperationResourceInfo ori = firstEntry.getKey();
>>>>> >
>>>>> >
>>>>> > Hopefully, I am not overwhelming everyone with too much information.
>>>>> > But is there a fix to this problem? I guess maybe add some class
>>>>> > hierarchy-awareness to findTargetMethod()?
>>>>> >
>>>>> > Thanks!
>>>>> > -Simon
>>>>>
>>>>> --
>>>>> Daniel Kulp
>>>>> [email protected]
>>>>> http://dankulp.com/blog
>>>>> Talend - http://www.talend.com
>>>>
>>>>
>>>> Application Integration Division of Talend
>>>> http://sberyozkin.blogspot.com
>>>
>>>
>>>
>>> --
>>> Sergey Beryozkin
>>>
>>> Application Integration Division of Talend
>>> http://sberyozkin.blogspot.com
>>>
>>
>

Reply via email to