How can I map a "root" Servlet so that other scripts are still runnable?

JavaGoogle App-EngineServletsweb.xml

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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 - Java

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 - Java

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 - Java

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 - Java

Try just to remove '*' from the pattern, i.e.

<url-pattern>/</url-pattern>

Solution 6 - Java

Solution 7 - Java

You can't redirect to WEB-INF. A servlet container will never serve requests for documents in that folder.

If you want your application (not just a servlet, but the entire application) to be available under the root context ("/" of "http://www.domainname.com/";), then you need to set up a context entry for it - not a servlet mapping.

With Tomcat, you add a new <Context> mapping (in one of about 3 different possible places).

Solution 8 - Java

Have you tried the below? (Note the missing *, which is a wild card and is the reason that your configuration catches everything.)

<servlet-mapping>
        <servlet-name>MainServlet</servlet-name>
        <url-pattern>/index.jsp</url-pattern>
</servlet-mapping>

(Edited as per comments from just /.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeremy LoganView Question on Stackoverflow
Solution 1 - JavanilskpView Answer on Stackoverflow
Solution 2 - JavaJebView Answer on Stackoverflow
Solution 3 - JavaSam LowryView Answer on Stackoverflow
Solution 4 - JavaVincent RamdhanieView Answer on Stackoverflow
Solution 5 - JavaGennady ShumakherView Answer on Stackoverflow
Solution 6 - JavaTomaszView Answer on Stackoverflow
Solution 7 - Javamatt bView Answer on Stackoverflow
Solution 8 - JavaStu ThompsonView Answer on Stackoverflow