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());
...
}
Related
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 am trying to pass multiple parameters to Jersey POST method . Currently I am following below steps to pass a single parameter to Jersey POST method.
Client client = ClientBuilder.newClient();
WebTarget target= client.target("http://localhost:8080/Rest/rest/subuser").path("/insertSubUser");
SubUserBean subUserBean=new SubUserBean();
subUserBean.setIdUser(1);
subUserBean.setIdSubUserType(1);
subUserBean.setIdSubUser(15);
subUserBean.setFirstName("Haritha");
subUserBean.setLastName("Wijerathna");
subUserBean.setNumberOfDaysToEditRecord(14);
subUserBean.setUserName("haritha");
subUserBean.setPassword("hariwi88");
subUserBean.setDateCreated(Common.getSQLCurrentTimeStamp());
subUserBean.setLastUpdated(Common.getSQLCurrentTimeStamp());
target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.entity(subUserBean, MediaType.APPLICATION_JSON_TYPE));
SubUserJSONService.java
#Path("/subuser")
public class SubUserJSONService {
#POST
#Path("/insertSubUser")
#Consumes(MediaType.APPLICATION_JSON)
public String updateSubUser(SubUserBean bean){
SubUserInterface table = new SubUserTable();
String result= table.insertSubUser(bean);
return result;
}
}
Now, I want to pass parameters to following method via Jersey POST method.
public String insertHistory(List<SocialHistoryBean> list, String comment){
//my stuffs
}
Have any ideas to do above work ?
Thank you.
You can try using MultivaluedMap.Add form data and send it to the server. An example below, code is not tested just for demo/logic flow.
WebTarget webTarget = client.target("http://www.example.com/some/resource");
MultivaluedMap<List, String> formData = new MultivaluedHashMap<List, String>();
formData.add(List, "list1");
formData.add("key2", "value2");
Response response = webTarget.request().post(Entity.form(formData));
Consume this on server side something like
#Path("/uripath")
#POST -- if this is post or #GET
#Consumes("application/x-www-form-urlencoded;charset=UTF-8") or json..
#Produces("application/json")
public void methodNameHere(#FormParam("list") List<String> list1, #FormParam("key2") String val2) {
System.out.println("Here are I am");
System.out.println("list1" + list1.size);
System.out.println("val2" + val2);
}
Read more here in docs..
In case you're using Jersey 1.x, check this example on how to post multiple objects as #FormParam
Client: (pure Java):
public Response testPost(String param1, String param2) {
// Build the request string in this format:
// String request = "param1=1¶m2=2";
String request = "param1=" + param1+ "¶m2=" + param2;
WebClient client = WebClient.create(...);
return client.path(CONTROLLER_BASE_URI + "/test")
.post(request);
}
Server:
#Path("/test")
#POST
#Produces(MediaType.APPLICATION_JSON)
public void test(#FormParam("param1") String param1, #FormParam("param2") String param2) {
...
}
JSON data cannot be passed to the server in a List. This means that you should create a wrapper around your SocialHistoryBean class (i.e around the list that holds your objects)
#XmlRootElement(name = "uw")
public class SocialHistoryBeanWrapper implements Serializable {
private List<SocialHistoryBean> sList ;//this will hold your SocialHistoryBean instances
public SocialHistoryBeanWrapper(){
sList = new ArrayList<User>();
}
public List<User> getUsrList(){
return sList;
}
}
Your server side code will be like
#POST
#Path("/history")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_JSON)
public String insertHistory( #QueryParam("comment") String comment, SocialHistoryBeanWrapper uw) {
do whatever you want with your history data
//userData.setUser(uw.getUsrList().get(0));
return comment; //just echo the string that we have sent from client
}
Note that comment is passed with #QueryParam (this means it's not part of the POST request (body) but is rather encoded in the URL string. For this to work, you can call your service as (the client code)
WebTarget target = client.target(UriBuilder.fromUri("http://localhost:8088/Rest/rest/subuser").build());
SocialHistoryBeanWrapper uw = new SocialHistoryBeanWrapper();
//just populate whatever fields you have;
uw.getUsrList().get(0).setName("Mark Foster");
uw.getUsrList().get(0).setProfession("writer");
uw.getUsrList().get(0).setId(55);
String s = target.path("history").queryParam("comment", "OK").request()
.accept(MediaType.TEXT_PLAIN).post(Entity.entity(uw, MediaType.APPLICATION_JSON), String.class);
System.out.println(s);//this prints OK
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.
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 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