Discussions

News: Featured Article: Dynamically merging webapp directories

  1. Howard Lewis Ship is working on a project in which he needs to split out specific skin content, from common web artefacts. He wanted to create a virtual directory, and talked about how he was able to do this with Jetty.

    Introduction
    I'm working on converting an existing web site from homebrew servlets and JSPs to Tapestry. What's interesting is that the application in question is deployed into different hosts using different "skins". Certain stylesheets and images are different, and there are minor differences in layout and behavior.

    So, I'm working with their workspace directory layout; there's a common directory that contains the main content (images, stylesheets, Tapestry artifacts). Then there's additional directories, such as defaultskin, that contain skin-specific assets and artifacts.

    When building and deploying, the content is merged together to form a composite web application context.

    For development purposes, I want to leave the directory structure intact, but that makes it impossible to run the application (the assets and artifacts in the defaultskin directory simply aren't visible. What I need is to be able to have a virtual directory within my web application that points to an entirely different directory; I want to map /skin in my context to the defaultskin folder, so I can use URLs like http://.../skin/images/about.gif.

    Did a bit of research and realized that the correct approach was to create my own implementation of Jetty's WebApplicationContext that included the necessary hooks.
    Clever Jetty Hack: Dynamically merging directories inside a web application context
  2. servlet filter[ Go to top ]

    I would have done this with a servlet filter, it is a lot more portable, and configurable in web.xml with a servlet filter parameter (i.e. skin directory)
  3. I haven't given it a lot of thought, but I'm curious what a servlet filter implementation of this would look like -- can you expand on what you were thinking?
  4. I think it can look like this:

     filterConfig.getServletContext().
    getContext(skin).getRequestDispatcher(path).forward(request,response);
  5. A similar problem...[ Go to top ]

    This is similar to something that's been bothering me for a long time...the inability to easily seperate 'dynamic' portions of a WebApp from the 'static' portions. If one has a site that relies heavily on JSP, it's very difficult to selectively manage JSP resources seperately from compiled code resources. Ideally, I would like to be able to deploy a WebApp with just the compiled code and have it use a distinct directory structure for the dynamic (JSP) portions. JSP is great for abstracting presentation code, but IMHO you lose much of the benefit by forcing everything to be bundled tightly together in a WAR (especially in environments with rigid deployment hygiene).

    I know that there is support for this feature in WebLogic (and possibly other containers), but it would be nice to have a standard way to do it...

    -chris
  6. dynamic directories[ Go to top ]

    I've never done this before, I usually change the links in the pages, what takes a lot more work, or at least a custom tag to handle this.

    I loved the idea, and will try this on the next web project I work :-)

    Thanks.
  7. We just encountered this problem today using Tomcat: we wantedt to have a static directory house images and documents while the rest of the application be dynamically controlled. We did not want to pack all the images that may be uploaded by our users inside the WAR file.
    Our solution:
    Add contexts to the server.xml file, for example:
    <code>
    <Context className="org.apache.catalina.core.StandardContext" cachingAllowed="true" charsetMapperClass="org.apache.catalina.util.CharsetMapper" cookies="true" crossContext="true" debug="0" displayName="CTC Documents" docBase="C:/dev/documents" mapperClass="org.apache.catalina.core.StandardContextMapper" path="/documents" privileged="false" reloadable="true" swallowOutput="false" useNaming="true" wrapperClass="org.apache.catalina.core.StandardWrapper">
    </Context>
    </code>
    The important thing there being the setting of the <code>crossContext</code> element to true.
    Then, using JSTL's <code><c:url></code> tag one is able to access resources from another context. For example:<code>
    <img src="<c:url value="/logo.gif" context="/images">">
    </code>
    (Where c: stands for the prefix of the core library in JSTL).
  8. I've actually extended my little hack to support multiple redirected URIs.

    The point is ... paths in web URLs are virtual folders, there's no reason why there needs to be a fixed directory structure for all of it. It would be nice if the servlet API and servlet deployment descriptors addressed some of these features (or at least allowed for them).

    Again, my workspace doesn't match how the Ant build files will construct my WAR. The WAR will have "normal" directory structure; for testing purposes, I need to magically make my workspace match the deployed structure, and I've done that using virtual folders.

    The issue you mentioned is very worthwhile, that there is a difference between "deployable" content (Tapestry apps and, those, er, JS somethings) and non-deployable, largely static content.