I am using RESTEasy in my API development. My url is http://localhost:8080/project/player/M or http://localhost:8080/project/player
it means am pasing {gender} as path param.
my problem is how to mapp this url to REST method, i use below mapping
#GET
#Path("player/{gender}")
#Produces("application/json")
but if use it, it maps for http://localhost:8080/project/player/M but not for http://localhost:8080/project/player.
i need a regular expression to map zero or more path parameters
Thanks.
Is there any reason this must be a path parameter and not a query string ? If you change it to use the latter, then you can use a #DefaultValue annotation.
So your code would then look like the following:
#GET
#Path("player") //example: "/player?gender=F"
#Produces("application/json")
public Whatever myMethod(#QueryParam("gender") #DefaultValue("M") final String gender) {
// your implementation here
}
Path parameters (#PathParam) aren't optional. If you want to map;
http://localhost:8080/project/player/M
http://localhost:8080/project/player
You will need two methods. You can use method overloading;
#GET
#Path("player/{gender}")
#Produces("application/json")
public Whatever myMethod(#PathParam("gender") final String gender) {
// your implementation here
}
#GET
#Path("player")
#Produces("application/json")
public Whatever myMethod() {
return myMethod(null);
}
See the below link which has a sample of optional path parameters via regular expressions
RestEasy #Path Question with regular expression
You should use regex when you want have optional parameter in path.
So your code would then look like the following:
#GET
#Path("/player{gender : (/\\w+)?}")
#Produces("application/json;charset=UTF-8")
public Whatever myMethod(#QueryParam("gender") #DefaultValue("M") final String gender) {
// your implementation here
}
For more information see https://docs.jboss.org/resteasy/docs/1.1.GA/userguide/html/Using__Path_and__GET___POST__etc..html
Related
I am using spring to build a REST api with PageAble, to get numberofPages,itens...
first, i did a mapping like this
public ResponseEntity<Data> findByName(#PathVariable(value="name",required=true) String name, #RequestParam(value="page", defaultValue="0") Integer page, #RequestParam(value="qtd", defaultValue="10") Integer linesPerPage, #RequestParam(value="sort", defaultValue="nome") String sort, #RequestParam(value="direction", defaultValue="ASC") String direction)
So in my url i get for example "url?name=erick&direction=asc" but i need to change to "url?name=erick!asc"
How can i change it?
You can do this. Look at page 3 of https://www.ietf.org/rfc/rfc1738.txt
In you case,you should use #RequestParam("name") instead of #PathVariable.Then the request url will be like "url?name=erick&direction=asc"
Spring has three kinds of Annotation.
#PathVariable
This annotation means the variable is on the url.For example:
#RequestMapping("/{id}")
public void pathVariable(#PathVariable("id") Long id){}
The variable was put between the brace at the url.
#RequestParam
This annotation means the variable is part of the quest param,the request url looks like
stackoverflow.com?name=hhhh
For example:
#RequestMapping("/")
public void requestParam(#RequestParam("id")Long id){}
#RequestBody
This annotation means you will receive some data from request body.And some kind of converter,like jackson,will convert it into a properly object.For example:
#PostMapping("/")
public void requestBody(#RequestBody Example example){}
I want to dynamically enter my spring restful url, how to do this?
first of all, before i trying to create dynamical url, i create the static one. Here is what i do :
#RequestMapping(value = "/insert/{id}/{name}/{address}", method = RequestMethod.GET,headers="Accept=application/json")
public void insertsoheaderdinamis(#PathVariable String id, #PathVariable String name, #PathVariable String address) throws ParseException {
}
above is my static url code. in the future, what i need is, i need a new pathvariable like this localhost:8080/SpringServiceJsonSample/service/updatepool/insert/{here goes id}/{here goes name}/{here goes address}/{new variable goes phone number}/{here goes age}.
i don't want to change my code, so i decided to create a dynamic url. While i read around internet.
i trying to do this :
#RequestMapping(value = "/insert/{path}/**", method = RequestMethod.GET,headers="Accept=application/json")
public void insertdynamicurl(#PathVariable("path") String path, HttpServletRequest request) throws ParseException {
}
but this won't do, even i can't get into my function while debuging it. It always give me "noHandlerFound" in my console log. How to do the dynamically url for springrestful service properly?
You can have a look at URI Template Patterns with Regular Expressions which suggests on using regular expressions in #RequestMapping annotations.
The #RequestMapping annotation supports the use of regular expressions in URI template variables. The syntax is {varName:regex} where the first part defines the variable name and the second - the regular expression. For example:
#RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\d\.\d\.\d}.{extension:\.[a-z]}")
public void handle(#PathVariable String version, #PathVariable String extension) {
// ...
}
}
In addition to this, you can match rest of the URL string using request attribute name HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, as shown below.
#RequestMapping("/{id}/**")
public void foo(#PathVariable("id") int id, HttpServletRequest request) {
String restOfTheUrl = (String) request.getAttribute(
HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
...
}
Shishir's approach is good, but even the regular expression will match the value only up to a first forward slash, because the default AntPathMatcher uses a forward slash as a delimiter for path variables.
This means that you'll always have to statically list the mappings with all the possible path variable combinations. However, on the side of function arguments you don't have to list all the path variables, as you can use a map that will catch all the path variables regardless of the count, and this you can use to achieve a level of generality, something like
#RequestMapping(value = {"/insert/{id}/{name}/{address}", "/insert/{id}/{name}/{address}/{phoneNumber}", "/insert/{id}/{name}/{address}/{phoneNumber}/{age}"} , method = RequestMethod.GET,headers="Accept=application/json")
public void insertsoheaderdinamis(
#PathVariable Map<String, String> pathVariables) {
// to access the values of your path variables do something like
if (pathVariables.containsKey("id")) {
String id= pathVariables.get("id");
}
// do your stuff
}
I would like to have two GET methods on my Rest resource class.
one would react if query param has value1 and second on value2
Lets say:
#Path("/myApi")
public class MyApiService {
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response methodOne(...) {
...
return ...;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response methodTwo(...) {
...
return ...;
}
How to achieve conditional routing for query params
I would like to methodOne() reacts if QueryParam is ?type=one and methodTwo() if QueryParam is ?type=two
Choosing servlet handlers based on QueryParam is not a good aproach, and by default no library gives you oportunity to do so.
The closest that comes to mind is PathParam, that is something like Path("\api\{param1}\{param2}") but it's not what you are looking for.
To achieve want your want just
unregister those methods as servlet handlers (Optional, if you don't need them outside of queryparam selection scope)
define a new one that will choose based on query param
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response methodThree(QueryParam('type') String type) {
return type.equals("type1") ? this.methodOne() : this.methodTwo();
}
You cannot have two methods with identical parameters for the same path.
It's not pretty, but it will work..
#GET
#Produces(MediaType.APPLICATION_JSON)
public Response myMethod(#QueryParam("type") String type){
if(type.equals("one"))
return methodOne();
else
return methodTwo();
}
So I want to get the metadata of a youtube video (say this one: https://www.youtube.com/watch?v=qlTA3rnpgzU).
I'm going to encode it and wrap it in another url like so: http://www.youtube.com/oembed?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DqlTA3rnpgzU&format=json
My interface definition will look like this:
public interface YoutubeApi {
#GET ("oembed")
YoutubeMetaData metaData (#Query (QUERY_VIDEO_URL) final String url,
#Query(QUERY_FORMAT) final String alwaysJson);
}
That's all fine and dandy, but I don't ever want to specify any format other than JSON here (format=json is a fixed part of this url).
Is there a way to specify this in my interface declaration and reduce my interface to:
public interface YoutubeApi {
#GET ("oembed")
#Magic ("format=json")
YoutubeMetaData metaData (#Query (QUERY_VIDEO_URL) final String url);
}
Thanks.
Just put it right in the relative URL:
public interface YoutubeApi {
#GET("oembed?format=json")
YoutubeMetaData metaData(#Query(QUERY_VIDEO_URL) String url);
}
In kotlin you can specify the default parameter:
interface YoutubeApi {
#GET ("oembed")
suspend fun metaData (
#Query (QUERY_VIDEO_URL) url: String,
#Query(QUERY_FORMAT) alwaysJson: String = "json"
): Response<YoutubeMetaData>
}
I have a service in rest that looks like:
#GET
#Path("get-policy/{policyNumber}/{endorsement}/{type}")
#Produces(MediaType.APPLICATION_XML)
public String getPolicyIndividual(
#PathParam("policyNumber")String policyNumber,
#PathParam("endorsement")String endorsement,
#PathParam("type")String type){
...
}
And i want to know if there is a way that i can accept every parameter as null value if they are not sent, so if somene makes a call to my service without the params or with not all the params still can match the definition of my service.
Examples:
http://localhost:8080/service/policy/get-policy/
or this:
http://localhost:8080/service/policy/get-policy/5568
or this:
http://localhost:8080/service/policy/get-policy/5568/4
Im well aware that i can define a regex expression like in this answer, but in that case there was only 1 path param defined, what if i have more than one?
That didnt work for me but maybe im doing something wrong, i tried this with no success:
#GET
#Path("get-policy/{policyNumber: .*}/{endorsement: .*}/{type: .*}")
#Produces(MediaType.APPLICATION_XML)
public String getPolicyIndividual(
#PathParam("policyNumber")String policyNumber,
#PathParam("endorsement")String endorsement,
#PathParam("type")String type){
...
}
is the only way to achive this trough a POST? Im using Jersey btw!
You have to create a complete use case scenario for this and call a general method every time if you dont want to write code multiple times.
Say: For an instance use only one parameter passed, then 2 and then all, and none
#GET
#Path("get-policy/{policyNumber: .*}")
#Produces(MediaType.APPLICATION_XML)
public String getPolicyIndividual(
#PathParam("policyNumber")String policyNumber)
{
doSomething(policyNumber, "", "");
}
#GET
#Path("get-policy/{policyNumber: .*}/{endorsement: .*}")
#Produces(MediaType.APPLICATION_XML)
public String getPolicyIndividual(
#PathParam("policyNumber")String policyNumber,
#PathParam("endorsement")String endorsement)
{
doSomething(policyNumber,endorsement, "");
}