1 servlets & jsps, part 2: persistency & contexts – everything you ever wanted to know but...

69
1 Servlets & JSPs, Servlets & JSPs, Part 2: Part 2: Persistency & Persistency & Contexts – Contexts – Everything Everything you ever wanted to know you ever wanted to know but were afraid to ask but were afraid to ask

Post on 22-Dec-2015

225 views

Category:

Documents


1 download

TRANSCRIPT

1

Servlets & JSPs, Part 2:Servlets & JSPs, Part 2:Persistency & Contexts –Persistency & Contexts –

Everything you ever wanted to know Everything you ever wanted to know but were afraid to askbut were afraid to ask

2

The Servlet ContextThe Servlet Context

Read more about the ServletContext Interface

3

The Servlet Context ObjectThe Servlet Context Object

• A Servlet context represents the Web application in which Servlets live.

• There is a single ServletContext per Web-app.

• You can get the Servlet context from within doXXX using the method getServletContext().

• In JSPs there’s no need to call this method - it’s already stored in a variable called application.

• Different Servlets in the same web-app will get the same ServletContext object, when calling getServletContext() (also during different sessions – discussed later).

4

Uses of ServletContextUses of ServletContext• Communicating with the Servlet container (e.g., Apache

Tomcat)

• Stores Web application initialization parameters.

• Stores and can be used to manipulate application-shared attributes (objects that are kept throughout the application's life).

• Can be used to access the logger.

• Can be used to dispatch requests to other resources

• The context can be locked (using synchronize) to protect a critical section from all Web-application accesses.

5

ServletContext MethodsServletContext Methods• Access initialization parameters:

getInitParameter(String name), getInitParameterNames()

• Read Web-application scoped attributes:getAttribute(String name), getAttributeNames()

• Manipulate Web-application scoped attributes:setAttribute(String, Object), removeAttribute(String)

• Transform context-relative paths to absolute paths and vice versa:getRealPath(String path), URL getResource(String path)

e.g. get the servlet’s class filename

from its mapping

Run http://localhost/dbi/context.htmlJNDI = Java Naming and Directory Interface

e.g. get the URL from a static resource

(doesn’t work well with

servlet-mappings)

6

More ServletContext MethodsMore ServletContext Methods

• Write to the application log:

log(String msg), log(String message, Throwable exception)

• Get a request dispatcher (discussed later): RequestDispatcher getRequestDispatcher(String path)

• Name and version of the Servlet container: String getServerInfo()

Also writes the stack trace

$CATALINA_BASE/logs/…

7

An Example: Service CountAn Example: Service Count

public class CounterServlet extends HttpServlet { public void init() throws ServletException { Integer counter = (Integer) getServletContext().getAttribute("counter"); if (counter == null) { getServletContext().setAttribute("counter",new Integer(0)); }}

We cannot use int since

an attribute must not

be a primitive

The counter may already be initialized, if the server is running

but the instance of CounterServlet was removed from the

memory (or if another Servlet already created it).

In this case we wouldn’t like to reinitialize the counter with 0.

8

public void doGet(HttpServletRequest req,HttpServletResponse res) throws ServletException, IOException {

PrintWriter out = res.getWriter(); res.setContentType("text/html"); int counter = 0; synchronized(this) { counter = ((Integer)getServletContext(). getAttribute("counter")).intValue(); getServletContext(). setAttribute("counter",new Integer(++counter)); } out.println("<html><head><title>Counter</title><body><h1>" + "[" + counter + "]</h1></body></html>");}}

The character encoding of the

response cannot be set after

the writer was created

A new Integer must

be created since

the value of an

Integer cannot be

modified (why?)

9

Context ListenersContext Listeners

• A context listener is an object that reacts to the following events:- Context initialization

- Context destruction

• We can use a context listener to perform application initialization or termination tasks

• To implement such a listener,- Implement the interface ServletContextListener- Put the class file in myApp/WEB-INF/classes like all the other

classes

- Register the listener with the server

Read more about the ServletContextListener Interface

10

Cheating with Service CountCheating with Service Countpublic class CounterInitializer implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { sce.getServletContext(). setAttribute("counter",new Integer(1000)); }

public void contextDestroyed(ServletContextEvent sce) {}} <web-app>

<listener> <listener-class>CounterInitializer</listener-class> </listener></web-app>

Uncomment the listener lines in web.xml or use web2.xml

For whoever needs a reminder, web.xml was

discussed in depth in the Tomcat lecture

11

Servlets and CookiesServlets and Cookies

12

CookiesCookies

• Cookies are a general mechanism that server-side applications can use to both store and retrieve long-term information on the client side

• Servers send cookies in the HTTP response and browsers are expected to save and to send the cookie back to the Server, whenever they make additional requests to the Server

13

• Java Servlet API provides comfortable mechanisms to handle cookies

• The class javax.servlet.http.Cookie represents a cookie

- Getter methods:

• getName(), getValue(), getPath(), getDomain(), getMaxAge(), getSecure()…

- Setter methods:

• setValue(), setPath(), setDomain(), setMaxAge()…

The domain to which the cookie

is attached

Servlets and Cookies APIServlets and Cookies API

Kind of expiration

date

The path (prefix) to which

the cookie is attached

Send cookies on secure

connections only or

on any connection

Read more about the Cookie Class

14

Servlets and Cookies API (cont)Servlets and Cookies API (cont)

• Get the cookies from the servlet request:

Cookie[] HttpServletRequest.getCookies()

• Add a cookie to the servlet response:

HttpServletResponse.addCookie(Cookie cookie)

15

An ExampleAn Example

<html>

<head><title>Insert your Name</title></head>

<body> <h1>What is your name?</h1>

<form action="welcomeback" method="get">

<p>

<input type="text" name="username" />

<input type="submit" />

</p>

</form>

</body>

</html>

getname.html

16

An Example (cont)An Example (cont)

public class WelcomeBack extends HttpServlet {

public void doGet(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

String user = req.getParameter("username");

if (user == null) { // Find the "username" cookie

Cookie[] cookies = req.getCookies();

for (int i = 0; cookies != null && i < cookies.length; ++i) {

if (cookies[i].getName().equals("username"))

user = cookies[i].getValue();

}

} else res.addCookie(new Cookie("username", user));

WelcomeBack.java

Look for “username”

cookie

If “user” parameter was sent, create a

“username” cookie

Look for

“username”

parameter in the

query

17

An Example (cont)An Example (cont)

if (user == null) // No parameter and no cookie

res.sendRedirect("getname.html");

res.setContentType("text/html");

PrintWriter out = res.getWriter();

out.println("<html><body><h1>Welcome Back " + user

+ "</h1></body></html>");

}

} WelcomeBack.java

Run /dbi/welcomeback twice or more.Check the sent headers

Delay setting the

ContentType until it’s

clear that a content

should be sent at all

18

Session Management with Session Management with ServletsServlets

19

Sessions – A ReminderSessions – A Reminder• HTTP is stateless• But some web applications need states (e.g. online

stores)• A session captures the notion of a continuous interaction

between a server and a client• Session management should be efficient

- The client should not send the whole shopping cart every time a single product is added (Once upon a time There was a shopping site which saved the entire cart, including prices and discounts in a cookie – why is this really really bad?)

• We’ll discuss 2 mechanisms- Session Cookies- URL rewriting

20

Session CookiesSession Cookies

Web browser 1

Web server

request request

ServletServlet

id1

response

put cookie id1

response

Create Session

id1

The cookie contains the session-ID: a unique (sometimes random) identifier

assigned by the Servlet container. This is an example for something called

an opaque identifier (coat-checks, typically implemented in C with void*

are another very different example worth knowing). Why is it a good

strategy to “store” the session data using an opaque identifier on the client?

21

Session CookiesSession Cookies

Web browser 2

Web server

request request

ServletServlet

id1

response

put cookie id2

response

Create Session

id2id2

22

Session CookiesSession Cookies

Web server

request

ServletServlet

id1

response response

request

Cookie: id1

id2

Session read/write

Web browser 1

id1

23

Session CookiesSession Cookies

Web server

request

ServletServlet

id1

response response

request

Cookie: id2

id2

Session read/write

Web browser 2

id2

24

sessionId list

The lists are kept on

the server side

The cookies are kept

on the client side

25

Here’s an example that demonstrates the session is attached to a specific application:

1. Two new applications are available – test1, test2

2. Read the code of /test1/test1.jsp

3. Read the code of /test2/test2.jsp

4. Run /test1/test1.jsp, and use the links to go to the other application’s JSP and back several time.Notice that 2 session-cookies are set by the server, one for every application.

5. Invalidate any of the application’s session and notice that the other application is still valid

A Session is attached to an ApplicationA Session is attached to an Application

26

Accessing the Session DataAccessing the Session Data

• The session object is represented by the class HttpSession.

• Use the methods HttpServletRequest.getSesssion() or HttpServletRequest.getSesssion(true) within doXXX to get the current HttpSession object, or to create one if it doesn’t exist. In JSP simply access the object session (we’ll learn later how to tell a JSP not to create a session).- Only when a new session is created, the server automatically

add a session cookie to the response (set-cookie header)- As a result you must call this method before the response is

committed (don’t worry, JSP calls it before your code runs).

• Use HttpServletRequest.getSesssion(false) if you do not want to create a new session when no session exists.

27

HttpSession MethodsHttpSession Methods• Session data is accessed in a hash-table fashion:

- setAttribute(String name,Object value)

- Where is this value stored? (server-side or client-side)

- Object getAttribute(String name)

• More methods:

- getId()

- removeAttribute()

- Enumeration getAttributeName()

- isNew()

- getCreationTime(),

getLastAccessedTime()

True iff there’s an active session

which the client hasn’t joined yet.

That is:

• The server created a session and

sent session-cookie

• This session timeout was not

reached,

• No response from the client

containing this session-cookie

was received

The session-id

discussed earlier

Read more about the HttpSession Interface

28

Session Expiration – Client sideSession Expiration – Client side• Session may expire because of client-side reasons

- The client agent runs on another process (was restarted)

- Session cookie has expired (exceeded max-age)

- Client used external links (writing the URL explicitly in the address-bar) instead of the server’s rewritten ones

Unless the session-cookie has max-age and you manage to open another

browser before max-age expired.

For example open http://localhost/dbi/session?timeout=100&reload=

50&maxage=20

Close your browser and open a new one with this URL again…

We’ll discuss the code in few more slides

Applies to URL-Rewriting (discussed soon). If the client uses cookies,

external links should raise no problem. (The session-cookie will be

sent, though only to URLs under the path like always…)

29

Session Expiration – Server sideSession Expiration – Server side• Server calls session.invalidate()

- User asked to logout

• Session idle time has passed

- You can also set/get the timeout of a specific session

and override the server default values using session.getMaxInactiveInterval(),

session.setMaxInactiveInterval()

<web-app> <session-config>

<session-timeout>10</session-timeout> </session-config></web-app>

web.xml

Timeout is given in

minutes.

A zero or negative value

means infinite timeout

webapps/myApp/WEB-INF/web.xml

30

Session Expiration ExampleSession Expiration Examplepublic class SessionTester extends HttpServlet {

private int nReloads = 1;

public void doGet(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

int timeout = Integer.parseInt(request.getParameter("timeout"));

int refresh = Integer.parseInt(request.getParameter("reload"));

int maxage =

Integer.parseInt(request.getParameter("maxage"));

HttpSession session = request.getSession();

SessionTester.java

#Reloads (#GET request) with the

same session

Either find an existing session (in this case the client already accepted its

session-cookie which was sent in a previous response and sent it back in

the current request), OR create a new session and send a session cookie

Read request

paramters

31

if (session.isNew()) {

session.setMaxInactiveInterval(timeout);

nReloads = 1;

Cookie newCookie = new Cookie("JSESSIONID", session.getId());

newCookie.setMaxAge(maxage);

newCookie.setPath(request.getContextPath());

response.reset();

response.addCookie(newCookie);

} else { ++nReloads; }

response.setContentType("text/html");

PrintWriter out = response.getWriter();

Date found = (Date)session.getAttribute("lastdate");

Date now = new Date();

Reset counter

Search for “lastdate” in the session. This

attribute value is the session’s creation date

Only if a new session was created

Delete the headers

containing the old

cookie and add the

new cookie

Advance the counter

Set server-side limits on

session

Create a new cookie

identical to the old one

and set client-side

limits on the session

using the max-age

32

out.println("<html><head><title>Session Tester</title>");

out.println("<meta http-equiv=\"refresh\" content=\""

+ refresh + "\"/></head>\n");

out.println("<body>");

Cookie[] cookies = request.getCookies();

for (int i = 0; cookies != null && i < cookies.length; ++i) {

out.println("<h2>Client sent cookie : " + cookies[i].getName()

+ " = " + cookies[i].getValue() + "</h2>\n");

}

if ((cookies == null) || (cookies.length) == 0) {

out.println("<h2>Client sent no cookies</h2>\n");}

Set the refresh rate

Print the request cookies

Or print that there are no cookies…

33

if (session.isNew()) {

out.println("<h2>(New) Session ID = " + session.getId() + "</h2>\n");}

else { out.println("<h2>Session ID = " + session.getId() + "</h2>\n");}

out.println("<h2>Session max inactive interval = " +

session.getMaxInactiveInterval() + "</h2>\n");

out.println("<h2>Current date = " + now + "</h2>\n");

if (found == null) {session.setAttribute("lastdate", now);

out.println("<h2>No lastdate found in session<h2>\

n");}

else {out.println("<h2>Found in session lastdate = " + found + "<h2>\n");}

out.println("<h2>#Responses with this session = " + nReloads + "</h2>\n");

out.println("</body></html>"); }

Set the new

session’s

creation date

Print the session ID and declare if it’s a new one

34

Running the exampleRunning the example1. Run http://localhost/dbi/session.html

with timeout=10, reload=5, max-age=20.notice that the set-cookie isn’t sent in the response unless a new session is created

2. Rerun with timeout=20, reload=5, max-age=10

3. Now deny to the servlet cookies modification request.Check the sent request headers, notice that in the next reload the server will ask again to set the session-cookie with a new session ID

4. Run http://localhost/dbi/session?timeout=100&reload=50&maxage=100Run http://127.0.0.1/dbi/session?timeout=100&reload=50&maxage=100notice that a new session is created since the HOST string is different even tough 127.0.0.1 is the IP of localhost

5. Run http://localhost/dbi/session2?timeout=100&reload=5This is a similar code without the explicit new cookie creation and max-age feature.Deny to save the session-cookie and notice that you’ll be asked to save a session-cookie after every reloadConclude that the call getSession() itself creates a new set-cookie header if no session was accepted by the user, and not the header manipulation code in which purpose is to set the max-age cookie property

If the client denies, it will not

send this cookie back with

future requests

35

Example: A Basic Shopping CartExample: A Basic Shopping Cart

• In the following example a basic shopping cart for an online store is implemented

• The application consists of two Servlets:- Store.java: the main store site

- ShoppingCart.java: handles cart manipulation

36

Online-Store ExampleOnline-Store Example

public class Store extends HttpServlet {

public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

res.setContentType("text/html");

PrintWriter out = res.getWriter();

out.println("<html><head>"

+ "<link rel=\"stylesheet\" type=\"text/css\""

+ " href=\"cartstyle.css\"/></head><body>");

HttpSession session = req.getSession();

if (session.getAttribute("item-list") == null) {

out.println("<h1>Hello new visitor!</h1>");

session.setAttribute("item-list", new LinkedList());

}

List itemList = (List) session.getAttribute("item-list");

Store.java

37

Online-Store Example (cont)Online-Store Example (cont)

out.println("<h2>Your Shopping Cart:</h2><ol>");

for (Iterator it = itemList.iterator(); it.hasNext();)

out.println("<li>" + it.next() + "</li>");

out.println("</ol>");

out.println("<form method=\"post\" action=\"cart\">");

out.println("<p>Add item:<input name=\"item\" type=\"text\"/>"

+ "<input type=\"submit\" value=\"send\"/></p>"

+ "<p><input type=\"submit\" value=\"empty cart\" "

+ "name=\"clear\"/></p></form>");

out.println("</body></html>");

}

} Store.java

2 buttons of type submit and

therefore they are named

(the 2nd one) , so the

servlet can identify which

one was pressed

38

Online-Store Example (cont)Online-Store Example (cont)

public class ShoppingCart extends HttpServlet {

public void doPost(HttpServletRequest req, HttpServletResponse

res) throws ServletException, IOException {

res.setContentType("text/html");

PrintWriter out = res.getWriter();

List items = (List) req.getSession().getAttribute("item-list");

out.println("<html><head><link rel=\"stylesheet\""

+ " type=\"text/css\" href=\"cartstyle.css\"/>"

+ "</head><body>");

ShoppingCart.java

39

Online-Store Example (cont)Online-Store Example (cont)

if (req.getParameter("clear") != null) {

items.clear();

out.println("<h2>Your Shopping Cart is Empty!</h2>");

} else {

String item = req.getParameter("item");

items.add(item);

out.println("<h2>The item <i>" + item +

"</i> was added to your cart.</h2>");

}

out.println("<h2><a href=\"store\">Return to the store</a></h2>");

out.println("</body></html>");

}} ShoppingCart.java

40

URL RewritingURL Rewriting• Cookies might cause some security risk

- Would you really like any server to put files claimed to be “cookies” on you computer ?

- A computer is being used by multiple users• User A buys some products• User B comes right after user A finished working• Cookies are kept as local files• User B can read the private content of A’s cookies

• Solution 1- Use session cookies instead of other cookies so that B can

only read the session ID- But B can still read the domain and the path (e.g., and

discover that A visited adult sites or divorce lawyers sites)

• Solution 2- Use URL-rewriting (user A still better clean her history…)

41

URL RewritingURL Rewriting

Web browser

Web server

request request

ServletServlet

id1

response response

Create Session

<HTML…>

< A HREF=“servletURL;sessID=id1>”

/<…HTML>

The domain and path are not sent with

the rewritten URLs, since the

session-ID is attached to the URL

only as long as the user follows inner

links. If the user writes a complete

URL in the address-bar, she will

probably won’t copy the session-ID

part (or it will have expired)

42

URL RewritingURL Rewriting

Web server

request

ServletServlet

id1

response response

request

)no cookie(

id2

Session read/write

Web browser 1

GET servletURL;sessID=id1 HTTP/1.0

<HTML…>

<A HREF=“servletURL2;sessID=id1>”

/<…HTML>

43

Servlet URL RewritingServlet URL Rewriting

• Use the following methods of the doXXX response object to rewrite URLs:- String HttpServletResponse.encodeURL(String url)

• Use for HTML hyperlinks

- String HttpServletResponse.encodeRedirectURL(String url)• Use for HTTP redirections

• These methods contain the logic to determine whether the session ID needs to be encoded in the URL

• For example, if the request has a session cookie, then url is returned unchanged

• Some servers implement the two methods identically

44

Back to our StoreBack to our Store• The Store example assumes that the client supports cookies

• To fix the program, we should encode the links we supply:• Store.java:

"<form method=\"post\" action=\"" + res.encodeURL("cart") + "\">"

• ShoppingCart.java: “<a href=\"" + res.encodeURL("store") + "\">"

Clear the cookies, run again http://localhost/dbi/store, and this time deny saving cookies.

How does the server know before the client denies/accepts what to put in the href?

First understand the problem and try to think how you would solve it.

Now check the first item’s URL sent to /cart and compare to the other items. You could also compare the source of /store at the 1st access and on subsequent accesses

45

The Session ListenerThe Session Listener

• The session listener reacts to the following events:- A new session has been created

- A session is being destroyed

• To obtain a session listener, implement the interface javax.servlet.http.HttpSessionListener

Read more about the HttpSessionListener Interface

Right now you should be experiencing a strong feeling of déjà

vu, as we’ve already met ContextListeners that react in a

similar way to the events of context creation / destruction…

46

Session-Listener Example (cont)Session-Listener Example (cont)

public class CartInitializer implements HttpSessionListener {

public void sessionCreated(HttpSessionEvent se) {

List itemList = new LinkedList();

se.getSession().setAttribute("item-list",itemList);

itemList.add("A Free Apple");

}

public void sessionDestroyed(HttpSessionEvent se) {}

} CartInitializer.java

<listener>

<listener-class>CartInitializer</listener-class>

</listener> web.xml

Run again http://localhost/dbi/store, only this time uncomment the listener

47

Variables in JSP Variables in JSP

48

Implicit ObjectsImplicit Objects

• As seen before, some useful variables, like request and session are predefined

• These variables are called implicit objects

• Implicit objects are part of the JSP specifications

• Implicit objects are defined in the scope of the service method- Can these be used in JSP Declarations? (what would

you expect their to be within a declaration?)- What about redefinitions within JSP Scriptlets?Check the result of : no-redefinition, redefinition within a Declaration, redefrinition within a Scriptlet

49

The objectsThe objects request request and and responseresponse

• request and response are the HttpServletRequest and HttpServletResponse arguments of the service method

• Using these objects, you can:

• Read request parameters

• Set response headers

• etc. (everything we learned and will learn in Servlet lectures)

Read more about HttpServletRequest Interface, HttpServletResponce Interface

50

The objectThe object out out

• This is the Writer used to write output into the response body

• This object implements the interface JspWriter that combines the functionality of PrintWriter and BufferedWriter

• Recall that you can adjust the buffer size, or turn buffering off, through use of the buffer attribute of the page directive

Read more about JspWriter Class

51

The objectThe object pageContext pageContext• pageContext is a new object introduced by JSP

• This object stores all important elements used by the

generated Servlet, like the application context, the session,

the output writer, etc.

• It enables vendors to extend their JSP implementation

- E.g. Apache could extend the PageContext class so it’ll store some

additional application context, extend HttpJspBase

class so that the new PageContext could be obtained …

• This object is also used to store page-scoped attributes

(e.g., Java Beans - discussed later)

• This object is a field of Apache’s HttpJspBase classRead more about PageContext Class

52

The objectThe object session session• This is the HttpSession object associated with the

request

• If the session attribute in the page directive is turned off (<%@ page session="false" %>) then this object is not available (use this if you do not want to always automatically create a session or want to create the session yourself – try to find examples for scenarios which require this).

• Otherwise (by default) a session is created.

Read more about HttpSession Interface

Check the result of using a session after defining “no session”

53

The objectThe object config config

• This is the ServletConfig of the page, as received in the init() method

• Reminder: contains Servlet specific initialization parameters

• Later, we will study how initialization parameters are passed to JSP pages

• Recall that you can also obtain the ServletContext from config as explained in the next slide…

Read more about ServletConfig Interface

54

The objectThe object application application

• This is the ServletContext as obtained via

getServletConfig().getContext()

• Reminder from about an hour ago:

- The ServletContext is shared by all Servlets belonging to the

same Web-application (including those generated from JSP)

- Getting and setting attributes is accomplished using

getAttribute and setAttribute of ServletContext

- You can use this object to get application-wide initialization

parameters

Read more about ServletContext Interface

55

Page Scope VariablesPage Scope Variables

• service() local variables

• pageContext attributes

client 1

client 2

a.jsp

b.jsp

i.e. objects defined within Scriptlets

i.e. objects set using pageContext.setAttribute()

The JSPs reside in the same application in the following

examples

The values of these variables are only retained for the

single execution of one JSP in

response to one client.

56

Request ScopeRequest Scope

• request attributes

client 1

client 2

a.jsp

b.jsp

client 1

client 2

a.jsp

b.jsp

A simple scenario

A more complex scenario in which the request is

forwarded to another JSP

57

Session ScopeSession Scope

• session attributes

client 1

client 2

a.jsp

b.jsp

Many JSPs (which belong to the same

application) have the same session

attributes when responding to the

same single Client

i,e. set with session.setAttribute()

Run http://localhost/test1/test1.jspConclude that there is a different session for every application.

58

Servlet ScopeServlet Scope

• Servlet members

client 1

client 2

a.jsp

b.jsp

i.e. defined within Declarations.

The data members of a single JSP

have the same values for all clients since there’s only a

single instance of the

generated Servlet sub-

class

59

Application ScopeApplication Scope

• application attributes

client 1

client 2

a.jsp

b.jsp

i.e. defined using application.setAttribute()

Possibly many JSPs to many Clients

60

Servlet Package and Helper ClassesServlet Package and Helper Classes

• The generated Servlet has a named package

• In Tomcat, this package is: org.apache.jsp

• In Java, you cannot use classes from the default package (i.e. with no package declaration) from a named package!

• Therefore, helper classes used by JSP pages must have a named package

For example, classes which are imported using the page directive

61

The Request DispatcherThe Request Dispatcher

62

The Request DispatcherThe Request Dispatcher

• The RequestDispatcher object is used to send a client request to any (other) resource on the server

• Such a resource may be dynamic (e.g. a Servlet or a JSP file) or static (e.g. an HTML document)

• To send a request to a resource x, use:getServletContext().getRequestDispatcher("x")

Path must begin with a “/” and is interpreted as relative to

the current context root (web application directory)

63

Request Dispatcher MethodsRequest Dispatcher Methods

• void forward(ServletRequest request,

ServletResponse response)

- Forwards a request from a Servlet to another resource (do

not write to the contents if calling this)

• void include(ServletRequest request,

ServletResponse response)

- Includes the content of a resource in the response of the

current servlet (may write to the contents before or after)

Read more about the RequestDispatcher Interface

64

Passing on DataPassing on Data

• 3 different ways to “pass data” to (that is, make data available to) the Servlet or JSP to which the request is forwarded:

- Data that will be used only for this request:

request.setAttribute("key", value);

- Data will be used for this client (also for future requests):

session.setAttribute("key", value);

- Data that will be used in the future for every client:

context.setAttribute("key", value);

65

An ExampleAn Example

• The Servlet JokesAndImages enables a user to choose a random joke or a random image

• The server has 5 images in the directory images/ and 5 jokes (txt files) in the directory jokes/

• Empty requests are forwarded to an HTML file that enables the user to choose a joke or an image

• Requests to a joke are forwarded to the servlet Jokes

• Requests to an image are forwarded to a random image from the directory images/

66

Jokes and ImagesJokes and Images

<html>

<head><title>Images and Jokes</title></head>

<body>

<h1>Please Select:</h1>

<form method="post" action="JokesAndImages">

<h2>

<input type="submit" name="joke"

value="A Joke" />

<input type="submit" name="image"

value="An Image" />

</h2>

</form>

</body></html> imagesJokesOptions.html

67

Jokes and Images (cont)Jokes and Images (cont)

public class JokesAndImages extends HttpServlet {

public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

int randomNum = 1 + Math.abs((new Random()).nextInt() % 5);

if (req.getParameter("joke") != null) {

req.setAttribute("jokeNumber", new Integer(randomNum));

getServletContext().getRequestDispatcher("/Jokes").forward(req,res);

} else if (req.getParameter("image") != null) {

getServletContext().getRequestDispatcher("/images/image" +

randomNum + ".gif").forward(req, res);

} else getServletContext().getRequestDispatcher

("/imagesJokesOptions.html"). forward(req,res);

}

public void doGet ... }} JokesAndImages.java

68

Jokes and Images (cont)Jokes and Images (cont)public class Jokes extends HttpServlet {

public void doPost(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

res.setContentType("text/html"); PrintWriter out = res.getWriter();

out.println("<html><body><h1>A Joke</h1><pre>");

int jokeNum = ((Integer) req.getAttribute("jokeNumber")).intValue();

getServletContext().getRequestDispatcher

("/jokes/joke" + jokeNum + ".txt").include(req, res);

out.println("\n</pre>");

out.println("<a href=\"" + req.getRequestURL() + "\">Back</a>");

out.println("</body></html>");

}}

Jokes.java

Actually since this request was forwarded using a RequestDispatcher, the

URL reflects the path used to obtain the RD and not the path specified

by the client as usual. You can use another request parameter, or simply

some plain old Javascript (history.back()) to fix this problem.

Check http://localhost/dbi/forward1 to understand this problem.

69

Forwarding versus RedirectionForwarding versus Redirection• HttpServletResponse.SendRedirect() requires extra

communication on part of the client (Why?)

• SendRedirect does not pass the request, therefore the request parameters cannot be obtained easily

• You can’t reach external resources with RequestDispatcher but you can use SendRedirect

• You can forward to resources inside WEB-INF (why is this good?)

• SendRedirect ends up with a different URL on the client

• Be careful: Which image will be loaded in the following scenario? Servlet /forwardjoke forwards to /jokes/joke1.html and joke1.html contains <img src="image1.gif".../>

You can use either the session or the context to pass those parameters

Open /dbi/image1.gif, /dbi/jokes/image1.gif, /dbi/jokes/joke1.html, /dbi/forwardjoke and check…