Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping extension content types in Apache CXF JAX-RS

JAX-RS offers a wonderful way to specify content types in @Produces, and the framework will automatically determine the best content type from the client's HTTP Accept header and, wonder of wonders, even convert your object to that type (e.g. XML using JAXB or JSON using Jackson) when returning information to the caller.

My (work) client, as clients often do, made a simple job more difficult by requesting I specify the content type by the extension in the URL, e.g. api/widgets.json. This would force me to have various getWidgetsXXX() methods, one with @Produces("application/json"), another with @Produces("application/xml"), etc.

But I'm using Apache CXF and I was delighted to find that I could configure CXF to map various extensions to content types using the jaxrs.extensions init parameter!

<!-- registers extension mappings -->
<init-param>
  <param-name>jaxrs.extensions</param-name>
  <param-value>
    xml=application/xml
    json=application/json
  </param-value>
</init-param>

But I can find absolutely no documentation on how this works in the real world. I naively thought I could just annotate a method with a path with an extension and it would mimic the Accepts header:

@Path("/widgets.{extension}")
@GET
@Produces({ "application/json", "application/xml" })
public List<Widget> getWidgets();

So I call it using api/widgets.json, and it returns XML! Which is particularly odd, because JAX-RS specifies that the default content type is the first one listed.

Where can I find out how to use CXF extension content type mapping?

P.S. I am not using Spring.

like image 256
Garret Wilson Avatar asked Apr 03 '12 20:04

Garret Wilson


2 Answers

Adding the following in your <jaxrs:server> works:

<jaxrs:extensionMappings>
    <entry key="json" value="application/json" />
    <entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>

Source: http://cxf.apache.org/docs/jax-rs.html#JAX-RS-Debugging

like image 67
praseodym Avatar answered Oct 11 '22 12:10

praseodym


Don't know whether that help you or not but I was also facing the same issue to introduce something like that in my JAX-RS services. I achieved this functionality using JAX-RS_Content_Negotiation Following location has details about it.

https://docs.jboss.org/resteasy/docs/3.0.6.Final/userguide/html/JAX-RS_Content_Negotiation.html

You just have to map your media types with the values which you want

 <context-param>
        <param-name>resteasy.media.type.mappings</param-name>
        <param-value>
          html : text/html, json : application/json, xml :           
           application/xml
       </param-value>
 </context-param>


 @GET
        @Path("/second/{param}")
        @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
        public Response printStudent(@PathParam("param") String msg) {


}

now i can access my services like that and response is according the extension which i put at the end

http://localhost:8080/RESTfulExample/rest/message/second/bill.json

you can put .xml OR .json at the end of the url and service will generate response accordingly.

like image 22
Bill Avatar answered Oct 11 '22 13:10

Bill