570 likes | 579 Views
JSP Revisited. Instructors: Geoffrey Fox and Bryan Carpenter Dept. of Computer Science School of Computational Science and Information Technology 400 Dirac Science Library Florida State University Tallahassee Florida 32306-4120 http://www.csit.fsu.edu http://aspen.csit.fsu.edu/webtech/xml/.
E N D
JSP Revisited Instructors: Geoffrey Fox and Bryan Carpenter Dept. of Computer Science School of Computational Science and Information Technology 400 Dirac Science LibraryFlorida State UniversityTallahassee Florida 32306-4120 http://www.csit.fsu.edu http://aspen.csit.fsu.edu/webtech/xml/ it2ejb http://aspen.csit.fsu.edu/it2spring01
This Lecture Set • Review of material on JSP from IT1 lectures. • Extended discussion of customized tag libraries. • Integration of JSP/servlet code with Enterprise Java Beans. it2ejb http://aspen.csit.fsu.edu/it2spring01
References • Web Development with JavaServer Pages, Duane K. Fields and Mark A. Kolb, Manning Publications, 2000. • Thorough, insightful, and current. • Java Server Pages, Hans Bergsten, O’Reilly, 2001. • Brand new! Looks good. • Core Servlets and JavaServer Pages, Marty Hall, Prentice Hall, 2000. • IT1 lectures on JSP, at: http://aspen.csit.fsu.edu/it1spring01 it2ejb http://aspen.csit.fsu.edu/it2spring01
Summary • Java Server Pages, recall, allow special tags and Java code to be embedded in HTML files. These tags and code are processed by the Web server to dynamically produce a standard HTML page for the browser. • Produce dynamic Web pages on the server side (like Servlets), but separate application logic from the appearance of the page. • May also produce XML documents, instead of HTML. it2ejb http://aspen.csit.fsu.edu/it2spring01
Translating and Executing JSP Pages • A JSP page is executed in a JSP container, generally installed in a Web server. • The underlying semantic model is that of a servlet. • A typical JSP container will translate the JSP page to a Java servlet. • By default translation and compilation of a JSP page is likely to occur the first time it is accessed. it2ejb http://aspen.csit.fsu.edu/it2spring01
Possible Architecture URL JSP page request HTTP request Tag Library JSP container compiles to a servlet response HTTP response Enterprise Java Bean HTTP page DB Browser Web server it2ejb http://aspen.csit.fsu.edu/it2spring01
JSP elements reviewed • JSP elements include: • Scriptlet enclosed in <%and%>markers:a small script in Java to perform arbitrary functions. Executed in the underlying servlet context. • Expression: anything between <%=and %>markers is evaluated by the JSP engine as a Java expression in the servlet context. • JSP directive enclosed in <%@and %> markers—passes information to the JSP engine (guides “compilation”). • JSP actions or tags are a set of customizable XML-style tags for particular actions, e.g. predefine jsp:useBean instantiates a JavaBean class on the server. • Here we will be most interested in custom tags, or “actions”. it2ejb http://aspen.csit.fsu.edu/it2spring01
Actions vs Scripting Elements • They are distinguished by syntax: • Scripting elements are largely unconstrained Java “inserts”, whereas actions follow an XML-like syntax (although JSP isn’t strict XML). • Also distinguished at a software engineering level: • Scripting elements provide a quick way to achieve an effect, but depend on knowledge of the underlying servlet model. • Custom actions, and the associated tag libraries offer a potentially higher level of abstraction. • As with all good libraries, actions should be easy to use. But they are relatively hard work to implement. it2ejb http://aspen.csit.fsu.edu/it2spring01
Tag Libraries Revisited it2ejb http://aspen.csit.fsu.edu/it2spring01
Motivations • There are two kinds of action in JSP: the standard actions, and custom actions. • The standard actions are quite limited: around 5 tags, that enable interaction of the page with library code implemented as JavaBeans. • As illustrated in earlier lectures, one can get quite a long way by creating JavaBeans, and getting and setting their properties. But the standard actions get clumsy when complex behaviors are needed. • In complex situations, the JavaBeans approach doesn’t always give a good separation between presentation logic and application logic. • . . .because the JSP interface is limited to getting and setting properties of the JavaBean. Conditional or iterative behavior is limited—we are forced back to scripting elements. it2ejb http://aspen.csit.fsu.edu/it2spring01
Customized Actions • Unlike the standard actions, a customized action can accept multiple arguments (as attributes) from the HTML document. • We no longer have to shoehorn all functionality into the get and set methods associated with JavaBean properties. • A customized action element can do non-trivial processingon the text in its body. • A customized action element can process the template text and nested tags in its body more thanonce. This allows repeating structures like menus and tables to be created dynamically. • Without resorting to scripting elements involving explicit loops. it2ejb http://aspen.csit.fsu.edu/it2spring01
An Iterative Element <%@ taglib uri="selectlib.tld" prefix="test" %> <html><head></head><body> <table border cellspacing=0 cellpadding=5> <tr bgcolor=lightblue> <td>Login id</td> . . . <td>Dept</td> </tr> <test:select columns="*" table="it1fall00"> <tr> <td> <test:field column="1"/> </td> <td> <test:field column="2"/> </td> <td> <test:field column="3"/> </td> <td> <test:field column="4"/> </td> <td> <test:field column="5"/> </td> </tr> </test:select> </table> </body></html> it2ejb http://aspen.csit.fsu.edu/it2spring01
The Generated HTML <html><head></head><body> <table border cellspacing=0 cellpadding=5> <tr bgcolor=lightblue> <td>Login id</td> . . . <td>Dept</td> </tr> <tr> <td> wcao </td> <td> Cao </td> <td> Whenzhong </td> <td> wcao@cs.fsu.edu </td> <td> CSIT </td> </tr> <tr> <td> flora </td> <td> Flora </td> <td> Albertine Mary </td> <td> flora@eng.fsu.edu </td> <td> EE </td> </tr> . . . </table> </body></html> it2ejb http://aspen.csit.fsu.edu/it2spring01
The Displayed Page it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • The select action from selectlib.tldexecutes an SQLSELECTquery on some database. • Details of the query are specified by the table and columns attributes. • The body of the element is processed once for every row returned by the query. • In our page, each evaluation of the body generates one row of an HTML table. • This is not part of the library—the library just provides iteration over a selected data set. • The field action from the selectlib library returns the column value with index specified by the column attribute. • All HTML generation is handled in the JSP page—the Java code is only responsible for accessing the data base and managing iteration over the result set. it2ejb http://aspen.csit.fsu.edu/it2spring01
The Tag Library Directive • The jsp:taglib directive informs the JSP container that this page will be using a library of customized tags. • The most important attribute of the directive is uri. • The value of this directive is a URL referencing the Tag Library Descriptor file(TLD). • This is an XML document describing the syntax of the custom elements, and specifying where to find the associated tag handler classes. • The prefix attribute just specifies a prefix that will be appended to the tag names within this document—similar to a namespace declaration in standard XML. it2ejb http://aspen.csit.fsu.edu/it2spring01
Tag-Handling Classes • In JSP tag libraries, each kind of element has an associated Tag-Handling class. • In our example, the select element is handled by a class called SelectTag. • A tag-handling class like SelectTag (for an element that does non-trivial processing on its body) generally extends the standard class javax.servlet.jsp.tagext.BodySupportTag. • This implements the interface javax.servlet.jsp.tagext.BodyTag • The simpler field element (which doesn’t have to process its body) is handled by a class called FieldTag, which can extend a standard class javax.servlet.jsp.tagext.TagSupport instead. • This implements javax.servlet.jsp.tagext.Tag. BodyTag extends Tag. • The association between JSP elements and tag-handling classes is defined in the TLD. it2ejb http://aspen.csit.fsu.edu/it2spring01
Life Cycle of BodyTag Handler setPageContext() setParent() Set context e.g.,setColums() setTable(), . . . Set attributes doStartTag() EVAL_BODY_TAG setBodyContent() setInitBody() Initialize body content SKIP_BODY Process body doAfterBody() SKIP_BODY EVAL_BODY_TAG doEndTag() SKIP_PAGE EVAL_PAGE release() release() it2ejb http://aspen.csit.fsu.edu/it2spring01
Life Cycle Methods from Tag void setPageContext(PageContext pc) • Called before doStartTag(). Informs handler page context. void setParent(Tag t) • Called before doStartTag(). Informs handler its parent. int doStartTag() • Tells handler to process the start tag for the element. Returns EVAL_BODY_TAG or SKIP_BODY. int doEndTag() • Tells handler to process end tag for element. Returns EVAL_PAGE or SKIP_PAGE. If the latter, the remainder of the page is ignored. void release() • Clean up. it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • When a custom tag is encountered in a JSP page, setProperty() methods are invoked on the handler for each of the attributes defined in the tag. • In our example there are two properties: columns and table. • The doStartTag() method is then invoked. • In general this can process the attributes, optionally generate some output, and decide what, if anything, should be done about the body of the element. • The doStartTag() method may return Tag.SKIP_BODY or Tag.EVAL_BODY_TAG, telling the container respectively to ignore the body of the element or go ahead and process it. • For simple tag-handlers—not implementing the extended BodyTag interface—another option is Tag.EVAL_BODY_INCLUDE, which tells the JSP container to process the body in the default way. it2ejb http://aspen.csit.fsu.edu/it2spring01
More Life Cycle Methods for BodyTag • The BodyTag interface extends the Tag interface, and adds life-cycle methods relevant to tag handlers which need to do non-default processing of the text in their bodies: int doInitBody() • Informs handler to prepare for (first) evaluation of body. Typically used for loop initialization code in elements that process their bodies repeatedly. int doAfterBody() • Called after some body has been evaluation. Returns either EVAL_BODY_TAG or SKIP_BODY. If the former, the JSP container will process the body again. it2ejb http://aspen.csit.fsu.edu/it2spring01
Handling Class for the select Tag • Our handler for the select element will be a class called SelectTag. • The class SelectTag extends the utility class BodyTagSupport. • The BodyTagSupport class implements the BodyTag interface, and provides convenient default implementations for methods like setPageContext(), setParent(), . . . , etc. • The SelectTag class only needs to define its application-specific property-setting methods—setColumns() and setTable()—and override the three methods doStartTag() and doAfterBody(), doEndTag(). it2ejb http://aspen.csit.fsu.edu/it2spring01
The SelectTag Class package mytags ; import javax.servlet.* ; import javax.servlet.http.*; import javax.servlet.jsp.* ; import javax.servlet.jsp.tagext.* ; import java.io.* ; import java.sql.* ; public class SelectTag extends BodyTagSupport { public int doStartTag() throws JspException { . . . } public int doAfterBody() throws JspException { . . . } public int doEndTag() throws JspException { . . . } public void setTable(String table) {this.table = table ; } public void setColumns(String columns) {this.columns = columns ; } ResultSet rs ; private String columns, table ; } it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • The tag-handling class belongs to a package mytags. • Some JSP containers require that tag library classes are put in packages. • The class has two properties, columns and table, who’s values are stored in private instance variables. • The names of these properties correspond directly to the allowed attribute-names of the tag. • The other instance variable, rs, has default, package-wide accessibility. • This means it is accessible from other tag-handling classes in the same library. it2ejb http://aspen.csit.fsu.edu/it2spring01
The doStartTag() Method public int doStartTag() throws JspException { try { HttpSession session = pageContext.getSession() ; DBSession dbs = (DBSession) session.getAttribute(“dbs”) ; if(dbs == null) { dbs = new DBSession() ; session.setAttribute(“dbs”, dbs) ; . . . } rs = dbs.stat.executeQuery("SELECT " + columns + " FROM " + table) ; if (rs.next()) return EVAL_BODY_TAG ; else return SKIP_BODY ; } catch (. . .) {. . .} } it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • The method starts with some boilerplate, servlet session-tracking code. • We recycle the DBSession from the servlet version of the student database example of the IT1 lectures. • The pageContext instance variable allows us to retrieve JSP predefined variables like session. • The instance variablescolumns and table correspond to the tag attributes. • They were initialized in setColumns() and setTable(). • The main business is in the executeQuery() method. • Its result is placed in the instance variable, rs. • The return value of doStartTag() is determined by rs.next(). • On its first call, this returns true iff the result set is not empty. it2ejb http://aspen.csit.fsu.edu/it2spring01
The doAfterBody() Method public int doAfterBody() throws JspException { try { if(rs.next()) return EVAL_BODY_TAG ; else return SKIP_BODY ; } catch (. . .) { . . . Rethrow exception asJspException . . . } } it2ejb http://aspen.csit.fsu.edu/it2spring01
The doEndTag() Method public int doEndTag() throws JspException { try { BodyContent body = getBodyContent() ; body.writeOut(getPreviousOut()) ; return EVAL_PAGE ; } catch (. . .) { . . . Rethrow exception asJspException . . . } } it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • Before returning the value EVAL_PAGE, which tells the JSP container to process the remainder of the page, the method outputs the accumulated result of (repeatedly) processing its body. • Any tag handler that implements BodyTag has accepted this responsibility. it2ejb http://aspen.csit.fsu.edu/it2spring01
The JspWriter and BodyContent Classes • In general, output generated by a JSP page is written to an object of type JspWriter. • JspWriter is a subclass of the standard java.io.Writer. • This object is accessible in scriptlet code through the variable out. • When the JSP container encounters a custom tag implementing BodyTag,it reassigns out with a reference to an object of type BodyContent. • BodyContent is a subclass of JspWriter that buffers content written to it. • The container gives the tag handling class a reference to the new object by calling the life cycle method setBodyContent(). • As the element is processed, output is now written to this BodyContent object instead of the original JspWriter. it2ejb http://aspen.csit.fsu.edu/it2spring01
The BodyContent Stream • BodyContent provides methods that allows its buffered content to be extracted, and, for example, written to another stream, presumably when processing of the element is complete. • One such method, used above, is writeOut(). In the fragment: BodyContent body = getBodyContent() body.writeOut(getPreviousOut()) ; the call getBodyContent() returns the BodyContent object for this element; getPreviousOut() returns the JspWriter associated with out in the surrounding text. • In this example, the text generated while processing the body (of the select element) is accumulated in a BodyContent object. When doEndTag() is executed, all this text is copied unmodified to the main JSP output stream. it2ejb http://aspen.csit.fsu.edu/it2spring01
Output from Nested BodyTag Elements out body1 . . . <tag1> . . . <tag2> . . . <tag3> . . . </tag3> . . . </tag2> . . . </tag1> . . . body2 body3 it2ejb http://aspen.csit.fsu.edu/it2spring01
Non-default Processing of Body • The doEndTag() or doAfterBody() methods can subject the contents accumulated in the BodyContent stream to arbitrary processing, before copying it to the parent output stream, e.g.: BodyContent b = getBodyContent() ; JspWriter out = getPreviousOut() ; out.write( doTransformation(b.getString()) ) ; • Here the function doTransformation() can do any desired transformation to the text accumulated by processing the body of the element. • For example, the body might contain XML. The transformation function could parse this XML using DOM and apply some XSLT transformation to it. . . <transformXML stylesheet=“mystyle.xsl”> . . . Arbitrary XML . . . </transformXML> it2ejb http://aspen.csit.fsu.edu/it2spring01
Handling Class for the field Tag • We still have to discuss the implementation of the handling class for the field element, which accesses column values in the rows enumerated by select. • The handling class, FieldTag, does not need to process a body. • It can therefore extend the simpler TagSupport utility class. • It only needs to define the setter method for the column attribute, and doStartTag() or doEndTag(). • But there is a new issue that needs to be addressed: somehow the handling objects for nested field elements need to access the ResultSet object generated by the select handler. it2ejb http://aspen.csit.fsu.edu/it2spring01
Accessing Parents and Ancestors • This isn’t hard in principle. The container gives a tag handling object a reference to the handler for the most closely enclosing custom tag by invoking the setParent() life-cyle method. • In the tag support classes, this value can be accessed by getParent(). • Often one doesn’t necessarily want the most closely enclosing element; one wants the most closely enclosing element of a particular type. • A utility method is provided for this. • Using Java reflection, the method findAncestorWithClass() chases parent links until it finds an ancestor with a specified tag-handling class. it2ejb http://aspen.csit.fsu.edu/it2spring01
The FieldTag Class package mytags ; import javax.servlet.jsp.* ; import javax.servlet.jsp.tagext.* ; import java.sql.* ; public class FieldTag extends TagSupport { public int doStartTag() throws JspException { . . . } public void setColumn(String column) {this.column = column ; } private String columns ; } it2ejb http://aspen.csit.fsu.edu/it2spring01
The doStartTag() Method public int doStartTag() throws JspException { try { JspWriter out = pageContext.getOut() ; SelectTag parent = (SelectTag) findAncestorWithClass(this, SelectTag.class) ; out.print(parent.rs.getString(Integer.parseInt(column))) ; } catch (. . .) { . . . } return SKIP_BODY ; } it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • The tag-handling object for the enclosing selectelement by passing this object and the class object for SelectTag to the findAncestorWithClass() utility. • The column value can then be extracted from the rs field of that object—i.e. the ResultSet computed by the select element. it2ejb http://aspen.csit.fsu.edu/it2spring01
The Tag Library Descriptor File • The TLD file is in XML format. • It has some preamble describing the XML version and document type. • The main body is a taglib element. • This element in turn contains some global information about the library, then (most importantly) a series of tag elements. • Each tag element defines the syntax and (indirectly) the semantics of a custom tag: • Tag name. • Handler class. • Attribute names and properties. • How to deal with the element body, if there is one. it2ejb http://aspen.csit.fsu.edu/it2spring01
TLD File for the “selectlib” Example <?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>myselect</shortname> <uri></uri> <info> Simple SQL query library </info> . . .tagelements . . . </taglib> it2ejb http://aspen.csit.fsu.edu/it2spring01
A TLD tag Element <tag> <name>select</name> <tagclass>mytags.SelectTag</tagclass> <info> Do a simplified SQL select query, and iterated over results </info> <attribute> <name>columns</name> <required>true</required> </attribute> <attribute> <name>table</name> <required>true</required> </attribute> <bodycontent>JSP</bodycontent> </tag> it2ejb http://aspen.csit.fsu.edu/it2spring01
Another TLD tag Element <tag> <name>select</name> <tagclass>mytags.FieldTag</tagclass> <info> Extract field from current row </info> <attribute> <name>column</name> <required>true</required> </attribute> <bodycontent>EMPTY</bodycontent> </tag> it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • The preamble defines the XML version and an XML Document Type Definition file for the document. • Required elements inside a taglib element are • the tlibversion element which give a version number for the tag library, and • the shortname element used to identify the library. • A tag element specifies: • Java classes that define thebehaviorof the action. • attributeelements that define the tag’s attributes. • An attribute may be “required” or optional. • Its value may be required to be a constant string, or allowed to be a dynamic, request-time expression (“rtexprval” element). • The body content of the the defined element may be specified to be EMPTY. • It may also be specified to beJSP, or tagdependent. it2ejb http://aspen.csit.fsu.edu/it2spring01
Simple Deployment • The TLD file is just an ordinary Web document, accessed with a relative or absolute URL. • It may sit alongside the HTML and JSP files. • The class files for the handler classes may be placed under the WEB-INF/classes subdirectory along with servlet classes. • Note however that the usual rules about directories and packages apply: in our example the class files should go in WEB-INF/classes/mytags. it2ejb http://aspen.csit.fsu.edu/it2spring01
Packaging a Tag Library • If you are distributing a tag library for use in multiple applications, you will want to create a jar archive. • Rename selectlib.tld to taglib.tld (this seems to be necessary) and arrange the files in a directory structure like (e.g.): META-INF/ taglib.tld mytags/ SelectTag.class FieldTag.class DBSession.class DBConstants.class • Create an archive by jar cvf selectlib.jar META-INF mytags • Copy the jar file to a directory WEB-INF/lib/ in the context document root. • You can then import the tag library by, e.g.: <%@ taglib uri=”/WEB-INF/lib/selectlib.jar" prefix="test" %> it2ejb http://aspen.csit.fsu.edu/it2spring01
Tags that Define Scripting Variables • Some JSP actions define variables that are subsequently accessible in scriplet inserts. One example is the standard action jsp:usebean. • In the earlier lectures we were rather purist about use of JavaBeans in JSP pages, and only accessed their properties through jsp:getProperty and jsp:setProperty methods, e.g. <jsp:useBean id=“now” class=“DateBean”/> <html><head></head><body> Now is <jsp:getProperty name=“now” property=“date”/> </body></html> • In fact the jsp:useBean action also introduces a servlet-code variable, now, into the page, which can be be accessed directly in scriptlets; we could replace the jsp:getProperty action with: <%= now.getDate() %> it2ejb http://aspen.csit.fsu.edu/it2spring01
Custom Tags that Declare Variables • One of the advantages of JSP actions is supposed to be that they reduce or eliminate the need for complex programming inserts in Web pages. • On the other hand scripting elements can certainly be convenient if they are used in a disciplined way, • e.g., just make an occasional call to a Java library method. • For example, the mechanism of the previous page could be used to circumvent the restrictions of the standard actions, calling methods on a bean class besides property “getters” and “setters”. • JSP accordingly provides a mechanism whereby custom tags can introduce scripting variables. it2ejb http://aspen.csit.fsu.edu/it2spring01
An Example • Here is a relatively complex example adapted from The Java 2 Enterprise Edition Developer’s Guide: <%@ taglib uri=“taglib.tld” prefix=“j2ee” > <html><head></head><body> <% Converter converter ; %> <j2ee:ejb jndiName=“java:comp/env/ejb/MyConverter”, homeInterface=“ConverterHome”, homeVar=“converterHome”> <% converter = converterHome.create() ; %> </j2ee:ejb> dollarToYen: <%= converter.dollarToYen(100.00) %> <p> yenToEuro: <%= converter.yenToEuro(100.00) %> </body></html> it2ejb http://aspen.csit.fsu.edu/it2spring01
Remarks • This example actually uses scripting inserts rather freely—to explicitly declare a local variable converter, and to explicitly call methods in various places. • The example is interesting in its own right, as it uses JSP—and in particular tag libraries—to manipulate an EnterpriseJava Bean. • However, the main point to notice here is the variable converterHome. • Unlike converter, there is no explicit, scriplet declaration for converterHome—it is created and initialized by the custom tag, j2ee:ejb. • In this example we can assume that the scope of the variable convertHome is the body of the j2ee:ejb element. • This contrasts with jsp:useBean, where the scope of the introduced scripting variable is the part of the page following the element. it2ejb http://aspen.csit.fsu.edu/it2spring01
Compilation of the JSP Page • How can a custom tag introduce or modify a variable that is local to servlet code? • Recall the main code for the custom tag goes in tag handler classes, defined in some precompiled library. • Somehow the tag library must influence the process of “compilation” of the JSP page to servlet code, in such a way that extra statements (declarations of, and assignments to, local variables) are added. • One possibility might be to add the extra information to the tag library descriptor, since this already guides the compilation process. • This might be inflexible though, because the name and type of the introduced variables generally isn’t known when the XML is written. • Both jsp:useBean and j2ee:ejb take these from attribute values specified in the actual JSP. it2ejb http://aspen.csit.fsu.edu/it2spring01