I've seen a Java RESTFUL webservice, that allowed the content-type to be requested in the URL with an extension at the end, such as
.xml.json
This is the style of content negotiation I am striving to achieve in my own Web Service.
I am aware of the @Produces annotation, and the fact a method can resolve multiple types with the (value = {}) syntax, by adding an Accept header, say with Postman, the Chrome extension.
But I'm not sure how to effectively extract out the information in one method, and delegate to another method.
I'm assuming REGEX's can be use with @Path and @PathParam, but my attempts to do this have yet to be fruitful.
Can anyone provide an example?
This is my attempt thus far:
package com.extratechnology.caaews;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.extratechnology.caaews.model.Log;
@Path("et")
@Produces(MediaType.APPLICATION_JSON)
public class CAAEWS {
@GET
@Path("\\.{format}")
@Produces(value = {MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
public Log getLog(
@PathParam("format") String format
){
Log result = null;
switch (format) {
case "json":
result = this.getJSON();
case "xml":
result = this.getXML();
}
return result;
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Log getJSON() {
return new Log("JSON!");
}
@GET
@Produces(MediaType.TEXT_XML)
public Log getXML() {
return new Log("XML!");
}
}
package com.extratechnology.caaews.model;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Log {
private String log;
public Log(String log) {
this.log = log;
}
public String getLog() {
return log;
}
public void setLog(String log) {
this.log = log;
}
}
The project can be setup from Spring Tool Suite/Eclipse, by creating a Maven project (similar, but more up to date than here circa 4:50) using the following:
- org.glassfish.jersey.archetypes
- jersey.quickstart.webapp
- 2.26
Then you uncomment the part of the pom.xml provided to enable JSON support, which effectively adds a few more JARS to your WAR.
I found I had some nasty BCEL errors too, and had to append some entries to the catalina.properties file, under the key:
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
....
javax.json-api-1.1.jar, javax.json.bind-api-1.0.jar, javax.json-1.1.jar, \
yasson-1.0.jar
http://localhost:18080/caaews/webapi/et
yields:
{"log":"JSON!"}
http://localhost:18080/caaews/webapi/et.xml or
http://localhost:18080/caaews/webapi/et.json
yields:
HTTP Status 404 - Not Found
I'm also wondering if there's some sort of HTTP Interceptor type approach to this. My Java is a bit rusty, but is it servlet filters, or something akin to an AOP before advice.
Thanks to @user1803551 I have put breaks in switch statements.
Thanks to @callmepills I have tweaked code a bit.
The class level @Path annotation now has this. @Produces(value = {MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
The getLog @Path annotation is ".{format}".
In order to have the getLog be called and delegate, you have to use this syntax for the URL:
http://localhost:18080/caaews/webapi/et
http://localhost:18080/caaews/webapi/et/.xml
http://localhost:18080/caaews/webapi/et/.json
The need to have a '/' in the path isn't what I'm after, so I think I will probably have to resolve to servlet filters rather than @PathParam approach..