Monday, December 21, 2009

9.3 JavaServer Pages



[ Team LiB ]






9.3 JavaServer Pages



JavaServer Pages are the
Java way to build web-based user interfaces using Java as a scripting
language for generating dynamic


XHTML.[2] In other words,
JSP enables you to embed Java code inside your XHTML so that the full
content of the XHTML page can be dependent on the state of the system
when a user requests a page. Example 9-3 shows your
obligatory "Hello World"
application as a JSP page.

[2] JSPs are not limited to XHTML. They can generate HTML, XML, or
any other kind of textual markup.




Example 9-3. A simple JSP page

<%@ page info="Hello World" %>

<% String msg = "Hello World!"; %>

<html>
<head>
<title><%=msg%></title>
</head>

<body>
<h1><%=msg%></h1>
<p>
Though this example is largely uninteresting, it does
demonstrate how Java can be embedded in an XHTML page to
generate content dynamically.
</p>
</body>
</html>



As with any "Hello World"
application, this one is mind-numbingly dull. What you should take
from it, however, is the basic structure that enables you to call
methods in Java objects and drive content from Java values. Though I
used a simple String instance in this example, the
<title> and <h1>
values could have been drawn from a database.



The web server or application server in which the JSP runs interprets
anything between <% and
%> as Java code and anything between
<%= and %> as values to
be printed out. When a request is made for a JSP page, that page is
turned into a Java object. Your embedded Java code becomes part of
that compilation. The XHTML in your page becomes a string to send
out. The server then executes the method into which your Java code
was compiled.



This compile happens only once as long as the server remains running
and no one changes the JSP source. If you make a change to the JSP
source, however, the server will recompile it the next time it is
requested.



JSPs become interesting when you hook them up to an EJB system or a
database. Naturally, we will be doing just that throughout Part II of
this book. This section simply describes the basics behind JavaServer
Pages.




9.3.1 Page Structure



A JSP page consists of static
content, JSP directives, Java code, and JSP tags:




Static content



Static content is the XHTML into which your
JSP code is embedded.




JSP directives



These elements appear between
<%@ and
%> markers. They indicate directives to the
server prior to compiling the JSP page.




Java code



Java code is everything between
<% and
%> and between <%= and
%> tags. This code is executed for each page
view.




JSP tags



A JSP tag
is an XML-like interface into a library of Java code. The JSP
specification prescribes a core set of tags, but you can add your own
through custom tag libraries.





As a general rule, the fewer lines of Java code in your JSP page, the
better. When you add a lot of Java code to a JSP page, you, in a
sense, defeat the purpose of using JSPs over the Java Servlet API.
Specifically, defining your user interface as a set of JSPs enables
you to transfer the work of user interface writing to XHTML
programmers instead of Java programmers. This transfer hopefully
results in more creative resources being responsible for UI
development.





9.3.2 JSP Programming



Example 9-4 provides a
more typical JSP page than the "Hello
World" code in Example 9-3.




Example 9-4. A JSP page that drives content from a content management database

<%@ page info="Page Loader" %>
<%@ page import="org.dasein.tractatus.jsp.ErrorLog" %>
<%@ page import="org.dasein.tractatus.jsp.Tractatus" %>

<%@ taglib uri="/WEB-INF/tld/tractatus.tld" prefix="tractatus" %>

<jsp:useBean id="user" scope="session" class="org.dasein.security.User"/>
<% pageContext.setAttribute(Tractatus.USER, user); %>
<% user.setPreferredLocale(request.getLocale( )); %>

<tractatus:setTarget/>

<% pageContext.setAttribute("template", target.getTemplate( )); %>
<% if( target.getContent( ) != null ) { %>
<% pageContext.setAttribute("contentTemplate",
target.getContent( ).getTemplate( )); %>
<% } else { %>
<% pageContext.setAttribute("contentTemplate", null); %>
<% } %>

<tractatus:authorize>
<tractatus:allowed>
<tractatus:isNull name="template">
<tractatus:true>
<tractatus:isNull name="contentTemplate">
<tractatus:true>
<tractatus:printContent/>
</tractatus:true>
<tractatus:false>
<jsp:include page="<%=target.getContent( ).getTemplate( ).getRelativeURL( )%>"/>
</tractatus:false>
</tractatus:isNull>
</tractatus:true>
<tractatus:false>
<jsp:include page="<%=target.getTemplate( ).getRelativeURL( )%>"/>
</tractatus:false>
</tractatus:isNull>
</tractatus:allowed>
<tractatus:denied>
<% String msg = "<p class=\"error\">Access denied.</p>"; %>
<jsp:include page="page.jsp">
<jsp:param name="target"
value="<%=target.getSite( ).getErrorPage( ).getPageID( )%>"/>
<jsp:param name="error" value="<%=ErrorLog.storeException(msg)%>"/>
</jsp:include>
</tractatus:denied>
<tractatus:unauthenticated>
<%
response.sendRedirect(target.getSite( ).getLoginPage( ).getRelativeURL( ) +
"&previous=" + target.getPageID( ));
%>
</tractatus:unauthenticated>
</tractatus:authorize>



Though all of the content for this page is dynamically generated,
very little of it is direct Java code. It starts out with three
directives:



<%@ page info="Page Loader" %>
<%@ page import="org.dasein.tractatus.jsp.ErrorLog" %>
<%@ page import="org.dasein.tractatus.jsp.Tractatus" %>

<%@ taglib uri="/WEB-INF/tld/tractatus.tld" prefix="tractatus" %>


The first directive provides metainformation about the JSP page for
tools. The second and third directives tell the server what Java
import statements to use for this page when compiling it. The final
one tells the server where to find definitions for the custom tags in
use in this page.



Only the last directive requires any elaboration. When you build a
library of Java objects that can serve as JSP tags, you need to
create an XML descriptor file that maps tag
names to Java classes. The uri value for the
taglib directive points to this XML file. The
prefix value then names what prefix will appear
for the tags in this JSP page. In this case, the prefix is
tractatus.



You will use the tag in the next line of code,
<jsp:useBean>, in
almost all of your JSP pages. It enables you to store and access a
regular JavaBean as part of the user session information. In this
case, I am storing a User object representing the
site visitor.



The next two lines are the first bit of actual Java code:



<% pageContext.setAttribute(Tractatus.USER, user); %>
<% user.setPreferredLocale(request.getLocale( )); %>


You probably gather that the user variable in the second line comes
from the call to <jsp:UseBean>. On the other
hand, it is entirely unclear where the pageContext
variable comes from. A JSP page defines several page-level variables
to which you have access. The two you will most commonly use are
pageContext and request. The
pageContext variable represents information about
the context of the page execution. In this example, I am setting an
attribute that can be used by my custom tags. The
Tractatus.USER constant is simply a
String constant for
"user".[3]

[3] I believe
it is a good solid practice never to have literal values in your
source code, except as constant definitions. This line reflects that
practice.



The other variable you will commonly need,
request, represents the HTTP request coming in
from the browser. It contains information about the requester and the
headers of the request. In the second line, I am looking for
internationalization information from the request. Specifically, I am
trying to find out what locales the browser is set to accept.



The next line is the first custom tag in this JSP page:



<tractatus:setTarget/>


Behind this tag's simplicity is some complex Java
code for setting a variable named target to a
custom Java object of type
org.dasein.tractatus.Page based on the request
sent to the server. For example, if the URL was http://www.imaginary.com/page.jsp?target=5,
then the <tractatus:setTarget> tag will go
to the database, find the Page with a
pageID of 5, and then set the
target variable to that Page
instance.



Perhaps you can imagine the level of complexity I would have added to
this page had I not hidden everything behind a JSP tag. Now, XHTML
programmers do not need to know anything about looking up custom
objects hidden in a database. They simply include this one empty tag
and they are all set.



The rest of the code is mostly custom tags with a small mix of Java
code. In short, it does the following:



  1. Verifies that the user has access to the requested page.

  2. Verifies that the user is disallowed, allowed, or not yet
    authenticated:

    • If disallowed, the user is redirected to a page telling him he does
      not have the proper permissions.

    • If allowed, the user is shown the actual content through the
      <jsp:include> tags.

    • If the user has yet to be authenticated and the web page is not open
      to the public, the user is redirected to a login page.




9.3.3 Custom Tags



The
power of JavaServer Pages lies in the ability to build reusable Java
components and then hide them behind custom tags. The creation of
custom tags is quite simple. You write a class that implements a
specific API and then map that class to a tag name via an XML
descriptor file. A simple custom tag looks like Example 9-5.




Example 9-5. A simple custom tag

package org.dasein.tractatus.jsp;

import java.io.IOException;
import java.util.Locale;

import javax.servlet.ServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.dasein.persist.PersistenceException;
import org.dasein.security.User;
import org.dasein.tractatus.Page;

public class HTMLTitleTag extends TagSupport {
public int doEndTag( ) throws JspException {
try {
Page p = (Page)pageContext.getAttribute(Tractatus.TARGET);
User u = (User)pageContext.getAttribute(Tractatus.USER);
Locale def = p.getSite( ).getDefaultLocale( );
String ttl;

ttl = "<title>" + p.getTitle(u.getPreferredLocale(def))
+ "</title>";
pageContext.getOut( ).println(ttl);
}
catch( IOException e ) {
throw new JspException(e.getMessage( ));
}
catch ( PersistenceException e ) {
throw new JspException(e.getMessage( ));
}
return EVAL_PAGE;
}
}



This custom tag extends the TagSupport class from
the JSP API and implements a single method,
doEndTag( ). This
method is triggered when the server reaches the end tag of your
custom tag. Because this particular tag is an empty tag, the end
happens right after the start. In this example, the tag finds the
current target value (previously set by
<tractatus:setTarget>) as well as the
current user value (previously set by
<jsp:useBean>). It then prints out the XHTML
for the page's title translated into the
user's preferred language.



To add this tag to the web site, you need to edit the XML tag library
descriptor file to map a tag name to this class. If this tag were the
only tag in the tag library, the descriptor file would look like
Example 9-6.




Example 9-6. Sample tag descriptor

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1/EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<taglib>

<tlibversion>1.0</tlibversion>
<jspversion>1.1</jspversion>
<shortname>tractatus</shortname>

<tag>
<name>htmlTitle</name>
<tagclass>org.dasein.tractatus.jsp.HTMLTitleTag</tagclass>
<bodycontent>empty</bodycontent>
</tag>

</taglib>



The code in bold shows the definition of the custom tag. It maps the
name htmlTitle to the class
org.dasein.tractatus.jsp.HTMLTitleTag and
establishes the constraint that the tag should be an empty tag.
Consequently, whenever the server encounters the following in a JSP
page:



<tractatus:htmlTitle/>


The server prints out the title of the page referenced by the
target variable localized for the user.



Custom tags do get more complicated. Some contain XHTML code, while
others contain other custom tags. A full description of this API is
well beyond the scope of this book. For more information, take a look
at JavaServer Pages (O'Reilly)
by Hans Bergsten.








    [ Team LiB ]



    No comments: