Why Apache CXF converts String to JSON incorrectly?

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?

Answers


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, not application/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.)

@Path(ROOT_URL)
public class SomeRestService {
    @GET
    @Path(SERVICE_URL)
    @Produces("text/plain")
    public Response getString() {
        return Response.ok("OK").build();
    }
}
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).

@Path(ROOT_URL)
public class SomeRestService {
    @GET
    @Path(SERVICE_URL)
    @Produces("application/json")
    public Response getServiceMessage() {
        ServiceMessage result = new ServiceMessage();
        result.message = "OK";
        return Response.ok(result).build();
        // Or: return Response.ok(result,"application/json").build();
        // Or: return Response.ok(result).type("application/json").build();
    }

    @XmlRootElement  // This annotation _is_ required, can be customized further
    public static class ServiceMessage {
        @XmlElement  // This annotation isn't required, but documents intention
        public String message;
    }
}

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.


Need Your Help

Does the jquery Droppable hoverClass work in Internet Explorer?

jquery jquery-ui

I can't seem to get it to work. It works fine in Firefox, but in IE nothing happens when the droppable has an item held over it. I tried using the hoverClass, and also tried just manually changing ...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.