The problem turns out to be a simple missing Accept header:
Accept: application/json
Adding this to the request resolves the problem.
سؤال
I'm getting the following error:
WARNING: No message body writer has been found for response class ArrayList.
On the following code:
@GET
@Consumes("application/json")
public List getBridges() {
return new ArrayList(bridges);
}
I know it's possible for CXF to handle this case because I've done it before - with a platform that defined the CXF and related maven artifacts behind the scenes (i.e. I didn't know how it was done).
So, the question: how can I get CXF to support this without adding XML bindings or other source code modifications?
Note the following answer addressed the same problem with XML bindings, which is not satisfactory for my case: No message body writer has been found for response class ArrayList
المحلول
The problem turns out to be a simple missing Accept header:
Accept: application/json
Adding this to the request resolves the problem.
نصائح أخرى
The best thing is indeed to use Jackson. The following post gives a great description of why and how to do it.
for your convinience I've summerized the main things:
You will need to set Jackson as the provider, the best way to do it is to use your custom Application overriding javax.ws.rs.core.Application
you will need to add the following code
@Override
public Set<Object> getSingletons() {
Set<Object> s = new HashSet<Object>();
// Register the Jackson provider for JSON
// Make (de)serializer use a subset of JAXB and (afterwards) Jackson annotations
// See http://wiki.fasterxml.com/JacksonJAXBAnnotations for more information
ObjectMapper mapper = new ObjectMapper();
AnnotationIntrospector primary = new JaxbAnnotationIntrospector();
AnnotationIntrospector secondary = new JacksonAnnotationIntrospector();
AnnotationIntrospector pair = new AnnotationIntrospector.Pair(primary, secondary);
mapper.getDeserializationConfig().setAnnotationIntrospector(pair);
mapper.getSerializationConfig().setAnnotationIntrospector(pair);
// Set up the provider
JacksonJaxbJsonProvider jaxbProvider = new JacksonJaxbJsonProvider();
jaxbProvider.setMapper(mapper);
s.add(jaxbProvider);
return s;
}
Finally, do not forget to add Jackson to your maven
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.7</version>
<scope>compile</scope>
</dependency>
Having the same problem I've finally solved it like this. In your Spring context.xml
define bean:
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider"/>
And use it in the <jaxrs:server>
as a provider:
<jaxrs:server id="restService" address="/resource">
<jaxrs:providers>
<ref bean="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
In your Maven pom.xml add:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.0</version>
</dependency>
If you are using Jackson you can write custom message body writer.
public class KPMessageBodyWriter implements
MessageBodyWriter<ArrayList<String>> {
private static final Logger LOG = LoggerFactory.getLogger(KPMessageBodyWriter.class);
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public long getSize(ArrayList<String> t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return t.size();
}
public void writeTo(ArrayList<String> t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(entityStream, t);
}
}
In cx configuration file add the provider
<jaxrs:providers>
<bean class="com.kp.KPMessageBodyWriter" />
</jaxrs:providers>