Hi

At the moment JAXBElementProvider is capable of working with
@XmlJavaTypeAdapter but it does not check the interfaces. The workaround :
add @XmlJavaTypeAdapter as a method annotation to getAll() or to
BaseballCardImpl

Regarding the limited WADL description : the generator can not get much info
from the BaseballCard interface, so you may want to add
org.apache.cxf.jaxrs.ext.xml.XmlName annotation to it...

cheers, Sergey

On Wed, Jun 16, 2010 at 7:09 PM, Daniel Kulp <[email protected]> wrote:

>
> This is probably a bug in the CXF JAXB Provider.  It's probably just
> grabbing
> the "raw" class files and not really looking for the XmlJavaTypeAdapter
> things.    Can you create a small test case and attach to a JIRA?
>
> Dan
>
>
> On Tuesday 15 June 2010 3:49:04 pm peter.giles wrote:
> > Hello CXF cognoscenti,
> >
> > I'm trying to get a test service working that uses an interface for my
> > return type and am running into trouble.  I am under the possibly false
> > impression that I should be able to get this to work using an
> > @XmlJavaTypeAdapter (JAXB style -- see
> >
> https://jaxb.dev.java.net/guide/Mapping_interfaces.html#Use__XmlJavaTypeAda
> > pter). When I try to access my service I get "JAXBException occurred : 2
> > counts of IllegalAnnotationExceptions. "  Here's the error from tomcat
> log
> > with hopefully enough stack context:
> >
> > Jun 15, 2010 11:59:14 AM
> org.apache.cxf.jaxrs.provider.AbstractJAXBProvider
> > handleJAXBException
> > WARNING: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2
> counts
> > of IllegalAnnotationExceptions
> > service.BaseballCard is an interface, and JAXB can't handle interfaces.
> >       this problem is related to the following location:
> >               at service.BaseballCard
> > service.BaseballCard does not have a no-arg default constructor.
> >       this problem is related to the following location:
> >               at service.BaseballCard
> >
> >       at
> >
> com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(Illeg
> > alAnnotationsException.java:102) at
> >
> com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.
> > java:472) at
> >
> com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302
> > ) at
> >
> com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBCo
> > ntextImpl.java:1136) at
> > com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154)
> >       at
> > com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121)
> >       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> >       at
> >
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:3
> > 9) at
> >
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImp
> > l.java:25) at java.lang.reflect.Method.invoke(Method.java:597)
> >       at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
> >       at javax.xml.bind.ContextFinder.find(ContextFinder.java:363)
> >       at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
> >       at
> >
> org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getClassContext(Abstract
> > JAXBProvider.java:351) at
> >
> org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getJAXBContext(AbstractJ
> > AXBProvider.java:344) at
> >
> org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getJaxbQName(AbstractJAX
> > BProvider.java:258) at
> >
> org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getCollectionWrapperQNam
> > e(AbstractJAXBProvider.java:221) at
> >
> org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollection(JAXBEle
> > mentProvider.java:258) at
> >
> org.apache.cxf.jaxrs.provider.JAXBElementProvider.writeTo(JAXBElementProvid
> > er.java:233) at
> >
> org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRS
> > OutInterceptor.java:241) *snip*
> >
> > I thought this was what the type adapter was supposed to take care of --
> do
> > I need to do something special to point out the type adapter to CXF?  I
> > apologize for the amount of code here, but I've stripped my test to the
> > bare minimum.  Here it is:
> >
> > @Path("/collection/") @Produces("application/xml")
> > public interface BaseballCardCollectionService {
> >
> >     @GET
> >     public List<BaseballCard> getAll();
> >
> >     @POST
> >     @Path("/BaseballCard")
> >     public Integer add(BaseballCard card);
> > }
> >
> > @XmlJavaTypeAdapter(BaseballCardImpl.BaseballCardAdapter.class)
> > public interface BaseballCard {
> >
> >     public String getPlayerName();
> >     public String getCardType();
> >     public Integer getYear();
> >
> > }
> >
> > @XmlRootElement
> > public class BaseballCardImpl implements BaseballCard {
> >
> >     private String cardType;
> >     private String playerName;
> >     private Integer year;
> >
> >     public BaseballCardImpl() {}
> >
> >     public BaseballCardImpl(String playerName, String cardType, Integer
> > year) {
> >         this.playerName = playerName;
> >         this.cardType = cardType;
> >         this.year = year;
> >     }
> >
> >     public void setCardType(String cardType) { this.cardType = cardType;
> }
> >     public void setPlayerName(String playerName) { this.playerName =
> > playerName; }
> >     public void setYear(Integer year) { this.year = year; }
> >     public String getCardType() { return cardType; }
> >     public String getPlayerName() { return playerName; }
> >     public Integer getYear() { return year; };
> >
> >     public static class BaseballCardAdapter extends
> > XmlAdapter<BaseballCardImpl, BaseballCard> {
> >
> >         @Override
> >         public BaseballCardImpl marshal(BaseballCard v) throws Exception
> {
> >             return new BaseballCardImpl(v.getPlayerName(),
> v.getCardType(),
> > v.getYear());
> >         }
> >
> >         @Override
> >         public BaseballCard unmarshal(BaseballCardImpl v) throws
> Exception
> > { return v; }
> >     }
> > }
> >
> > public class BaseballCardCollectionServiceImpl implements
> > BaseballCardCollectionService {
> >
> >     private Map<Integer, BaseballCard> cards = new
> > ConcurrentHashMap<Integer, BaseballCard>();
> >     private AtomicInteger nextId = new AtomicInteger(1);
> >
> >     public BaseballCardCollectionServiceImpl() {
> >         add(new BaseballCardImpl("Leroy Paige", "Leaf", 1949));
> >     }
> >
> >     public Integer add(BaseballCard card) {
> >         Integer result = null;
> >         if (card != null) {
> >             int id = nextId.addAndGet(1);
> >             cards.put(id, card);
> >             result = id;
> >         }
> >         return result;
> >     }
> >
> >     public List<BaseballCard> getAll() {
> >         return new ArrayList<BaseballCard>(cards.values());
> >     }
> >
> > }
> >
> > Here is the important part of my spring config:
> >
> >     <import resource="classpath:META-INF/cxf/cxf.xml" />
> >     <import
> > resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
> >     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
> >
> >     <jaxrs:server id="collectionService" address="/">
> >         <jaxrs:serviceBeans>
> >             <ref bean="collectionImpl" />
> >         </jaxrs:serviceBeans>
> >         <jaxrs:extensionMappings>
> >             <entry key="xml" value="application/xml" />
> >         </jaxrs:extensionMappings>
> >     </jaxrs:server>
> >
> >     <bean id="collectionImpl"
> > class="service.BaseballCardCollectionServiceImpl" />
> >
> > The URL I'm hitting for my service is
> > http://localhost:8080/cxf-rest-example/collection/ which gives me the
> short
> > version of the error message.  I can see the wadl at
> > http://localhost:8080/cxf-rest-example/collection?_wadl&_type=xml but I
> > must admit that I don't know anything about wadl so I am not getting any
> > clues from it:
> >
> > <application>
> >  <grammars/>
> >   <resources base="http://localhost:8080/cxf-rest-example/";>
> >    <resource path="/collection/">
> >     <method name="GET">
> >      <response>
> >       <representation mediaType="application/xml"/>
> >      </response>
> >     </method>
> >     <resource path="BaseballCard">
> >      <method name="POST">
> >       <request>
> >        <representation mediaType="*/*"/>
> >       </request>
> >       <response>
> >        <!-- Primitive type : xs:int -->
> >        <representation mediaType="application/xml"/>
> >       </response>
> >     </method>
> >    </resource>
> >   </resource>
> >  </resources>
> > </application>
> >
> > Does anybody see what am I doing wrong?
> >
> > Thank you!
> > Peter Giles
>
> --
> Daniel Kulp
> [email protected]
> http://dankulp.com/blog
>

Reply via email to