Will Hartung Will Hartung - 3 months ago 7
Java Question

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

In Java, web apps are bundled in to WARs. By default, many servlet containers will use the WAR name as the context name for the application.

Thus myapp.war gets deployed to http://example.com/myapp.

The problem is that the webapp considers its "root" to be, well, "root", or simply "/", whereas HTML would consider the root of your application to be "/myapp".

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".

However, you can't do that with, say, the IMG tag in HTML. If you do <img src="/myimage.gif"/> you will likely get a 404, because what you really wanted was "/myapp/myimage.gif".

Many frameworks have JSP tags that are context aware as well, and there are different ways of making correct URLs within JSP (none particularly elegantly).

It's a nitty problem for coders to jump in an out of when to use an "App Relative" url, vs an absolute url.

Finally, there's the issue of Javascript code that needs to create URLs on the fly, and embedded URLs within CSS (for background images and the like).

I'm curious what techniques others use to mitigate and work around this issue. Many simply punt and hard code it, either to server root or to whatever context they happen to be using. I already know that answer, that's not what I'm looking for.

What do you do?

Answer

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.