Spring using ModelAndView addObject

Mike HT picture Mike HT · Feb 11, 2014 · Viewed 20.9k times · Source

I am trying to display objects in a jsp page that are loaded using addObject() and returned via a controller. I am not seeing the objects in the jsp. Here is my controller:

import java.util.ArrayList;
import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.apress.pss.terrormovies.model.Movie;
import com.apress.pss.terrormovies.service.MoviesService;

@Controller
@RequestMapping("/movies")
public class MovieController {

    @Autowired
    private MoviesService moviesService;

    ... Other Mapped mehtods not shown ...

    // Respond to http://localhost:8080/movies and require login
    // Get a list of movie objects in an ArrayList and return to view
    @RequestMapping(method = RequestMethod.GET, value="/")
    public ModelAndView getAllMovies() {
        ModelAndView mv = new ModelAndView("allMovies");

        // Debug
        for (Movie movie: moviesService.getAllMovies()) {
           System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " + movie.getName());
        }

        mv.addObject("movies", moviesService.getAllMovies());
        return mv;

    }

}   

Here is my MoviesServiceImpl that implements moviesService.getAllMoivies()

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.security.access.prepost.PostFilter;

import com.apress.pss.terrormovies.model.Movie;

public class MoviesServiceImpl implements MoviesService {

private static final Map<String, Movie> MOVIES = new HashMap<String, Movie>();

    static {
    //System.out.println("----------------- Entering Die Hard");
    MOVIES.put("die hard", new Movie("Die Hard", "20000000"));
    // Create another movie for testing PostAuthorize in MoviesController
    //System.out.println("----------------- Entering two days in paris");
    MOVIES.put("two days in paris", new Movie("two days in paris", "1000000"));
    }

    ... Other methods not shown....

    // Allow ROLE_ADMIN to have access to movies with budget over 5000000. Other 
    // users will see only movies with budgets < 5000000
    @PreAuthorize("isFullyAuthenticated()")
    @PostFilter("hasRole('ROLE_ADMIN') or (hasRole('ROLE_USER') and T(java.lang.Integer).parseInt(filterObject.budget) < 5000000)")
    public Collection<Movie> getAllMovies() {
        return new ArrayList<Movie>(MOVIES.values());
    }
}

Here is the jsp page I am using to display the results:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="security"
uri="http://www.springframework.org/security/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Terror movies</title>
</head>
<p>Movies:</p>
<body>

<c:if test="${not empty movies}">
    <c:forEach items="${movies}" var="movie">   
        ${movie.name}<br />
    </c:forEach> 
</c:if>

</body>
</html>

Finally, here is my Movies class:

public class Movie {

    private String name;
    private String budget;

    public Movie(String name, String budget) {

        super();
        this.name = name;
        this.budget = budget;
    }

    public String getName() {
    return name;
    }

    public String getBudget() {
        return budget;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setBudget(String budget) {
        this.budget = budget;
    }

    public String toString() {
        return "Title: " + name + "; Budget: " + budget;
    }

}

When I got to the URL /movies (on localhost) I am prompted for login. When I login as ADMIN I should see both the movies added into the MOVIES Map in MoviesServiceImpl. I can see the debug in the static block load the movies. I can see the movies accessed by the debug in the MovieController.getAllMovies() method. I am correctly directed to the allMovies.jsp page, but the only thing output is "Movies:". If I remove the check around the for loop in allMovies.jsp I get the following output: Movies: ${movie.name}. There are no exceptions thrown or other errors I can see, however I don't believe I am using ModelAndView.addObject() correctly. Some help would be appreciated. Thank you in advance.

Update: If I put the following statemnt in my jsp page: <% System.out.println("jsp: movie " + pageContext.findAttribute("movies")); %> I will get the following output: "jsp: movie [Title: Die Hard; Budget: 20000000, Title: two days in paris; Budget: 1000000]" So the Object array is getting to the jsp page, I am just not accessing it correctly but don't see the error.

Answer

sshah picture sshah · Feb 11, 2014

Can you please check with Model.addAttribute(name, value) instead of ModelAndView.addObject(name, value)? I think you should get the same problem with the Model.addAttribute approach as well.

Please try adding the following

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

to the JSP.