45
COMP 321 Week 11

COMP 321 Week 11. Overview Lab 8-1 Solution Tag Files Custom Tags Web Application Deployment

Embed Size (px)

Citation preview

COMP 321

Week 11

Overview

Lab 8-1 Solution

Tag Files

Custom Tags

Web Application Deployment

Lab 8-1 (“Servlets”) Solution

Tag Files

Allow creation of reusable content

Better than jsp:include and c:import– Don’t require adding request parameters to

pass information around

Easier to read than jsp:include or c:import

Tag Files<!-- Header.tag file - placed in WEB-INF/tags directory --><img src="images/Web-Services.jpg"><br>

<!-- Home.jsp --><%@ taglib prefix="myTags" tagDir="/WEB-INF/tags" %>

<html><body>

<!-- This used to be <jsp:include page="Header.jsp"/> --><myTags:Header/>

Welcome to our site.</body></head>

Passing Parameters<!-- The old way --><!-- Header.jsp file --><img src="images/Web-Services.jpg"><br><em><strong>${param.subTitle}</em></strong><br>

<!-- Main.jsp file --><html><body>

<jsp:include page="Header.jsp"> <jsp:param name="subTitle" value="We take the string out of SOAP." /></jsp:include>

<br>Contact us at: ${initParam.mainEmail}</body></html>

Passing Parameters<!-- The better way --><!-- Header.tag file --><%@ attribute name="subTitle" required="true" rtexprvalue="true" %>

<img src="images/Web-Services.jpg"><br><em><strong>${subTitle}</em></strong><br>

<!-- Main.jsp file --><html><body>

<!-- This is easier to read, and the parameters only have tag scope, too! -->

<myTags:Header subTitle="We take the string out of SOAP." />

<br>Contact us at: ${initParam.mainEmail}</body></html>

Passing Parameters<!-- Use jsp:doBody for long values --><!-- Header.tag file --><%@ tag body-content="tagdependent" %>

<img src="images/Web-Services.jpg"><br><em><strong><jsp:doBody></em></strong><br>

<!-- Main.jsp file --><html><body><myTags:Header> We take the sting out of SOAP. OK, so it's not Jini,<br> but we'll help you get through it with the least<br> frustration and hair loss.</myTags:Header>

<br>Contact us at: ${initParam.mainEmail}</body></html>

Finding Tag Files

The container looks for tag files in: WEB-INF/tags Subdirectories of WEB-INF/tags META-INF/tags in library JAR files Subdirectories of META-INF/tags in library

JAR files

If the tag file is in a JAR, there must be a TLD file for it!

Sharpen Your Pencil

What do you put in the Tag File to declare that the tag has one required attribute called title, that can use an EL expression as its value?

What do you put in the Tag File to declare that the tag must NOT have a body?

Draw a Tag File in each of the locations where the Container will look for Tag Files.

WEB-INF

classes foo

lib JAR META-INF

tags myTags

TLDstags moreTags

Sharpen Your Pencil

What do you put in the Tag File to declare that the tag has one required attribute called title, that can use an EL expression as its value?

<%@ attribute name=“title” required=“true” rtexprvalue=“true” %>

What do you put in the Tag File to declare that the tag must NOT have a body?

<%@ tag body-content=“empty” %>

Sharpen Your Pencil

Draw a Tag File in each of the locations where the Container will look for Tag Files.

WEB-INF

classes foo

lib JAR META-INF

tagsfoo.tag

myTags foo.tag

TLDs bar.tld

tagsmoreTags foo.tag

foo.tag

Custom Tag Handlers

Allow much more flexibility than Custom Tag Files

Written in Java

Come in two flavors Classic Simple (JSP 2.0 and above)

Creating a Simple Tag Handler

1. Write a class that extends SimpleTagSupport

2. Override the doTag() method

3. Create a TLD for the tag

4. Deploy the tag handler and TLD

5. Write a JSP that uses the tag

Simple Tag Handlerspublic class SimpleTagTest1 extends SimpleTagSupport { public void doTag() throws JspException, IOException { getJspContext().getOut().write("Lamest tag EVAR!"); }}

<tag> <!-- In TLD --> <description>worst use of a custom tag</description> <name>simple1</name> <tag-class>foo.SimpleTagTest1<tag-class> <body-content>empty</body-content></tag>

<!-- In JSP --><%@ taglib prefix="myTags" uri="simpleTags" %><html><body><myTags:simple1/></body></head>

Simple Tag Handlerspublic class SimpleTagTest2 extends SimpleTagSupport { public void doTag() throws JspException, IOException { getJspBody().invoke(null); }}

<tag> <!-- In TLD --> <description>slightly better use of a custom tag</description> <name>simple2</name> <tag-class>foo.SimpleTagTest2<tag-class> <body-content>scriptless</body-content></tag>

<!-- In JSP --><myTags:simple2> This is the body</myTags:simple2>

Tag Handler Lifecycle

1. Load and instantiate class

2. Call setJspContext(JspContext)3. If tag is nested, call

setParent(JspTag)4. If tag has attributes, call setters

5. If tag has a body, call setJspBody(JspFragment)

6. Call doTag()

Tags and Expressions<!-- In JSP --><myTags:simple3> <!-- What if message isn't defined yet? --> This is the message: ${message}</myTags:simple2>

public class SimpleTagTest3 extends SimpleTagSupport { public void doTag() throws JspException, IOException { getJspContext().setAttribute("message", "Wear sunscreen."); getJspBody().invoke(null); }}

Tags with Attributes<tag> <!-- In TLD --> <description>takes an attribute and iterates over body</description> <name>simple5</name> <tag-class>foo.SimpleTagTest5<tag-class> <body-content>scriptless</body-content> <attribute> <name>movieList</attribute> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute></tag>

Tags with Attributes<table> <myTags:simple5 movieList="${movieCollection}"> <tr> <td>${movie.name}</td> <td>${movie.genre}</td> </tr> </myTags:simple5></table>

public void setMovieList(List<Movie> movieList) { this.movieList = movieList; }

public void doTag() throws JspException, IOException { for(Movie movie : movieList) { getJspContext().setAttribute("movie", movie); getJspBody().invoke(null); }}

Sharpen Your Pencil

SkipPageException allows tag evaluation to be aborted without killing the rest of the page. What is the output of the tag below?

public void doTag() throws JspException, IOException { getJspContext().getOut().print("Message from within

doTag().<br>"); getJspContext().getOut().print("About to throw a

SkipPageException"); throw new SkipPageException();}

<%@ taglib prefix="myTags" uri="simpleTags" %><html><body>About to invoke a tag that throws SkipPageException <br><myTags:simply6/><br>Back in the page after invoking the tag.</body></html>

Sharpen Your Pencilpublic void doTag() throws JspException, IOException { getJspContext().getOut().print("Message from within doTag().<br>"); getJspContext().getOut().print("About to throw a SkipPageException"); throw new SkipPageException();}

<%@ taglib prefix="myTags" uri="simpleTags" %><html><body>About to invoke a tag that throws SkipPageException <br><myTags:simply6/><br>Back in the page after invoking the tag.</body></html>

Result:About to invoke a tag that throws SkipPageExceptionMessage from within doTag().About to throw a SkipPageException

Sharpen Your Pencilpublic void doTag() throws JspException, IOException { getJspContext().getOut().print("Message from within doTag().<br>"); getJspContext().getOut().print("About to throw a SkipPageException"); throw new SkipPageException();}

<html><body>This is page (A) that includes another page (B).<br>Doing the include now:<br><jsp:include page="badTagInclude.jsp" /><br>Back in page A after the include...</body></html>

<%@ taglib prefix="myTags" uri="simpleTags" %>This is page B that invokes the tag that throws SkipPageException.Invoking the tag now:<br><myTags:simply6/><br>Still in page B after the tag invocation…

Sharpen Your PencilOutput:

This is page (A) that includes another page (B).Doing the include now:

This is page B that invokes the tag that throws SkipPageException.Invoking the tag now:

Message from within doTag().About to throw a SkipPageException

Back in page A after the include…

Classic Tag Handlers<!-- No changes in JSP or TLD public class Classic1 extends TagSupport {

public int doStartTag() throws JspException { JspWriter out = pageContext.getOut();

try { out.println("classic tag output"); } catch(IOException e) { throw new JspException("IOException-" + e.toString()); }

return SKIP_BODY; }}

Classic Tag Handlers// Simple tag with a bodypublic class SimpleTag extends SimpleTagSupport { public void doTag() throws JspException, IOException { getJspContext().getOut().print("Before body."); getJspBody().invoke(null); getJspContext().getOut().print("After body."); }}

Classic Tag Handlerspublic int doStartTag() throws JspException { out = pageContext.getOut(); try { out.println("Before body."); } catch (IOException e) { throw new JspException("IOException-" + e.toString()); } return EVAL_BODY_INCLUDE;}

public int doEndTag() throws JspException { try { out.println("After body."); } catch (IOException e) { throw new JspException("IOException-" + e.toString()); } return EVAL_PAGE;}

Classic Tag Handlerspublic int doStartTag() throws JspException { out = pageContext.getOut(); try { out.println("Before body."); } catch (IOException e) { throw new JspException("IOException-" + e.toString()); } return EVAL_BODY_INCLUDE;}

public int doEndTag() throws JspException { try { out.println("After body."); } catch (IOException e) { throw new JspException("IOException-" + e.toString()); } return EVAL_PAGE;}

How can we make the tag body repeat?

Classic Tag Handlers

doStartTag()

Evaluate BODY

doAfterBody()

doEndTag()

Evaluate PAGE

Done

return EVAL_BODY_INCLUDE

return SKIP_BODYreturn EVAL_BODY_AGAIN

return SKIP_BODY

return EVAL_PAGE

return SKIP_PAGE

Sharpen Your Pencil// Write the classic tag handler that is the equivalent of this simple

handlerpublic void doTag() throws JspException, IOException { String [] movies = {"Spiderman", "Saved!", "Amelie"}; for (String movie : movies) { getJspContext().setAttribute("movie", movie); getJspBody().invoke(null); }}

public class MyIteratorTag extends TagSupport { public int doStartTag() throws JspException {} public int doAfterBody() throws JspException {} public int doEndTag() throws JspException {}}

Sharpen Your Pencilpublic class MyIteratorTag extends TagSupport { String [] movies = {"Spiderman", "Saved!", "Amelie"}; int movieCounter;

public int doStartTag() throws JspException { movieCounter = 0;

pageContext.setAttribute("movie", movies[movieCounter]); movieCounter++;

return EVAL_BODY_INCLUDE; }

Sharpen Your Pencil public int doAfterBody() throws JspException { if (movieCounter < movies.length) { pageContext.setAttribute("movie", movies[movieCounter]); movieCounter++; return EVAL_BODY_AGAIN; }

return SKIP_BODY; }

public int doEndTag() throws JspException { return EVAL_PAGE; }}

Dynamic Attributes<!-- remember our beer selection page? --><form method="POST" action="SelectBeer.do"> <p>Select beer color:</p> <select name="color" size="1"> <option value="light">light</option> ... </select> <input type="submit"></form>

<!-- We would like to do this instead --><form method="POST" action="SelectBeer.do"> <p>Select beer color:</p> <formTags:select name="color" size="1" optionsList="${applicationScope.colorList"/> <input type="submit"></form>

Dynamic Attributes

<select> supports the following attributes Core Attributes: id, class, style, title I18N Attributes: lang, dir Event Attributes: onclick, ondblclick, onmouseup, onmouseover, onmousemove, onmouseout, onkeypress, onkeyup, onkeydown

Form Attributes: name, disabled, multiple, size, tabindex, onfocus, onblur, onchange

Dynamic Attributespublic class SelectTagHandler extends SimpleTagSupport

implements DynamicAttributes { private String name; private List optionsList; private Map<String, Object> tagAttrs = new HashMap<String, Object>();

public void setName(String name) { this.name = name; } public void setOptionsList(List value) { this.optionsList = value; }

@Override public void setDynamicAttribute(String uri, String name, Object value)

throws JspException { tagAttrs.put(name, value); }

Dynamic Attributes public void doTag() throws JspException, IOException { JspWriter out = ((PageContext)getJspContext()).getOut();

out.print("<select "); out.print(String.format(ATTR, "name", name));

for(String attrName : tagAttrs.keySet()) { out.print(String.format(ATTR, attrName, tagAttrs.get(attrName))); }

out.println('>');

// Generate options from optionList here

out.println("</select>"); }

private static final String ATTR = "%s='%s' ";}

Dynamic Attributes<tag> <!-- In TLD --> <description>Builds select tag</description> <name>select</name> <tag-class>foo.SelectTagHandler<tag-class> <body-content>empty</body-content> <attribute> <name>name</attribute> <required>true</required> </attribute> <attribute> <name>optionsList</attribute> <type>java.util.List</type> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> <dynamic-attributes>true<dynamic-attributes></tag>

Deployment

MyApp

main.jsp

WEB-INF

web.xml

classes foo MyTag.class

lib my.jar

tags NavBar.tag

WAR Files

Pack your web application in one file

Allow library dependencies to be declared and checked at deployment time

Have the same structure as your webapp, except for adding META-INF/MANIFEST.MF

Accessing Static Content

Static HTML and JSPs can only be accessed if they are not inside WEB-INFThis allows pages to be hidden from direct access, but they can still be forwarded to or included in other pages

Servlet Mapping<web-app ...>

<servlet> <servlet-name>Beer</servlet-name> <servlet-class>com.example.BeerSelect</servlet-class> </servlet>

<servlet-mapping> <servlet-name>Beer</servlet-name> <!-- This has NOTHING to do with the actual layout of your files --> <url-pattern>/Beer/SelectBeer.do</url-pattern> </servlet-mapping>

</web-app>

Servlet Mapping - Three Types of url-pattern

Exact match: /Beer/SelectBeer.doDirectory match: /Beer/*Extension match: *.doContainer looks for matches in the above order

If more than one pattern matches, the longest (most-specific) is used

Welcome Files

A list of welcome files can be specified in the DD

When none of the servlet mappings match, the container looks for the specified files in order

<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>default.jsp</welcome-file></welcome-file-list>

Welcome Files - Example

1. Client requests www.wickedlysmart.com/MyTestApp/search

2. Container checks for a servlet mapping

3. Container checks for MyTestApp/search/index.html

4. Container checks for MyTestApp/search/default.jsp

Progress Check

Due this week: Exam 2