Java EE Servlet tutorial : Using JSPs to create header, footer area, formatting, and basic CSS for bookstore

From Resin 4.0 Wiki

Revision as of 00:00, 3 May 2012 by Rick (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Contents

Java EE Servlet/JSP tutorial: cleaning up our GUI

This tutorial is part of Java EE Tutorial covering JSP_2.2, and Servlets 3.0.

We are going to some cleanup of the GUI (make it look decent, or perhaps somewhat decent).

Adding site template using jsp:include, adding CSS, using JSTL fmt:formatDate and fmt:formatNumber

After the last step, we have a working CRUD Book listing that implements a rudimentary model 2 architecture. We can add, edit/update, list and read. Before we add any more functionality, let's create a site template with jsp:include.

This builds on the first two lessons. I suggest starting with those if you want some coherence, and perhaps not if you are just looking for a quick answer for using CSS, jsp:inclue, etc.

A lot of folks use Tiles (a JSP extension framework) instead of JSP. When Tiles first came out, JSP was somewhat limited in what it could do to reuse JSP pages. JSP has improved and now has JSP tag files (covered in a later cook book). This is not to say that you should avoid Tiles, but merely to state that unless you have a very complicated site layout, and perhaps even if you do have a complicated site layout, JSP is usually enough. Don't add complexity and another framework you need to learn unless and until you have explored what JSP can actually do.

Let me put it another way, don't include the Tiles framework on a greenfield application until you have fully explored JSP tag files. If you know and like Tiles then it might be ok to stick with it on a new project, but if you are not familiar with Tiles start with JSP includes and JSP tag files (covered later).

Defining a simple template with JSP parma.X

Here is an example of a JSP template.

/WEB-INF/pages/template.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML>
<html>
<head>
<title>${param.title}</title>
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath}/resources/style.css" />
</head>
<body>
	<jsp:include page="/WEB-INF/pages/header.jsp"/>

	
	<h1>${param.title}</h1>

	<jsp:include page="/WEB-INF/pages/${param.content}.jsp"/>
	
	<jsp:include page="/WEB-INF/pages/footer.jsp"/>
	
	
</body>
</html>

This template will be called by book-form.jsp and book-list.jsp. This allows us to remove all of the boiler plate HTML code from book-form.jsp and book-list.jsp. When book-form.jsp and book-list.jsp call template.jsp they will pass two parameters via jsp:param, namely, title and content. The title is the title of the page, and the content is the short name of the JSP that actually is the content for the page.

Personal note, I like my JSP fragments to be well formed, i.e., I don't like starting a tag like <body> on one JSP page and finishing it on another. I have found over the years that this makes the JSP templates very hard to modify and maintain. This is more of a personal preference than a best practice.


Calling the template from book-form.jsp and book-list.jsp

Here are the book-form.jsp and book-list.jsp calling the template with <jsp:include>


/WEB-INF/pages/book-list.jsp

<jsp:include page="/WEB-INF/pages/template.jsp">
	<jsp:param name="content" value="book-list-content"/>
	<jsp:param name="title" value="Book Listing"/>
</jsp:include>

/WEB-INF/pages/book-form.jsp

<jsp:include page="/WEB-INF/pages/template.jsp">
	<jsp:param name="content" value="book-form-content"/>
	<jsp:param name="title" value="Book Form"/>
</jsp:include>

template.jsp walk through

The template itself allows us to handle all common tasks for site layout in one location. The logic of this template is fairly simple, but since it can and does use JSTL core tags, the logic could be a lot more sophisticated.

Let's walk through this template step by step:

/WEB-INF/pages/template.jsp page directive and include JSTL core


<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

Above we just do our standard JSP page directive and import the JSTL core tag library for display logic.

/WEB-INF/pages/template.jsp


<!DOCTYPE HTML>
<html>
<head>
<title>${param.title}</title>
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath}/resources/style.css" />
</head>
<body>

Above just defines that basic HTML structure notice that we import the CSS file called /resources/style.css. This defines the look and feel for our site.

Note the style.css is a CSS code copied from various tutorials and sample CSS templates with some slight customizations. A true coverage of CSS is beyond the scope of this tutorial and cook book. But the general strategy I have used for doing CSS is follows:

  1. Ask customer what they might like the site to look like, tell them to send you links to similar looking sites
  2. see if there is budget enough to hire someone who is artistic and has style and loves doing site design, if then hire him, and let him do all of the pixel pushing
  3. If no budget to hire someone good at web design, look on Internet for sample CSS projects and/or look at sites customers liked, copy style and CSS layout

Problem with the above is that customers don't always let you know what they want, but are very clear about what they don't want. I've done all three. I prefer to let others send me look and feel, mockups (prefer mockups done in CSS and HTML), and then I hack it until it looks close enough. You need to learn CSS well enough to muck with CSS that you find on the Internet. Start by going through this tutorial W3 Schools CSS tutorial. There are times when you just can't find a CSS example that does exactly you want, in those cases you may find it helpful to consult the actual CSS specification.

Here is the style.css for completeness (please only skim it), note that it is a collection of stuff I could find in five minutes to make the site look somewhat decent without spending a lot of time. (Color palate for sample is really disgusting at the moment, the H1 is cartoonish big and the logo is too big, and I am not going to change any of it, ever.)

/resources/style.css


/* The CSS for the table was based of an example at wc3 schools. 
http://www.w3schools.com/css/tryit.asp?filename=trycss_table_fancy
*/
table.listing 
{
font-family: Arial, Helvetica, sans-serif;
width:80%;
border-collapse:collapse;
}


.listing td, th 
{
font-size:1em;
border:1px solid #98bf21;
padding:3px 7px 2px 7px;
}

.listing th
{
font-size:1.1em;
text-align:left;
padding-top:5px;
padding-bottom:4px;
background-color:#A7C942;
color:#ffffff;
}

.listing tr.alt td 
{
color:#000000;
background-color:#EAF2D3;
}


/* unvisited link */
a:link 
{
	text-decoration:none;
	color:#000000; 
}

/* visited link */
a:visited 
{
	text-decoration:none; 
	color: #707070 ;
}

a:hover {text-decoration:underline;}   /* mouse over link */
a:active {text-decoration:underline;}  /* selected link */

/* The CSS for the form was taken from this project. 
https://github.com/pmcelhaney/semantic-form.css/blob/master/index.html
*/

form.semantic {
	width:70%;
}

form.semantic fieldset
{
	clear: both;
	margin: 1em 0 0 0;
	padding: 10px;
	overflow: auto;
	background-color: #f8f8f8;
	border: 1px solid #888;
}

form.semantic legend
{
	font-weight: bold;
}

form.semantic div
{
	clear: both;
	margin: 0;
	padding: 0.5em 0 0 0;
	overflow: visible;
}


form.semantic label 
{
	display: block;
	float: left;
	width: 120px;
	text-align: right;
	padding: 2px 1ex 6px 0;
	vertical-align: baseline;
}
          
form.semantic label.after 
{
	width: auto;
	text-align: left; 
	display: inline; 
	float: none;
}

form.semantic label.long 
{
	clear: both;
	width: auto;
	text-align: left;
	float: none;
}

form.semantic input
, form.semantic select
, form.semantic textarea
{
	float: left;
}

form.semantic input.date {
	width : 100px;
}


form.semantic input.money {
	width : 100px;
}

form.semantic input[type=radio]
, form.semantic input[type=checkbox]
{
	vertical-align: text-bottom;
}

form.semantic ul {
	list-style-type: none; 
	float: left;
	padding: 0;
	margin: 0;
}

form.semantic li {
	clear: both;
	padding: 0.2em 0;
}

form.semantic li label {
	width: auto;
	text-align: left;
	padding: 0;
}   

form.semantic div.field-row 
{
	clear: none;
	float: left;
	margin: 0;
	padding: 0;
	overflow: visible;
}

form.semantic div.field-row *
{
	float: none;
	display: inline;
}

form.semantic .button-row
{
	text-align: right;
}

form.semantic .button-row input
{
	float: none;
}

form.semantic div.long label 
{
	width: auto;
	text-align: left;  
	float: none;
}

form.semantic div.long textarea 
{
	width: 100%;
}

/* Errors -- for use with JQuery Validate, etc. */

form.semantic input.error
, form.semantic select.error
, form.semantic textarea.error
{
	background-color: #77002a;
	color: white;
}                                                

form.semantic label.error
{
	width: auto;
	color: #77002a;
	text-align: left;
}       

/* from caucho.com */
#footer hr
{
  width: 100%;
}
#footer
{
  font-size: 80%;
  text-align: right;
}

/* bottom nav */

.bottom {
  font-family: Verdana, Helvetica, Arial, sans-serif;
  font-size : 90%;
  color : #999;
}

ul.bottom {
  list-style-type : none;
  padding : 0em;
  margin : 0;
  margin-top : 3em;
  text-align : center;
}

.bottom li {
  display : inline;
  margin : 0.1em 0.1em;
  padding : 0.0em;
}

.bottom a {
  color : #999;
}

.bottom a:hover {
  color : #ffcc33;
}

/* bottom */

.about {
  color : #999;
  font-family : Helvetica, Arial, sans-serif;
  text-align : center;
  font-size : 90%;
}

div.about {
  margin-top : 1em;
}

You can notice that I do use these styles now in book-form-content.jsp and the book-list-content.jsp.

Formating dates and numbers in book-listing.jsp with fmt:formatNumber and fmt:formatDate

In the last step of the tutorial the book listing did not format the dates or number very well. JSTL includes the format tag library to format numbers and dates, which we can use in the book-list.jsp as follows:

/WEB-INF/pages/book-list-content.jsp

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

<a href="${pageContext.request.contextPath}/book">Add Book</a>

<table class="listing">
	<tr>
		<th>Title</th>
		<th>Description</th>
		<th>Price</th>
		<th>Publication Date</th>
	</tr>
	
	<c:forEach var="book" items="${books}" varStatus="status">
		<tr class="${status.index%2==0 ? 'alt' : ''}">
			<td><a href="${pageContext.request.contextPath}/book?id=${book.id}">${book.title}</a></td>
			<td>${book.description}</td>
			<td>
			<fmt:formatNumber value="${book.price}" type="currency"/>
			</td>
			<td>
			<fmt:formatDate value="${book.pubDate}" type="both" dateStyle ="short" timeStyle ="short"/>
			</td>
		</tr>
	</c:forEach>
</table>



Notice the use of <code>fmt:formatNumber</code> and <code>fmt:formatDate</code> as follows:

==== /WEB-INF/pages/book-list-content.jsp fmt:formatNumber and fmt:formatDate====
<pre>
<a href="${pageContext.request.contextPath}/book">Add Book</a>
...

			<fmt:formatNumber value="${book.price}" type="currency"/>
...
			<fmt:formatDate value="${book.pubDate}" type="both" dateStyle ="short" timeStyle ="short"/>
</table>

The fmt:formatNumber formats the price as currency while the fmt:formatDate formats the publication date using the short form. We will go into more detail about this format tags when we cover internationalization (i18n) as both these tags and other tags from the JSTL fmt library support i18n. To learn more about these tags see the documentation as at JSTL fmt documentation.


Book listing Using c:forEach varStatus to alternate the row colors in a table

You can use c:forEach varStatus to alternate the rows colors with CSS.

In the CSS file (/resources/style.css) we have defined this CSS rule:

/resources/style.css

...
.listing tr.alt td 
{
color:#000000;
background-color:#EAF2D3;
}
...

The above basically says if you are in a table that is using the listing class and it is a row tag (<tr>) which is using the alt class, then set the color to #000000 and the background color of the column (td) to #EAF2D3.

Now from a JSP/JSTL perspective, we need to detect even rows and output the class attribute of the row as alt. You can do that with the varStatus as follows:

/WEB-INF/pages/book-list-content.jsp c:forEach varStatus

...
	<c:forEach var="book" items="${books}" varStatus="status">
		<tr class="${status.index%2==0 ? 'alt' : ''}">
...

The c:forEach's varStatus="status" captures the status object as a variable we can use. The status object has a current index as well as other properties about the current loop state.

The expression ${status.index%2==0 ? 'alt' : } says output alt if this row is even otherwise output an empty string. This binds every even number row to the alt CSS class.


Book Form

Nothing has really changed with book-form proper other than we moved it to book-form-content.jsp to take advantage of the new template.

/WEB-INF/pages/book-form-content.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<form class="semantic" method="post"
	action="${pageContext.request.contextPath}/book">
	<fieldset>
		<legend>
			<c:choose>
				<c:when test="${not empty book.id }">
						Updating Book
					</c:when>
				<c:otherwise>
						Adding Book
					</c:otherwise>
			</c:choose>
		</legend>

		<div>
			<label for="title">Title</label> <input type="text" name="title"
				id="title" value="${book.title}" />
		</div>

		<div>
			<label for="description">Description</label>
			<textarea name="description" id="description" rows="2" cols="60">${book.description}</textarea>
		</div>

		<div>
			<label for="price">Price $</label> <input name="price" id="price"
				class="money" value="${book.price}" />
		</div>

		<div>
			<label for="pubDate">Publication Date</label> <input name="pubDate"
				id="pubDate" class="date" value="${bookPubDate}" /> <label
				class="after">(MM/DD/YYYY)</label>
		</div>

		<c:if test="${not empty book.id}">
			<input type="hidden" name="id" value="${book.id}" />
		</c:if>

	</fieldset>

	<div class="button-row">
		<a href="${pageContext.request.contextPath}/book/">Cancel</a>  or <input type="submit" value="Submit" />
	</div>
</form>

Last but not least footer.jsp and header.jsp

We added two JSPs that implement the header and footer regions of our template as follows:

/WEB-INF/pages/footer.jsp

<div id="footer">
  <ul class="bottom">
  <li><a href="http://www.caucho.com/">HOME</a> |
  <li><a href="http://www.caucho.com/about/contact/">CONTACT US</a> |
  <li><a href="http://www.caucho.com/resin-4.0/">DOCUMENTATION</a> |
  <li><a href="http://blog.caucho.com/">BLOG</a> |
  <li><a href="http://wiki.caucho.com/">WIKI</a>

  </ul>
  
  <div class="about">
Copyright (c) 1998-2012 Caucho Technology, Inc. All rights reserved.<br><span class="caucho">caucho<sub>�</sub></span> ,
<span class="resin">resin<sub>�</sub></span> and
<span class="quercus">quercus<sub>�</sub></span>

are registered trademarks of Caucho Technology, Inc.
  </div>

  <div class="about">
     resin<sub>�</sub> is a cloud optimized, java<sub>�</sub> application server that supports the java ee webprofile <sub>�</sub>
  </div>
</div>


/WEB-INF/pages/header.jsp

<div>
<a href="${pageContext.request.contextPath}">
<img src="${pageContext.request.contextPath}/resources/logo.png"/>
</a>
</div>

The footer contains standard footer stuff (copyright notices and such). The header contains a company logo and a link to the root directory.



Other Cookbooks and Tutorials

Personal tools
TOOLBOX
LANGUAGES