I need to call a 3rd party rest service from my Java application with a formatted URI:
.../rest/v1/search?filter[first_name]=john&filter[last_name]=smith
The reason for this format is, that there are several query fields (20+) and I can't create a #QueryParam parameter for every fieldname.
#POST
#Path("/rest/v1/search")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
Response searchCustomer(#QueryParam("filter") Map<String, String> filter);
My example with a map results in
/rest/v1/search?filter={first_name=John,+last_name=Smith}
How do I achieve the URI form with square brackets?
You can use #Context UriInfo to get a map of all the query params instead of hardcoding every param
example:
#POST
#Path("/rest/v1/search")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public Response searchCustomer(#Context UriInfo info){
//here are some different ways you can use the uriinfo
MultivaluedMap<String,String> map = info.getQueryParameters();
String firstName = map.getFirst("filter");
String lastName = map.getFirst("lastName");
}
Related
I tried something like below, M getting error
[[FATAL] No injection source found for a parameter of type public Response
#context UriInfo wont work as i need different data types as query param,like it may be integers and date.Kindly Help.
#GET
#Path("/getdetails")
#Produces({ "application/json", "application/xml" })
public Response getDetails(#QueryParam("field1") String fieldOne,#QueryParam("field2") List<HasMap<String,String>> fieldTwo){
//Processing
}
You will have to use POST and attach the list inside the request body
If the list your passing is json, you should also add the appropriate #Consumes value.
#POST
#Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
#Consumes(MediaType.APPLICATION_JSON)
public void getDetails(List<HasMap<String,String>> listFromClient) {
// do something with your list..
}
I am currently trying to add a new feature to my REST API.
Basically I want to add the ability to add query parameters to the end of a path and turn this into a Map of all the query options for example.
my current code allows me to do things like
localhost:8181/cxf/check/
localhost:8181/cxf/check/format
localhost:8181/cxf/check/a/b
localhost:8181/cxf/check/format/a/b
and this will use all the #pathparam as String variables to generate a response.
What I want to do now is add:
localhost:8181/cxf/check/a/b/?x=abc&y=def&z=ghi&...
localhost:8181/cxf/check/format/a/b/?x=abc&y=def&z=ghi&...
and I would then have this generate a Map which can be used along with the pathparam to build the response
x => abc
y => def
z => ghi
... => ...
I was thinking something like this [Below] however the #QueryParam seem to only handle one key value and not a Map of them.
#GET
#Path("/{format}/{part1}/{part2}/{query}")
Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2, #QueryParam("query") Map<K,V> query);
below is my current interface code.
#Produces(MediaType.APPLICATION_JSON)
public interface RestService {
#GET
#Path("/")
Response getCheck();
#GET
#Path("/{format}")
Response getCheck(#PathParam("format") String format);
#GET
#Path("/{part1}/{part2}")
Response getCheck(#PathParam("part1") String part1,#PathParam("part2") String part2);
#GET
#Path("/{format}/{part1}/{part2}")
Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2);
}
QueryParam("") myBean allows to get all the query parameters injected. Remove also the last {query} part
#GET
#Path("/{format}/{part1}/{part2}/")
Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2, #QueryParam("") MyBean myBean);
public class MyBean{
public void setX(String x) {...}
public void setY(String y) {...}
}
You can also not declare parameters and parse the URI. This option could be useful if you can accept non-fixed parameters
#GET
#Path("/{format}/{part1}/{part2}/")
public Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2, #Context UriInfo uriInfo) {
MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
String x= params.getFirst("x");
String y= params.getFirst("y");
}
I want to handle dynamic query parameter in CXF RESTful service.
My concern here is from the service end i will not be knowing the number of parameters/key names that comes with the request. Could you please let me know how we can handle this situation/scenario.
For example my client code will look like below ,
Map<String, String> params = new HashMap<>();
params.put("foo", "hello");
params.put("bar", "world");
WebClient webClient = WebClient.create("http://url");
for (Entry<String, String> entry : params.entrySet()) {
webClient.query(entry.getKey(), entry.getValue());
}
Response res = webClient.get();
The below code works fine for me,
public String getDynamicParamter(#Context UriInfo ui){
System.out.println(ui.getQueryParameters());
MultivaluedMap<String, String> map = ui.getQueryParameters();
Set keys=map.keySet();
Iterator<String > it = keys.iterator();
while(it.hasNext()){
String key= it.next();
System.out.println("Key --->"+key+" Value"+map.get(key).toString());
}
return "";
}
However , could you please let me know the below,
Whether it is standard way?
And, is there any other ways to achieve it?
CXF version : 3.1.4
Getting the query parameters from the UriInfo
As you already guessed, there are some methods in UriInfo API that will provide you the query parameters:
getQueryParameters(): Returns an unmodifiable map containing the names and values of query parameters of the current request. All sequences of escaped octets in parameter names and values are decoded, equivalent to getQueryParameters(true).
getQueryParameters(boolean): Returns an unmodifiable map containing the names and values of query parameters of the current request.
The UriInfo can be injected in a resource class member using the #Context annotation:
#Path("/foo")
public class SomeResource {
#Context
private UriInfo uriInfo;
#GET
public Response someMethod() {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
...
}
}
And can be injected in a method parameter:
#GET
public Response someMethod(#Context UriInfo uriInfo) {
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
...
}
To get the unparsed query string, do the following:
#GET
public Response someMethod(#Context UriInfo uriInfo) {
String query = uriInfo.getRequestUri().getQuery();
...
}
Getting the query parameters from the HttpServletRequest
You could achieve a similiar result by injecting the HttpServletRequest with the #Context annotation, just like the UriInfo mentioned above. Here are a few methods that can be useful:
getParameterMap(): Returns an immutable map containing the names and values of parameters sent in the request.
getParameterNames(): Returns an Enumeration containing the names of the parameters contained in the request.
getParameterValues(String): Returns an array containing all of the values the given request parameter.
getParameter(String): Returns the value of a request parameter. Should only be used when you are sure the parameter has only one value. Otherwise, only the first value for the given parameter name will be returned.
getQueryString(): Returns the query string that is contained in the request URL.
Consider this case:-
I am injecting HttpServletRequest in a Rest Service like
#Context
HttpServletRequest request;
And use it in a method like:-
#GET
#Path("/simple")
public Response handleSimple() {
System.out.println(request.getParameter("myname"));
return Response.status(200).entity("hello.....").build();
}
This works fine but when I try to send it through POST method and replace the #GET by #POST annotation, I get the parameter value null.
Please suggest me where I am mistaking.
You do not need to get your parameters etc out of the request. The JAX-RS impl. handles that for you.
You have to use the parameter annotations to map your parameters to method parameters. Casting converting etc. is done automaticly.
Here your method using three differnt ways to map your parameter:
// As Pathparameter
#POST
#Path("/simple/{myname}")
public Response handleSimple(#PathParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
// As query parameter
#POST
#Path("/simple")
public Response handleSimple(#QueryParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
// As form parameter
#POST
#Path("/simple")
public Response handleSimple(#FormParam("myname") String myName) {
System.out.println(myName);
return Response.status(200).entity("hello.....").build();
}
Documentation about JAX-RS Annotations from Jersey you can find here:
https://jersey.java.net/documentation/latest/jaxrs-resources.html
I'm going over few pieces of code and came across something like this
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({ MediaType.APPLICATION_JSON , MediaType.APPLICATION_XML })
public Response getMedia(
#HeaderParam("X-META") String metaToken,
#QueryParam("provider") String provider, MultivaluedMap<String, String> formContext ,
#Context UriInfo uriInfo) {
Map<String, String> context = APIUtils.buildContext(formContext);
return getMediaInternal(metaToken, provider, context, uriInfo);
}
I know that Annotated vars are injected by jersey but I'm clueless as how the formContext is being injected. It's not annotated. What all values are put in here by jersey ? All the post parameters ? Whats a general rule to deduce whats being populated when not annotated ? Any pointers to reference material or a brief description of whats happening here is helpful
According to the Jersey User Guide, it seems like jersey will inject the MultiValuedMap<> type on a #POST request because form parameters are part of the message entity. This is the example:
Example 3.13. Obtaining general map of form parameters
#POST
#Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}