1

Tomcat is giving me StackOverflowError after constantly repeating these lines, where DiceBoardDispatcher is my HttpServlet and in line 34 I am calling requestDispatcher#forward().

nl.rickhurkens.rollDice.web.diceBoard.DiceBoardDispatcher.doGet(DiceBoardDispatcher.java:34)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
        nl.rickhurkens.rollDice.web.diceBoard.DiceBoardDispatcher.doGet(DiceBoardDispatcher.java:34)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

I guess it's got something to do with my deployment, here is the relevant part of my web.xml:

  <servlet-mapping>
    <servlet-name>DiceBoard</servlet-name>
    <url-pattern>/dices/*</url-pattern>
  </servlet-mapping>

  <filter-mapping>
    <filter-name>RollDiceFilter</filter-name>
    <url-pattern>/dices/roll</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>SetSettingsFilter</filter-name>
    <url-pattern>/dices/setup</url-pattern>
  </filter-mapping>

What I am trying to do is have 2 actions both landing on the same page. I thought I'd set it up like this. Each action goes through its own Filter and they both end in the Servlet that dispatches to a JSP.

My url-patter mapping used to be to /diceBoard/*, which is a folder somewhere in the web-app. Changing from there to /dices/* fixed the problem when going to url/dices. Now I can reach that page normally, but when going to url/dices/roll I get the infinite loop (no matter if POST or GET).

Edit: My servlet code:

public class DiceBoardDispatcher extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        RequestDispatcher view = request.getRequestDispatcher("diceBoardPage.jsp");
        view.forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher view = request.getRequestDispatcher("diceBoardPage.jsp");
        view.forward(request, response);
    }
}

And RollDiceFilter:

public class RollDiceFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse res = (HttpServletResponse)response;
        HttpSession session = req.getSession();

        DiceBoard diceBoard = (DiceBoard)session.getAttribute("diceBoard");
        String[] lockedValues = req.getParameterValues("lock");

        diceBoard.unlockAllDice();
        if (lockedValues != null) {
            for (String value : lockedValues) {
                if (value != null) {
                    try {
                        diceBoard.lockDice(Integer.parseInt(value));
                    } catch (DiceNotInCollectionException e) {
                        // TODO: redirect to error page.
                        e.printStackTrace();
                    }
                }
            }
        }
        diceBoard.getCup().roll();

        chain.doFilter(req, res);
    }

    public void init(FilterConfig fConfig) throws ServletException { }
    public void destroy() { }
}
Rick
  • 136
  • 12
  • **Where** is your servlet dispatching a forward to? Post the relevant lines of your code, please. – Little Santi Jan 31 '18 at 19:26
  • I have now posted the relevant code. I thought it had something to do with [this](https://bz.apache.org/bugzilla/show_bug.cgi?id=5599), that's why I didn't think the code was very relevant for this problem. – Rick Jan 31 '18 at 19:36

1 Answers1

3

This is the line where your error is located:

RequestDispatcher view = request.getRequestDispatcher("diceBoardPage.jsp");

According to the getRequestDispatcher API, the input uri is relative to the current servlet context, so when you are executing your servlet at

/dices/roll

... and it performs a dispatch to "diceBoardPage.jsp", it is actually dispatching to

/dices/diceBoardPage.jsp

And what servlet is mapped this pattern to? According to your deployment descriptor, every URL beginning with "/dices/*" is mapped to DiceBoard. I.E. the same servlet. Here comes the infinite loop that caused your StackOverflowError.

If the JSP must stay within the dices uri, you must restrict the URL pattern which maps the DiceBoard servlet. Do not hesitate to add several values if needed:

<servlet-mapping>
    <servlet-name>DiceBoard</servlet-name>
    <url-pattern>/dices/one</url-pattern>
    <url-pattern>/dices/two</url-pattern>
    <url-pattern>/dices/three</url-pattern>
</servlet-mapping>
Little Santi
  • 8,563
  • 2
  • 18
  • 46
  • Thanks! I just figured it out as well. I changed to argument to getRequestDispatcher() to `/diceBoardPage.jsp`, so now it is relative to the context root. Thanks for your help and for teaching me I can supply multiple ! – Rick Jan 31 '18 at 19:49