Transcript Slide 1

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
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)
1. Browser displays form - What type of beer do
2.
3.
4.
5.
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.
// Send a session cookie in the response
HttpSession session = request.getSession();
How do we get the session object on a
subsequent request?
// 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 = new Cookie("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>
public class BeerSessionCounter implements HttpSessionListener {
static private int activeSessions;
public static int getActiveSessions() { return activeSessions; }
public void sessionCreated(HttpSessionEvent event) {
activeSessions++;
}
public void sessionDestroyed(HttpSessionEvent event) {
activeSessions--;
}
}
Attribute Listener Example
// Deployment descriptor identical to session listener, except for class name
public class BeerAttributeListener implements HttpSessionAttributeListener{
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("Attr added: " + event.getName() + ": " +
event.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("Attr removed: " + event.getName() + ": " +
event.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("Attr replaced: " + event.getName() + ": " +
event.getValue());
}
}
Attribute Class Events
public class Dog implements HttpSessionBindingListener,
HttpSessionActivationListener, Serializable {
public void valueBound(HttpSessionBindingEvent event) {
// Run some code now that I'm in a session
}
public void valueUnbound(HttpSessionBindingEvent event) {
// Run some code now that I'm not part of a session
}
public void sessionWillPassivate(HttpSessionEvent event) {
// Save my non-serializable fields somehow
}
public void sessionDidActivate(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;
public class Counter {
private static int count;
public static synchronized int getCount() {
count++;
return count;
}
}
A Simple JSP Example
<html>
<body>
The page count is:
<%
out.println(Counter.getCount());
%>
This causes
</body>
</html>
an error! Why?
package foo;
public class Counter {
private static int count;
public static synchronized int getCount() {
count++;
return count;
}
}
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());
%>
But wait! I thought we were trying
</body>
eliminate all of the calls to println?
</html>
to
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>
If this is creating
</html>
a Java class,
can't we get rid of Counter?
A Simple JSP Example
<html>
<body>
<% int count = 0; %>
The page count is:
<%= ++count %>
</body>
Will this
</html>
work? What code will
be generated?
A Simple JSP Example
<html>
<body>
<% int count = 0; %>
The page count is:
<%= ++count %>
</body>
</html>
public void _jspService(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
PrintWriter out = response.getWriter();
response.setContentType("text/html");
out.write("<html><body>");
int count = 0;
out.write("The page count is now:");
out.print(++count);
out.write("</body></html>");
}
A Simple JSP Example
<html>
<body>
<%! int count = 0; %>
The page count is:
<%= ++count %>
</body>
</html>
A Simple JSP Example
<html>
<body>
<%! int count = 0; %>
The page count is:
<%= ++count %>
</body>
</html>
int count = 0;
public void _jspService(HttpServletRequest request,
HttpServletResponse response) throws IOException, 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
HttpServletRequest
HttpServletResponse
HttpSession
ServletContext
ServletConfig
Throwable
PageContext
Object
out
request
response
session
application
config
exception
page context
page
Be the Container
<!-- What output is produced? -->
<html><body>
Test scriptlets...
<% int y = 5 + x; %>
<% int x = 2; %>
</body></html>
Be the Container
<!-- What output is produced? -->
<html><body>
Test scriptlets...
<% int y = 5 + x; %>
<% int x = 2; %>
</body></html>
Compile Error!
Be the Container
<!-- What output is produced? -->
<%@ page import="java.util.*" %>
<html><body>
Test scriptlets...
<% ArrayList list = new ArrayList();
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 = new ArrayList();
list.add("foo");
%>
<%= list.get(0) %>
</body></html>
Test scriptlets... foo
Be the Container
<!-- What output is produced? -->
<html><body>
Test scriptlets...
<%! int x = 42; %>
<% int x = 22; %>
<%= x %>
</body></html>
Be the Container
<!-- What output is produced? -->
<html><body>
Test scriptlets...
<%! int x = 42; %>
<% int x = 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
1. JSP is deployed in a web app
2. Container reads DD, but doesn’t do anything yet
3. Client requests JSP
4. Container translates JSP to a servlet, compiles it, and
loads the servlet
5. Servlet instance is created, and jspInit() is executed
6. Container creates thread to handle request, and calls
_jspService() method.
7. 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