490 likes | 658 Views
COMP 321. Week 10. Overview. Using Beans in JSP Expression Language JSTL Lab 10-1 Introduction Exam Review. Accessing Attributes. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
E N D
COMP 321 Week 10
Overview • Using Beans in JSP • Expression Language • JSTL • Lab 10-1 Introduction • Exam Review
Accessing Attributes protectedvoiddoPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException { String name = request.getParameter("userName"); request.setAttribute("name", name); RequestDispatcher view = request.getRequestDispatcher("/result.jsp"); view.forward(request, response); } <html><body> Hello <%= request.getAttribute("name") %> </body> </html>
Accessing Attributes // What if the attribute is an object? foo.Person p = newfoo.Person(); p.setName("Evan"); request.setAttribute("person", p); RequestDispatcher view = request.getRequestDispatcher("/result.jsp"); view.forward(request, response); <body> <% foo.Person p = (foo.Person) request.getAttribute("person"); %> Person is: <%= p.getName() %> Person is: <%= ((foo.Person) request.getAttribute("person")).getName() %> </body>
Accessing Attributes // What if the attribute is an object? foo.Person p = newfoo.Person(); p.setName("Evan"); request.setAttribute("person", p); RequestDispatcher view = request.getRequestDispatcher("/result.jsp"); view.forward(request, response); <body> <% foo.Person p = (foo.Person) request.getAttribute("person"); %> Person is: <%= p.getName() %> Person is: <%= ((foo.Person) request.getAttribute("person")).getName() %> </body>
Accessing Attributes <!-- Using scripting--> <body> <% foo.Person p = (foo.Person) request.getAttribute("person"); %> Person is: <%= p.getName() %> </body> <!-- Using standard actions --> <body> <jsp:useBean id="person" class="foo.Person" scope="request" /> Person is: <jsp:getProperty name="person" property="name" /> </body> <!-- jsp:useBean will create a new bean if it's not found --> <!-- Use jsp:setProperty to initialize this default bean --> <jsp:useBean id="person" class="foo.Person" scope="page"> <jsp:setProperty name="person" property="name" value="Fred" /> </jsp:useBean>
Accessing Attributes // What if we want to use polymorphism? publicabstractclassPerson { public void setName(String name) { ... } public String getName() { ... } } public classEmployee extendsPerson { public void setEmpID(int id) { ... } public int getEmpID() { ... } } <!-- This won't work. Why not? --> <jsp:useBean id="person" class="foo.Person" scope="page"> <jsp:setProperty name="person" property="name" value="Fred" /> </jsp:useBean>
Accessing Attributes // What if we want to use polymorphism? publicabstractclassPerson { ... } public classEmployee extendsPerson { ... } <jsp:useBean id="person" type="foo.Person" class="foo.Employee" scope="page"> <jsp:setProperty name="person" property="name" value="Fred" /> </jsp:useBean> // Generated code foo.Person person = null; // Code to get person attribute if (person == null) { person = newfoo.Employee(); ... } <!– We can use type without class, as long as the bean already exists --> <jsp:useBean id="person" type="foo.Person" scope="page" />
HTML -> JSP <!-- The form can send the request directly to the JSP --> <form action="TestBean.jsp"> name: <input type="text" name="userName"> ID#: <input type="text" name="userID"> <input type="submit"> </form> <!-- We can get to the parameter using scripting... --> <jsp:useBean id="person" type="foo.Person" class="foo.Employee" /> <% person.setName(request.getParameter("userName")); %> <!-- ...or we can use param --> <jsp:useBean id="person" type="foo.Person" class="foo.Employee" /> <jsp:setProperty name="person" property="name" param="userName" /> </jsp:useBean>
HTML -> JSP <!-- We can do better if the form field name matches the bean attribute --> <form action="TestBean.jsp"> name: <input type="text" name="name"> ID#: <input type="text" name="empID"> <input type="submit"> </form> <!-- Now we don't specify any value --> <jsp:useBean id="person" type="foo.Person" class="foo.Employee" /> <jsp:setProperty name="person" property="name" /> </jsp:useBean> <!-- If all of the fields match, we can set them all at once, and type --> <!-- conversions happen automatically. Notice that type is now Employee, --> <!-- so that EmpID can be found. --> <jsp:useBean id="person" type="foo.Employee" class="foo.Employee" /> <jsp:setProperty name="person" property="*" /> </jsp:useBean>
EL Expressions • Follow the format ${First.Second} or ${First[Second]} • First is either an implicit object or an attribute • Second is a key, member, index, or expression
EL Expressions - Implicit Objects • Maps • pageScope, requestScope, sessionScope, applicationScope • param, paramValues • header, headerValues • cookie • initParam • pageContext – the page context object
EL Expressions <!-- The dot operator is used to access properties or map values --> <!-- Get the name property from the person attribute in some scope --> ${person.name} <!-- The [] operator is used to access properties, map values, or --> <!-- List/array elements --> ${person["name"]} String [] myMusic = { "Zero 7", "Tahiti 80", "BT" }; request.setAttribute("musicList", myMusic); <!-- prints "Zero 7" --> ${musicList[0]} <!-- "1" is coerced to an int, so this prints "Tahiti 80" --> ${musicList["1"]}
EL Expressions <!-- For beans and maps, either operator works --> Map musicMap = new HashMap(); musicMap.put("Ambient", "Zero 7"); request.setAttribute("musicMap", musicMap); <!-- Both of these evaluate to "Zero 7" --> ${musicMap.Ambient} ${musicMap["Ambient"]} <!-- If the argument isn't a string literal, it's evaluated --> <!-- This doesn't work --> ${musicMap[Ambient]} request.setAttribute("Genre", "Ambient"); <!-- Now this evaluates to ${musicList["Ambient"]}, which --> <!-- evaluates to "Zero 7" --> ${musicList[Genre]}
EL Expressions <!-- Accessing request parameters --> ${param.userName} <!-- Accessing multi-valued request parameters --> ${paramValues.food[0]} ${paramValues.food[1]} <!-- Accessing request headers --> ${header.host} <!-- Accessing request object properties --> ${pageContext.request.method}
EL Expressions <!-- Specifying scope --> ${requestScope.person.name} <!-- Accessing attribute without legal Java name --> ${requestScope["foo.person"].name} <!-- Accessing cookies --> ${cookie.userName.value} <!-- Accessing context init parameters --> ${initParam.mainEmail}
EL Functions • Can be used to call static methods in Java classes: • Write a Java class with a static method • Create a Tag Library Descriptor (TLD) file • Add a taglib directive to your JSP • Use EL to call the function
EL Functions classDiceRoller { publicstaticintrollDice() { return(int)((Math.random() * 6) + 1); } } <!-- In TLD file--> <uri>DiceFunctions</uri> <function> <name>rollIt</name> <function-class>foo.DiceRoller</function-class> <function-signature>int rollDice()</function-signature> </function> <!-- In JSP --> <%@ taglib prefix="mine" uri="DiceFunctions"%> <html><body> ${mine:rollit()}
JSP Include Directive <!-- Header.jsp --> <img src="images/Web-Services.jpg"/><br> <em><string>We know how to make SOAP suck less.</strong></em><br> <!-- Contact.jsp --> <html><body> <%@ include file="Header.jsp" %> <br> <em>We can help.</em><br><br> Contact us at: ${initParam.mainEmail} </body></html> • Equivalent to pasting the header into Contact.jsp • Position-dependent • Takes place once at translation time
JSP Include Action <!-- Header.jsp --> <img src="images/Web-Services.jpg"/><br> <em><string>${param.subTitle}</strong></em><br> <!-- Contact.jsp --> <html><body> <jsp:includepage="Header.jsp" <jsp:paramname="subTitle"value="We know how to make SOAP suck less."/> </jsp:include> <em>We can help.</em><br><br> Contact us at: ${initParam.mainEmail} </body></html> • Request and response are forwarded to included JSP • Takes place at execution time • Happens once per request • jsp:param can be used to pass parameters
Code Magnets publicclassToy { privateString name; // Getters/setters } publicclassPerson { privateDog dog; privateString name; // Getters/setters } publicclassDog { privateString name; privateToy[] toys; // Getters/setters }
Code Magnets Person p = newPerson("Leelu"); Dog d = newDog("Clyde"); Toy t1 = newToy("stick"); Toy t2 = newToy("neighbor's cat"); Toy t3 = newToy("Barbie doll head"); d.setToys(newToy[]{t1, t2, t3}); p.setDog(d); request.setAttribute("person", p); Desired output: Leelu's dog Clyde's toys are: stick, neighbor's cat, and a Barbie doll head
Code Magnets Person p = newPerson("Leelu"); Dog d = newDog("Clyde"); Toy t1 = newToy("stick"); Toy t2 = newToy("neighbor's cat"); Toy t3 = newToy("Barbie doll head"); d.setToys(newToy[]{t1, t2, t3}); p.setDog(d); request.setAttribute("person", p); Desired output: Leelu's dog Clyde's toys are: stick, neighbor's cat, and a Barbie doll head EL: ${person.name}'s dog ${person.dog.name}'s toys are: ${person.dog.toys[0].name}, ${person.dog.toys[1].name}, and a ${person.dog.toys[2].name}
Sharpen Your Pencil request.setAttribute("num", "2"); request.setAttribute("integer", newInteger(3)); ArrayList list = newArrayList(); list.add("true"); list.add("false"); list.add("2"); list.add("10"); request.setAttribute("list", list); What prints for each of these? ${num > 3} ${integer le 12} ${requestScope["integer"] ne 4 and 6 le num || false} ${list[0] || list["1"] and true} ${num > integer} ${num == integer - 1} ${42 div 0}
Sharpen Your Pencil request.setAttribute("num", "2"); request.setAttribute("integer", newInteger(3)); ArrayList list = newArrayList(); list.add("true"); list.add("false"); list.add("2"); list.add("10"); request.setAttribute("list", list); What prints for each of these? ${num > 3} false ${integer le 12} true ${requestScope["integer"] ne 4 and 6 le num || false} false ${list[0] || list["1"] and true} true ${num > integer} false ${num == integer - 1} true ${42 div 0} Infinity
JSTL <div class="tipBox"> <b>Tip of the day:</b><br/><br/> ${pageContent.currentTip} </div> <!-- If currentTip="<b></b> tags make things bold", we have a problem --> <div class="tipBox"> <b>Tip of the day:</b><br/><br/> <b></b> tags make things bold </div> <!-- We actually wanted this... --> <div class="tipBox"> <b>Tip of the day:</b><br/><br/> <b></b> tags make things bold </div>
JSTL <!-- We can use c:out to escape the XML special characters --> <div class="tipBox"> <b>Tip of the day:</b><br/><br/> <c:outvalue="${pageContent.currentTip}" /> </div> <!-- The c:out prints what we wanted originally --> <b></b> tags make things bold <!-- We can also use c:out to provide default values --> Hello, <c:outvalue="${user}" default="guest"/> Hello, <c:outvalue="${user}">guest</c:out>
JSTL Looping <!-- Using scripting --> <table> <% String [] items = (String[])request.getAttribute("movieList"); String var = null; for(int i = 0; i < items.length; i++) { var = items[i]; %> <tr><td><%= var %></td></tr> <% } %> </table> <!-- Using JSTL --> <table> <c:forEachvar="movie"items="${movieList}" > <tr><td>${movie}</td></tr> </c:forEach> </table>
JSTL Conditionals <c:iftest="${userType eq 'member' }" > <jsp:include page="inputComments.jsp"/> </c:if> <c:choose> <c:whentest="${userPref == 'performance' }"> Now you can stop even if you drive insanely fast. </c:when> <c:whentest="${userPref == 'safety' }"> Our brakes won't lock up, no matter how badly you drive. </c:when> <c:otherwise> Our brakes are the best. </c:otherwise> </c:choose>
JSTL <!-- c:set var sets attribute variables --> <c:setvar="userLevel"scope="session"value="Cowboy"/> <c:setvar="Fido"value="${person.dog }"/> <c:setvar="userLevel"scope="session">Sheriff, Bartender, Cowgirl</c:set> <!-- c:set target sets bean properties, or Map values --> <!-- The target expression must evaluate to the actual object --> <c:settarget="${PetMap}" property="dogName"value="Clover"/> <c:settarget="${person}" property="name"> ${foo.name} </c:set> <!-- c:set will remove attributes if the value is null, but it's better--> <!-- to use c:remove --> <c:remove var="userStatus"scope="request"/>
JSTL <!-- c:import - another way to include content from another source --> <!-- c:import can include resources that live outside the web app --> <c:import url="http://wickedlysmart.com/skyler/horse.html" /> <!-- c:import can pass values to the included resource --> <c:import url="Header.jsp"> <c:param name="subTitle" value="We take the sting out of SOAP." /> </c:import> <!-- The included file --> <em><strong>${param.subTitle}</strong></em>
JSTL <!-- c:url - handles URL rewriting from a JSP --> <a href="<c:url value='/inputComments.jsp' />">Click here</a> <!-- We can use var to remember the URL for later--> <c:setvar="last"value="Hidden Cursor"/> <c:setvar="first"value="Crouching Pixels"/> <c:urlvalue="/inputComments.jsp?first=${first}&last=${last}" var="inputURL"/> The URL using params is: ${inputURL} <br>
JSTL <!-- c:url - handles URL rewriting from a JSP --> <a href="<c:url value='/inputComments.jsp' />">Click here</a> <!-- We can use var to remember the URL for later--> <c:setvar="last"value="Hidden Cursor"/> <c:setvar="first"value="Crouching Pixels"/> <c:urlvalue="/inputComments.jsp?first=${first}&last=${last}" var="inputURL"/> The URL using params is: ${inputURL} <br> What's wrong with the URL above?
JSTL <!-- c:url - handles URL rewriting from a JSP --> <a href="<c:url value='/inputComments.jsp' />">Click here</a> <!-- We can use var to remember the URL for later--> <c:setvar="last"value="Hidden Cursor"/> <c:setvar="first"value="Crouching Pixels"/> <c:urlvalue="/inputComments.jsp?first=${first}&last=${last}" var="inputURL"/> The URL using params is: ${inputURL} <br> What's wrong with the URL above? We should be encoding the parameters!
JSTL <!-- c:url - handles URL rewriting from a JSP --> <a href="<c:url value='/inputComments.jsp'/>">Click here</a> <!-- We can use var to remember the URL for later--> <c:setvar="last"value="Hidden Cursor"/> <c:setvar="first"value="Crouching Pixels"/> <c:urlvalue="/inputComments.jsp"var="inputURL"/> <c:paramname="firstName" value="${first}"/> <c:paramname="lastName" value="${last}"/> </c:url/> The URL using params is: ${inputURL} <br>
Error Pages <!-- The error page - displayed when an exception occurs --> <%@ page isErrorPage="true" %> <html><body> <strong>Bummer.</strong><br> You caused a ${pageContext.exception} on the server.<br> <imgsrc="images/bummerGuy.jpg"/> </body></html> <!-- The page that has an error --> <%@pageerrorPage="errorPage.jsp"%> <html><body> About to be bad... <%intx = 10/0; %> </body></html>
Error Pages and the DD <!-- Declaring a catch-all error page --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/errorPage.jsp</location> </error-page> <!-- Declaring an exception-specific error page --> <error-page> <exception-type>java.lang.ArithmeticException</exception-type> <location>/arithmeticError.jsp</location> </error-page> <!-- Declaring an error page based on an HTTP status code --> <error-page> <error-code>404</error-code> <location>/notFoundError.jsp</location> </error-page>
Handling Exceptions in a JSP <!-- c:catch can be used to catch an exception within the page --> <html><body> About to do a risky thing... <br> <c:catch> <%intx = 10 / 0; %> </c:catch> If you see this, we survived. </body></html>
Handling Exceptions in a JSP <!-- The var attribute can be used to get the exception object --> <html><body> About to do a risky thing... <br> <c:catch var="myException"> <%intx = 10 / 0; %> </c:catch> <c:iftest="${myException != null}"> There was an exception: ${myException.message} <br> </c:if> If you see this, we survived. </body></html>
Deciphering the TLD <?xml version="1.0" encoding="ISO-8859-1" ?> <taglib xmlns=…> <tlibversion>1.2</tlibversion> <shortname>RandomTags</shortname> <!-- Used by tools--> <uri>randomThings</uri> <!-- used in the taglib directive --> <tag> <description>random advice</description> <name>advice</name> <!-- used in the JSP - <my:advice> --> <tag-class>foo.AdvisorTagHandler</tag-class> <body-content>empty</body-content> <attribute> <name>user</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <!-- Can be a runtime expression --> </attribute> </tag>
Using a Custom Tag <%@ taglib prefix="mine" uri="randomThings" %> Advisor Page<br> <mine:adviceuser="${userName}" /> publicclass AdvisorTagHandler extendsSimpleTagSupport { privateString user; publicvoidsetUser(String user) { this.user = user; } publicvoiddoTag() throwsJspException, IOException { getJspContext().getOut().write("Hello " + user + " <br>"); getJspContext().getOut().write("Your advice is: " + getAdvice()); } privateString getAdvice() { // Code to give advice here } }
Finding the TLD • Since JSP 2.0, the container finds TLDs for you in: • WEB-INF and its subdirectories • Inside JAR files in the lib directory - in the META-INF directory and its subdirectories • <!-- The old (pre-JSP 2.0) way is to use the DD --> • <web-app> • ... • <jsp-config> • <taglib> • <taglib-uri>randomThings</taglib-uri> • <taglib-location>/WEB-INF/myFunctions.tld</taglib-location> • </taglib> • </jsp-config> • </web-app>
Learning Activity – Music Search • Implement MusicSearch servlet using model class • Implement SearchResults.jsp using scripting • Implement SearchResults2.jsp without scripting
Progress Check • Due this week: • Lab 8-1 Servlets • Due next week: • Exam 2