Mapping extension content types in Apache CXF JAX-RS

JAX-RS offers a great way to specify content types in @Produces, and the structure will automatically determine the best content type from the client HTTP Acceptheader and, miraculously, it even converts your object to this type (for example, XML using JAXB or JSON using Jackson) when returning information to the caller.

My (working) client, as clients often do, simplified the work by asking me to specify the type of content with an extension in the URL, for example. api/widgets.json. This will make me have different methods getWidgetsXXX(), one with @Produces("application/json"), the other with @Produces("application/xml"), etc.

But I use Apache CXF, and I was glad to find that I could configure CXF to map various content type extensions using jaxrs.extensionsthe 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 not find absolutely no documentation on how this works in the real world. I naively thought that I could just comment on the method using the extension path, and it would mimic the header Accepts:

@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 especially strange because JAX-RS indicates that the default content type is first.

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

PS I do not use Spring.

+5
source share
4 answers

<jaxrs:server>:

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

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

+4

, , , - JAX-RS. , JAX-RS_Content_Negotiation. .

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

,

 <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) {


}

, ,

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

.xml OR.json URL-, .

+1

, @Produces */* (.. ), . , , :

@javax.ws.rs.GET
@javax.ws.rs.Path("{filename}")
@javax.ws.rs.Produces("*/*")
javax.ws.rs.core.Response getDirectoryOrFileContents(
        @javax.ws.rs.PathParam("filename") String filename,
        @javax.ws.rs.core.Context javax.ws.rs.core.HttpHeaders headers);

- - HTTP (: headers.getAcceptableMediaTypes()), . , , "". (, , , .) , Response, .

Yes, this is more than letting CXF handle all of this for you (it usually generates a lot of templates to do all this), but in a difficult case you will be happy to manage.

0
source

The extension mimics the title Accept, you guessed it. However, you should not declare extenstion in the annotation @Path:

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

Then you can call widgets.xmlorwidgets.json

0
source

All Articles