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

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

Related

Difference between use #RequestMapping with and without method

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

Spring MVC: How to test whether param exists when there's no value?

I want to display an error message with my custom login.jsp form. When there's an error, the url is ../loginForm?error without any value assigned to error. (This seems to be the behavior of Spring Security.) If there's no error, the url is simply ../loginForm (without the parameter). In the controller I can capture the parameter with #RequestParam, but how do I check whether or not error is passed? In other words, how can I test a parameter alone without a value?
Here's the controller code I have now:
#RequestMapping("/loginForm")
public String showLoginForm(#RequestParam(value="error", defaultValue="false")
boolean error,
Model model)
{
if (error == true)
{
model.addAttribute("loginError", "Invalid username and password.");
}
return "/user/loginForm";
}
...and here's the JSP snippet:
<c:if test="${not empty loginError}">
<tr>
<td><c:out value="${loginError}" /></td>
</tr>
</c:if>
At this point I'm not including the Security configuration I have set up, since everything else seems to be working and I want to keep this focused on the issue at hand.
Thanks in advance for any suggestions!
Ok, I figured it out (while taking a break). The #RequestParam only works when there's actually a parameter available for mapping. If no such parameter is passed in, it's useless. So instead, I checked the Map provided by ServletRequest:
#RequestMapping("/loginForm")
public String showLoginForm(ServletRequest request, Model model)
{
Map<String, String[]> paramMap = request.getParameterMap();
if (paramMap.containsKey("error"))
{
model.addAttribute("loginError", "Invalid username and password.");
}
return "/user/loginForm";
}
It works fine now.
There is another way to do that. Just create one more method where #RequestMapping will check presence of "error" parameter, add required attribute and return view. Both methods could exist together.
#RequestMapping(value = "/loginForm", params = {"error"})
public String loginError(Model model)
{
model.addAttribute("loginError", "Invalid username and password.");
return "/user/loginForm";
}
#RequestMapping(value = "/loginForm")
public String login()
{
return "/user/loginForm";
}

How To Pass formdata parameters into ASP.NET WebAPI without creating a record structure

I have data coming into my form that looks like the image below (sessionsId: 1367,1368).
I've create c# in my webapi controller that works as below. when I've tried ot just make use SessionIds as the parameter (or sessionIds) by saying something like PostChargeForSessions(string SessionIds) either null gets passed in or I get a 404.
What is the proper way to catch a form parameter like in my request without declaring a structure.
(the code below works, but I'm not happy with it)
public class ChargeForSessionRec
{
public string SessionIds { get; set; }
}
[HttpPost]
[ActionName("ChargeForSessions")]
public HttpResponseMessage PostChargeForSessions(ChargeForSessionRec rec)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, new ShirtSizeReturn()
{
Success = true,
//Data = shirtSizeRecs
});
return response;
}
You can declare the action method like this.
public HttpResponseMessage Post(string[] sessionIds) { }
If you don't want to define a class, the above code is the way to go. Having said that, the above code will not work with the request body you have. It must be like this.
=1381&=1380

ID in Spring-MVC 2.5 edit form using #Controller

I have a problem with the my Controller code. GET works fine (both empty form + form populated from db), POST works fine only for creating new object, but doesn't work for editing. Part of my #Controller class:
#RequestMapping(value = "/vehicle_save.html", method = RequestMethod.GET)
public String setUpForm(#RequestParam(value="id", required = false) Long id, ModelMap model) {
Vehicle v;
if (id == null) {
v = new Vehicle();
} else {
v = vehicleManager.findVehicle(id);
}
model.addAttribute("vehicle", v);
return "vehicle_save";
}
#RequestMapping(value = "/vehicle_save.html", method = RequestMethod.POST)
public String save(#ModelAttribute("vehicle") Vehicle vehicle, BindingResult result, SessionStatus status) {
vehicleValidator.validate(vehicle, result);
if (result.hasErrors()) {
return "vehicle_save";
}
if(vehicle.getId() == null) {
vehicleManager.createVehicle(vehicle);
} else {
vehicleManager.updateVehicle(vehicle);
}
status.setComplete();
return "redirect:vehicle_list.html";
}
The first method creates a vehicle object (including its ID). But the second method gets the same object without the ID field (set to null).
What could I do: manually set vehicle.setID(id from parameters) and then save it to database. This causes JPAOptimisticLockException + I don't like that solution.
Is there a way to pass my Vehicle object with ID to the second method? BTW, I would like to avoid adding hidden ID field to the JSP.
the example you suggested is using session to store the value. the #SessionAttribute is to bind an existing model object to the session. Look at the source code the class is annotated with #SessionAttributes("pet").Which means your model attribute named "pet" is getting stored in session.Also look at the code in processSubmit method of EditPetForm class
#RequestMapping(method = { RequestMethod.PUT, RequestMethod.POST })
public String processSubmit(#ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "pets/form";
}
else {
this.clinic.storePet(pet);
status.setComplete(); //look at its documentation
return "redirect:/owners/" + pet.getOwner().getId();
}
}
I havnt used something like this before.But i guess putting ur id in session is the way
BTW, I would like to avoid adding hidden ID field to the JSP.
This is common solution. What's wrong with it ? You should create hidden input with id.
May be you can try using session, cause you cant store info between two request. But that will be uglier i guess.
Btw, Can you please explain a little why you want to avoid adding hidden fields? I'm little curious

Struts 1 custom validator

I need to write custom validator which will simply check an array of strings for malformed data. This array of course comes from form as a property and actually it values comes from request through html:multibox tags (these are simple ID of elements in a string form). So I want to validate this data.
The problem is that official guide has nothing to say about handling non-string properties. I don't know how to retrieve this array.
Here is the example from struts valiator guide:
public static boolean validateTwoFields(
Object bean,
ValidatorAction va,
Field field,
ActionErrors errors,
HttpServletRequest request,
ServletContext application) {
String value = ValidatorUtils.getValueAsString(
bean,
field.getProperty());
String sProperty2 = field.getVarValue("secondProperty");
String value2 = ValidatorUtils.getValueAsString(
bean,
sProperty2);
if (!GenericValidator.isBlankOrNull(value)) {
try {
if (!value.equals(value2)) {
errors.add(field.getKey(),
Resources.getActionError(
application,
request,
va,
field));
return false;
}
} catch (Exception e) {
errors.add(field.getKey(),
Resources.getActionError(
application,
request,
va,
field));
return false;
}
}
return true;
}
As you can see this perfectly explains how to handle string values, but what about other types ?
I think, you should use PropertyUtils.getProperty() and then make use of the Object returned. You can see the example mentioned in the link below:
http://www.webkaifa.com/jsp/jakartaStrutsCookbook/059600771x/jakartastrutsckbk-chp-8-sect-9.html

Resources