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
