Wednesday, August 25, 2010

request.getRequestDispatcher vs servletContext.getRequestDispatcher

ServletRequest.getRequestDispatcher(String path)

The pathname specified may be relative,
although it cannot extend outside the current servlet context.
If the path begins with a "/" it is interpreted as relative to the current context root.
...
If it is relative, it must be relative against the current servlet

ServletContext.getRequestDispatcher(String path)

The pathname must begin with a "/" and
is interpreted as relative to the current context root.
Use getContext to obtain a RequestDispatcher
for resources in foreign contexts.

Basic difference is that

request.getRequestDispatcher allows for relative paths.
Relative to what ?

relative path as coincidence

If the servlet (let's call him B) is accessible using only one URI (/ctx/B)
that seems to be easy answer.
Event if mapped with with url-pattern /path/B,
most containers are "trailing slash ignorant" and your servlet will be accessible with
both /ctx/path/B and /ctx/path/B/ variants.
With the same code in servlet:
request.getRequestDispatcher("../c.jspx").include(request, response);
you will get two different results of course,
/ctx/c.jsp and /ctx/path/c.jspx
one of them will end up with null pointer of course.


Usually using realtive path is coincidence and not design decision.


relative path as design

But wait "relative path" can be used as intentional design:

Imagine that the same servlet is accessible using

/a/a/a
/a/b
/f/g/h/ mappings

and based on the requested uri you want to include different view (c.jspx).
If the view exists in the relative location use it, otherwise use predefined global view.


// get view on current level
d=request.getRequestDispatcher("./c.jspx");
if(d==null)
{
d=request.getRequestDispatcher("/c.jspx");
}
d.include();


Reative Path - Double dispatch

what if b is already dispathed.
If the call goes througn A to B and the to C.
What "it must be relative against the current servlet" means ?
(test your self on several containers, reading specs is not enough for this case ;-))


My suggestion


PREFERE:
getServletContext().getRequestDispatcher() and /contextRelativePath

OVER:
request.getRequestDispatcher and relativePath

Otherwise you code may
not be movable up and down in web hierarchy withou moving views,
not work when mapped to different level URIs" without duplicating views,
and probably will suffer from container's trailing slash ignoracy.

Use realtivePaths only "as design not as coincidence",
and always document relative path dependencies in your servlet documentation.

No comments:

Post a Comment