How to pass single parameter to contoller in Spring MVC? - spring-mvc

I have some questions from a design point of view in Spring Web MVC.
Is it good practice to use Request Object in controller? If not, then what is alternative way to pass pass one text fields value to controller? Do I need to create one new from bean for this single fields?

It depends of the situation, in a few cases I used the HttpServletRequest; for example for writing a file to the output stream.
If you want to get the Request Parameters you can use the annotation #RequestParam, that it´s more easy to get the parameters from the request.
Depends that you want to handle, for example for a form you can use #ModelAttribute and this attribute can be in a session or in the request.
For example:
#Controller
public class YourController {
#RequestMapping(value = "someUrl", method = RequestMethod.GET)
public String someMethod(#RequestParam("someProperty") String myProperty)
{
// ... do some stuff
}
}
Check the documentation here:
#RequestParam
#ModelAttribute
#PathVariable

Related

Get all annotated classes and call each method to get a return value

I am creating a small validation application using Spring MVC. I am very new to Spring MVC and would like to ensure that what I want is possible.
I have simplified my problem.
I have setup a controller that will be called when a URL is executed. localhost/validate/{SOME TEXT}
The {SOME TEXT} value with be sent to all my validation classes I created.
I currently have 4 classes which does the validation and returns another Object data about what happened during the validation
The 4 validation classes are:
CreditCardValidator
AddressValidator
ZipcodeValidator
AccountNumberValidator
I have a main controller bean that when called I want the string to be passed to each class and the object returned from each to be stored and then finally all results are sent back in a response.
Normally, I would do this without Spring by creating an interface that each validation class implements. Then iteration through the list of classes and execute a method.
The problem doing it that way is that whenever I need to add a new validation class I'll need to register it so the request can use it. This involved modifying existing classes.
Since I am using Spring quick heavily in this application I am wondering if this is possible to do via Spring and annotated classes.
I was thinking of creating a custom annotation that each validation class has and then using spring component-scan to get the classes. This would allow me to create new validations without modifying existing code.
Below is the what I am trying to do.
#Controller
public class StringValidationController {
#RequestMapping(value = "/validate/{text:.+}", method = RequestMethod.GET)
public ModelAndView index(#PathVariable("text") String text) {
ModelAndView model = new ModelAndView();
model.setViewName("index");
model.addObject("result", getListOfValidatedData());
return model;
}
public List getListOfValidatedData(){
//Scan for IValidator annotation
//call each concrete class and pass in text
// get object with has validation information in it
}
}

How to call a method for every page?

I'm writing an application using Spring MVC.
I have a method that returns values from a database. And I want to display these values in the site's header (which is shown on all pages). How I can do this?
I need to call this method in every controller.
Declare a class with #ControllerAdvice annotation, then declare a method with #ModelAttribute annotation. For example:
#ControllerAdvice
public class GlobalControllerAdvice {
#ModelAttribute
public void myMethod(Model model) {
Object myValues = // obtain your data from DB here...
model.addAttribute("myDbValues", myValues);
}
}
Spring MVC will invoke this method before each method in each MVC controller. You will be able to use the myDbValues attribute in all pages.
The #ControllerAdvice class should be in the same Java namespace where all your MVC controllers are (to make sure Spring can detect it automatically).
See the Spring Reference for more details on #ControllerAdvice and #ModelAttribute annotations.
You could write your own interceptor.

which design patten in this situation?

I use Spring MVC and need to provide ability to change fields of some object separately. For example in controller I have method for every field (new value is assigned in service method) but I'm wondering if there is good design pattern to use in this situation. I mean to have in controller only one method for all fields. I thought about sending new value of field and name and then check which field should be changed in controller but in this situation I get many if statements... Is there any widely used method in this situation?
class Controller {
#RequestMapping(value = "/field", method = RequestMethod.POST)
public String changeFieldValue(#RequestParam("fieldname") String fieldName, #RequestParam("newValue") String newValue, ModelMap model){
if(fieldname.equals("age")){
Object.setAge(newValue);
}
.
.
.
}
}
I think about sth similar to this, I know that I can populate whole object at once. but requirements are to change fields separately
Spring has a BeanWrapper implementation to ease this task.
http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/beans/BeanWrapperImpl.html
BeanWrapper wrapper = new BeanWrapperImpl(object);
wrapper.setPropertyValue(fieldName, newValue);

jsr-303 annotations on a spring mvc controller parameter

Is it possible to use Bean Validation annotations like #Past or #Length on Request Parameters in spring mvc?
I would like to do something like:
#RequestMapping(method = RequestMethod.POST)
public RedirectView initiateSignup(#RequestParam #Valid #Past Date birthdate, BindingResult birthdateResult,
HttpServletResponse httpServletResponse) throws HttpMediaTypeNotAcceptableException {
I made it work with the help of a blog post:
http://blog.codeleak.pl/2012/03/how-to-method-level-validation-in.html
an additional annotation and a bean post processor were nessecary, but now it works.
I don't think that's possible. You can apply #Valid but not e.g. #Past. You can instead create a model class with fields that correspond to your request parameters, and put the JSR-303 annotations on the class's fields. You can then use that class as the controller method argument type, with #Valid on it, and Spring should validate it appropriately.
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/validation.html#validation-mvc-jsr303

How do I omit ModelAttribute parameters from the ModelAndView returned by a Spring 3 MVC action?

I have a Spring MVC controller with an action that's called using AJAX.
#SessionAttributes({"userContext"})
public class Controller
{
...
#RequestMapping(value = "/my-url", method= { RequestMethods.POST })
public ModelAndView doSomething(#ModelAttribute("userContext") UserContext context,
SessionStatus sessionStatus)
{
BusinessObject obj = doSomeBusinessLogic(context.getUserName());
sessionStatus.setComplete();
ModelAndView mav = new ModelAndView("jsonView");
mav.addObject("someInt", obj.getId());
return mav;
}
}
When I run this action, I get the following exception:
net.sf.json.JSONException: There is a cycle in the hierarchy!
at t.sf.json.util.CycleDetectionStrategy$StrictCycleDetectionStrategy.handleRepeatedReferenceAsObject(CycleDetectionStrategy.java:97)
at net.sf.json.JSONObject._fromBean(JSONObject.java:833)
at net.sf.json.JSONObject.fromObject(JSONObject.java:168)
at org.springframework.web.servlet.view.json.writer.jsonlib.PropertyEditorRegistryValueProcessor.processObjectValue(PropertyEditorRegistryValueProcessor.java:127)
at net.sf.json.JSONObject._fromMap(JSONObject.java:1334)
Truncated. see log file for complete stacktrace
After doing some debugging I found out that Spring is placing the UserContext object onto the ModelAndView that I am returning. If I hard-code my user name and remove the context object from the method's parameters, the action runs successfully. Is there a way to configure Spring to omit the ModelAttribute-annotated parameters from the returned ModelAndView? As you can see, sessionStatus.setComplete() has no effect.
I've had similar problems in the past with #SessionAttributes. By declaring #SessionAttributes({"userContext"}) you're telling Spring that you want "userContext" to always be available in the model, and so Spring has no choice but to send your UserContext object out to the model, just in case you're going to be redirecting or doing something else which might end up at another Controller.
The "solution" (and I didn't like it much, but it worked) was to omit the #SessionAttributes annotation on the controller, add an HttpSession parameter to the necessary methods and "manually" manage what's in it.
I'm interested to see if there's a better way, because it seems #SessionAttributes has tremendous potential to tidy up controller-level code.
I registered a WebArgumentResolver to get to my session variable. This allowed me to keep this session variable out of the response while keeping my action unit testable.
Along with #ModelAttribute, pass #ModelMap as a method argument.
Based on business logic, error conditions -- if you do not need the attribute for certain scenarios, then remove it from the map.
public ModelAndView foo(#ModelAttribute("userContext") UserContext, #ModelMap map){
if(success){
return success.jsp
}
else{
map.remove("userContext");
return "error.jsp"
}
}
Not totally satisfied with having to pass the ModelMap as well, but I did not find any other easier way of doing it.
Cheers!!

Resources