Internet Technologies 9 - Servlets and JavaBeans
- F. Ricci
Internet Technologies 9 - Servlets and JavaBeans F. Ricci - - PowerPoint PPT Presentation
Internet Technologies 9 - Servlets and JavaBeans F. Ricci 2010/2011 Content p Implementing session tracking from scratch p The session-tracking API p Storing immutable objects vs. storing mutable objects p Examples of usage of the
p Implementing session tracking from scratch p The session-tracking API p Storing immutable objects vs. storing mutable objects p Examples of usage of the session-tracking API p Understanding the benefits of beans p Creating beans p Installing bean classes on your server p Accessing bean properties p Explicitly setting bean properties p Automatically setting bean properties from request
p Sharing beans among multiple servlets and JSP pages
Most of the slides were made available by www. coreservlets.com
p Idea: associate cookie with data on server
p Still to be done: n Extracting cookie that stores session identifier n Setting appropriate expiration time for cookie n Associating the hash tables with each request n Generating the unique session identifiers
p Idea n Client appends some extra data on the end of each
n Server associates that identifier with data it has
n E.g., http://host/path/file.html;jsessionid=1234 p Advantage n Works even if cookies are disabled or unsupported p Disadvantages n Must encode all URLs that refer to your own site n All pages must be dynamically generated n Fails for bookmarks and links from other sites.
p Idea:
p Advantage n Works even if cookies are disabled or
p Disadvantages n Lots of tedious processing n All pages must be the result of form
p Session objects live on the server p Sessions automatically associated with client via cookies
p Use request.getSession() to get session n Behind the scenes, the system looks at cookie or URL
n If so, it returns that stored session object n If not, it creates a new one, assigns a cookie or URL
p Hashtable-like mechanism lets you store arbitrary
n setAttribute(name, value) stores values n getAttribute(name) retrieves values
p Access the session object n Call request.getSession to get HttpSession object
p This is a hashtable associated with the user
p Store information in a session n Use setAttribute with a key (String) and a value
p Look up information associated with a session n Call getAttribute on the HttpSession object, cast
p Discard session data n Call removeAttribute discards a specific value n Call invalidate to discard an entire session.
HttpSession session = request.getSession(); SomeClass value = (SomeClass)session.getAttribute("credentials"); if (value == null) { value = new SomeClass(...); session.setAttribute("credentials", value); } doSomethingWith(value);
n Do not need to call setAttribute again (after
n But, if value is immutable (e.g. a String object),
p Session tracking code: No change p Code that generates hypertext links back to same
n Pass URL through response.encodeURL()
p If server is using cookies, this returns URL
p If server is using URL rewriting, this appends the
p E.g.:
p Code that does sendRedirect to own site: n Pass URL through response.encodeRedirectURL()
p getAttribute n Extracts a previously stored value from a session
p setAttribute n Associates a value with a name n If you want to monitor changes: value must implement
p removeAttribute n Removes values associated with name p getAttributeNames n Returns names of all attributes in the session p getId n Returns the unique identifier.
p isNew n Determines if session is new to client (e.g. the
p getCreationTime n Returns time at which session was first created p getLastAccessedTime n Returns time at which session was last sent from
p getMaxInactiveInterval,setMaxInactiveInterval n Gets or sets the amount of time session should go
p invalidate n Invalidates current session.
public class ShowSession extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); HttpSession session = request.getSession(); String heading; Integer accessCount = (Integer)session.getAttribute("accessCount"); if (accessCount == null) { accessCount = new Integer(0); heading = "Welcome, Newcomer"; } else { heading = "Welcome Back"; accessCount = new Integer(accessCount.intValue() + 1); } session.setAttribute("accessCount", accessCount);
call Must be an
an int)
PrintWriter out = response.getWriter(); …
(docType + "<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<CENTER>\n" + "<H1>" + heading + "</H1>\n" + "<H2>Information on Your Session:</H2>\n" + "<TABLE BORDER=1>\n" + "<TR BGCOLOR=\"#FFAD00\">\n" + " <TH>Info Type<TH>Value\n" + … " <TD>Number of Previous Accesses\n" + " <TD>" + accessCount + "\n" + "</TABLE>\n" + "</CENTER></BODY></HTML>");
session.getId() new Date (session.getCreat ionTime()) new Date (session.getLastAcc essedTime())
call
public class ShowItems extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); ArrayList previousItems = (ArrayList)session.getAttribute("previousItems"); if (previousItems == null) { previousItems = new ArrayList(); session.setAttribute("previousItems", previousItems); } String newItem = request.getParameter("newItem"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); String title = "Items Purchased"; String docType = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n";
"<HTML>\n" + "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n" + "<BODY BGCOLOR=\"#FDF5E6\">\n" + "<H1>" + title + "</H1>"); synchronized(previousItems) { if (newItem != null) { previousItems.add(newItem); } if (previousItems.size() == 0) {
} else {
for(int i=0; i<previousItems.size(); i++) {
}
} }
} }
call call
p This servlet displays three forms n Two ("update order" submit) call again the same servlet
n The third call the checkout page (not displayed here)
p Session tracking code stays the same as in simple
p Shopping cart is an attribute of the session object p Shopping cart class is relatively complex n Identifies items by a unique catalog ID n Does not repeat items in the cart
p Instead, each entry has a count associated
p If count reaches zero, item is deleted from
p Pages built automatically from objects that have
p Some servers support distributed Web applications n Load balancing used to send different requests to
p Some servers support persistent sessions n Session data written to disk and reloaded when server is
p Tomcat 5 and 6 support this
p To support both, session data should implement the
n There are no methods in this interface; it is just a flag:
... }
n Builtin classes like String and ArrayList are already
p Scripting elements calling servlet code
p Scripting elements calling servlet code
p Beans p Servlet/JSP combo (MVC) p MVC with JSP expression language p Custom tags p MVC with beans, custom tags, and a
p Java classes that follow certain conventions: n Must have a zero-argument (empty) constructor
p You can satisfy this requirement either by explicitly
p Not required if no JSP creates instances
n Should have no public instance variables (fields)
p You should follow this practice and use accessor
n Persistent values should be accessed through methods
p If class has method getTitle that returns a String,
p Boolean properties use isXxx instead of getXxx.
p jsp:useBean - in the simplest case, this element
p jsp:setProperty - this element modifies a bean
p jsp:getProperty - this element reads and outputs
p User submits form that refers to a JSP page
p JSP page instantiates a bean
p The JSP page passes some request data to the
p The JSP page outputs some value(s) derived from
package coreservlets; public class StringBean { private String message = "No message specified"; public String getMessage() { return(message); } public void setMessage(String message) { this.message = message; } }
p Beans installed in normal Java directory n Let the IDE to decide where to create n Deployment: WEB-INF/classes/
p Beans must always be in packages!
<jsp:useBean id="stringBean" class="coreservlets.StringBean" /> <OL> <LI>Initial value (from jsp:getProperty): <I><jsp:getProperty name="stringBean" property="message" /></I> <LI>Initial value (from JSP expression): <I><%= stringBean.getMessage() %></I> <LI><jsp:setProperty name="stringBean" property="message" value="Best string bean: Fortex" /> Value after setting property with jsp:setProperty: <I><jsp:getProperty name="stringBean" property="message" /></I> <LI><% stringBean.setMessage ("My favorite: Kentucky Wonder"); %> Value after setting property with scriptlet: <I><%= stringBean.getMessage() %></I> </OL>
call
p To be a bean, you cannot have public fields p So, you should replace public double speed; p with private double speed; public double getSpeed() { return(speed); } public void setSpeed(double newSpeed) { speed = newSpeed; } p You should do this in all your Java code anyhow.
p You can put constraints on values:
p You can change your internal representation without
p You can perform arbitrary side effects
p If users of your class accessed the fields
p Too much work and runs huge risk of having
<!DOCTYPE ...> ... <jsp:useBean id="entry" class="coreservlets.SaleEntry" /> <%-- setItemID expects a String --%> <jsp:setProperty name="entry" property="itemID" value='<%= request.getParameter("itemID") %>' />
p Here we have used a JSP expression for the value
p JSP attribute values must be fixed strings but for the value
p Single quote is used because double quote is used in the
<% int numItemsOrdered = 1; try { numItemsOrdered = Integer.parseInt(request.getParameter("numItems")); } catch(NumberFormatException nfe) {} %>
<jsp:setProperty name="entry" property="numItems" value="<%= numItemsOrdered %>" />
<% double discountCode = 1.0; try { String discountString = request.getParameter("discountCode"); discountCode = Double.parseDouble(discountString); } catch(NumberFormatException nfe) {} %>
<jsp:setProperty name="entry" property="discountCode" value="<%= discountCode %>" />
SaleEntry1.jsp SaleEntry1-Form.jsp Bean SaleEntry.java Reading parameters and creating a bean with property values equal to the parameters. Displaying the bean property values. call
p Use the param attribute of jsp:setProperty to
n Value should come from specified request
n Simple automatic type conversion from the
p boolean, Boolean, byte, Byte, char,
<jsp:useBean id="entry" class="coreservlets.SaleEntry" /> <jsp:setProperty name="entry" property="itemID" param="itemID" /> <jsp:setProperty name="entry" property="numItems" param="numItems" /> <jsp:setProperty name="entry" property="discountCode" param="discountCode" />
SaleEntry2.jsp
p Use "*" for the value of the property attribute of
n Value should come from request parameter whose
n Simple automatic type conversion should be
<jsp:useBean id="entry" class="coreservlets.SaleEntry" /> <jsp:setProperty name="entry" property="*" />
p This is extremely convenient for making "form
SaleEntry3.jsp
p No action is taken when an input parameter
p Automatic type conversion does not guard
p Bean property names and request
p Up to now the beans we created are bound to local
p You can use the scope attribute to specify additional
n <jsp:useBean id="…" class="…"
p Lets multiple servlets or JSP pages share data p Also permits conditional bean creation n Creates new object only if it can't find existing one
n Only if it has not been created by another JSP or
Values: page, request, session, application.
p page1.jsp
p page2.jsp
p Possible scenario 1 n Joe goes to page 2: output is n Jane goes to page 1: output is p Possible scenario 2 n Joe goes to page 1: output is n Jane goes to page 2: output is
p Page: <jsp:useBean … scope="page"/> or
n Default value: bean object is placed in the
n Methods in the generated servlet can access the
p Application: <jsp:useBean … scope="application"/> n Bean will be stored in ServletContext - available
n ServletContext is shared by all servlets in the
p Session: <jsp:useBean … scope="session"/> n Bean will be stored in the HttpSession object
p Request: <jsp:useBean … scope="request"/> n Bean object should be placed in the
n Do not miss getAttribute with getParameter,
package coreservlets; public class BakedBean { private String level = "half-baked"; //default value private String goesWith = "hot dogs"; //default value public String getLevel() { return(level); } public void setLevel(String newLevel) { level = newLevel; } public String getGoesWith() { return(goesWith); } public void setGoesWith(String dish) { goesWith = dish; } } BakedBean.java
p Create the bean n Use jsp:useBean with scope="page" (or no
p Modify the bean n Use jsp:setProperty with property="*" n This will supply request parameters that match
p Access the bean n Use jsp:getProperty
… <BODY> <H1>Baked Bean Values: page-based Sharing</H1> <jsp:useBean id="pageBean" class="coreservlets.BakedBean" /> <jsp:setProperty name="pageBean" property="*" /> <H2>Bean level: <jsp:getProperty name="pageBean" property="level" /> </H2> <H2>Dish bean goes with: <jsp:getProperty name="pageBean" property="goesWith" /> </H2> </BODY></HTML> BakedBeanDisplay-page.jsp No scope attribute page scope is default
p A parameter is passed to the JSP: goesWith=fish call
p A second call without passing a parameter p The value of the bean property goesWith, set in
call
p Create the bean n Use jsp:useBean with scope="request" p Modify the bean n Use jsp:setProperty with property="*" n When calling the JSP supply request parameters
p Access the bean in the 1st (main) page n Use jsp:getProperty n Use jsp:include (action not the directive) to
p Access the bean in the 2nd (included) page n Use jsp:useBean with the same id as in the first
n Then, use jsp:getProperty.
… <BODY> <H1>Baked Bean Values: request-based Sharing</H1> <jsp:useBean id="requestBean" class="coreservlets.BakedBean" scope="request" /> <jsp:setProperty name="requestBean" property="*" /> <H2>Bean level: <jsp:getProperty name="requestBean" property="level" /></H2> <H2>Dish bean goes with: <jsp:getProperty name="requestBean" property="goesWith" /></H2> <jsp:include page="BakedBeanDisplay-snippet.jsp" /> </BODY></HTML> BakedBeanDisplay-request.jsp
<H1>Repeated Baked Bean Values: request-based Sharing</H1> <jsp:useBean id="requestBean" class="coreservlets.BakedBean" scope="request" /> <H2>Bean level: <jsp:getProperty name="requestBean" property="level" /> </H2> <H2>Dish bean goes with: <jsp:getProperty name="requestBean" property="goesWith" /> </H2> BakedBeanDisplay-snippet.jsp
p The property goesWith, set to fish in the main
call
p Code
<jsp:include page="/fragments/StandardHeading.jsp"> <jsp:param name="bgColor" value="YELLOW" /> </jsp:include>
p Requested URL n http://host/path/MainPage.jsp?fgColor=RED p Main page n fgColor: RED n bgColor: null
p Regardless of whether you check before or after
p Included page n fgColor: RED n bgColor: YELLOW
p Create the bean n Use jsp:useBean with scope="session" p Modify the bean n Use jsp:setProperty with property="*" n Then, supply request parameters that match the bean
p Access the bean in the initial request n Use jsp:getProperty in the request in which
p Access the bean later n Use jsp:getProperty in a request that does not include
n If this request is from the same client the previously
… <BODY> <H1>Baked Bean Values: session-based Sharing</H1> <jsp:useBean id="sessionBean" class="coreservlets.BakedBean" scope="session" /> <jsp:setProperty name="sessionBean" property="*" /> <H2>Bean level: <jsp:getProperty name="sessionBean" property="level" /> </H2> <H2>Dish bean goes with: <jsp:getProperty name="sessionBean" property="goesWith" /> </H2></BODY></HTML> BakedBeanDisplay-session.jsp
p In the initial request we pass a parameter
call
p In a second request we do not pass the
call
p Create the bean n Use jsp:useBean with scope="application" p Modify the bean n Use jsp:setProperty with property="*" n Then, supply request parameters that match the bean
p Access the bean in the initial request n Use jsp:getProperty in the request in which
p Access the bean later n Use jsp:getProperty in a request that does not include
n Whether this request is from the same client or a
<BODY> <H1>Baked Bean Values: application-based Sharing</H1> <jsp:useBean id="applicationBean" class="coreservlets.BakedBean" scope="application" /> <jsp:setProperty name="applicationBean" property="*" /> <H2>Bean level: <jsp:getProperty name="applicationBean" property="level" /> </H2> <H2>Dish bean goes with: <jsp:getProperty name="applicationBean" property="goesWith"/> </H2></BODY></HTML> BakedBeanDisplay-application.jsp
call
p Bean conditionally created n jsp:useBean results in new bean being
n If a bean with same id and scope is found, the
p Bean properties conditionally set n <jsp:useBean ... />
n The statements (jsp:setProperty elements) are