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.

Reply via email to