jonm.dev

The Art of Writing Software



How to call domain object methods from JSP

Series [ Calling domain objects from JSPs ] Tags [ controller, domain object method, DTO, Java, JSP, JSP method calls, MVC, software design, taglib ]

It seems like the earlier post about super() spawned at least a little (offline) discussion, so here’s another comparison of some different ways of approaching a problem. People should definitely feel free to post some comments , lend your opinions, offer up code snippets, etc. Ok, so here’s the deal. We have a middleware domain object that has a method with arguments, and we essentially want to call that method from a JSP page. To make this concrete, let’s suppose we have some software supporting a blog. Here’s the middleware for a blog post:

public class Post {
  public String getTopic() { /* ... */ }
  public List<Comment> getCommentsByRange(int first, int max) {  /* ... */ }
}

So, we let’s say we have a web page where we want to show, for example, the first eight comments under the post itself. Probably the JSP page will want to, somehow, essentially call post.getCommentsByRange(0,8).


Approach A

Call from controller, add to model. Our controller will look like this (assuming Spring MVC).

public class PostController implements Controller {
  public ModelAndView handleRequest(...) {
    Map model = new HashMap();
    String postId = request.getParameter("postId");
    Post post = postDao.getPost(postId);
    List<Comment> comments = post.getCommentsByRange(0, 8);
    model.put("post", post);
    model.put("comments", comments);
    return new ModelAndView(..., model);
  }
}

And our jsp page will contain the following snippet:

<c:foreach items="${model['comments']}" var="comment">
  <!-- display a Comment in here -->
</c:forEach>

Pros:

Cons:


Approach B

Create a data transfer object. This creates a special class whose methods take no arguments:

public class PostDTO {
  private Post post;
  private List<Comment> comments;
  public PostDTO(Post post, int start, int max) {
    this.post = post;
    this.comments = post.getCommentsByRange(start,max);
  }
  public getTopic() { return post.getTopic(); }
  public getComments() { return comments; }
}

Now the controller looks like as below. Notice that there’s only one object put into the model, so the controller is very simple.

public class PostController implements Controller {
 public ModelAndView handleRequest(...) {
   Map model = new HashMap();
   String postId = request.getParameter("postId");
   Post post = postDao.getPost(postId);
   PostDTO postDTO = new PostDTO(post, 0, 8);
   model.put("postDTO", postDTO);
   return new ModelAndView(..., model);
 }
}

Finally, the JSP snippet looks like:

<c:foreach items="${model['postDTO'].comments}" var="comment">
  <!-- display a Comment in here -->
</c:forEach>

Pros:

Cons:


Approach C

Use a taglib. I’m not going to show the code here (want to keep to my self-imposed time limit), but essentially, we create a taglib that knows how to call the getCommentsByRange() method of a post. The JSP would look like:

<c:set var="comments" value=""/>
<mytags:postComments post="${model['post']}" start="0" max="8" outvar="comments"/>
<c:foreach items="comments" var="comment">
  <!-- display a Comment in here -->
</c:forEach>

Pros:

Cons:

Exercise for the Reader. Which approach would you use, and why? Does it depend on the situation?