All you never wanted to know about the JSP integration of OpenCms and therefore didn't bother to ask

This page provides some nitty-gritty background information about the JSP OpenCms integration. Usually these details should not bother you very much in the practical process of JSP developing, but they might be good to know anyway.

How does OpenCms manage JSP pages?

All OpenCms files usually reside in a database, in the so called OpenCms Virtual File System (VFS). This means you will not find the file structure you are looking at in the OpenCms workplace explorer on your local file system (see below for static export options). However, in order for JSP to work, all OpenCms JSP pages are "mirrored" to the local FS.

To fully understand this process let's first look on the "standard" way how JSPs are handled:

  1. A JSP file has to reside in or under the web application's home directory.
  2. It has to have the suffix "*.jsp" (you can change this in the web.xml configuration).
  3. In case the Servlet container receives a request for any JSP file in a web application, this requested JSP is first translated to a java class source code, i.e. a file with the "*.java" extension.
  4. During the translation process, JSP directives (i.e. like <%@ include file= "..." %> are resolved and replaced with Java code.
  5. The created "*.java" source code is then compiled into a Class which implements the Servlet interface.
  6. Finally, service() is called on that servlet.

To enable OpenCms to be independed of the servlet container, it uses a simple trick - it mirrors it's JSP's from the VFS to the "real" file system like this:

  1. All requests for OpenCms resources are handled by the OpenCms servlet, usually mapped to /opencms/opencms.
  2. In case OpenCms receives a request for a JSP resource, it dumps the contents of the requested JSP into it's own web application home directory in the subfolder /WEB-INF/jsp.
  3. Since OpenCms distinguishes between online and offline resources, a subfolder online or offline is appended to this directory.
  4. In this folders, the dumped JSP files will be written with their full VFS path and, an ".jsp" suffix will always be appended to the filename. 
  5. For example if your JSP is called "/index.jsp" in the OpenCms VFS, it will be mirrored to /WEB-INF/jsp/online/index.jsp.jsp in the "real" file system. Lets call this the "translated filename" of the JSP.
  6. While OpenCms dumps the resource, a preprocessing of the JSP contents is made with a simple parser to find directives that refer to other JSP filenames. Most notably this is <%@ include file= "..." %> and <%@ page errorPage= "..."%>. If such a directive is found, the target file name is replaced with the translated filename for this resource in the real FS.
  7. Now we have a JSP file in a web application directory with the name, let's say, "{file.jsp}".
  8. The OpenCms servlet (that still has the control) now calls requestDispatcher("{file.jsp}").include() and transfers control to the standard servlet container. This will just do all of the steps described above for the "standard" JSP in the web application. Note that during this process, OpenCms also uses Request and Response wrappers to generate entries for the FlexCache. See the FlexCache Reference for more details.

How are online and offline JSP separated?

This is very simple: Since OpenCms dumps the online and the offline version of a JSP in two separate directories in the web application context (see above), they are treated as two separate pages by the servlet container. This enables you to make changes to an offline JSP without disturbing the online version.

Important: Both online and offline JSP reside essentially in the same web application context. Because of that, they share a common application context object which access the same set of data for both on- and offline pages, resulting in unwanted side effects if not used carefully. You can avoid these side effects by strictly controlling access to the application context object.

How to use the OpenCms static export with JSP?

Using the OpenCms static file export can improve the performance of your website. However, to describe the full range of options of the static export is outside of the scope of this part of the documentation.

The static export is fully supported for JSP's managed with OpenCms. Of course, JSP's usually are used for dynamic pages, so all generated JSP get the export property automatically set to false. In case you want to export a JSP, you have to manually enable the export by changing that property value to true.

To support linking to statically exported resources, the <cms:link> tag has been introduced in the OpenCms taglib. Please check out the available examples and the OpenCms taglib documentation for some demonstrations on how to use link replacement with this tag or in JSP scriplets.

What about the XML - Style JSP Syntax?

The issue: Experienced JSP developers might know that as of JSP 1.2, there are two ways to write a JSP page which achieve the exact same results: "JSP" and "XML" style. The "JSP" way uses <% ... %> style brackets, for example <%@ include file="..." %>. The "XML" style syntax for that would be <jsp:directive.include file="..." />. To get a full overview, you might look at the JSP reference card available from SUN.

So what about the XML - Style syntax?

The short answer is: It currently doesn't work in OpenCms, so don't use it. Stick with the "classic" JSP style by using <% ... %> notation.

The long answer is: As said above OpenCms parses a JSP page before it writes it to the "real" file system in order to adjust certain tags that contain file references like <%@ include file="..." %> or <%@ page errorPage="..." %>. This is required because the servlet container must have the "real" file system paths in the JSP, not the OpenCms VFS paths. That parser is very simple and currently does not support the XML - style syntax. So in case you use <jsp:directive.include file="..." /> the filename in the tag is not adjusted, and therefore the servlet container is unable to find the JSP since it still points to the OpenCms VFS path, not the "real" file system path. Note that most XML style commands that are not dealing with filenames will work fine. For example <jsp:useBean id="..." /> or <jsp:setProperty name="..." /> can be used without problems.

What about using <jsp:forward page="..." /> with OpenCms?

Again, the short answer is:  It currently doesn't work in OpenCms, so don't use it. You should consider using the OpenCms tablib (or scriptlet API) to achieve your results.

The long answer is: As described above, OpenCms loads any JSP with an internal requestDispatcher("{file.jsp}").include() call. It expects to get the control back after that include call. This is not the case when you use <jsp:forward /> , as the final page will terminate the request. This currently causes the JSP integration in OpenCms to break. We hope to provide that feature in a future OpenCms release. Note that the filename adjustment issue described above also applies to the forward tag.

What about redirecting the response?

In case you use the preferred way of including sub-elements (please see the next page for more information about this), you should know that in this case all OpenCms JSP output is always buffered first. This enables you to use response.sendRedirect("targeturi"); everywhere on your page and even in included sub-elements, as no output is written to the response until all page processing is finished. That way you can create forms and other dynamic functionality very easy. This default buffering can be turned off by setting the JSP property "stream" to "true", in which case the output is written to the stream as soon as it becomes available. This property must be set on a "per-JSP" basis. If "stream" is set to "true" you can not redirect after anything has been written to the response, as it is usual in standard JSP developing.

What about using  <jsp:include page="..." /> with OpenCms?

Please read on to the next page for more information about this topic.