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 >
