460 likes | 553 Views
COMP 321. Week 9. Overview. Lab 7-1 “Preparing to Build Web Applications” Solution Session Management Cookies JSP. Lab 7-1 Solution. Session Management. HTTP is stateless – each request from the client looks like a new conversation
E N D
COMP 321 Week 9
Overview • Lab 7-1 “Preparing to Build Web Applications” Solution • Session Management • Cookies • JSP
Session Management • HTTP is stateless – each request from the client looks like a new conversation • Web applications need to maintain state across pages (think of browsing Amazon and putting books in your shopping cart) • How can we do this?
Session Management (cont’d) • Stateful EJB • Works, but it’s complicated. Also, requires a full J2EE application server • Database • Also works, but could be slow and is overkill for many applications • HttpSession • This is a nice, lightweight solution. We assign an HttpSession object to each client connection, and use them to maintain conversational state
Session Management (cont’d) • Browser displays form - What type of beer do you like? • Diane submits page with response - dark • Container stores response in Diane’s session, returns another page with another question - What price range? • Diane answers question, submits second page with response • Container stores this answer in session, continues…
Session Management (cont’d) • How can the container remember which client is which? • IP Address? • This does not work because of NAT • HTTPS Security Context? • Would require HTTPS for each connection • Session ID • Container can send unique session ID to each client
Session Management (cont’d) • Cookies are used to store the session ID • Cookies are a name-value pair that the browser stores under a web domain • When subsequent requests are sent to the domain, the cookie data is included: HTTP/1.1 200 OK Set-Cookie: JSESSIONID=0AAB6C8DE415 ... POST /select/selectBeerTaste2.do HTTP/1.1 Host: www.wickedlysmart.com User-Agent: Mozilla/5.0 Cookie: JSESSIONID=0AAB6C8DE415
Session Management (cont’d) • How do we create a session in the servlet? Just ask for one. • How do we get the session object on a subsequent request? // Send a session cookie in the response HttpSession session = request.getSession(); // Get the session for this conversation HttpSession session = request.getSession();
URL Rewriting • Can be used to maintain session state without cookies • Works by appending session information to the end of every link: http://www.wickedlysmart.com/BeerTest.do;jsessionid=0AAB6C8DE415 • Must be done on every page in the application - no static HTML allowed • Must use response.encodeURL() for every URL in the generated pages
Session Expiration • Session times out • Timeout was set in deployment descriptor • Timeout was set by calling setMaxInactiveInterval() • invalidate() was called • Web application goes down
Why Use Cookies? • They survive longer than the session! // Create a new cookie, and return as part of response Cookie cookie = newCookie("username", name); cookie.setMaxAge(30*60); // 30 minutes response.addCookie(cookie); // On next request, find cookie Cookie[] cookies = request.getCookies(); for(Cookie cookie : cookies) { if(cookie.getName().equals("username")) { String username = cookie.getValue(); out.println("Hello, " + username); break; } }
Session Lifecycle Events • Lifecycle – HttpSessionListener • Session created • Session destroyed • Attributes – HttpSessionAttributeListener • Attribute added • Attribute replaced • Attribute removed • Migration – HttpSessionActivationListener • Session about to be passivated • Session has been activated
Session Migration • What happens to ServletContext, ServletConfig, and HttpSession in a clustered (distributed) environment? • Most parts of the web application are duplicated on each VM, but session objects are unique • When a session is needed on a specific VM, it is moved to that VM
Session Migration in Action • Request is sent to VM1, session #123 is created • Next request from same client goes to VM2, servlet asks for session #123 • VM2 sees that session 123 exists in VM1 • Session is passivated in VM1, moved to VM2, and activated there • Servlet execution in VM2 continues normally
Session Listener Example <web-app ...> <listener> <listener-class>com.example.BeerSessionCounter</listener-class> </listener> </web-app> publicclassBeerSessionCounterimplementsHttpSessionListener { staticprivateintactiveSessions; publicstaticintgetActiveSessions() { returnactiveSessions;} publicvoidsessionCreated(HttpSessionEvent event) { activeSessions++; } publicvoidsessionDestroyed(HttpSessionEvent event) { activeSessions--; } }
Attribute Listener Example // Deployment descriptor identical to session listener, except for class name publicclassBeerAttributeListener implementsHttpSessionAttributeListener{ publicvoidattributeAdded(HttpSessionBindingEvent event) { System.out.println("Attr added: " + event.getName() + ": " + event.getValue()); } publicvoidattributeRemoved(HttpSessionBindingEvent event) { System.out.println("Attr removed: " + event.getName() + ": " + event.getValue()); } publicvoidattributeReplaced(HttpSessionBindingEvent event) { System.out.println("Attr replaced: " + event.getName() + ": " + event.getValue()); } }
Attribute Class Events publicclass Dog implementsHttpSessionBindingListener, HttpSessionActivationListener, Serializable { publicvoidvalueBound(HttpSessionBindingEvent event) { // Run some code now that I'm in a session } publicvoidvalueUnbound(HttpSessionBindingEvent event) { // Run some code now that I'm not part of a session } publicvoidsessionWillPassivate(HttpSessionEvent event) { // Save my non-serializable fields somehow } publicvoidsessionDidActivate(HttpSessionEvent event) { // Restore whatever I did in sessionWillPassivate } }
JSP • Avoids ugly HTML embedded in Java code • Helps to separate presentation from implementation logic • Causes a servlet class to be generated and compiled automatically
A Simple JSP Example <html> <body> The page count is: <% out.println(Counter.getCount()); %> </body> </html> package foo; publicclassCounter { privatestaticintcount; publicstaticsynchronizedintgetCount() { count++; returncount; } }
A Simple JSP Example <html> <body> The page count is: <% out.println(Counter.getCount()); %> </body> </html> package foo; publicclassCounter { privatestaticintcount; publicstaticsynchronizedintgetCount() { count++; returncount; } } This causes an error! Why?
A Simple JSP Example <!-- We need to import the package Counter lives in... --> <%@ page import="foo.*" %> <html> <body> The page count is: <% <!-- ...or use a fully scoped name --> out.println(foo.Counter.getCount()); %> </body> </html>
A Simple JSP Example <!-- We need to import the package Counter lives in... --> <%@ page import="foo.*" %> <html> <body> The page count is: <% <!-- ...or use a fully scoped name --> out.println(foo.Counter.getCount()); %> </body> </html> But wait! I thought we were trying to eliminate all of the calls to println?
A Simple JSP Example <%@ page import="foo.*" %> <html> <body> The page count is: <%= Counter.getCount() %> <!-- Notice there's no ; up there --> </body> </html>
JSP Expressions • Which of these are valid? <%= 27 %> <%= ((Math.random() + 5) * 2); %> <%= “27” %> <%= Math.random() %> <%= String s = “foo” %> <%= new String[3] %> <% = 42 * 20 %> <%= 5 > 3 %> <%= false %> <%= new Counter() %>
JSP Expressions • Which of these are valid? <%= 27 %> <%= ((Math.random() + 5) * 2); %> Can’t have semicolon <%= “27” %> <%= Math.random() %> <%= String s = “foo” %> Can’t have variable declaration <%= new String[3] %> <% = 42 * 20 %> Can’t have space between the % and the = <%= 5 > 3 %> <%= false %> <%= new Counter() %>
A Simple JSP Example <%@ page import="foo.*" %> <html> <body> The page count is: <%= Counter.getCount() %> <!-- Notice there's no ; up there --> </body> </html> If this is creating a Java class, can't we get rid of Counter?
A Simple JSP Example <html> <body> <%intcount = 0; %> The page count is: <%= ++count %> </body> </html> Will this work? What code will be generated?
A Simple JSP Example <html> <body> <%intcount = 0; %> The page count is: <%= ++count %> </body> </html> publicvoid_jspService(HttpServletRequest request, HttpServletResponse response) throwsIOException, ServletException { PrintWriter out = response.getWriter(); response.setContentType("text/html"); out.write("<html><body>"); intcount = 0; out.write("The page count is now:"); out.print(++count); out.write("</body></html>"); }
A Simple JSP Example <html> <body> <%!intcount = 0; %> The page count is: <%= ++count %> </body> </html>
A Simple JSP Example <html> <body> <%!intcount = 0; %> The page count is: <%= ++count %> </body> </html> intcount = 0; publicvoid_jspService(HttpServletRequest request, HttpServletResponse response) throwsIOException, ServletException { PrintWriter out = response.getWriter(); response.setContentType("text/html"); out.write("<html><body>"); out.write("The page count is now:"); out.print(++count); out.write("</body></html>"); }
Implicit Objects • JspWriter out • HttpServletRequest request • HttpServletResponse response • HttpSession session • ServletContext application • ServletConfig config • Throwable exception • PageContext page context • Object page
Be the Container <!-- What output is produced? --> <html><body> Test scriptlets... <%inty = 5 + x; %> <%intx = 2; %> </body></html>
Be the Container <!-- What output is produced? --> <html><body> Test scriptlets... <%inty = 5 + x; %> <%intx = 2; %> </body></html> Compile Error!
Be the Container <!-- What output is produced? --> <%@ page import="java.util.*" %> <html><body> Test scriptlets... <% ArrayList list = newArrayList(); list.add("foo"); %> <%= list.get(0) %> </body></html>
Be the Container <!-- What output is produced? --> <%@ page import="java.util.*" %> <html><body> Test scriptlets... <% ArrayList list = newArrayList(); list.add("foo"); %> <%= list.get(0) %> </body></html> Test scriptlets... foo
Be the Container <!-- What output is produced? --> <html><body> Test scriptlets... <%!intx = 42; %> <%intx = 22; %> <%= x %> </body></html>
Be the Container <!-- What output is produced? --> <html><body> Test scriptlets... <%!intx = 42; %> <%intx = 22; %> <%= x %> </body></html> Test scriptlets... 22
JSP Comments <!-- HTML comment --> This is included in the HTML sent to the browser, and then ignored. <%-- JSP comment --%> This is ignored by the compiler, and never makes it into the servlet class.
Generated Servlet API • jspInit() – called from the servlet's init() method. Can be overridden. • jspDestroy() – called from the servlet's destroy() method. Can be overridden. • _jspService() – called from the servlet's service() method. Can't be overridden.
JSP Lifecycle • JSP is deployed in a web app • Container reads DD, but doesn’t do anything yet • Client requests JSP • Container translates JSP to a servlet, compiles it, and loads the servlet • Servlet instance is created, and jspInit() is executed • Container creates thread to handle request, and calls _jspService() method. • The rest of the request is handled like an ordinary servlet request
JSP Attributes • Application application.setAttribute("foo", barObj); • Request request.setAttribute("foo", barObj); • Session session.setAttribute("foo", barObj); • Page pageContext.setAttribute("foo", barObj);
JSP Attributes <!-- PageContext can be used to get/set attributes for all scopes --> <!-- Get page-scoped attribute --> <%= pageContext.getAttribute("foo") %> <!-- Get request-scoped attribute --> <%= pageContext.getAttribute("foo", PageContext.REQUEST_SCOPE) %> <!-- Get session-scoped attribute --> <%= pageContext.getAttribute("foo", PageContext.SESSION_SCOPE) %> <!-- Get an application-scoped attribute --> <%= pageContext.getAttribute("foo", PageContext.APPLICATION_SCOPE) %> <!-- Find an attribute in most-specific scope --> <%= pageContext.findAttribute("foo") %>
Eliminating Java in JSPs • This is the ultimate goal – presentation and implementation should be completely separate • Allows designers to edit JSPs without fear of breaking things, and vice versa
EL Sneak Preview <!-- Instead of... --> Please contact: <%= application.getAttribute("mail") %> <!-- ...we use --> Please contact: ${applicationScope.mail} <!– We can disable scripting elements in the DD: --> <web-app ...> ... <jsp-config> <jsp-property-group> <url-pattern>*.jsp</url-pattern> <scripting-invalid>true</scripting-invalid> </jsp-property-group> </jsp-config> ... </web-app>
Progress Check • Due next week: • Lab 8-1 Servlets