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__XmlJavaTypeAdapter).
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(IllegalAnnotationsException.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(JAXBContextImpl.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:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.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(AbstractJAXBProvider.java:351)
at
org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getJAXBContext(AbstractJAXBProvider.java:344)
at
org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getJaxbQName(AbstractJAXBProvider.java:258)
at
org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getCollectionWrapperQName(AbstractJAXBProvider.java:221)
at
org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollection(JAXBElementProvider.java:258)
at
org.apache.cxf.jaxrs.provider.JAXBElementProvider.writeTo(JAXBElementProvider.java:233)
at
org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.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
--
View this message in context:
http://old.nabble.com/JAX-RS-service-w--interface-result-type%2C--%40XmlJavaTypeAdapter-tp28895564p28895564.html
Sent from the cxf-user mailing list archive at Nabble.com.