Reputation: 2572
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);
}
Upvotes: 9
Views: 5651
Reputation: 8151
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 !!
Upvotes: 1
Reputation: 9415
Not sure why you are trying a Map
and not simply a List
:
@Path("/v1/restclienturi/")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public interface RestClient {
@POST
@Path("/samplecall/evaluate")
Response evaluateChange(
@HeaderParam("HEADER") List<String> headers,
@Context HttpServletResponse response, Request request
);
}
Now I did not test this, but this would require all HeaderParams to be called 'HEADER', and they will/should be stored in the List<String>
following the order of occurrence.
Upvotes: 0
Reputation: 2572
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.
Upvotes: 4
Reputation: 36
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.
Upvotes: 2
Reputation: 7744
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), ...);
Upvotes: 2