JavaBeans and standard actions

When dealing with simple JSP pages, we can happily mix HTML and Java without caring much about the mess we are doing. But "real" JSP pages could be hard to mantain, so better would be to keep these two world as distinct as possible, to help development, testing and maintenance.

We can address this issue using standard actions and EL, the Expression Language. We could use JavaBeans (not the Enterprise ones, but the "plain" JavaBeans) to pass around information in a web application and manage them using standard actions.

To see how this work, we'll refactor the beer selector, putting the information on the selected beer in a JavaBean, and then using it in a JSP by standard actions.

This is our bean to store beer information:
package ch08;

public class BeerInfo {
    private String brand;
    private String size;

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}
Then we should create a servlet, I used the NetBeans wizard to do that, specifying that I wanted it in the ch08 package; servlet name WhichBeer; URL pattern ./WhichBeer.do, then I modified the processRequest() code to generate a bean on the fly, put it the request scope as an attribute, and finally forward to a JSP:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
    BeerInfo bi = new BeerInfo();
    bi.setBrand("Localhost SuperDuper");
    bi.setSize("Medium");

    request.setAttribute("beer", bi);

    RequestDispatcher view = request.getRequestDispatcher("beerInfo.jsp");
    view.forward(request, response);
}
The question now is how to actually display in a JSP page the data stored in the bean. Here the section in beerInfo.jsp that does the job, using scripting tags, as we are used to to:
<h1>Our beer suggestion</h1>
Scripting:
<% ch08.BeerInfo bi = (ch08.BeerInfo) request.getAttribute("beer"); %>
<%= bi.getBrand() %>,
<%= bi.getSize() %>
Quite simple, isn't it? But we want to avoid mixing up Java code and HTML, so we'll write the same thing using standard actions:
Standard Action:
<jsp:useBean id="beer" class="ch08.BeerInfo" scope="request" />
<jsp:getProperty name="beer" property="brand" />,
<jsp:getProperty name="beer" property="size" />
<br />
The jsp:useBean standard action gets the beer attribute from the request scope, specifying that the object is actually an ch08.BeerInfo instantiation.
With jsp:getProperty we access a property in the bean specified by name.

One could wonder what happens if, for any reason, no beer attribute is available in the request. A new attribute is created on the fly by jsp:useBean, but it has no clue on how it could possibly set its properties.

If we want that, in case no beer bean is created by the servlet, a default beer NoBrand, size large, should be created as a default, we could write:
<jsp:useBean id="beer2" class="ch08.BeerInfo" scope="request">
    <jsp:setProperty name="beer2" property="brand" value="NoBrand" />
    <jsp:setProperty name="beer2" property="size" value="Large" />
</jsp:useBean>
<jsp:getProperty name="beer2" property="brand" />,
<jsp:getProperty name="beer2" property="size" />
<br />
If no beer2 attribute exists in the request scope (as we expect), a new one is created and put there, moreover, the jsp:setProperty standard action is called twice as specified in the body of jsp:useBean.
Is important to be aware that the body of the useBean element is considered only if a new bean has been created - we do not modify the bean if it already exists.

I firstly wrote this stuff while reading the eighth chapter of Head First Servlet and JSP.

No comments:

Post a Comment