I have a rest api implementation as below -
#RequestMapping(value = "/getAllProductsByCategory/{category}/{pageNo}/{numberOfProducts}", method = RequestMethod.GET)
public List<ProductProperties> getAllProdutsByCategory(#PathVariable("category") String categoryID, #PathVariable("pageNo") int pageNo,
#PathVariable("numberOfProducts") int numberOfProducts) {
return productService.getProductsByCategory(categoryID, pageNo, numberOfProducts);
}
Now i want to test this method where category variable should be like "men/clothing/jeans". I tried to use escape character %2F to replace forward slash, but had no luck. Is there any way to pass forward slash in uri ? I tried to google same question but didn't find any satisfactory answer.
Related
I'm a bit new to Spring and trying to replace my parameters to pass as key:value pairs and also replace an ampersand with a literal "and" to avoid issues when hitting the screen. Example:
I want to go from: mySite/myPage.html?myId=154933680&myRequest='QT'
to have a separate method/entrypoint that will work like this:
myPage?search=myId=154735535 and myRequest="RT"
Now, my current header looks like this:
#RequestMapping(value = "myPage.html", method = RequestMethod.GET) public ModelAndView getSite(HttpServletRequest request, #RequestParam String myId, #RequestParam String myRequest)
I'm trying to do something like this instead, but its not working:
#RequestMapping(value = "myPage?search=", method = RequestMethod.GET) public ModelAndView mySearch(HttpServletRequest request, #RequestParam String myId, #RequestParam String myRequest) {
But I would like to pass in them as key:value params rather than straight Strings as well. I'm a little all over the place here, I guess my main question would be with what I have above, how do I swap my URL to not string the parameters together with a "&" but to use "and" instead?
#RequestMapping(value = "/{userId:\\d+}", method = RequestMethod.DELETE)
public void delete(#PathVariable Long userId) {
try{
this.authorService.delete(userId);
}catch(Exception e){
throw new RuntimeException("delete error");
}
}
Anybody know what url should I match for this definition "/{userId:\d+}", could you give me an example, like "/userid=1", is this right?
I guess that definition like this "/{userId:\d+}" , using regular expression in url to make sure it pass a number parameter.I am not sure about that , if anybody knows it please give me a link for further learning, thank you!
No, that expression maps /1 for example, all the digits.
The syntax {varName:regex} declares a URI variable with a regular expressions with the syntax {varName:regex} — e.g. given URL "/spring-web-3.0.5 .jar", the below method extracts the name, version, and file extension:
#GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(#PathVariable String version, #PathVariable String ext) {
// ...
}
Check the complete doc here
It will match any digit. For example,
/1, /11, /123.
/{userId:\\d+} ===> map one or more digits after / to variable userId.
Regular expression for one or more digits is \d+, but since you are using it as a string you need to escape it using another \.
When using Spring MVC, is there a way to create two entry points by whether or not any query string has been supplied in the request.
Something like below where * is a wildcard?
#RequestMapping(value = "/page", method = RequestMethod.GET, params = {"*"})
public String getResourceWithQuery(...)
#RequestMapping(value = "/page", method = RequestMethod.GET, params = {"!*"})
public String getResourceWithoutQuery(...)
Is this possible with Spring?
Edit: To be clear, I'm not looking for a particular query parameter, I'm looking to separate the methods by the existence of any query string being present at all.
The fall back is to have one method and then check in code for query parameters and split accordingly. Having a filter method like this is messy and I'd prefer not to have to do this. Unfortunately the splitting functionality by query pattern is common in my code as it is required by the business.
One end point is enough.
You can set default value for request parameter(or query string), this will make request parameter optional.
As per java doc,
defaultValue:
public abstract String defaultValue The default value to use as a fallback > when the request parameter is not provided or has
an empty value. Supplying a default value implicitly sets required()
to false.
For example,
public String doSomething(#RequestParam(value = "name", defaultValue = "anonymous") final String name) {
Your are trying to map the request URI which having the query string or not.you are using the params in #RequestMapping which actually use for narrow the Request matching.Read below link
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#params--
.By using below code you can accept anything after ~/page/ URI.I hope this will help
#RequestMapping(value = "/page/**", method = RequestMethod.GET)
public String getResourceWithQuery(...)
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.)