I have the following code snippet for invoking rest call. I have around 8 headers to pass on for this rest call. But the problem is that it is difficult to manage. If in case the list of headers are increased in future, I need to change evaluateChange
method signature to include the additional headers as method params
.
@Path("/v1/restclienturi/")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public interface RestClient {
@POST
@Path("/samplecall/evaluate")
Response evaluateChange(
@HeaderParam("HEADER1") String header1,
@HeaderParam("HEADER2") String header2,
@HeaderParam("HEADER3") String header3,
@HeaderParam("HEADER4") String header4,
@HeaderParam("HEADER5") String header5,
@HeaderParam("HEADER6") String header6,
@HeaderParam("HEADER7") String header7,
@HeaderParam("HEADER8") String header8,
@Context HttpServletResponse response, Request request);
}
Please provide your thoughts or code snippet to accommodate this.
I tried the following code snippet but it did not work(where headerMap contains all the 8 headers in it):
@Path("/v1/restclienturi/")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public interface RestClient {
@POST
@Path("/samplecall/evaluate")
Response evaluateChange(
@RequestHeader Map<String, String> headerMap,
@Context HttpServletResponse response, Request request);
}
So if you want to retrieve a specific header by its name then use getHeader(String headerName) or header(String headerName) who returns a String which is actually the value of that header. If you want to retrieve all headers of response then use headers() or getHeaders() who return Headers object.
You can pass duplicate headers as well and there will not be any overwritten of values. For example, If we pass two values of header1 as value1 and value2 then it will be merged and will be passed as header1=value1 and header1=value2. It is the default behaviour.
API headers are like an extra source of information for each API call you make. Their job is to represent the meta-data associated with an API request and response. If you ever encounter issues with an API, the first place you should look is the headers, since they can help you track down any potential issues.
I found a solution using javax.ws.rs.core.Form:
@Path("/v1/restclienturi/")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public interface RestClient {
@POST
@Path("/samplecall/evaluate")
Response evaluateChange(
@Form MyHeader headers,
@Context HttpServletResponse response, Request request);
}
The following is the MyHeader which is a pojo:
public class MyHeader{
@HeaderParam("HEADER1")
private String header1;
@HeaderParam("HEADER2")
private String header2;
.....
// getters and setters present
}
Instantiate MyHeader and set the values to pass it on to the REST service like:
MyHeader headers = new MyHeader();
headers.setHeader1("HEADER1_VALUE");
...
and call: evaluateChange(headers, null,request);
PROBLEM: The very big problem with this approach is that everytime there is a new header added we need to make a code change to set and get the values. If the solution is something like passing as a colletion then we don't have that code change involved when new headers are added. like:
Map<String,String> headersMap = new HashMap();
headers.put("HEADER1","HEADER1_VALUE");
....
evaluateChange(headersMap,null,request);
I am looking for a solution like this. But the above code did not work. Looking for suggestions.
Not exactly sure what you mean, but if you want to get all headers how about this:
public Response evaluateChange(@Context HttpHeaders headers, ...) {
String header1 = headers.getRequestHeader("HEADER1").get(0);
...
}
Found some more code about this here: http://www.mkyong.com/webservices/jax-rs/get-http-header-in-jax-rs/
Edit: How to call the method with a map of key-values.
public class MapHttpHeaders implements HttpHeaders {
private Map<String, String> values;
public MapHttpHeaders(Map<String, String> values) {
this.values = values;
}
@Override
public String getHeaderString(String key) {
return values.get(key);
}
@Override
public List<String> getRequestHeader(String key) {
String value = getHeaderString(key);
if (value == null) {
return null;
} else {
return asList(value);
}
}
...and so on...
}
And then just do:
evaluateChange(new MapHttpHeaders(values), ...);
Couldn't you just inject HttpServletRequest and then use its getHeader(String name) method?
API
@POST
@Path("/samplecall/evaluate")
Response evaluateChange(
@RequestHeader Map<String, String> headerMap,
@Context HttpServletResponse response,
@Context HttpServletRequest httpRequest,
Request request);
Impl
@Override
public Response evaluateChange(
@RequestHeader Map<String, String> headerMap,
@Context HttpServletResponse response,
@Context HttpServletRequest httpRequest,
Request request) {
String header1 = httpRequest.getHeader("HEADER1");
...
Of course, that way you are hiding part of your contract in the implementation.
You can send all headers set in a MultivaluedHashMap (javax.ws.rs.core.MultivaluedHashMap) to the Form. this is an acceptable constructor argument for the Form.
MultivaluedMap<String, String> headerMap = new MultivaluedHashMap<String, String>();
headersMap.putSingle("HEADER1","HEADER1_VALUE");
headersMap.putSingle("HEADER2","HEADER1_VALUE");
.
.
.
headersMap.putSingle("HEADER8","HEADER8_VALUE");
evaluateChange(headersMap,null,request);
and change your evaluateChange
as below,
Response evaluateChange(
@Form MultivaluedMap headers,
@Context HttpServletResponse response, Request request);
Hope this helps.. Good luck !!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With