I faced with unexpected Apache CXF behavior: when I return String from my service it doesn’t converted properly to JSON — instead of adding double quotes around the string, Apache CXF returns it as is.
My service:
@Path(ROOT_URL)
@Produces(MediaType.APPLICATION_JSON)
public class SomeRestService {
@GET
@Path(SERVICE_URL)
public Response getString() {
return Response.ok("OK").build();
}
}
Part of Apache CXF configuration:
<jaxrs:server id="RestService" address="/api">
<jaxrs:serviceBeans>
<bean class="org.example.project.ws.rest.SomeRestService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
Can you help me to understand why this is working that way and how to tell to CXF return string as really JSON?
JSON is a way of serializing complex objects, which Java’s strings are (effectively) not. This means that there is no way to directly serialize a string into a JSON object; the serializer just doesn’t know what to map it as and so bails out (or rather it doesn’t enable itself for
String). There are two possible fixes for this.Option 1: Use a Different Content Type
The natural mapping for a string is to message content of type
text/plain, notapplication/json. This mapping is built into CXF (and any other JAX-RS implementation too) and it’s really easy to make it work. (I prefer to put produces and consumes annotations on individual methods rather than an overall class, but that’s personal choice.)Option 2: Wrap the String in a JAXB-Annotated Object
If you really want the data to go as JSON, you need to provide additional metadata. The overwhelmingly-simplest way of doing this by adding a wrapper class that has JAXB annotations, which then allows Jettison (the serialization library used by CXF) to spit the right thing out. In the sample below, I am using a static inner class, because it keeps a (fundamentally boring) class close to the only place that uses it, but YMMV; it does have to be an annotated public “struct” though (i.e., a class with a no-arg constructor and either public fields or suitably trivial getters and setters).
I’ve omitted building out a full set of constructors for
ServiceMessage, which makes using it slightly less convenient than it might be; the code is (almost) purely bare bones minimal.