Search code examples
javatomcatherokuopenshiftcontextpath

May context path change on every request?


I am developing a web application and something really strange happens. I run my JEE application on my local tomcat and all goes well. When I deploy my application online (on Heroku or Openshift, both), the context path changes on every request. For example, if I click on a link the app does everything correctly showing the content I expect, but from now on the context path (that I use in JSPs to generate links) changes to the current url. If I modify the url in the browser to the main page of the site it changes again. May be a configuration issue? I'm having an headache. I'm using urlrewrite to have pretty urls, so, if the home of my site is http://homesite/ , an article is on http://homesite/article/year/month/article_slug. When, on the homepage, I click on a link to view an article and the page changes accordingly. After page changed, if I click on "Home" link in menu (generated with ${pageContext.request.contextPath}) it goes to to the same page I'm already. In every page of the site I added a javascript variable like this:

<script type="text/javascript">
    context = "<%=request.getContextPath()%>";
</script>

and here contextpath is always empty, as it must be, I believe. This is the content of the JSP that generates the main menu of my site:

<nav class="red accent-4">
    <div id="uc-nav-menu-container" class="nav-wrapper">
        <!--<a href="#" class="brand-logo right">Unical Coin</a>-->
        <a href="#" data-activates="mobile-demo" class="button-collapse left"><i class="material-icons">menu</i></a>
        <ul id="nav-mobile" class="left hide-on-med-and-down">
            <li class="active"><a href="${pageContext.request.contextPath}">Home</a></li>
            <li><a href="#">Mission</a></li>
            <li><a href="#">Tecnologia</a></li>
            <li><a href="#">About</a></li>
            <li><a href="#">Links</a></li>
        </ul>
        <ul class="red accent-4 side-nav" id="mobile-demo">
            <li class="active"><a href="${pageContext.request.contextPath}">Home</a></li>
            <li><a class="white-text" href="#">Mission</a></li>
            <li><a class="white-text" href="#">Tecnologia</a></li>
            <li><a class="white-text" href="#">About</a></li>
            <li><a class="white-text" href="#">Links</a></li>
        </ul>
        <div id="uc-user-menu-container" class="right"></div>
    </div>
</nav>

And this is the JSP that generates an article page:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
         pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <jsp:include page="/WEB-INF/components/imports/default-head-imports.jsp"></jsp:include>
    </head>
    <body class="blue-grey lighten-5">
        <jsp:include page="/WEB-INF/components/nav-menu.jsp"></jsp:include>
        <div class="container">
            <jsp:include page="/WEB-INF/components/single-article-content.jsp"></jsp:include>
        </div>
        <jsp:include page="/WEB-INF/components/footer.jsp"></jsp:include>
        <jsp:include page="/WEB-INF/components/imports/default-foot-imports.jsp"></jsp:include>
    </body>
</html>

The javascript variable in each page is generated only in "/WEB-INF/components/imports/default-head-imports.jsp" included.


Solution

  • The problem here is that the ROOT application's context path is actually "" (empty string) and not / as you might expect. If you deploy the application as ROOT, you'll get your "Home" links looking like this:

    <li class="active"><a href="">Home</a></li>
    

    So you'll end up on the current page if you click that link.

    If you really want to go to the root of the current context, your link needs to be done like this:

    <li class="active"><a href="${pageContext.request.contextPath}/">Home</a></li>
    

    Note the trailing / characted in the href attribute.

    If you are authenticating users, you should really also use the proper encoding of links to preserve users' sessions if cookies are not available:

    <li class="active"><a href="$response.encodeURL("${pageContext.request.contextPath}/")">Home</a></li>
    

    (That may not be valid EL... I'm no EL expert but you get the idea.)

    Oh, and while / may be a "legal" context path, it's not likely to give you the results you are expecting. Never put a path in a <Context> element and never put a <Context> element in server.xml unless you absolutely have to. Instead, use the WAR file's name or the deployment descriptor XML's filename to deploy the context on the desired path, including ROOT if you want it to be the root web application.