Spring MVC Controllers Return Type - spring

I've seen examples where a controller returns a String (which indicates the view)
#RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(#PathVariable String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
return "displayOwner"
}
And I also see examples where a controller returns a "ModelAndView" object type
public ModelAndView helloWorld() {
ModelAndView mav = new ModelAndView();
mav.setViewName("helloWorld");
mav.addObject("message", "Hello World!");
return mav;
}
What is the difference between the two and which should I use? Cause either way I can get my view resolved.

It's the same logic but it's not the same version of spring.
The ModelAndView object is the spring 2.x way of handling model and views.
In the example you gave, the modelandview object will load the "helloWorld" view (depending on your templating engine could be helloWorld.jsp, or helloWorld.html, ...) with one data "message" in the model.
The other way is the spring 3.x way. You could have wrote exactly the same example as your helloworld.
#RequestMapping(value="/helloWorld", method=RequestMethod.GET)
public String helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
The model is automaticly populated at request.
And we can simplify this notation as the url mapping "helloWorld" is directly the view name.
#RequestMapping(value="/helloWorld", method=RequestMethod.GET)
public void helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
}
the helloWorld view will be automaticly loaded

If we are talking about MVC 3, than, both are correct. But directly returning ModelAndView is the old way, and more verbal.
If you are returning just a string (without #ResponseBody which is something else), this string is treated as view name, and spring pushes it to view resolvers - so, you dont have to worry (at least, while you are writing controllers), what type of view renderer you'll use (let it be jsp or velocity, it doesn't matter). You only propagate the Model instance, and returnes a hint what to do with it next. Proper ModelAndView object is made later internally by string.
Generally, spring 3 gives you more flexibility with arguments and return types (see Defining #RequestMapping handler methods section in Spring documentaton).

In Spring MVC, you should return ModelAndView if you want to render jsp page
For example:
#RequestMapping(value="/index.html", method=RequestMethod.GET)
public ModelAndView indexView(){
ModelAndView mv = new ModelAndView("index");
return mv;
}
this function will return index.jsp when you are hitting /index.html
In addition you can return any JSON or XML object using #ResponseBody annotation and serializer.
For example:
#RequestMapping(value="/getStudent.do",method=RequestMethod.POST)
#ResponseBody
public List<Student> getStudent(#RequestParam("studentId") String id){
List<Student> students = daoService.getStudent(id);
return students;
}
In this example you will return List as JSON in case and you have enabled Jackson serializer. In order to enable that you need to add the following to your Spring XML:
<context:annotation-config/>
And the Serializer itself:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
Hope it helps.

Returning ModelAndView or a string does the same job. It resolves into a view (a jsp page) and giving a model object to be rendered in the view. If you return a string, spring internally resolves to a view using viewResolver, create a ModelAndView Object and return it. The returning of ModelAndView object is from the older version. You can do either of this based on your convenient.
Have a look at this question
Also bunch of answers are pointing out to #RequestBody. Its not exactly related to your question. But keep in mind that it will convert your object based on content-type using available converters and the resuly will be part of the document body.

If you are using a template language like freemarker or velocity to create the response then you can return the ModelAndView.
If you want to return a json/xml or some string as the response(ex: ajax requests) then you can use the first method. I think it should be public #ResponseBody String findOwner(#PathVariable String ownerId, Model model), you need to add a annotation called #ResponseBody to indicate that the returned value should be converted as the response text. Using #ResponseBody will enable you to use libraries like Jackson or JaxB to create json/xml responses respectively.
These returned values will be converted using the messageConverters registered with AnnotationMethodHandlerAdapter.
Ref: http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/

public String findOwner(#PathVariable String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
return "displayOwner"
}
in this method the return type is String and we adding Model as a parameter so to add a value with model we will add like
modelparam.addAttribute("obj",value);
and return to the displayowner to jsp as per view resolver
public ModelAndView helloWorld() {
ModelAndView mav = new ModelAndView();
mav.setViewName("helloWorld");
mav.addObject("message", "Hello World!");
return mav;
}
in this method the return type is ModelAndView so we will return the model
and here the mav is the object of ModelAndView so here we should add like
model.addObject("object","value");
here the viewname is returned to helloworld.jsp as per the viewResolver

Related

ModelAndView or ResponseEntity return type for controllers?

So far in my experience with Spring I have mainly seen ResponseEntity return types for controllers. However, I have seen ModelAndView return types. Why would someone use ModelAndView over ResponseEntity or vice versa?
In other words, what are the benefits and negatives of either, as I can't really find a comparison of such online?
ResponseEntity is used for RestController, where you want to return a response (200, 400, etc..) with a payload (Json, etc..).
#GetMapping("/hello")
ResponseEntity<String> hello() {
return new ResponseEntity<>("Hello World!", HttpStatus.OK);
}
ModelAndView is used for MVC Controller, where you return the view (HTML, jsp, etc..) templates with data fields set to values you fill the templates with.
Example: an HTML page named employeeDetails with two fields (employeeObj, msg)
ModelAndView model = new ModelAndView("employeeDetails");
model.addObject("employeeObj", new EmployeeBean(123));
model.addObject("msg", "Employee information.");
return model;

Spring MVC autobinding can not access map data in thymeleaf

I am new to java and was trying to test thymeleaf in springboot.
with code like the first controller I can access the data in a map through thymeleaf
but can not access the data in a map by the second controller.
why declaring map like 2nd method can't work?
can someone help me? thx
public class ViewController {
public String index(Map<String, Object> map) {
map.put("hello","Bonjour");
map.put("Users", Arrays.asList("Ken","Yu","JY"));
return "index";
}
}
public class ViewController {
public String index() {
Map<String, Object> map=new HashMap<String, Object>();
map.put("hello","Bonjour");
map.put("Users", Arrays.asList("Ken","Yu","JY"));
return "index";
}
}
Springboot follows the Model View Controller (MVC) architecture . Simply put Models are used to supply attributes to the view to be rendered.Here you are using thyme-leaf as the view renderer while the model is fed into the thyme-leaf template.Model, ModelMap, and ModelAndView are used to define a model in a Spring MVC application.Spring boot automatically takes care of binding the view and the model together.
As such springboot #RequestMapping handler method expects the method argument for model as :
java.util.Map / org.springframework.ui.Model /
org.springframework.ui.ModelMap for enriching the implicit model that
is exposed to the web view.
Doc
So if you provide a map as a method parameter it is automatically bound the view.In your second case that it not happening automatically .That is the reason second method does not work.Example using ModelAndView :
#GetMapping("/goToIndexPage")
public ModelAndView methodWithModelAndViewReturn() {
ModelAndView modelAndView = new ModelAndView("index");
modelAndView.addObject("message", "Hello");
return modelAndView;
}

How can I return a response Body with Spring Rest MVC when i have also to return a Web page for MVC process?

This is my Code, i know that i should not make 2 return statements, but just for explaining my issue. Thanks
#PostMapping
#ResponseStatus(HttpStatus.Created)
public String addStudent(#RequestBody Student student){
return StudentRep.save(Student);// Should be PayLoad Client Response
return “Student”; // Should be redirect to Student.html
}
You don't need to return a ResponseBody. You can simply add attributes to your Model and then use them in your views.
#PostMapping
#ResponseStatus(HttpStatus.Created)
public String addStudent(#RequestBody Student student, Model model){
String id = StudentRep.save(Student);// Should be PayLoad Client Response
model.addAttribute("studentId", id);
// Will redirect to Student.html where you can use the id attribute.
return “Student”;
}
Now, if you were using Thymeleaf, you could use this new attribute anywhere you want in your template. I am not sure how you are creating your templates, so I just used Thymeleaf as an example.
<p th:text=${id}></p>
Now if you want to return a Stundet object, you would need to the following changes to your controller.
#PostMapping
#ResponseStatus(HttpStatus.Created)
public String addStudent(#RequestBody Student student, Model model){
StudentRep.save(Student);// Should be PayLoad Client Response
model.addAttribute("student", student);
// Will redirect to Student.html where you can use the student attribute.
return “Student”;
}
I think that i find the solution of my answer.
I should annotate the controller that contains my method by #RestController instead of #Controller.
So then, the response will automatically return a JSON HTTP response.

What is the benefit of Model / ModelMap over ModelAndView in Spring MVC?

What is the benefit of Model / ModelMap over ModelAndView in Spring MVC? When we should use Model/ModelMap instead of ModelAndView.
I checked many sites but answers are not clear!
I have read few pages and answers and there doesn't seem to be any differences really. Matter of taste. ModelAndView object wraps model and view. It seems that that is also done implicitly when returning a String. Use the way you prefer.
You can read here about the return types:
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-return-types
Model
Let’s start with the most basic concept here – the Model. Simply put, the model can supply attributes used for rendering views.
To provide a view with usable data, we simply add this data to its Model object. Additionally, maps with attributes can be merged with Model instances:
#GetMapping("/showViewPage")
public String passParametersWithModel(Model model) {
Map<String, String> map = new HashMap<>();
map.put("spring", "mvc");
model.addAttribute("message", "Baeldung");
model.mergeAttributes(map);
return "viewPage";
}
ModelMap
Just like the Model interface above, ModelMap is also used to pass values to render a view. The advantage of ModelMap is it gives us the ability to pass a collection of values and treat these values as if they were on a Map:
#GetMapping("/printViewPage")
public String passParametersWithModelMap(ModelMap map) {
map.addAttribute("welcomeMessage", "welcome");
map.addAttribute("message", "Baeldung");
return "viewPage";
}
ModelAndView
The final interface to pass values to a view is the ModelAndView.
This interface allows us to pass all the information required by Spring MVC in one return:
#GetMapping("/goToViewPage")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = new ModelAndView("viewPage");
modelAndView.addObject("message", "Baeldung");
return modelAndView;
}

What is the difference between return ModelAndView and return String in Spring MVC?

I want to know the different between ModelAndView and String.
#RequestMapping(value="/")
public ModelAndView mainPage() {
return new ModelAndView("home");
}
and the second piece of code is about returning String:
#RequestMapping(value="/")
public String mainPage() {
return "home";
}
You can return many things from a controller, and Spring will automatically try to deduce what to do from there.
When you return a ModelAndView all information that needs to be passed from the controller is embedded inside it. No suprise there.
If you return a String, it will assume that this is the name of the view to use. It will wrap this in a ModelAndView object with the string as the view and the existing model embedded as well.
Spring does a lot of 'magic' on the return types, but also on the parameter types.
This allows you to write code in a style that is more intuitive for you, i.e. the following two examples are the same:
#RequestMapping(value="/")
public ModelAndView mainPage() {
Model m = new Model();
m.put("key", "value");
return new ModelAndView(m,"main");
}
and
#RequestMapping(value="/")
public String mainPage(Model m) {
m.put("key", "value");
return "main";
}
This second variant is a little less verbose and easier to test separately. The model passed in will be an empty model (unless forwarded from some other controller).

Resources