spring controller convention to use - spring-mvc

There are 2 formats for writing controller handlers in spring.
Could someone help summarizing what determines the format to be used.
Also whats the format of preference?
Being a new-bie,this would help being on teh right track.
Option 1:
#RequestMapping(value=".....", method=RequestMethod.GET)
public String loadFormPage(Model m) {
m.addAttribute("subscriber", new Subscriber());
return "formPage";
}
#RequestMapping(value="....", method=RequestMethod.POST)
public String submitForm(#ModelAttribute Subscriber subscriber, Model m) {
m.addAttribute("message", "Successfully saved person: " + subscriber.toString());
return "formPage";
}
Option 2:
#RequestMapping(value=".....")
public ModelAndView personPage() {
return new ModelAndView("person-page", "person-entity", new Person());
}
#RequestMapping(value=".....")
public ModelAndView processPerson(#ModelAttribute Person person) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("person-result-page");
modelAndView.addObject("pers", person);
return modelAndView;
}

A controller method in Spring can support zero-to-many input parameters, and the principal mechanisms in Spring for specifying input parameters are the #RequestParam and the #ModelAttribute annotations.
The #RequestParam annotation is used to bind individual request parameters, like string and integers, to method parameters in the controller.
The #ModelAttribute annotation is used to bind complex objects, like domain objects, data transfer objects and/or form backing objects, to method parameters in a controller.
The annotaton is determined by the variable type.
primitive variables will be annotated with #RequestParam
complex variables will be annotated with #ModelAttribute
The annotation name is derived from the variable name
A controller method in Spring can also output model data, and the principal mechanism in Spring for specifying output model data is the ModelAndView object.
In the event that there isn't any data to be returned by the method, the controller method can simply return a String that represents the view that should be rendered.
If the controller method does return data, then a ModalAndView object needs to be instantiated and each output variable is added as a model attribute to the ModelAndView object.

Related

get or pass values from jsp to spring mvc controller with #RequestParam("VIEW") annotation

Hi everyone I'm trying to get or pass the values from my JSP to my controller because I want to write a method whose main function will be to save a new user in the database but I got an error like this:
(((java.lang.IllegalStateException: Mode mappings conflict between method and type level: [/myPath] versus [VIEW])))
I guess this two annotations, first in the class declaration #RequestMapping("VIEW") and the second in the method declaration for save the new user
#RequestMapping(value="/saveUser", method = RequestMethod.POST)
are in conflict by the use of the same annotation in tow times at the same controller but I have to say that I´ve been tried to remove the #RequestMapping annotation in the class declaration and after that, I get a different error like this:
(((java.lang.IllegalStateException: No portlet mode mappings specified - neither at type nor at method level)))
I don't know if I can use as many necessary controllers for differents operations as I will need, if I can, I will be happy to know the correct way to implement with this technique
Here is my controller:
#Controller
#RequestMapping("VIEW")
public class UsersController {
User currentUser = null;
#RenderMapping
public ModelAndView view(RenderRequest request, RenderResponse response)throws Exception {
ModelAndView modelView = new ModelAndView();
UserDTO usuarioAdd = new UserDTO();
//blah, blah, blah...
return modelView;
}
#RequestMapping(value="/saveUser", method=RequestMethod.POST)
public void saveUser(HttpServletRequest request) {
logger.info("***SAVE USER***);
System.out.println("***SAVE USER***);
}
}

Use of Model object as a param in the request handling methods

I just want to know
Why do we use Model object as a Parameter to the request handling method in the Spring MVC application?
Basic Explanation helps me a lot.
ModelAndView (or Model) is a specialized spring object to store name value pairs (kind of java Map). It is optional to have the Model Object as a parameter to the request method. However in case if your request method has anything that needs to be passed on to the View; then you need a Model.
So Model is basically a data structure that carries information from the service layer to the view layer.
You can also initialize a Model inside your request method as:
public ModelAndView listCarrier() {
HashMap<String, Object> model = new HashMap<String, Object>();
model.put("isView", request.getParameter("isView"));
return model;
}
You can add attribute to Model object and use that attribute inside your JSP like below.
#RequestMapping(method = RequestMethod.GET)
public String login(String name, Model model) {
model.addAttribute("name", name);
return "xyz";
}
and later on you can access this property in your xyz.jsp like below.
Name: ${name}
For more info refer :-Model API docs

RedirectAttributes changes object id between controllers

I am using Spring MVC and Hibernate in my project. Also I have 2 controllers UserController and BookController where BookController redirects to the users page and I am passing a Book object in addition.
I've found I can do this with RedirectAttributes but the problem is that the id of the passed Book object is changed during this transition to user.id.
BookController.java
public class BookController {
#RequestMapping("/users/{user_id}/books/edit/{book_id}")
public String editBook(#PathVariable("user_id") int user_id, #PathVariable("book_id") int book_id, final RedirectAttributes redirectAttrs){
bookDetail = this.bookService.getBookById(book_id)
redirectAttrs.addFlashAttribute("bookDetail", bookDetail);
System.out.println(bookDetail);
return "redirect:/users/"+user_id;
}
}
Prints: id=8, title=Motylek, description=Some description, user_id=2.
UserController.java
public class UserController {
#RequestMapping("/users/{id}")
public String detailUser(#ModelAttribute("bookDetail") Book bookDetail, #PathVariable("id") int id, Model model){
User u = this.userService.getUserById(id);
model.addAttribute("user", u);
model.addAttribute("bookDetail", bookDetail);
System.out.println(bookDetail);
return "user";
}
}
Prints: id=2, title=Motylek, description=Some description, user_id=2.
Do you have and idea why this happens or is it a bug? Thanks.
I'm going to assume that your Book class has a property called id, ie. a getter or setter called getId() and setId(..).
When Spring parses the request URL, it stores path segments as declared in the corresponding #RequestMapping. So for
/your-app/users/2
and
#RequestMapping("/users/{id}")
It will store
id=2
as a request parameter.
Spring will then proceed to generate an argument for
#ModelAttribute("bookDetail") Book bookDetail
It will check the various request, session, servlet attributes for an entry with the name bookDetail. (If it doesn't find one, it will create one and add it to the request attributes.) In your case, it will have found the object in the HttpSession. It will then bind any request parameters to matching object properties. Since the parameter above is called id, it will be bound to the Book property id.
You should be good by changing
#RequestMapping("/users/{id}")
to
#RequestMapping("/users/{user_id}")
along with the corresponding #PathVariable.

Spring MVC #ModelAttribute method

Question about Spring MVC #ModelAttribute methods, Setting model attributes in a controller #RequestMapping method verses setting attribute individually with #ModelAttribute methods, which one is considered better and is more used?
From design point of view which approach is considered better from the following:
Approach 1
#ModelAttribute("message")
public String addMessage(#PathVariable("userName") String userName, ModelMap model) {
LOGGER.info("addMessage - " + userName);
return "Spring 3 MVC Hello World - " + userName;
}
#RequestMapping(value="/welcome/{userName}", method = RequestMethod.GET)
public String printWelcome(#PathVariable("userName") String userName, ModelMap model) {
LOGGER.info("printWelcome - " + userName);
return "hello";
}
Approach 2
#RequestMapping(value="/welcome/{userName}", method = RequestMethod.GET)
public String printWelcome(#PathVariable("userName") String userName, ModelMap model) {
LOGGER.info("printWelcome - " + userName);
model.addAttribute("message", "Spring 3 MVC Hello World - " + userName);
return "hello";
}
The #ModelAttribute annotation serves two purposes depending on how it is used:
At Method level
Use #ModelAttribute at the method level to provide reference data for the model. #ModelAttribute annotated methods are executed before the chosen #RequestMapping annotated handler method. They effectively pre-populate the implicit model with specific attributes, often loaded from a database. Such an attribute can then already be accessed through #ModelAttribute annotated handler method parameters in the chosen handler method, potentially with binding and validation applied to it.
In other words; a method annotated with #ModelAttribute will populate the specified “key” in the model. This happens BEFORE the #RequestMapping
At Method Parameter level
At Method Parameter level
When you place #ModelAttribute on a method parameter, #ModelAttribute maps a model attribute to the specific, annotated method parameter. This is how the controller gets a reference to the object holding the data entered in the form.
Examples
Method Level
#Controller
public class MyController {
#ModelAttribute("productsList")
public Collection<Product> populateProducts() {
return this.productsService.getProducts();
}
}
So, in the above example, “productsList” in the Model is populated before the the #RequestMapping is performed.
Method parameter level
#Controller
public class MyController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(#ModelAttribute("product") Product myProduct, BindingResult result, SessionStatus status) {
new ProductValidator().validate(myProduct, result);
if (result.hasErrors()) {
return "productForm";
}
else {
this.productsService.saveProduct(myProduct);
status.setComplete();
return "productSaved";
}
}
}
Look here for detailed information with examples.
One is not better then the other. They both serve another purpose.
Method: If you need the model for a particular controller to be always populated with certain attributes the method level #ModelAttribute makes more sense.
Parameter: Use it on a parameter when you want to bind data from the request and add it to the model implicitly.
To answer your question on the better approach
I would say approach 2 is better since the data is specific to that handler.

Spring Controller - Fill DTO from Servlet Request manually

In Spring controller, I want to invoke same method for different HTML - Forms submission
So, taking HttpServletRequest as a RequestBody
#RequestMapping(value = "/Search")
public String doSearch(HttpServletRequest httpServletRequest, ModelMap map) {
// Now, looking for something like this...
if(req.getType.equals("x")
//X x = SOME_SPRING_UTIL.convert(httpServletRequest,X.class)
else
// Y y = SOME_SPRING_UTIL.convert(httpServletRequest,Y.class)
}
I want to convert request parameters to bean through Spring, As it converts while I take Bean as method argument
Use the params attribute of the #RequestMapping annotation to differentiate the request mapping mapping.
#RequestMapping(value="/search", params={"actionId=Actionx"})
public String searchMethod1(X search) {}
#RequestMapping(value="/search", params={"actionId=ActionY"})
public String searchMethod2(Y search) {}
This way you can create methods for each different action and let spring do all the heavy lifting for you.

Resources