I am using Jersey for Rest and have a method that accepts #QueryParam.
However, the users may send #QueryParam. like this:
contractName# where # is a number from 0-155.
How can I define it in QueryParam (like regex expression)?
You can't specify the regexp. However, you can define a custom Java type to represent that query param and implement your own conversion from String to that type - see http://jersey.java.net/nonav/documentation/latest/jax-rs.html#d4e255 (example 2.15).
I don't think you can do it with QueryParam, but you can get the list of parameters directly:
#GET
public String get(#Context UriInfo ui) {
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
}
and iterate through that looking for keys that match your regular expression.
#GET
public String get (#QueryParam(value="param") String param){
boolean test =testYourParamWithNativeRegexpTools(param);
if( test==false)return 400;
else //work
.....
}
Related
I'm trying to check if my method works through the API
#GetMapping(value = "/ads/in/rubrics/{ids}")
public List<Ad> findAllAdInRubricByIds(#PathVariable("ids") List<Integer> ids) {
return adService.findAllAdInRubricByIds(ids);
}
how can i set some parameters in get request?
that's how i tried
http://localhost:9999/mvc/ad/ads/in/rubrics/ids&ids=1&ids=2
http://localhost:9999/mvc/ad/ads/in/rubrics/ids&ids1=1&ids2=2
always get error 400 Bad Request
You're confusing PathVariables with RequestParams.
A PathVariable is a variable in the request path. It doesn't need to be the last character.
#GetMapping("/api/{version}/foo/{idFoo}")
public Void getFooNumber(#PathVariable("version") Integer version, #PathVariable("idFoo") Integer idFoo){
return "1";
}
Since PathVariables are part of the path, they're always required. If you don't incluide them in the request you'll end up invoking another endpoint or getting a 404 if the request can't be mapped to any endpoint.
The RequestParams are the parameters received at the end of the request URL, after the "?" character.
#GetMapping("/api/foo")
public Void getFooNumber(#RequestParam(value="version", required=false) Integer version, #RequestParam(value="idFoo", required=true) Integer idFoo){
return "1";
}
With RequestParams you can define for each one of them if it's required or not.
You can also mix them and have in the same method PathVariables and RequestParams.
In the first example the request URL would be ".../api/1/foo/25", while in the second example it would be ".../api/foo?version=1&idFoo=25"
As for having an array or a list, if you define the parameter as a List you can send multiple parameters of the same name:
#GetMapping("/ads/in/rubrics")
public Void findAllAdInRubricByIds(#RequestParam(value="ids", required=true) List<Integer> ids){
return adService.findAllAdInRubricByIds(ids);
}
In this case, you can use ".../ads/in/rubrics?ids=1&ids=2&ids=3&ids=4"
http://localhost:9999/mvc/ad/ads/in/rubrics/?ids1=1&ids2=2
For the first parameter use a ? and after that for each additional parameter a &
Am working on a REST API. This sample here works fine but am really confused about something here. My method getAll returns a String but the method has been annotated to Produce MIME MediaType of JSON. My question is , is the final returned response (doc) a JSONObject or just a json String(Thus a String in JSON format). So that I can know how to handle the response when I get it.
#Path("/membership/{pageNumber}")
#GET
#Produces("application/json")
public String getAll(#PathParam("pageNumber") String pageNumber){
Map<String , String > params = new HashMap<>();
String doc = HTTPClient.sendGet("localhost:9500/users/list/membership/field/"
+pageNumber, params, 60);
return doc;
}
This will really help me in my documentation as well.
All efforts are appreciated,Thanks.
My question is , is the final returned response (doc) a JSONObject or
just a json String(Thus a String in JSON format)
Yes it will return the json String,If you want to send JSON and HTTP Status together you can use Response as your return type.
Example:
#GET
#Path("/testGet")
#Produces("application/json")
public Response testGet() {
String json = //Create JSON String
return Response.ok(json, MediaType.APPLICATION_JSON).build();
}
You finally produce a JSON string.
Instead of just returning String it is recommended to use Entity
return Response.ok().entity(doc).build();
What is Actually Returned by a Method
Exactly what you return. This is Java. That is how Java works. There is not magic voodoo.
Maybe you're wondering something else.
All responses are written to the response output stream. It doesn't matter what the return type is. What matters is that there is a MessageBodyWriter that knows how to write that type to the output stream based on the #Produces content type. If the return type is a String, then there needs to be a writer that knows how to handle String-application/json combination. If the return type is JSONObject, then there need to be a writer that can handle that.
See Also: JAX-RS Entity Providers
The client needs to know nothing about any Java types (i.e. Sting, JSONObect, etc). It gets the data a stream of bytes and converts the data with whatever conversion method it uses.
I need to implement an API with these path params.
#Path("/job/{param1}/{optional1}/{optional2}/{param2}")
Can the second and third params by optional? So the client need not pass these, but have to pass the first and last.
If this is not possible, then is it recommended to rearrange the params in this way?
#Path("/job/{param1}/{param2}/{optional1}/{optional2}")
How to provide the optional params?
It might be easier to turn the optional path parameters into query parameters. You can then use #DefaultValue if you need it:
#GET #Path("/job/{param1}/{param2}")
public Response method(#PathParam("param1") String param1,
#PathParam("param2") String param2,
#QueryParam("optional1") String optional1,
#QueryParam("optional2") #DefaultValue("default") String optional2) {
...
}
You can then call it using /job/one/two?optional1=test passing only the optional parameters you need.
You can match the entire path ending in the REST request
#Path("/location/{locationId}{path:.*}")
public Response getLocation(
#PathParam("locationId") int locationId,
#PathParam("path") String path) {
//your code
}
Now the path variable contain entire path after location/{locationId}
You can also use a regular expressions to make the path optional.
#Path("/user/{id}{format:(/format/[^/]+?)?}{encoding:(/encoding/[^/]+?)?}")
public Response getUser(
#PathParam("id") int id,
#PathParam("format") String format,
#PathParam("encoding") String encoding) {
//your code
}
Now if you format and encoding will be optional. You do not give any value they will be empty.
Rearrange the params and try the following:
#Path("/job/{param1}/{param2}{optional1 : (/optional1)?}{optional2 : (/optional2)?}")
public Response myMethod(#PathParam("param1") String param1,
#PathParam("param2") String param2,
#PathParam("optional1") String optional1,
#PathParam("optional2") String optional2) {
...
}
to make request parameter optional set #requestparam to false in controller class
(#RequestParam(required=false)
We are using RESTful Web Services (Jersey) for API calls on java. While API needs optional parameter, we are doing as:
api-interface/user/userid/9000/companyid/90909/{optionalparameter*}
and we have to call this api when there is no optional parameter as:
api-interface/user/userid/9000/companyid/90909/
What needed is:
Case:1 If optional parameter exists
api-interface/user/userid/9000/companyid/90909/name/john/address/MA/age/34
Case:2 If Optional parameter doesn't exists.
api-interface/user/userid/9000/companyid/90909
My present implementation is:
#GET
#Path("user/companyid/{companyid}/userid/{userid}/{optionalparameter:.*}")
#Produces(MediaType.APPLICATION_JSON)
public Response getUserList(#PathParam("companyid") String companyId, #PathParam("userid") String userId,
#PathParam("optionalparameter") String syncDate) throws BadRequestException, InternalServerException {
//parsing the param.
}
In above code, I need to add trailing "/" but I am looking the way to remove this trailing "/" if anybody doesn't wants to pass those param.
I followed this link but it didn't worked while the preceding parameter's length is more then 1.
Please, Suggest me the best way.
Looking at your reference, have you tried this:
#Path("userid/{userid}/companyid/{companyid}{optparam:(/[^/]+?)*}")
public Response getLocation(
#PathParam("userid") int userid,
#PathParam("companyid") int companyid,
#PathParam("optparam") String optparam) {
String[] params = parseParams(optparam);
...
}
private String[] parseParams(String params) {
if (params.startsWith("/")) {
params = path.substring(1);
}
return params.split("/");
}
That should work, giving you all the parameters in a single array.
EDIT: I have updated the search string and verified it on a local install.
Background: we have build a RESTful API using Jersey a while ago where we map the uri /items.json to a json array of ids and /items/{id}.json to the json object of a single item. Now we want to create a list with some meta data for each item and would like to use a selector like /items.data.json, similar to apache sling.
So far: I just extended the UriConnegFilter to parse the uri for additional suffixes, something like this:
public class UriSelectorFilter extends UriConnegFilter {
protected List<String> selectors; // this list is populated in the constructor
public ContainerRequest filter(ContainerRequest request) {
super.filter(request);
// search for suffix in last path segment, see http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-server/src/main/java/com/sun/jersey/api/container/filter/UriConnegFilter.java?rev=5034
final String[] suffixes = segment.getPath().split("\\.");
for (int i = suffixes.length - 1; i >= 1; i--) {
final String suffix = suffixes[i];
if(selectors.contains(suffix)) {
request.getQueryParameters().putSingle("selector", suffix);
final int index = path.lastIndexOf('.' + suffix);
path = new StringBuilder(path).delete(index, index + suffix.length() + 1).toString();
suffixes[i] = "";
}
}
if (length != path.length()) {
request.setUris(
request.getBaseUri(),
request.getRequestUriBuilder().replacePath(path).build());
}
return request;
}
}
This filter works perfect, it finds the selector part of my uri and adds a query param to the request object. But in my Resource I added a #QueryParam attribute, which is only filled with the default value and not the added query value:
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(#DefaultValue("id") #QueryParam("selector") String selector) {
// query param is not filled with the selector that was found in the UriSelectorFilter
}
Does anybody have a suggestion how I can provide my resource with the selector that was detected? Is there a better way than using a QueryParam? (Note: if I add the query to my url like '?selector=something' then the attribute is filled correctly.)
Any help is very appreciated.
You need another argument that is annotated with #PathParam, and you need to specify in your #Path annotation (on the method or class) how to bind these bits together. For example, to deal with a path like /items/foobar42/data.json you might do this:
#GET
#Path("/items/{item}/data.json")
#Produces(MediaType.APPLICATION_JSON)
public Response getItemsJSON(#PathParam("item") String itemId,
#DefaultValue("id") #QueryParam("selector") String selector) {
// Now you've got an itemId and a possible selector...
}
Trying to do all the mapping with a filter… that seems difficult to me given that there's a nice declarative way of doing it instead. You can even specify a regular expression in the #Path to allow for matching a more complex variable section; I do that in my own code to create a method that can serve a whole hierarchical filesystem.
(Note that the {braced} item in the #Path should match the name in the #PathParam annotation, and you can have multiple items matched from the path if necessary; just use several #PathParam-annotated arguments.)