Difference between use #RequestMapping with and without method - spring

I'm learning about Spring and MVC.
So, in the controller class, I have this method:
#RequestMapping(value="/buscaUsuario/{apodo}", method= RequestMethod.GET)
public String searchUser(#PathVariable("apodo") String apodo){
String res;
int usrId = this.usuarioService.bucarUsuario(apodo);
if(usrId == 0) res = "/error";
else res =("/user/"+Integer.toString(usrId));
return ("redirect:"+res);
}
And it works. But if I change it deleting the "method=RequestMethod.GET" part. I mean, using it like this:
#RequestMapping(value="/buscaUsuario/{apodo}")
public String searchUser(#PathVariable("apodo") String apodo){
String res;
int usrId = this.usuarioService.bucarUsuario(apodo);
if(usrId == 0) res = "/error";
else res =("/user/"+Integer.toString(usrId));
return ("redirect:"+res);
}
It ALSO works. So, my question is What's the difference?

The #RequestMapping annotation handles all types of incoming HTTP request including GET, POST, PUT etc. By default, it’s assumed all incoming requests to URLs are of the HTTP GET kind. To differentiate the mapping by HTTP request type, you need to explicitly specify the HTTP request method. for more information

Related

Spring : How do I know where a query comes from? using #RequestHeader (value = "User-Agent")

Using Spring, I want to know in my #Controller whether the request comes from the browser or not. If so, then put a particular treatment. I thought of using #RequestHeader (value = "User-Agent") like this:
#RequestMapping(value = "/user-agent-test")
public String hello(#RequestHeader(value="User-Agent") String userAgent)
//toDo
if(browser){
//Make something
}else{
// Make something else
}
return "home";
}
But I do not know what condition I have to put.
thank you in advance.
You actually can not guarantee that the presence of the http-header "User-Agent" assures this is coming from a browser. This could also be any other script/library/program setting it. On the opposite, a missing header is not a sign that it is not a browser. You will be just doing an "educated guess".
Anyways, if you still want to follow your approach, you should use also "required=false" on the RequestHeader annotation, so the parameter is null when the header is not set instead of failing altogether. Then you just check if your parameter is null or not.
Like this:
#RequestMapping(value = "/user-agent-test")
public String hello(#RequestHeader(value="User-Agent", required=false) String userAgent)
if (null != userAgent) {
// could be a browser
} else {
// could be something else
}
return "home";
}
See springs javadoc on the annotation.
Also see this answer on the presence of the "User-Agent" header

How to do a redirect in Spring MVC controller?

I am trying use a PRG (Post-Redirect-Get) pattern in one of my Spring MVC controller. The controller collects user data from an HTML form, does some processing, stores data in DB and then shows a JSP page. After saving data a redirect should happen and then the JSP page should be displayed.
I also tried to prepend "redirect:" in front of the VIEW_NAME but I get 404 then.
Please guide.
CartPageController.java
#Controller
#RequestMapping("/cartPageController.do")
public class CartPageController {
private static final Logger LOG = Logger.getLogger(CartPageController.class);
private static final String VIEW_NAME = "cart";
#Autowired
protected MasterDao masterDao;
#RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView processRequest(HttpServletRequest request, HttpServletResponse response) {
LOG.debug("Into the CartPageController...");
HttpSession session = request.getSession();
ModelAndView mav = new ModelAndView();
//create Cart object and store it in session
Cart cart = null;
if (session.getAttribute("cart") != null) {
cart = (Cart) session.getAttribute("cart");
} else {
cart = createCart();
session.setAttribute("cart", cart);
}
LOG.debug("cart = " + cart);
//determine the cart operation
String btnAddToCart = GenericUtils.nullToEmptyString(request.getParameter("btnAddToCart"));
String removeProduct = GenericUtils.nullToEmptyString(request.getParameter("removeProduct"));
String updateProduct = GenericUtils.nullToEmptyString(request.getParameter("updateProduct"));
LOG.debug("btnAddToCart = " + btnAddToCart);
LOG.debug("removeProduct = " + removeProduct);
LOG.debug("updateProduct = " + updateProduct);
if (btnAddToCart.length() > 0) {
addToCart(request, cart);
} else if (removeProduct.length() > 0) {
removeProduct(request, cart);
} else if (updateProduct.length() > 0) {
updateCart(request, cart);
}
//TODO: Should use PRG pattern here
//TRIED TO APPEND "redirect:" here but does not work, gives me 404
mav.setViewName(VIEW_NAME);
return mav;
}
//some more code below here
}
You should redirect to url not a view name. as Spring doc says:
While
the use of RedirectView works fine, if the controller itself creates
the RedirectView, there is no avoiding the fact that the controller is
aware that a redirection is happening. This is really suboptimal and
couples things too tightly. The controller should not really care
about how the response gets handled. In general it should operate only
in terms of view names that have been injected into it.
The special redirect: prefix allows you to accomplish this. If a view
name is returned that has the prefix redirect:, the
UrlBasedViewResolver (and all subclasses) will recognize this as a
special indication that a redirect is needed. The rest of the view
name will be treated as the redirect URL.
you can try
return new ModelAndView(new RedirectView("/page"));
You can't just prepend "redirect:" to your view name which results in redirect:cart and then obviously 404, what you have to do for redirect is to specify the redirect path for e.g.:
redirect:/cart.htm
This should explain it more in details.
You can do this way
redirect:cart.do and have requestmapping in controller which will return cart view.
Hope this will work.

How do I pass multiple string parameters into WebAPI

I'm trying to write a simple WebAPI controller to validate a userId and password. Both parameters are strings and it's a bit frustrating that this always seems to be so difficult.
The Controller code looks like:
[Route("api/User/{userId}, {password}"), HttpGet]
public bool IsPasswordCorrect(string userId, string password)
{
UserModel sm = new UserModel(userId);
bool rtn = sm.Password == password;
return rtn;
}
The calling code looks like:
public bool IsPasswordValid(string userId, string password)
{
RestRequest request = new RestRequest("IsPasswordCorrect/{userId}, {password}", Method.GET);
request.AddUrlSegment("userId", userId);
request.AddUrlSegment("password", password);
RestClient restClient = new RestClient(Service.Location);
var response = restClient.Execute<bool>(request);
bool rtn = (bool)response.Data;
return true;
}
I am not able to get the calling code to access the controller code. Thanks
You have defined the route as:
GET {host}/api/User/{userId}, {password}
but looks like you are calling it as:
GET {Service.Location}/IsPasswordCorrect/{userId}, {password}
You should call the Web API resource by the route defined in the attribute not by action name as that would result in 404.

Execute a simple call to a WebAPI Get using RestRequest and a single string parameter

I have the following code in my receiving controller:
[Route("api/StudentUserId/{string}"), HttpGet]
public StudentDto StudentUserId(string userId)
{
StudentModel sm = new StudentModel(userId);
StudentDto dto = sm.ConvertToDto();
return dto;
}
After running this project, I have another project that I use to test the WebAPI controller calls. I use the following code to read a student record form the database using their userId:
protected T SendRequestToReadItemUsingString<T>(string resource, string userId) where T : new()
{
string resourceString = string.Format("{0}/{{userId}}", resource);
RestRequest request = new RestRequest(resourceString, Method.GET);
request.AddUrlSegment("userId", userId);
RestClient restClient = new RestClient(Service.Location);
var response = restClient.Execute<T>(request);
T retVal = response.Data;
return retVal;
}
Comparible code seems to work if I change the userId to an int Id in both the controller and calling code. I can't seem to get it to work with string. If I place a breakpoint in the controller code it never hits it and the calling code just returns a null.
Thanks for your help
Please note that WebApi works based on reflection this means that your curly braces {vars} must match the same name in your methods.
Therefore to match this api/StudentUserId/{string} your method needs to be declare like this:
[Route("api/StudentUserId/{userId}"), HttpGet]
public StudentDto StudentUserId(string userId)
return userId;
}
Where the parameter {string} was replaced by userId.
If you want to read more about this Routing Rules here is similar post on this;
WebApi Routing Configuration

REST with Spring Controller issue

I've my rest uri's as below
/leagues - Lists all the leagues organized so far
/leagues/{leagueName} - Details of the give leagueName
/leagues/{leagueName}/levels/ - Lists all the levels of a given league (For e.g. Playoffs, QF, SF etc)
Controllers
1.
#RequestMapping (value = "/leagues", method = RequestMethod.GET)
public String list(Model model)
{
return "/leagues/list";
}
2.
#RequestMapping (value = "/leagues/{leagueName}", method = RequestMethod.GET)
public String leagues(#PathVariable String leagueName, Model model)
{
return "/leagues/league";
}
3.
#RequestMapping (value = "/leagues/{leagueName}/levels", method = RequestMethod.GET)
public String levels(#PathVariable ("leagueName") String leagueName, Model model)
{
return "/leagues/levels/list";
}
The problem I am having is that the controller method for the (2) /leagues/{leagueName} is being invoked when I try (2) /leagues/levels/. Need help on how to fix this.
You forget to add the leguname to the url: use /leagues/SuperHero/levels/ instead (/leagues/levels/)
If you want to filter out /leagues/levels/`, then you can try to add an additional handler method:
#RequestMapping(value="/leagues/levels/")
for example, to return all levels of any league
The behavior is perfectly fine... The URL leagues/levels matches the second method's RequestMapping...
If you want to invoke the third method u need the URL as leagues/[some string]/levels

Resources