Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any clever ways of handling the context in a web app?

People also ask

What is web context in Java?

The context in which web components execute is an object that implements the ServletContext interface. You retrieve the web context using the getServletContext method. The web context provides methods for accessing: Initialization parameters. Resources associated with the web context.

What is the context root of a web application?

The context root for an application defines the location at which the module can be accessed. The context root is part of the URL you use to connect to the application.

How do you change the context root of a web application?

To change the context root of a web application that is already available in the Eclipse workspace, simply right-click on the web project and call the “Properties” action from the context menu.


You can use JSTL for creating urls.

For example, <c:url value="/images/header.jpg" /> will prefix the context root.

With CSS, this usually isn't an issue for me.

I have a web root structure like this:

/css
/images

In the CSS file, you then just need to use relative URLs (../images/header.jpg) and it doesn't need to be aware of the context root.

As for JavaScript, what works for me is including some common JavaScript in the page header like this:

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

Then you can use the context root in all your scripts (or, you can define a function to build paths - may be a bit more flexible).

Obviously this all depends on your using JSPs and JSTL, but I use JSF with Facelets and the techniques involved are similar - the only real difference is getting the context root in a different way.


For HTML pages, I just set the HTML <base> tag. Every relative link (i.e. not starting with scheme or /) will become relative to it. There is no clean way to grab it immediately by HttpServletRequest, so we need little help of JSTL here.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="req" value="${pageContext.request}" />
<c:set var="url">${req.requestURL}</c:set>
<c:set var="uri">${req.requestURI}</c:set>

<!DOCTYPE html>
<html lang="en">
  <head>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(uri))}${req.contextPath}/" />
    <link rel="stylesheet" href="css/default.css">
    <script src="js/default.js"></script>
  </head>
  <body>
    <img src="img/logo.png" />
    <a href="other.jsp">link</a>
  </body>
</html>

This has in turn however a caveat: anchors (the #identifier URL's) will become relative to the base path as well. If you have any of them, you would like to make it relative to the request URL (URI) instead. So, change like

<a href="#identifier">jump</a>

to

<a href="${uri}#identifier">jump</a>

In JS, you can just access the <base> element from the DOM whenever you'd like to convert a relative URL to an absolute URL.

var base = document.getElementsByTagName("base")[0].href;

Or if you do jQuery

var base = $("base").attr("href");

In CSS, the image URLs are relative to the URL of the stylesheet itself. So, just drop the images in some folder relative to the stylesheet itself. E.g.

/css/style.css
/css/images/foo.png

and reference them as follows

background-image: url('images/foo.png');

If you rather like to drop the images in some folder at same level as CSS folder

/css/style.css
/images/foo.png

then use ../ to go to the common parent folder

background-image: url('../images/foo.png');

See also:

  • Is it recommended to use the <base> html tag?

I agree with tardate. I have paid my attention at filters too and have found the solution in face of project UrlRewriteFilter. The simple configuration like following:

<rule>
    <from>^.+/resources/(.*)$</from>
    <to>/resources/$1</to>
</rule>

helps to forward all requests for */resources path to /resources pass (including context path prefix). So I can simply put all my images and CSS files under resources folder and continue using relative URLs in my styles for background images and other cases.


The Servlet API and JSP have facilities to help manage this. For example, if, in a servlet, you do: response.sendRedirect("/mypage.jsp"), the container will prepend the context and create the url: http://example.com/myapp/mypage.jsp".

Ah, maybe, maybe not - it depends on your container and the servlet spec!

From Servlet 2.3: New features exposed:

And finally, after a lengthy debate by a group of experts, Servlet API 2.3 has clarified once and for all exactly what happens on a res.sendRedirect("/index.html") call for a servlet executing within a non-root context. The issue is that Servlet API 2.2 requires an incomplete path like "/index.html" to be translated by the servlet container into a complete path, but doesn't say how context paths are handled. If the servlet making the call is in a context at the path "/contextpath," should the redirect URI translate relative to the container root (http://server:port/index.html) or the context root (http://server:port/contextpath/index.html)? For maximum portability, it's imperative to define the behavior; after lengthy debate, the experts chose to translate relative to the container root. For those who want context relative, you can prepend the output from getContextPath() to your URI.

So no, with 2.3 your paths are not automatically translated to include the context path.


I've used helper classes to generate img tags etc. This helper class takes care of prefixing paths with the application's contextPath. (This works, but I don't really like it. If anyone has any better alternatives, please tell.)

For paths in css files etc. I use an Ant build script that uses a site.production.css for site.css in production environment and site.development.css in development encironment.

Alternatively I sometimes use an Ant script that replaces @token@ tokens with proper data for different environents. In this case @contextPAth@ token would be replaced with the correct context path.