Monthly Archives: January 2011

About JSPs

I never really learned to use JSPs to their full potential, and now – in SOEN344, Concordia’s Software Architecture class which I’m currently tutoring – I’m supposed to be teaching students how to use them.

To that end, I’ve written up a little refresher for me to consult.

JSPs

In its simplest form, JSP is Java trying to do what PHP and Classic Asp do: embed code in markup.

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Hello World JSP</title>
    </head>
    <body>
        Hello, <%
            /*
              in the <% tags you can write Java code,
              similar to <? tags in PHP
            */
            Object o = request.getAttribute("greeting");
            if(o instanceof org.soen387.domain.Greeting) {
                out.print(((org.soen387.domain.Greeting)o).getName());
            }
        %>
    </body>
</html>

You could use the above as the View.jsp file from SOEN344′s Tutorial 1, and it would work. Feel free to try it… but don’t keep it like that.

Now, if you look at the above and think "This is a great idea!" you’re stuck in the Stone Age of Web Development and – to be blunt – you need to mature as a developer. Using scriptlets to embed Java code in markup flirts with being a violation of separation of concerns. It is a messy idea at best, and can easily lead to Domain Logic being embedded in markup:

The following technically works, but is considered bad practice

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Use Case Process Sale – System Operation Enter Item</title>
    </head>
    <body>
        <%
            /*
               If you do something like this,
               you're on the fast track to failure.
            */
            SalesLineItem sli = /* ... */
            Sale sale = /* ... */
            sli.associate(sli);
            out.println("Sales line item associated Sale!");
        %>
    </body>
</html>

Putting domain logic in your JSP (view) like this is no better than putting your markup (presentation) in your servlet, and once you start down the dark path of putting code in markup, forever will it dominate your destiny. So to avoid doing this, use a combination of the Unified Expression Language and the JavaServer Pages Standard Tag Library (JSTL) instead.

The Unified Expression Language

This brings us to the View.jsp file from SOEN344′s Tutorial 1:

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Hello World JSP</title>
    </head>
    <body>
        Hello, ${greeting.name}
    </body>
</html>

Take note that where we before had a <% scriptlet %> we now have ${ Unified Expression Language }. Take a minute and really compare the <% scriptlet %> with the ${ Unified Expression Language }. Marvel at the beauty and simplicity of UEL.

But greeting.name is private, isn’t it?

An attentive student might notice that greeting is an instance of org.soen387.domain.Greeting and that member name of class org.soen387.domain.Greeting is private, and thus should not be accessible using greeting.name. The magic lies in the fact that class org.soen387.domain.Greeting is a Java Bean because it respects the Java Bean conventions:

  • It has a public default constructor,
  • It is serializable,
  • The getter/setter methods for property name respect the Java Bean Properties naming convention.

For the moment you can think that since greeting is an instance of org.soen387.domain.Greeting, which in turn is a Java Bean, the UEL expression ${greeting.name} is the same as the JSP expression tag <%=request.getAttribute("greeting").getName()%>. The advantage in using UEL, however, is that it keeps our JSP de-coupled from class org.soen387.domain.Greeting and keeps the markup clean enough for a designer (designer like artist, not like engineer) can work with the JSP without needing to understand Java.

JavaServer Pages Standard Tag Library

I know what some of you are thinking: "But what if we need control structures like loops in our JSP?" Your instincts might get you to write a JSP like this one:

The following technically works, but is considered bad practice

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Hello World JSP</title>
    </head>
    <body>
        Hello, ${greeting.name }
        <%
            /*
              in the <% tags you can write Java code,
              similar to <? tags in PHP
            */
            if(true) {
                out.println("TROO!");
            }
            else {
                out.println("FALLS!");
            }
            
            for(int i=0; i<10; i++) {
                out.println(i+" ");
            }
        %>
    </body>
</html>

Don’t do that. Avoid using <% scriptlets %>, <%! declaration blocks %> and <%= expression tags %>. Instead us JSTL control tags.

The taglib directive

To use the JSTL you need to include a taglib directive:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

Include this at the top of your JSP and you can then include special JSTL tags in your JSP:

<c:out value="Witness the power of the JSTL" />

If you get an error along the lines of "Cannot find tag library descriptor" it means you need to add the JSTL jar files to your /WEB-INF/lib folder. See the bottom of this entry.

The prefix can be whatever you want, but you’ll often see c as the prefix.

Personally, for clarity, I like to use jstl as the prefix, like in the example below:

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="jstl" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <title>Hello World JSP</title>
    </head>
    <body>
        Hello, ${greeting.name }
        <jstl:choose>
            <jstl:when test="true">
                    TROO!
            </jstl:when>
            <jstl:otherwise>
                    FALLS!
            </jstl:otherwise>
        </jstl:choose>
        <jstl:forEach var="i" begin="1" end="10" step="1">
            <jstl:out value="${i}" />
        </jstl:forEach>
    </body>
</html>

A Quick JSTL Reference

The following is a brief (and incomplete) list of JSTL tags.

out

The <jstl:out> tag is used to output values. For example, the SOEN344 Tutorial 1 JSP could have replaced Hello, ${greeting.name } with:

Hello, <jstl:out value="${greeting.name}" />
set

Set will allow you to set variables to use in your JSP:

<jstl:set var="coinToss" value="heads"/>
Coin toss: <jstl:out value="${coinToss}" />
if

Use <jstl:if> for conditional blocks. Note that for an if-else construct, you need to use <jstl:choose>.

<jstl:if test="${greeting.name=='Richard'}">
    That guy sucked in 342
</jstl:if>
choose, when and otherwise

When there are several different conditions use a <jstl:choose> tag:

<jstl:choose>
    <jstl:when test="${coinToss=='heads'}">
        I win
    </jstl:when>
    <jstl:when test="${coinToss=='tails'}">
        You win
    </jstl:when>
    <jstl:otherwise>
        The coin landed on the edge!
    </jstl:otherwise>
</jstl:choose>
forEach

You saw <jstl:forEach> earlier.

<jstl:forEach var="i" begin="1" end="10">
    <jstl:out value="${i}" />
</jstl:forEach>

Addendum: cannot find tag library descriptor errors

If you’re getting a "cannot find tag library descriptor" problem in your JSPs like the one pictured here…

The Eclipse error message for Cannot Find Tag Library Descriptor

…it means you’re missing the JSTL jar files. TomCat usually comes with the JSTL, but it may not be included with the ENCS labs’ version of TomCat.

Go to the Apache Standard TagLib Page for the JSTL, and download the Standard 1.1 Taglib. Extract the file you download (probably named something like jakarta-taglibs-standard-1.1.2.tar.gz) and in it you should find a lib folder, which contains 2 jar files:

  • jstl.jar
  • standard.jar

Copy both files in your project’s /WEB-INF/lib folder.

Copy The JSTL jar files into your WEB-INF lib folder

Clean and rebuild your project, and the error message should go away.

Cleaning your Eclipse project
Click to enlarge

About Servlets and JSPs

In SOEN344 – Concordia’s Software Architecture course which I’m currently tutoring – the students are going to be working almost exclusively with Dynamic Web Projects in Eclipse. So I’ve decided to give myself something of a refresher, reviewing the basic anatomy of a Dynamic Web Project, which I have typed up in this news entry.

Creating a Dynamic Web Project

Assuming you’ve already gone through the sets of setting up the JDK6 and creating an Apache TomCat runtime, one should be able to simply select File > New > Dynamic Web Project. If you don’t see "Dynamic Web Project" under File > New you can instead select File > New > Other:

Select Other from the New menu under File
Click to enlarge

Expand the "Web" folder and select "Dynamic Web Project".

Select New Dynamic Web Project from under Web
Click to enlarge

Follow the steps in the New Project Wizard, and give the project a name of "TheAnatomyOfADynamicWebProject".

Once you’re done with the New Project Wizard, you should see the following in the Navigation Explorer:

The Navigation View of a Dynamic Web Project

Let’s take a look at some of the folders in your (currently empty) project:

  • src/ contains the source code for .java files in your project, just like for any other Eclipse project you’ve worked with in the past. This folder is only relevant to the Eclipse Project, and isn’t included when you deploy the application on a server.
  • WebContent/ contains everything which will get deployed to a server. The WebContent folder is kind of (only kind of) like the public_html or www on popular shared-hosting environments like GoDaddy.
  • WebContent/META-INF/ – Don’t touch this folder. It "contains the MANIFEST.MF file, which is used to map class paths for dependent JAR files that exist in other projects in the same Enterprise Application project", whatever that means.
  • WebContent/WEB-INF contains Web Resources which aren’t public (meaning they are not available over the Web)
  • WebContent/WEB-INF/classes may not exist in your project, but when you deploy your project, the compiled output is put in this folder.
  • WebContent/WEB-INF/lib contains any additional Jar files your project will need.

A Servlet

Let’s start our Java/TomCat adventure with a Servlet, so let’s create a new Servlet (File > New > ...), called "MyServlet", and put it in package leguen.java.web. Eclipse should create the following for you:

package leguen.java.web;
    
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
   
/**
 * Servlet implementation class MyServlet
 */
public class MyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public MyServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
    
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}
    
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}
    
}

The Servlet Methods doGet(…) and doPost(…)

The methods doGet(…) and doPost(…) correspond to HTTP methods GET and POST and (though they’re not in the code) Servlets also have doPut(…) and doDelete(…) (etc) methods too.

	protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	}
	
	protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	}

… but don’t bother adding them. Just fill in the doGet(…) method as follows:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getOutputStream().print("Hello World from the Servlet!");
	}

Build your project, stop your server, clean your server, publish the server and then right-click the Servlet class so as to select Run As > Run on Server and see the output in-browser.

Run the Servlet on Server
Click to enlarge

Currently, the output of our Servlet is not HTML; we could add HTML to the output, but this starts us down the dark road of violating Separation of Concerns:

The following technically works, but is considered bad practice

package leguen.java.web;
    
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
    
/**
 * Servlet implementation class MyServlet
 */
public class MyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public MyServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
    
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getOutputStream().println("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "+
                                                       "\"http://www.w3.org/TR/html4/loose.dtd\">");
		response.getOutputStream().println("<html>");
		response.getOutputStream().println("<head>");
		response.getOutputStream().println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
		response.getOutputStream().println("<title>MyServlet!</title>");
		response.getOutputStream().println("</head>");
		response.getOutputStream().println("<body>");
		response.getOutputStream().println("Hello World from MyServlet!");
		response.getOutputStream().println("</body>");
		response.getOutputStream().println("</html>");
	}
    
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}
    
}

Instead, we’ll want to separate the HTML into a JSP and forward the request to the JSP.

JSPs in WebContent/

Create a JSP file (File > New > ...) in folder WebContent/ and call it Public.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>/Public.jsp!</title>
</head>
<body>
	Hello World from /Public.jsp!
</body>
</html>

The name Public.jsp is arbitrary and has been selected just to help make a point.

Now, in your Servlet, you can leverage the ServletRequest.getRequestDispatcher(String) method to forward the request to the JSP:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/Public.jsp").forward(request, response);
	}

Again, build your project, stop your server, clean your server, publish the server and then right-click the Servlet class so as to select Run As > Run on Server and see the output in-browser. Take note of the URL in the browser’s address bar:

http://localhost:8080/TheAnatomyOfADynamicWebProject/MyServlet

JSPs in WEB-INF

There is a problem, however; since the WebContent folder is kind of (kind of) like the public_html folder of popular hosting environments the browser can request those files directly – without going through the Servlet. This is bad because all input should be going through the Servlet, since the model Id’ like to respect uses the Servlet as a Controller and the JSPs as Views. You shouldn’t be able to access the JSP directly using a URL like this one:

http://localhost:8080/TheAnatomyOfADynamicWebProject/Public.jsp

… but you can. Try it:right-click on Public.jsp and select Run As > Run on Server.

Run Public dot JSP on Server
Click to enlarge

You will see the output of the JSP in-browser – and if you look at the address bar you’re not at the same URL as you were when you were accessing the Servlet.

The output of Public dot JSP in the browser
Click to enlarge

So, to fix this, create another JSP file, this time in WebContent/WEB-INF/Views/Private.jsp.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>/WEB-INF/Private.jsp!</title>
</head>
<body>
	Hello World from /WEB-INF/Private.jsp!
</body>
</html>

Once you’ve stopped and re-published the server, right-click on the new Private.jsp and select Run As > Run on Server.

Run Public dot JSP on Server
Click to enlarge

This time, you should not see the output of your JSP but instead get a 404 page:

Trying to access the JSP in WEB INF gives a 404
Click to enlarge

Now modify your Servlet to forward to Private.jsp instead of Public.jsp.

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/Views/Private.jsp").forward(request, response);
	}

Once you’ve stopped and re-published the server, right-click on the Servlet and select Run As > Run on Server. You should see the output of Private.jsp:

Run Public dot JSP on Server
Click to enlarge

All this to emphasize that the JSPs which should only be accessed via the Servlet (Controller) should go inside the WEB-INF folder.