Exotic servlet mapping

I want to map the main page to root, but also have some other servlets and static resources. Mapping them to default servlet in web.xml doesn’t look portable.

Vaadin docs suggest two mapping options:

  • @WebServlet(value = "/*") to have just vaadin and nothing else. This overrides default servlets provided by container, not what I want.
  • @WebServlet(value = {"/myui/*", "/VAADIN/*"} to be able to map other servlets, but the main page goes to subdir.

There is a quetionable feature: in both cases you can append arbitrary path after the base url, e.g.:

http://localhost:8080/myui/foo/bar

and it will show the same main page. This page talks with the server using ajax requests (/myui/HEARTBEAT..., /myui/UIDL...). It also loads styles and stuff from /VAADIN/....


First I tried:

@WebServlet(value = {"", "/VAADIN/*"}

This broke the ajax requests, because they weren’t mapped. Then I reverted the change and tried to create a servlet or a filter that forwards root request to /myui/. This broke ajax too:

/myui/ -> /myui/UIDL... (good)
/myui/foo/bar -> /myui/UIDL... (good)

/ -> /UIDL... (404)

The fact that the second ajax URL isn’t /myui/foo/bar/UIDL suggest that it’s generated on server like this:

request.getServletPath() + "/UIDL..."

However, the third ajax URL looks like it was generated on client using Window.Location, because the client doesn’t know it was forwarded.

Is it because the client code compares Window.Location and the result of getServletPath() which came from server? Why at all use Window.Location?

My vaadin version is 7.4.3.

P.S.
By “exotic” mapping I mean something like:

[code]
@WebServlet(value = { “/testme/*” })
public static class Servlet2 extends Servlet {

    @Override
    protected void service(final HttpServletRequest request, final HttpServletResponse response)
            throws ServletException, IOException {
        getServletContext().getRequestDispatcher("/myui/").forward(request, response);
    }
}

[/code]And the url http://localhost:8080/testme/foo/bar should work IMO. Currently it cannot even load the vaadin .js file. See
http://stackoverflow.com/a/11387378/447503
on how to get the original URL

Would this work? With this I didn’t see any apparent problems. Let’s figure it out if it doesn’t work.

    @WebServlet(urlPatterns = { "/myservlet/*", "/VAADIN/*" }, name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
    public static class MyUIServlet extends VaadinServlet {
    }

    @WebFilter(urlPatterns = { "/*" })
    public static class MyUIServletFilter implements javax.servlet.Filter {

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub

        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String uri = httpRequest.getRequestURI();
            if (uri.equals("/") || uri.startsWith("/UIDL")) {
                httpRequest.getRequestDispatcher("/myservlet" + uri).forward(request, response);
            } else {
                chain.doFilter(request, response);
            }

        }

        @Override
        public void destroy() {
            // TODO Auto-generated method stub

        }

    }

Please try this with non-empty webapp contextPath. For maven jetty plugin it’s:

<webApp> <contextPath>/abc</contextPath> </webApp> </configuration> getServletPath should be used instead of getRequestURI, but even if that’s fixed, it cannot load the script again.
Looks like the relative path to vaadin js is incorrectly built in this case