I have a controller with the following GetMapping
#GetMapping(value = "/dawson/v1/{dataType}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<String> respondWithData(#PathVariable String dataType, #RequestParam(name = "minDate") String min_date, #RequestParam(name = "maxDate") String max_date, #RequestParam(USERID) String user_id, #RequestHeader(value = "Authorization") String authorizationHeader) {
where dataType can be one of either String, Map, Object or Calendar. I created another GetMapping as follows
#GetMapping(value = "/dawson/v1/signInReq")
public ResponseEntity<String> mySignInRequest(#RequestBody Map<String, String> paramMap, HttpServletRequest request, HttpServletResponse response) {
However, when I try to access the /dawson/v1/signInReq, it still hits the first mapping and not the signInReq one. Is there a way to exclude signInReq as a match for {dataType}?
I do have the workaround of listing all possible dataTypes in the first mapping above but was wondering if there was a better way to handle it(Regex maybe?).
I used a REGEX pattern to resolve the filtering of path as follows:
#GetMapping(value = "/dawson/v1/{dataType:^.*(?!signInReq)}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
The Regex will only match requests that are not signInReq.
Related
I am writing a feign client
#RequestMapping(
path = "/TrackingServlet?CompanyName=Test&UserName=&BranchCode=",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE
)
ResponseEntity<String> getInfo(
#RequestParam("DocumentNumbers") String bill);
when it is invoked the url becomes /TrackingServlet?CompanyName=Test&UserName&BranchCode
eliminating the = symbol, but the API needs it in that format, since its a third party API we cannot modify it.
Also tried
#RequestMapping(
path = "/TrackingServlet?CompanyName=Test&UserName=",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE
)
ResponseEntity<String> getInfo(
#RequestParam("DocumentNumbers") String bill,
#RequestParam(name = "BranchCode", required = true) String BranchCode);
default ResponseEntity<String> getInfo(String bill) {
return getInfo(bill, "");
}
this will not even have the param BranchCode
I am using org.springframework.cloud:spring-cloud-starter-openfeign:2.1.1.RELEASE
Spring boot version 2.1.4.RELEASE
is there anyway or workarounds for keeping empty params in urls as it is ?
If your URL is http://localhost:8080/trackingServlet/testing?userName=pratik
Use feign client:
#FeignClient(name = "tracking-servlet-service")
public interface TestFeignClient {
#GetMapping("/trackingServlet/testing")
public String getQueryParam(#RequestParam("userName") String name);
}
If you have 2 or more parameter then you can add same in #RequestParam
E.g
URL http://localhost:8080/trackingServlet/testing?userName=pratik&companyName=Test
#FeignClient(name = "tracking-servlet-service")
public interface TestFeignClient {
#GetMapping("/trackingServlet/testing")
public String getQueryParam(#RequestParam("userName") String name,
#RequestParam("companyName") String companyName);
}
The spring boot do not recognize my controllers only if i send more parameters on request. For example:
If i send normal GET request the spring boot recognize my controller:
http://localhost/idp/oauth/123/authorize
If i send GET request with extras parameters the spring boot do not recognize my controller:
http://localhost/idp/oauth/123/authorize?scope=public_profile
I need receive the request exactly for second example (with parameter scope), but the spring boot do not recognize the controller and redirect to /error.
code:
#Controller
#RequestMapping("/idp/oauth")
public class OAuthController {
#RequestMapping(value = "/{clientId}/authorize", method = RequestMethod.GET)
public String authorizeGet(
HttpServletRequest request,
HttpServletResponse response,
#PathVariable String clientId,
Model model) {
// ...
}
#RequestMapping(value = "/{clientId}/authorize", method = RequestMethod.POST)
public String authorizePost(
HttpServletRequest request,
HttpServletResponse response,
#PathVariable String clientId,
Model model) {
// ...
}
}
Since you are passing extra param with name "scope" Spring will search for #RequestParam in methods
It can't find any, thus the error
You need to modify your method to add all #RequestParam
You can also add optional fields if they are not mandatory with required = false
#RequestMapping(value = "/{clientId}/authorize", method = RequestMethod.GET)
public String authorizeGet(
HttpServletRequest request,
HttpServletResponse response,
#PathVariable String clientId,
#RequestParam(value = "scope") String scope,
#RequestParam(required = false, value = "optionalParam") String optionalParam,
Model model) {
// ...
}
You missed #RequestParam in the controller method definition.
More on #RequestParam
The client sends some data in one request param like:
example.com/test?myparam=some123data
I would like to convert myparam into several other params and call a necessary controller with such parameters. Like this one:
#RequestMapping(value = "/test")
public #ResponseBody MyObject test(
#RequestParam(value = "prefix") String prefix, // some
#RequestParam(value = "number") int number, // 123
#RequestParam(value = "suffix") String suffix) //data
{ ... }
It is possible to put some custom converter for such situation?
I'm not really sure if it can be made wit request params. Instead, you could use path variables with regular expressions in the following way:
#RequestMapping(value = "/test/{prefix:[a-z]+}{number:[0-9]+}{suffix:[a-z]+}")
public #ResponseBody MyObject test(
#PathVariable(value = "prefix") String prefix, // some
#PathVariable(value = "number") int number, // 123
#PathVariable(value = "suffix") String suffix) //data
{ ... }
In this case your request URL will look like this:
example.com/test/some123data
You can try to implement your own argument resolver, here an example
What is the difference between #RequestParam and #PathVariable while handling special characters?
+ was accepted by #RequestParam as space.
In the case of #PathVariable, + was accepted as +.
#PathVariable is to obtain some placeholder from the URI (Spring call it an URI Template)
— see Spring Reference Chapter 16.3.2.2 URI Template Patterns
#RequestParam is to obtain a parameter from the URI as well — see Spring Reference Chapter 16.3.3.3 Binding request parameters to method parameters with #RequestParam
If the URL http://localhost:8080/MyApp/user/1234/invoices?date=12-05-2013 gets the invoices for user 1234 on December 5th, 2013, the controller method would look like:
#RequestMapping(value="/user/{userId}/invoices", method = RequestMethod.GET)
public List<Invoice> listUsersInvoices(
#PathVariable("userId") int user,
#RequestParam(value = "date", required = false) Date dateOrNull) {
...
}
Also, request parameters can be optional, and as of Spring 4.3.3 path variables can be optional as well. Beware though, this might change the URL path hierarchy and introduce request mapping conflicts. For example, would /user/invoices provide the invoices for user null or details about a user with ID "invoices"?
#RequestParam annotation used for accessing the query parameter values from the request. Look at the following request URL:
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
In the above URL request, the values for param1 and param2 can be accessed as below:
public String getDetails(
#RequestParam(value="param1", required=true) String param1,
#RequestParam(value="param2", required=false) String param2){
...
}
The following are the list of parameters supported by the #RequestParam annotation:
defaultValue – This is the default value as a fallback mechanism if request is not having the value or it is empty.
name – Name of the parameter to bind
required – Whether the parameter is mandatory or not. If it is true, failing to send that parameter will fail.
value – This is an alias for the name attribute
#PathVariable
#PathVariable identifies the pattern that is used in the URI for the incoming request. Let’s look at the below request URL:
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
The above URL request can be written in your Spring MVC as below:
#RequestMapping("/hello/{id}") public String getDetails(#PathVariable(value="id") String id,
#RequestParam(value="param1", required=true) String param1,
#RequestParam(value="param2", required=false) String param2){
.......
}
The #PathVariable annotation has only one attribute value for binding the request URI template. It is allowed to use the multiple #PathVariable annotation in the single method. But, ensure that no more than one method has the same pattern.
Also there is one more interesting annotation:
#MatrixVariable
http://localhost:8080/spring_3_2/matrixvars/stocks;BT.A=276.70,+10.40,+3.91;AZN=236.00,+103.00,+3.29;SBRY=375.50,+7.60,+2.07
And the Controller method for it
#RequestMapping(value = "/{stocks}", method = RequestMethod.GET)
public String showPortfolioValues(#MatrixVariable Map<String, List<String>> matrixVars, Model model) {
logger.info("Storing {} Values which are: {}", new Object[] { matrixVars.size(), matrixVars });
List<List<String>> outlist = map2List(matrixVars);
model.addAttribute("stocks", outlist);
return "stocks";
}
But you must enable:
<mvc:annotation-driven enableMatrixVariables="true" >
#RequestParam is use for query parameter(static values) like: http://localhost:8080/calculation/pow?base=2&ext=4
#PathVariable is use for dynamic values like : http://localhost:8080/calculation/sqrt/8
#RequestMapping(value="/pow", method=RequestMethod.GET)
public int pow(#RequestParam(value="base") int base1, #RequestParam(value="ext") int ext1){
int pow = (int) Math.pow(base1, ext1);
return pow;
}
#RequestMapping("/sqrt/{num}")
public double sqrt(#PathVariable(value="num") int num1){
double sqrtnum=Math.sqrt(num1);
return sqrtnum;
}
1) #RequestParam is used to extract query parameters
http://localhost:3000/api/group/test?id=4
#GetMapping("/group/test")
public ResponseEntity<?> test(#RequestParam Long id) {
System.out.println("This is test");
return ResponseEntity.ok().body(id);
}
while #PathVariable is used to extract data right from the URI:
http://localhost:3000/api/group/test/4
#GetMapping("/group/test/{id}")
public ResponseEntity<?> test(#PathVariable Long id) {
System.out.println("This is test");
return ResponseEntity.ok().body(id);
}
2) #RequestParam is more useful on a traditional web application where data is mostly passed in the query parameters while #PathVariable is more suitable for RESTful web services where URL contains values.
3) #RequestParam annotation can specify default values if a query parameter is not present or empty by using a defaultValue attribute, provided the required attribute is false:
#RestController
#RequestMapping("/home")
public class IndexController {
#RequestMapping(value = "/name")
String getName(#RequestParam(value = "person", defaultValue = "John") String personName) {
return "Required element of request param";
}
}
it may be that the application/x-www-form-urlencoded midia type convert space to +, and the reciever will decode the data by converting the + to space.check the url for more info.http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
#PathVariable - must be placed in the endpoint uri and access the query parameter value from the request
#RequestParam - must be passed as method parameter (optional based on the required property)
http://localhost:8080/employee/call/7865467
#RequestMapping(value=“/call/{callId}", method = RequestMethod.GET)
public List<Calls> getAgentCallById(
#PathVariable(“callId") int callId,
#RequestParam(value = “status", required = false) String callStatus) {
}
http://localhost:8080/app/call/7865467?status=Cancelled
#RequestMapping(value=“/call/{callId}", method = RequestMethod.GET)
public List<Calls> getAgentCallById(
#PathVariable(“callId") int callId,
#RequestParam(value = “status", required = true) String callStatus) {
}
Both the annotations behave exactly in same manner.
Only 2 special characters '!' and '#' are accepted by the annotations #PathVariable and #RequestParam.
To check and confirm the behavior I have created a spring boot application that contains only 1 controller.
#RestController
public class Controller
{
#GetMapping("/pvar/{pdata}")
public #ResponseBody String testPathVariable(#PathVariable(name="pdata") String pathdata)
{
return pathdata;
}
#GetMapping("/rpvar")
public #ResponseBody String testRequestParam(#RequestParam("param") String paramdata)
{
return paramdata;
}
}
Hitting following Requests I got the same response:
localhost:7000/pvar/!##$%^&*()_+-=[]{}|;':",./<>?
localhost:7000/rpvar?param=!##$%^&*()_+-=[]{}|;':",./<>?
!# was received as response in both the requests
#RequestParam:We can say it is query param like a key value pair
#PathVariable:-It is came from URI
I have a complicated html form that dynamically created with java script.
I want to get the map of key-value pairs as a Map in java and store them.
here is my controller to get the submitted data.
#RequestMapping(value="/create", method=RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createRole(Hashmap<String, Object) keyVals) {
....
}
but my map is empty.
How can i get form data as a map of name-value pairs in Spring mvc controller?
You can also use #RequestBody with MultiValueMap
e.g.
#RequestMapping(value="/create",
method=RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createRole(#RequestBody MultiValueMap<String, String> formData){
// your code goes here
}
Now you can get parameter names and their values.
MultiValueMap is in Spring utils package
I,ve just found a solution
#RequestMapping(value="/create", method=RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createRole(HttpServletRequest request) {
Map<String, String[]> parameterMap = request.getParameterMap();
...
}
this way i have a map of submitted parameters.
Try this,
#RequestMapping(value = "/create", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createRole(#RequestParam HashMap<String, String> formData) {
The answers above already correctly point out that #RequestParam annotation is missing. Just to add why thta is required,
A simple GET request would be soemthing like :
http://localhost:8080/api/foos?id=abc
In controller, we need to map the function paramter to the parameter in the GET request. So we write the controller as
#GetMapping("/api/foos")
#ResponseBody
public String getFoos(#RequestParam String id) {
return "ID: " + id;
}
and add #RequestParam for the mapping of the paramter "id".