My client would send a request corresponding to:
GET http://example.com/services/rs/calendar/origin/destination/outwardDate/returnDate?nbPax=&typo=&card
I do this:
#Path("/service/rs") public class MyServiceImpl {
public MyServiceImpl() {
super();
}
#GET
#Path("/{origin}/{destination}/{goDate}/{returnDate}")
public Response getCalendar(#PathParam("origin") String origin, #PathParam("destination") String destination, #PathParam("goDate") String goDate, #PathParam("returnDate") String returnDate, #QueryParam("nbPax") String nbPax, #QueryParam("typo") String typo, #QueryParam("card") String card) {
//print my parameters
return Response.ok("Success").build();
}
}
there cannot map my query parameter, fails with 404, why ?
You need to correct the signature of your method and add the placeholders inside the #Path annotation to map the path parts to those #PathParam-annotated arguments. The parts that are query params should use the #QueryParam annotation.
#GET
#Path("/calendar/{origin}/{destination}/{outwardDate}/{returnDate}")
public Response getInfo(#PathParam("origin") String origin,
#PathParam("destination") String destination,
#PathParam("outwardDate") String outwardDate,
#PathParam("returnDate") String returnDate,
#QueryParam("nbPax") String nbPax,
#QueryParam("typo") String typo,
#QueryParam("card") String card) {
Also, be aware that if you web application is rooted at some context path (this is typical for applications deployed inside Servlet containers like Tomcat or JBoss), the context path will be part of the URL, e.g.
http://[server host]/[app context path]/[class' #Path]/[method's #Path]
This is the address
http://example.com/services/rs/calendar/
and you are calling
http://example.com/services/rs/calendar/origin/destination/outwardDate/returnDate
where you are treating word "origin" (and the rest) as parameter, while its actually part of address, I believe you have no REST service attached to:
http://example.com/services/rs/calendar/origin/destination/outwardDate/returnDate
Thats why you are getting 404.
Those words you are trying to pull are of type #PathParam, #QueryParam is what you have after ? sign
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 have a spring web service method where i want to get a string as a parameter. The string is sent in body of the request. My web service class is:
#Controller
#RequestMapping(value = "/users/{uid}/openchart")
public class OpenChartWebService {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public String saveABC(#PathVariable("uid") Long uid,
#RequestBody String myString) {
System.out.println("sent string is: "+myString);
return "something";
}
}
My request in body is :
{
"name":"Ramesh"
}
But this is not working. This shows "Bad Request" HTTP error(400). How to send a string in a body and how to get a string sent in a body inside webservice method?
As #Leon suggests, you should add the media type to your request mapping, but also make sure you have Jackson on your classpath. You'll also want to change your #RequestBody argument type to something that has a "name" property, rather than just a String so that you don't have to convert it after.
public class Person {
private name;
public getName() {
return name;
}
}
If your data object looked like the above, then you could set your #RequestBody argument to Person type.
If all you want is a String, then perhaps just pass the value of "name" in your request body rather than an object with a name property.
I've a request mapping that handles any string after the context e.g. www.example.com/anystring
I'm handling it as follows:
#RequestMapping(value="/{str}", method = RequestMethod.GET)
public String getApp(#PathVariable("str") String anyString, ModelMap model) {
//Do something
}
The problem is I've 2-3 URLs in my app where the URL is as follows: www.example.com/about, www.example.com/contact etc.
I wrote Request Mappings for them as follows:
#RequestMapping("/about")
public String getAboutPage() {
return "about";
}
But obviously, since I've already declared that any string should be handled by the getApp(), the getAboutPage() never gets executed.
How can I exclude /about, /contact etc from getApp() mapping.
We can obviously add another keyword to the URL string, but that's not possible in my app use case.
Kindly help. :(
EDIT:
Should I just handle /about, /contact inside getApp() like:
#RequestMapping(value="/{str}", method = RequestMethod.GET)
public String getApp(#PathVariable("str") String anyString, ModelMap model) {
if(anyString.equals("about")){
//do about related stuff
}
if(anyString.equals("contact")){
//do contact related stuff
}
//Do something
}
Is there a better way?
Specifying the HTTP request method in the "catch-all" mapping is probably making the path matcher consider it to be more specific than the absolute path mappings.
Specify the request method on the absolute paths, and the mapping comparator should order the absolute matches before the one containing the path variable.
eg.
#RequestMapping("/about", method = RequestMethod.GET)
Alternatively, you could remove the method specification on the catch-all:
#RequestMapping("/{str}")
It is entirely dependent upon your url structure and whether or not any of those paths will accept different http request methods.
I am kind of new to RESTful web services and need some help. I have service which will return a list of products. The URL looks like the following:
/example/product/6666,6667?expand=sellers&storeIds=2,1
To define this service I have this interface:
#Path("/example")
public interface Service {
#GET
#Path("/products/{pIds}")
#Produces( "application/json" )
public ServiceResponse<ProductsList> getProducts(
#PathParam("pIds") String productsIds,
#QueryParam("expand") String expand,
#QueryParam("storeIds") String storeIds) throws Exception;
}
I am assuming here that I am getting the productsIds as a string and that I will need to manually split this string into a list of ids, with delimiter as a comma.
Is there a way to instead get the parameters as list, instead of doing manually it from my side? Or is there a library that I can use to do this in an automated way?
Thanks
You can deserialize the product id's directly into a list with some minor change to your service definition. Try this instead:
#Path("/example")
public interface Service {
#GET
#Path("/products/{pIds}")
#Produces( "application/json" )
public ServiceResponse<ProductsList> getProducts(
#PathParam("pIds") List<String> productsIds,
#QueryParam("expand") String expand,
#QueryParam("storeIds") String storeIds) throws Exception;
}
Change String productsIds to List<String> productsIds.
On a side note, I would recommend passing in the product id's as a query parameter. Your URI should identify a unique resource (in this case products) and it should be stateless.