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