Search code examples
jax-rscxf

How to provide a custom MessageBodyWriter for Strings in CXF


I have registered a custom MessageBodyWriter<Object> implementation in my JAX-RS application. This writer can convert various types, including strings.

The custom converter is successfully used for other types, but for strings, CXF does not consider it: It does not even call isWriteable. (This was different in CXF 2.x, so there seems to have been a regression in CXF 3.x.)

Stepping through the CXF 3.1.11 code, I see that in the ProviderFactory.messageWriters list has two entries (StringTextProvider, JAXBElementTypedProvider) before my custom provider. The first one wants to convert strings, and being first in the list, it is preferred by CXF.

How can I change this to make my provider the preferred provider for strings? E.g. is it possible to drop the StringTextProvider? Or is it possible to reorder the list so that my provider comes first?


Solution

  • I found out that subclassing StringTextProvider and registering that class works:

    @Provider
    @Produces(MediaType.APPLICATION_JSON)
    public class CustomeStringProvider extends StringTextProvider {
    
        @Override
        public void writeTo(String object, Class<?> type, Type genType, Annotation[] annotations, MediaType mediaType,
                MultivaluedMap<String, Object> httpHeaders, OutputStream outputStream) throws IOException {
            // ...
        }
    }
    

    I got the idea for this approach from looking at the implementation of ProviderFactory.MessageBodyWriterComparator, which checks class hierarchies for ordering converters.