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(...)
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 &
If i have something like
#GetMapping(value = "/list")
public ResponseEntity<MyDTO> findStatusPerEC(#RequestParam final List<Long> numbersEC)
How do I add numbersEC in my url on the frontend? Is this query parameter?
I know this one was for old call that didn´t had query parameters and data was only a number (long)
return this.http.get<any>(URL_API + '/simulator/status/' + data);
But now I have to send a list of long values...may you help me?
return this.http.get<any>(URL_API + '/simulator/status/' + data);
Since you mentioned data is only a long type, what you are referring to here when you make the above request is a PathVariable it is slightly different to a RequestParam.
Path variables have the syntax: /simulator/status/:statusID where statusID is dynamic and extracts values from the URI.
Request parameters have the syntax: ?arg=val&arg2=val2 etc... and extract values from the request query string.
Solution
To answer your question, to send an array across as request parameters, you can do it like so:
?myparam=myValue1&myparam=myValue2&myparam=myValue3
As you can see, above myparam is unchanging, and the values are variable, hence the data within your list data structure.
So when you're making your request it will look similar to this:
Angular/Javascript
return this.http.get<any>(URL_API + '/list' + '?myparam=myValue1&myparam=myValue2&myparam=myValue3');
Java
#GetMapping(value = "/list")
public ResponseEntity<MyDTO> findStatusPerEC(#RequestParam final List<Long> numbersEC)
I hope this helps.
My understanding so far is on our controller request mapping method we can specify RedirectAttributes parameter and populate it with attributes for when the request gets redirected.
Example:
#RequestMapping(value="/hello", method=GET)
public String hello(RedirectAttributes redirAttr)
{
// should I use redirAttr.addAttribute() or redirAttr.addFlashAttribute() here ?
// ...
return "redirect:/somewhere";
}
The redirect attributes will then be available on the target page where it redirects to.
However RedirectAttributes class has two methods:
addAttribute()
addFlashAttribute()
Have been reading Spring documentation for a while but I'm a bit lost. What is the fundamental difference between those two, and how should I choose which one to use?
Here is the difference:
addFlashAttribute() actually stores the attributes in a flashmap
(which is internally maintained in the users session and removed
once the next redirected request gets fulfilled)
addAttribute() essentially constructs request parameters out of
your attributes and redirects to the desired page with the request
parameters.
So the advantage of addFlashAttribute() will be that you can store pretty much any object in your flash attribute (as it is not serialized into request params at all, but maintained as an object), whereas with addAttribute() since the object that you add gets transformed to a normal request param, you are pretty limited to the object types like String or primitives.
Assume you have 2 controllers.If you redirect from one controller to
another controller the values in model object won't be available in the
other controller. So if you want to share the model object values
then you have to say in first controller
addFlashAttribute("modelkey", "modelvalue");
Then second controller's model contains now the above key value pair..
Second question ? What is difference between addAttribute and addFlashAttribute in RedirectAttributes class
addAttribute will pass the values as requestparameters instead of model,so when you add some using addAttribute you can access those values from request.getParameter
Here is the code.I have used to find out what is going on :
#RequestMapping(value = "/rm1", method = RequestMethod.POST)
public String rm1(Model model,RedirectAttributes rm) {
System.out.println("Entered rm1 method ");
rm.addFlashAttribute("modelkey", "modelvalue");
rm.addAttribute("nonflash", "nonflashvalue");
model.addAttribute("modelkey", "modelvalue");
return "redirect:/rm2.htm";
}
#RequestMapping(value = "/rm2", method = RequestMethod.GET)
public String rm2(Model model,HttpServletRequest request) {
System.out.println("Entered rm2 method ");
Map md = model.asMap();
for (Object modelKey : md.keySet()) {
Object modelValue = md.get(modelKey);
System.out.println(modelKey + " -- " + modelValue);
}
System.out.println("=== Request data ===");
java.util.Enumeration<String> reqEnum = request.getParameterNames();
while (reqEnum.hasMoreElements()) {
String s = reqEnum.nextElement();
System.out.println(s);
System.out.println("==" + request.getParameter(s));
}
return "controller2output";
}
Javadoc description:
"A FlashMap provides a way for one request to store attributes intended for use in another. This is most commonly needed when redirecting from one URL to another -- e.g. the Post/Redirect/Get pattern. A FlashMap is saved before the redirect (typically in the session) and is made available after the redirect and removed immediately."
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
.....
}
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.)