Java Optional query string paramters and Server side API's - java

Here is my requirement:
Step Five: Add searching by title
This method's purpose is to enable searching by title. You'll pass in an optional query string parameter that returns all auctions with the search term in the title.
In AuctionController.java, return to the list() action method. Add a String request parameter with the name title_like. You'll need to make this parameter optional, which means you set a default value for it in the parameter declaration. In this case, you want to set the default value to an empty string "".
Look in MemoryAuctionDao.java for a method that returns auctions that have titles containing a search term. Return that result in the controller method if title_like contains a value, otherwise return the full list like before.
My code that is NOT passing is this:
#RequestMapping(value = "title_like = ", method = RequestMethod.GET)
public List<Auction> searchByTitle(#RequestBody String title_like) {
if (!title_like.isEmpty()) {
for (Auction auction : auctions) {
if (dao.searchByTitle(title_like).contains(title_like)) {
auctions.add(auction);
return auctions;
}
}
}
return null;
}
}

Refactor the code like below
#RequestMapping(value = "search", method = RequestMethod.GET)
public ResponseEntity<List<Auction>> searchByTitle(#RequestParam(name="title_like", required=false) String title_like) {
...
return ResponseEntity.ok().body(<body>).build();
}

You are using GET method. With Get, it contain no body.
That why your signature don't work.
#RequestMapping(value = "title_like = ", method = RequestMethod.GET)
public List<Auction> searchByTitle(#RequestBody String title_like)
So you have to change #RequestBody to #RequestParam with GET method.
#RequestParam(name="title_like", required=false) String title_like
Other ways, you can change to different method to support body like (RequestMethod.POST, PUT...).
#RequestMapping(value = "title_like = ", method = RequestMethod.POST)
public List<Auction> searchByTitle(#RequestBody String title_like)

Related

Using a String variable in RequestMapping value

I have the following:
#Value("${apiVersion")
private String apiVersion;
#RequestMapping(value = "/{apiVersion}/service/call", method = RequestMethod.POST)
And I expected the URL to be:
/apiVersion/service/call
But it turns out {foo} accept any value, it doesn't actually use the String.
Is there a way for me to use the String value as part of the URL?
EDIT
The issue is that I have multiple calls that us that value.
#RequestMapping(value = apiVersion + "/call1", method = RequestMethod.POST)
#RequestMapping(value = apiVersion + "/call2", method = RequestMethod.POST)
#RequestMapping(value = apiVersion + "/call3", method = RequestMethod.POST)
etc.
Technically I can declare constants for each one like you suggested, but it doesn't sound optimal. If there is no way to do it then it is fine, I was just wondering if there is.
SOLUTION
Adding general mapping to the controller.
#RequestMapping("${apiVersion}")
If you want to apply it for all methods in a controller declare it on the controller class level:
#RestController
#RequestMapping("/test")
public class MyController { ...
and you do not need to prepend it before method path.
Otherwise it should be constant so like:
private static final String FOO = "test";
and prepend it before method path like:
FOO + "/service/call"
If you just want to predefine the path in Java just do
#RequestMapping(value = foo + "/service/call", method = RequestMethod.POST)
PathVariables in SpringMvc are meant to be a placeholder for endpoints like in the following
#GetMapping(value = "/books/{id}")
public String displayBook(#PathVariable id) { ... }

How to find the id of the source link in a Spring controller [duplicate]

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&param2=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&param2=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

Pass attribute in spring from controller to external url and back

I have some external url for payment. After payment is done it redirects to me back.
#RequestMapping(value = "/first", method = RequestMethod.GET)
public String first(#RequestParam("id") String id) {
doSomething(id);
return "redirect:/externalurl"
}
// This method is called from external url
#RequestMapping(value = "/second", method = RequestMethod.GET)
public String second() {
// I want to get here id from first call
}
Is it possible somehow to do it with RedirectAttributes or other similar approach like to add it in first() method and to get it in second() method ?

How to know if a parameter value is provided in post request body in spring?

I am building web service with spring and come across with following problem.
There is a post service as follow.
#RequestMapping(value = "/postSomething", method = RequestMethod.POST)
public ResponseDTO postSomething(#RequestBody ADto aDto){
//post data
//return response
}
public class ADto{
private String firstParam;
private String secondParam;
// getter setter
}
So, my question is how can I know whether value of firstParam and secondParam is provided in request body or not.
RequestBody: { paramFirst: null, paramSecond: null}
Edit1:
Sorry for incomplete question:
For RequestBody: {paramFirst: first Value} and for above request value of paramSecond will be null.
So, how would I know whether paramSecond is included in request or not.
Edit2:
I don't want to validate. What I want to know is whether
request contains a particular parameter or not.
Because there are two different cases, one is value of a parameter is given null and other is paramter is not included in request.
You could use the #Valid annotation like so (pseudo code, didn't test it):
#RequestMapping(value = "/postSomething", method = RequestMethod.POST)
public ResponseDTO postSomething(#Valid #RequestBody ADto aDto){
// MethodArgumentNotValidException will be thrown if validation fails.
}
You'll need an exception handler to handle the validation error.
#ExceptionHandler
#ResponseBody
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public Error handleException(MethodArgumentNotValidException exception) {
//do something with the validation message: exception.getBindingResult()
}
And your class.
public class ADto{
#NotNull(message = "First parameter can not be null")
private String firstParam;
#NotNull(message = "Second parameter can not be null")
private String secondParam;
// getter setter
}
Try using Hibernate Validator (http://hibernate.org/validator/), it's really easy to integrate it with Spring.
That way, you'll need to annotate your Dto to enforce validation of required params and then call validate.
public class ADto{
#NotNull
private String firstParam;
#NotNull
private String secondParam;
// getter setter
}
#RequestMapping(value = "/postSomething", method = RequestMethod.POST)
public ResponseDTO postSomething(#RequestBody ADto aDto){
validator.validate(aDto)
//post data
//return response
}
You could make firstParam and secondParam type Optional:
ADto class
public class ADto {
private Optional<String> firstParam;
private Optional<String> secondParam;
// getter setter
}
postSomething method
#RequestMapping(value = "/postSomething", method = RequestMethod.POST)
public ResponseDTO postSomething(#RequestBody ADto aDto) {
if (Optional.ofNullable(aDto.getFirstParam()).isPresent()) {
// firstParam is provided in the request
} else {
// firstParam is not provided in the request
}
if (Optional.ofNullable(aDto.getSecondParam()).isPresent()) {
// secondtParam is provided in the request
} else {
// secondtParam is not provided in the request
}
}
Note that isPresent() will return false if and only if firstParam (as well as for secondParam) is not present in the request. Otherwise, even if the value is set to null, it will return true.

Multiple route with the same pattern url

I m actually creating a simple application and I need to have routing pattern identical in multiple case :
/*
* Returns a list of all the root directories accepting query string on name
*/
#RequestMapping(value = "/directories", method = RequestMethod.GET)
public List<DirectoryEntity> find() {
return directoryService.findAll();
}
/*
* Returns a list of all the root directories accepting query string on name
* #param name Name of the ressources to search. Query string at format : *name*
*/
#RequestMapping(value = "/directories", method = RequestMethod.GET)
public List<DirectoryEntity> findByCriteria(#RequestParam(value = "name", required = true) String name) {
return directoryService.findByName(name);
}
In fact, I dont want to manage criteria request in the same function as findAll one. Is there anyway to handle this case without be forced to manage everything inside the same function ?
Thanks for advance
Try changing the second method #RequestMapping annotation adding params:
#RequestMapping(value = "/directories", method = RequestMethod.GET, params = "name")
public List<DirectoryEntity> findByCriteria(#RequestParam(value = "name", required = true) String name) {
return directoryService.findByName(name);
}
See also the Spring Documentation for more details.
I'm not quite sure what you are asking, but assuming the decision as to which method to call is based on request parameters (it must be since they're both the same URL and HTTP method), then something like this might help:
#RequestMapping(method=RequestMethod.GET, params={"name"})
public #ResponseBody List<DirectoryEntity> findByCriteria(#RequestParam(value = "name", required = true) String name) {
//do your stuff
}
The inclusion of the params attribute in the #RequestMapping annotation removes the ambiguity in which method to call.
I've also added #ResponseBody to the return type, just in case you want Spring to return the list in the HTTP response.

Categories

Resources