问题
My MessageBodyWriter
@Provider
@Produces("text/csv")
public class CSVMessageBodyWriter implements MessageBodyWriter<JaxbList>
public static final String CONTENT_DISPOSITION_HEADER = "Content-Disposition";
//$NON-NLS-1$
private final static HeaderDelegate<ContentDispositionHeader> header = RuntimeDelegate.getInstance().createHeaderDelegate(ContentDispositionHeader.class);
public long getSize(JaxbList t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return -1;
}
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return CsvSerializer.class.isAssignableFrom(type);
}
public void writeTo(JaxbList t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException, WebApplicationException {
// set content disposition. This will enable browsers to open excel
ContentDispositionHeader contentDispositionHeader = ContentDispositionHeader.createContentDispositionHeader(MediaTypeUtils.CSV_TYPE);
contentDispositionHeader.setFileName("representation"); //$NON-NLS-1$
httpHeaders.putSingle(CONTENT_DISPOSITION_HEADER, header.toString(contentDispositionHeader));
Charset charset = Charset.forName(ProviderUtils.getCharset(mediaType));
OutputStreamWriter writer = new OutputStreamWriter(entityStream, charset);
PrintWriter printWriter = new PrintWriter(writer);
Iterator<String[]> rows = ((CsvSerializer) t).getEntities();
while (rows.hasNext()) {
printWriter.println(CsvWriter.getCSVRow(rows.next()));
}
printWriter.flush();
}
}
My REST Application
@Path("app/v3")
@GZIP
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, "text/csv"})
public class ApplicationREST
Extension of Application
@ApplicationPath("/")
public class JaxRsActivator extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public JaxRsActivator() {
singletons.add(new CSVMessageBodyWriter());
classes.add(ApplicationREST.class);
}
@Override
public Set<Object> getSingletons() {
Set<Object> defaults = super.getSingletons();
singletons.addAll(defaults);
return singletons;
}
public Set<Class<?>> getClasses() {
return classes;
}
}
When I run in debug mode I can hit my JaxRsActivator class, so I know that the providers are being loaded. However I get the error "Could not find MessageBodyWriter for response object of type: net.comp.jaxb.JaxbList of media type: text/csv"
回答1:
Based on your code above it would appear that your CSVMessageBodyWriter
is being called, but it is failing your isWriteable
check.
Your isWriteable
check is always going to return false. You are checking if JaxbList
is assignable from CSVSerializer
. This is always going to fail and your CSVMessageBodyWriter
will not be deemed able to handle text/csv
.
Try changing your isWriteable method to the following:
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType)
{
return true;
}
This will serialize all text/csv
annotated methods. If you want to constrain it to JaxbList
then you can do something like this:
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType)
{
ParameterizedType paramType = (ParameterizedType) genericType;
if(paramType.getRawType().equals(JaxbList.class))
{
return true;
}
return false;
}
Here is a simple working example of configuring a custom MessageBodyWriter
:
Application
public class ProductGuideApplication extends Application
{
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public ProductGuideApplication()
{
singletons.add(new CSVMessageBodyWriter());
classes.add(FooResource.class);
}
@Override
public Set<Object> getSingletons()
{
return singletons;
}
@Override
public Set<Class<?>> getClasses()
{
return classes;
}
}
Resource
@Path("/foo")
public class FooResource
{
@GET
@Produces("text/csv")
public List<Consumer> getConsumers()
{
Consumer consumer1 = new Consumer();
consumer1.setId("1234");
consumer1.setGender("Male");
Consumer consumer2 = new Consumer();
consumer2.setId("2345");
consumer2.setGender("Male");
List<Consumer> consumers = new ArrayList<Consumer>();
consumers.add(consumer1);
consumers.add(consumer2);
return consumers;
}
}
MessageBodyWriter
@Provider
@Produces("text/csv")
public class CSVMessageBodyWriter implements MessageBodyWriter<List<Consumer>>
{
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType)
{
ParameterizedType paramType = (ParameterizedType) genericType;
if(paramType.getRawType().equals(List.class))
{
if(paramType.getActualTypeArguments()[0].equals(Consumer.class))
{
return true;
}
}
return false;
}
@Override
public long getSize(List<Consumer> t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType)
{
return 0;
}
@Override
public void writeTo(List<Consumer> t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException
{
//Write your CSV to entityStream here.
}
}
来源:https://stackoverflow.com/questions/17593474/resteasy-doesnt-recognize-custom-message-body-writer