views:

65

answers:

2

I wrote Front Controller Pattern and ran the test. Somehow request.getPathInfo() is returning null when it should return the path info.

1. HTML that calls servlet

<a href="tmp.do">Test link to invoke cool servlet</a>

2. Map the servlet in DD.
Anything that has .do extension (ex tmp.do) will invoke the servlet "Redirector"

<!-- SERVLET (centralized entry point) -->
    <servlet>
        <servlet-name>RedirectHandler</servlet-name>
        <servlet-class>com.masatosan.redirector.Redirector</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RedirectHandler</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

3. The servlet that takes request from *.do

 public class Redirector extends HttpServlet {

        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            try {
                //test - THIS RETURNS NULL!!!!
                System.out.println(request.getPathInfo());

                Action action = ActionFactory.getAction(request); //return action object based on request URL path
                String view = action.execute(request, response); //action returns String (filename) 
                if(view.equals(request.getPathInfo().substring(1))) {
                    request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
                }
                else {
                    response.sendRedirect(view);
                }
            }
            catch(Exception e) {
                throw new ServletException("Failed in service layer (ActionFactory)", e);
            }
        }
    }//end class

The problem is that request.getPathInfo() returns null. Based on the Head First book,

The servlet life cycle moves from "does not exist" state to "initialized" state (meaning ready to service client's request) beginning with its constructor. The init() always completes before the first call to service().

This tells me that somewhere between the constructor and init() method, the servlet is not-fully-grown servlet.

So, that means, by the time service() method is called, the servlet should be fully-grown servlet and request method should be able to call getPathInfo() and expect the valid value to return instead of null.

UDPATE

Very interesting. (http://forums.sun.com/thread.jspa?threadID=657991)

(HttpServletRequest - getPathInfo() )

If the URL is like below:

http://www.myserver.com/mycontext/myservlet/hello/test?paramName=value.

If you web.xml discribe the servlet pattern as /mycontext/* getPathInfo() will return myservlet/hello/test and getQueryString() will return paramName=value

(HttpServletRequest - getServletPath() )

If the URL is like below:

http://hostname.com:80/mywebapp/servlet/MyServlet/a/b;c=123?d=789

String servletPath = req.getServletPath();

It returns "/servlet/MyServlet"

This page is also very good one: http://www.exampledepot.com/egs/javax.servlet/GetReqUrl.html

+3  A: 

According to the Javadoc:

Returns any extra path information associated with the URL the client sent when it made this request. The extra path information follows the servlet path but precedes the query string. This method returns null if there was no extra path information.

You don't have any path info when using a prefixed mapping (*.do, in your case).

Vivien Barousse
Thanks for the tip!
masato-san
+1  A: 

@Vivien is correct. You'd like to use HttpServletRequest#getServletPath() instead (sorry, I overlooked that bit while writing the answer which you undoubtely was reading, I've updated the answer).

To clarify: getPathInfo() does not include servlet path as definied in web.xml (only the path thereafter) and getServletPath() basically returns only the servlet path as definied in web.xml (and thus not the path thereafter). If the url pattern contains a wildcard, particularly that part is included.

BalusC
I should have looked the doc, didn't know getServletPath() exists!
masato-san
Gottya so in DD, if I specify <url-pattern>/foo/*.do</url-pattern>, getPathInfo() would only get path AFTER the ".do" <br /> That means, /foo/test.do/blah?name=myname then it returns "/blah?name=myname"
masato-san
`/foo/*.do` is not a valid url pattern, so it won't be able to return anything :) Even then, in theory it would only give `/blah`. It doesn't include the query string. For that you have the `getQueryString()` method (or just the usual `getParameter()` methods).
BalusC