I am building a generic web service and need to grab all the query parameters into one string for later parsing. How can I do this?
You can access a single param via #QueryParam("name") or all of the params via the context:
#POST
public Response postSomething(#QueryParam("name") String name, #Context UriInfo uriInfo, String content) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
}
The key is the #Context jax-rs annotation, which can be used to access:
UriInfo, Request, HttpHeaders,
SecurityContext, Providers
The unparsed query part of the request URI can be obtained from the UriInfo object:
#GET
public Representation get(#Context UriInfo uriInfo) {
String query = uriInfo.getRequestUri().getQuery();
...
}
Adding a bit more to the accepted answer. It is also possible to get all the query parameters in the following way without adding an additional parameter to the method which maybe useful when maintaining swagger documentation.
#Context
private UriInfo uriInfo;
#POST
public Response postSomething(#QueryParam("name") String name) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String nameParam = queryParams.getFirst("name");
}
ref
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);
}
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 !!
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.
I use SoapUi to test my web service. I want to sent from SoapUi a list of parameter for a post method. Here is the code where I want to handle the list but is not working, I get a null pointer exception :
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("/subscribeList")
public Response subscribe( final MultivaluedMap<String, String> listoffields )
{
System.out.println( "The list has: " + listoffields.size() );
return Response.ok().build();
}
From soapui I send the parameters as queryparam.
Can anyone help me solve this problem and be able to send a list?
Inject UriInfo as the method parameter, and get the map with UriInfo.getQueryParameters().
public Response subscribe( #Context UriInfo uriInfo ) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
String name = queryParams.getFirst("name");
}
Or you can explicitly specify the each query param in the method signature
public Response subscribe( #QueryParam("name") String name,
#QueryParam("age") int age ) {
So I wanted to know my web service's client's locale or ip etc.. How do I get it?
My endpoint method:
#POST
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
#Path("/{EmployeeID}/Shifts/{ShiftID}/Confirm")
public Response confirmShift(#PathParam("EmployeeID")String employeeId, String params, #PathParam("ShiftID")String tbId);
How I get it in interceptor:
Map<String, List> headers = (Map<String, List>) message.get(Message.PROTOCOL_HEADERS);
I think protocol header must contain this info, I havn't checked it by the way. But how do I get it in web service.
Note: I want to avoid getting/setting stuff in cxf request context.
You need to inject MessageContext into your method, which contains HTTP servlet request.
For e.g.:
#POST
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
#Path("/{EmployeeID}/Shifts/{ShiftID}/Confirm")
public Response confirmShift(#PathParam("EmployeeID") String employeeId,
String params,
#PathParam("ShiftID") String tbId,
#Context MessageContext context){
HttpServletRequest request = context.getHttpServletRequest();
String ip = request.getRemoteAddr();
/** ..... **/
}
Also there are some other ways of getting HTTP servlet request, one would be:
Message message = PhaseInterceptorChain.getCurrentMessage();
HttpServletRequest httpRequest = (HttpServletRequest) message.get(AbstractHTTPDestination.HTTP_REQUEST);
Hope this helps.
I have following jersey method:
#POST
#Path("path")
#Produces({MediaType.APPLICATION_JSON})
public Response isSellableOnline(#QueryParam("productCodes") final List<String> productCodes,
#QueryParam("storeName") final String storeName,
#Context HttpServletRequest request) {
System.out.println(storeName);
System.out.println(productCodes.size());
...
}
in rest client I sends following data:
in console I see
null
0
What do I wrong?
You're reading the parameters from query string, which go in the form:
http://yourserver/your/service?param1=foo¶m2=bar
^ start of query string
But you're sending the parameters as part of the form.
Change the way you consume the parameters in your service:
#POST
#Path("path")
#Produces({MediaType.APPLICATION_JSON})
public Response isSellableOnline(#FormParam("productCodes") final List<String> productCodes,
#FormParam("storeName") final String storeName,
#Context HttpServletRequest request) {
System.out.println(storeName);
System.out.println(productCodes.size());
...
}