IBM Skip to main content
Search for:   within 
      Search help  
     IBM home  |  Products & services  |  Support & downloads   |  My account

developerWorks > Java technology
developerWorks
JSP best practices: Manipulate dynamic content with jsp:include
69 KBe-mail it!
Contents:
The trouble with caching
The jsp:include tag
How jsp:include works
A mix-and-match solution
Resources
About the author
Rate this article
Related content:
JSP best practices series
Introduction to JavaServer Pages technology
Test Java code with JSP Explorer
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
A simple JSP tag for building dynamic Web sites

Level: Introductory

Brett McLaughlin (mailto:brett@oreilly.com?cc=&subject=Manipulate dynamic content with jsp:include)
Author, O'Reilly and Associates
29 April 2003

Column iconIn this follow-on to his first JSP best practices installment, Java tipster Brett McLaughlin shows you how to extend the JSP technology inclusion functionality for dynamic content. Learn the differences between the static include directive and the dynamic jsp:include element, and find out how to mix and match the two for optimum performance.

In the previous installment in the new JSP best practices series, you learned how to use the JSP include directive to include static content such as header, footer, and navigation components into your Web pages. Like server-side includes, the JSP include directive lets one page pull in content or data from another page. Listing 1 will refresh your memory of the include directive.

Listing 1. The JSP include directive

<![CDATA[
<%@ page language="java" contentType="text/html" %>
<html>
<head>
      <title>newInstance.com</title>
      <meta http-equiv="Content-Type" 
        content="text/html; charset=iso-8859-1" />
      <link href="/styles/default.css" 
        rel="stylesheet" type="text/css" />
</head>

<body>

<%@ include file="header.jsp" %>
<%@ include file="navigation.jsp" %>
<%@ include file="bookshelf.jsp" %>
<%@ include file="/mt-blogs/index.jsp" %>
<%@ include file="footer.jsp" %>

</body>
</html>
]]>

What you'll need
All of the best practices in this series are based on JavaServer Pages technology. To run any of them, you'll need to set up a JSP technology-compliant Web container, either on your local machine or on a test server. You'll also need to use a text editor or IDE to code your JSP pages.

While include works very well for incorporating static content into your Web pages, it doesn't work so well for dynamic content. We discovered this in the last installment when we attempted to reload a cached file. Unlike most header and footer files, dynamic content changes frequently and must always be up to date. We'll start out with a quick recap of the limitations of the include directive, then I'll show you how to extend the JSP inclusion capability with the jsp:include tag.

The trouble with caching
One of the downsides of the JSP include directive is that it causes your Web browser to cache complete pages. This makes sense when it comes to dealing with static components such as a footer, a copyright notice, or a set of static links. These files don't change, so there's no reason for the JSP interpreter to constantly re-poll their data. And caching should be implemented wherever possible, because it aids your application performance.

JSP testing and development
When you're building a Web application or Web site, you may need to update your headers, footers, and navigation links quite a bit. It can be a pain to have to constantly close out your browser or clear its cache just to see the changes you've made to your included files. On the other hand, it's just as much of a pain to come to the end of your development cycle only to have to sweep through and change hundreds of pages that employ the include directive. My advice is to disable your browser cache during testing. In most cases this will resolve the problem altogether. In the rare cases where this doesn't work, you can always restart your Web container to ensure no caching is occurring, either on the browser or on the server.

In some cases, however, caching can cause more trouble than it's worth. If you're pulling in content from a program that uses dynamic data (such as a Weblog or a database-driven JSP file), or even if your included content is a highly volatile bit of HTML (such as a time stamp), then you need the latest version of these files or programs to show up whenever your Web page is loaded. And unfortunately the JSP include directive doesn't have that functionality. This problem is commonly handled in the test-and-development cycle (see the sidebar "JSP testing and development") by disabling caching on the browser. But for working applications, where performance is an important factor in any design decision, disabling caching isn't a viable long-term solution. A better solution is to use a jsp:include tag.

The jsp:include tag
jsp:include is simply a different directive from include. The advantage of jsp:include is that it will always check for changes in the included file. We'll get into how the new tag works in just a moment. But first we'll take a look at the code for each of the two includes, so that you can see the similarities and differences between them.

Listing 2 shows a simple page that uses the original JSP include directive.

Listing 2. The JSP include directive

<![CDATA[
<%@ page language="java" contentType="text/html" %>
<html>
     <head>
      <title>JSP include element test</title>
     </head>
     <body>
      This content is statically in the main JSP file.<br />
      <%@ include file="included.html" %>
     </body>
</html>
]]>

Listing 3 is the same page converted to use the jsp:include tag.

Listing 3. Converting to jsp:include

<![CDATA[
<%@ page language="java" contentType="text/html" %>
<html>
     <head>
      <title>JSP include element test</title>
     </head>
     <body>
      This content is statically in the main JSP file.<br />
      <jsp:include page="included.html" flush="true" />
     </body>
</html>
]]>

You should notice two big differences between the two code types. First, the jsp:include element doesn't use the %@ syntax that is part of the include directive. Instead, the jsp prefix lets the JSP compiler know that it should look for the element in the standard JSP set of tags. Second, the attribute that specifies the file to include has changed from file to page. If you like, you can test the results of the new tag for yourself. Simply change the content of your own included.html file from the last installment (see Resources), reload your browser page, and you'll see the new content immediately.

The flush attribute
You may have noted the flush attribute in the jsp:include code example. As its name suggests, flush indicates whether any existing buffer should be flushed before reading in the included content. The flush attribute is required in JSP 1.1, so you'll get an error if you leave it out of your code. In JSP 1.2, however, the flush attribute defaults to false. Because flushing is rarely a big concern, my advice is to leave flush set to true for JSP 1.1 and leave it off for JSP 1.2 and above.

How jsp:include works
If you're even mildly geeky, you're probably anxiously wondering why the jsp:include tag behaves differently from the include directive. It's actually pretty simple: jsp:include includes the response from the included URI, rather than the URI itself. This means that the indicated URI is interpreted and the resulting response is included. If the page is HTML, you get the HTML essentially unchanged. But if it's a Perl script, a Java servlet, or a CGI program, you'll get the interpreted result from that program. While this usually turns out to be HTML, the actual program is just a means to an end. And, because interpretation happens at every page request, the results are never cached as they were with the include directive. It's such a minor change, but it makes all the difference in the behavior you see.

A mix-and-match solution
The include directive has its place on some Web sites. For example, if your site includes header, footer, and navigation files that rarely (if ever) change, then the basic include directive is a fine choice for these components. Because the include directive mandates caching, you'll only need to pull in the included files once, the content will be cached, and your site will receive a nice performance boost as a result.

For many of today's Web applications or sites, however, blanket caching won't work. While your headers and footers may be static, it's unlikely that your whole site will be. It's not uncommon to pull navigation links from a database, for example, and many JSP technology-based sites pull content from dynamic JSP pages on other sites or applications. If you are dealing with dynamic content, you will need to employ jsp:includes to handle that content.

Of course, the best solution is often to mix and match, using each construct where it is most appropriate. Listing 4 is an example of a mix-and-match include solution.

Listing 4. A mix-and-match solution

<![CDATA[
<%@ page language="java" contentType="text/html" %>
<html>
<head>
  <title>newInstance.com</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  <link href="/styles/default.css" rel="stylesheet" type="text/css" />
</head>

<body>

<jsp:include page="header.jsp" flush="true">
  <jsp:param name="pageTitle" value="newInstance.com"/>
  <jsp:param name="pageSlogan" value=" " />
</jsp:include>
<%@ include file="/navigation.jsp" %>
<jsp:include page="bookshelf.jsp" flush="true" />

<jsp:include page="/mt-blogs/index.jsp" flush="true" />

<%@ include file="/footer.jsp" %>
</body>
</html>
]]>

The above code shows the example index page from the previous installment. The navigation links and footer are static content, changing once a year at most. For these files, I've used the include directive. The content pane includes Weblog and "bookshelf" components, which are generated dynamically. Both of these components need to be always up to date, so for them I've used the jsp:include tag. The header.jsp file is the oddball of the lot. This component is pulled from another JSP page that is essentially static. But, as you'll note, it pulls in the page "slogan" from the including page and writes that out. To deal with this shared information, I have to pass in parameters to the header file. And to deal with those parameters, I have to use the jsp:include element.

If you're wondering about those parameters, rest assured that you won't wonder for long. In the next installment, I'll explain JSP parameters and how they interact with JavaBeans components. Until then, I'll see you online.

Resources

About the author
Photo of Brett McLaughlinBrett McLaughlin has been working in computers since the Logo days (remember the little triangle?). He currently specializes in building application infrastructure using Java and Java-related technologies. He has spent the last several years implementing these infrastructures at Nextel Communications and Allegiance Telecom Inc. Brett is one of the co-founders of the Java Apache project Turbine, which builds a reusable component architecture for Web application development using Java servlets. He is also a contributor of the EJBoss project, an open source EJB application server, and Cocoon, an open source XML Web-publishing engine. Contact Brett at brett@oreilly.com.


69 KBe-mail it!

What do you think of this document?
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Comments?



developerWorks > Java technology
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact