How can I map a "root" Servlet so that other scripts are still runnable?
I'm trying to build a Servlet that calls a JSP page similar to the following:
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
req.getRequestDispatcher("/WEB-INF/main.jsp").forward(req, resp);
}
I need this Servlet to respond to the domain's root (eg: http://example.com/) so I'm using the following mapping in the web.xml:
<servlet-mapping>
<servlet-name>MainServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The problem I'm having is that this matches EVERYTHING, so when the dispatcher forwards to "/WEB-INF/main.jsp" this matches the url-pattern so the Servlet gets run again. This results in a loop that runs until it dies with a java.lang.StackOverflowError.
How can I match the root without preventing other scripts from being runnable?
Solution 1:
Use an empty pattern, e.g.
<servlet-mapping>
<servlet-name>MainServlet</servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
The servlet 3.0 spec has clarified this:
The empty string ("") is a special URL pattern that exactly maps to the application's context root
So it should at least work on a 3.0 container, and I've verified that it works on Jetty 8
Solution 2:
Using the welcome-file element of web.xml worked for me, on app engine. Here's mine:
<web-app>
<servlet>
<servlet-name>RootServlet</servlet-name>
<servlet-class>com.foo.RootServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RootServlet</servlet-name>
<url-pattern>/foo</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>foo</welcome-file>
</welcome-file-list>
</web-app>
Solution 3:
The original question doesn't mention that they're trying to map a root servlet on App Engine - it's easy on Tomcat (and other servlet containers as far as I know) but App Engine isn't a normal servlet container.
My normal way of building a web application with servlets is to extend HttpServlet, add a "page" object with title, content, errors, messages etc. and for output forward to a JSP template. This has been an absolute nightmare getting working in App Engine.
- JSP files can't be "named" without a "/" at the beginning.
- JSP files can't be in a subdirectory
- Servlets can't be mapped to the root of your application with a "/" url-pattern
Here's my web.xml (edited for brevity) which finally worked.
<web-app>
<servlet>
<!-- this servlet needs to redirect to a NamedDispatcher
called "template" -->
<servlet-name>Home</servlet-name>
<servlet-class>my.domain.HomeSv</servlet-class>
</servlet>
<servlet>
<!-- jsp file must apparently be in root directory and have "/" at
start of path -->
<servlet-name>template</servlet-name>
<jsp-file>/template.jsp</jsp-file>
</servlet>
<servlet-mapping>
<!-- map your home servlet to somewhere other than "/" -->
<servlet-name>Home</servlet-name>
<url-pattern>/home</url-pattern>
</servlet-mapping>
<welcome-file-list>
<!-- make your Home servlet the welcome file -->
<welcome-file>home</welcome-file>
</welcome-file-list>
</web-app>
I haven't been particularly scientific about validating all this - but it seems to work for me now and I'm pretty happy about that.
Solution 4:
You can create a welcome file named index.jsp in the root with the following code using JSTL or otherwise.
<c:redirect url="/main"/>
So in the web.xml file you will have this:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
So anyone requesting the root will be redirected to /main. Now your servlet can be mapped to main.
<servlet-mapping>
<servlet-name>MainServlet</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
Solution 5:
Try just to remove '*' from the pattern, i.e.
<url-pattern>/</url-pattern>