Java EE Servlet tutorial : Using JSPs to create header, footer area, formatting, and basic CSS for bookstore
From Resin 4.0 Wiki
Line 1: | Line 1: | ||
== Java EE Servlet/JSP tutorial: cleaning up our GUI == | == 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 == | ==Adding site template using jsp:include, adding CSS, using JSTL fmt:formatDate and fmt:formatNumber == | ||
Line 23: | Line 27: | ||
== Defining a simple template with JSP parma.X == | == Defining a simple template with JSP parma.X == | ||
+ | |||
+ | Here is an example of a JSP template. | ||
+ | |||
==== /WEB-INF/pages/template.jsp ==== | ==== /WEB-INF/pages/template.jsp ==== | ||
<pre> | <pre> |
Latest revision as of 00:00, 3 May 2012
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:
- Ask customer what they might like the site to look like, tell them to send you links to similar looking sites
- 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
- 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>
We added two JSPs that implement the header and footer regions of our template as follows:
<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
- Building a simple listing in JSP: covers model 2, Servlets, JSP intro.
- Java EE Servlet tutorial : Adding create, update and delete to the bookstore listing: covers more interactions.
- Java EE Servlet tutorial : Using JSPs to create header, footer area, formatting, and basic CSS for bookstore.
- Java EE Servlet tutorial : Adding MySQL and JDBC to bookstore example.
- Java EE Servlet tutorial : Adding validation and JSP tag files to bookstore example.
- Java EE Servlet tutorial : Adding I18N support to bookstore example.
- Java EE Servlet tutorial : Load testing and health monitoring using bookstore example.
- Java EE Servlet tutorial : Setting up clustering and session replication.
- Java EE Servlet tutorial : Setting up security for bookstore example.
- Java EE Servlet tutorial : File uploads for bookstore example.
- Java EE Servlet tutorial : Using JPA for bookstore example.
- Java EE Servlet tutorial : Using JCache for bookstore example.