Apr 14, 2011

JSP: To @include or jsp:include?

Just a short time ago I was reviewing some JSPs in search of a bug. While searching, I noticed indifferent and inconsistent use of the <jsp:include page=””> and <%@ include file=”” %> tags. A brief discussion led to the revelation that <jsp:include> was chosen as the standard for style reasons, but the other was allowed where the chosen one didn’t seem to work. It seemed to be the case that it was believed that they were mostly interchangeable, and the decision to use one over the other could be made arbitrarily.

It is greatly not the case that they are interchangeable. At least not in the sense that it was being used where I was bug-hunting.

It’s quite normal to put common and frequently repeated JSP into a separate file and then include it in other files. This is often done for boiler-plate text such as page headers and footers, and even some dynamic content such as navigation. I’m neither knocking or defending the use of included JSP, nor do I intend to impress the use of one over the other; I’m only pointing-out the differences, so that the impact can be properly weighed when choosing to include one JSP in another, and by which method to include the page.

The more straight-forward of the two has the behavior that was expected. The <%@include file=”” %> tag will inject the contents of the named file into the JSP containing the tag, as if it were copied and pasted. This is done before the content of the included file is parsed, instead parsing it while the containing JSP is parsed. This is most akin to a C #include directive, where during pre-processing the included file is “pasted” into place before the file is compiled. After the content is included, it is evaluated, all in the same context, and therefore with the same accesses and constraints the included code would have if the contents were simply typed in place.

The <jsp:include page=””/> tag behaves differently in that the result of rendering the specified page is injected into the containing JSP at the point of the tag. This is done by essentially submitting the requested page to the same container, as a separate rendering request, and taking the results, not the content of the file. This request is done in its own context, meaning it doesn’t use the same page information as the page that contains the <jsp:include> tag. This can be handy, especially if the included content may have conflicting variables, for example.

In a lot of cases, the distinction might not be an important one. For example, if the included file is fairly static, or if its dynamic content is self-contained (in that it doesn’t rely on other information on the page), then the only cost is that there are two rendering requests when using <jsp:include> to include another JSP. Sometimes it might be very important, for example if the included file expects the page context to be prepared for use. It’s also important if the included page needs to be free from worrying about its own contents. In either case, though, there must be consideration for what’s expected, and what remains after the include is complete.

Let’s consider the following trivial JSP. It’s a short example of a common include situation; something in this page is set up (our “rightnow” bean) and the included file is going to do something with it. Again, I’m not judging or suggesting this is good or bad use, it’s just use I see frequently.

&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;
&lt;jsp:useBean class="java.util.Date" id="rightnow"/&gt;
&lt;p&gt;With @include &lt;%@include file="included.jsp" %&gt;&lt;/p&gt;
&lt;p&gt;With jsp:include &lt;jsp:include page="included.jsp" /&gt;&lt;/p&gt;

In a more real-world example, the include might be in the body of a <c:forEach> tag or inside a <c:choose> block, leaving the containing JSP clear of the work that builds the display of the current content. Unlike other real-world examples, I’ve included both kinds of includes to do the same work. This is to demonstrate the different results from the different include tags.

In our included JSP, we have another simple example. Here, we’re just going to print whatever the value of our page’s “rightnow” bean.

&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;
&lt;c:out value="${rightnow}" default="Not defined!"/&gt;

In a more real-world example we would expect to see some more complex decision-making, formatting, or layout. Again, this is only to demonstrate the different results; obviously it’d be easier to directly inject the <c:out> in our JSP instead of the include. Running it as is will give us the following output (date not withstanding).

With @include Thu Apr 07 10:01:37 CDT 2011

With jsp:include Not defined!

We can see that the <%@include%gt; tag found and displayed the value correctly. This is because it was essentially the case that the <c:out> was injected in place, and the value was therefore available when the tag was evaluated. In the case of <jsp:include>, however, the value wasn’t available, as that JSP was being rendered as a “stand alone” test.

Let’s consider what happens if we define our value in the included JSP. Without changing the containing JSP, let’s add the bean definition to our included file.

&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;
&lt;jsp:useBean class="java.util.Date" id="rightnow"/&gt;
&lt;c:out value="${rightnow}" default="Not defined!"/&gt;

When we run this, we get an unfriendly error!

useBean: Duplicate bean name: rightnow

This is happening because our <%@include%gt; is getting injected, and we essentially have two identical <jsp:useBean> tags. Astute readers will notice that we’ve included the core taglib twice, and that doesn’t cause an error; that’s only an error if the same prefix is re-used with different a URI.

If we correct the error, by removing the useBean defined in the containing JSP, we resolve the error, and end up in that “self-contained” model of included JSP. Sort of. Let’s see what happens first, and then see what that “sort of” means.

With @include Thu Apr 07 10:07:14 CDT 2011

With jsp:include Thu Apr 07 10:07:14 CDT 2011

In this case we’re fine for the first pass, but we have to remember now that <%@include> has defined a bean that is now in our containing page’s content. If we (for whatever reason) re-include that page with @include, we’ll run into the same error we had defining the bean twice.

To that end, it’s simply important to understand the requirements, contents, and implications of an included JSP before deciding which one to use. There are good uses for each, and each has its limitations.

About the Author

Object Partners profile.

One thought on “JSP: To @include or jsp:include?

  1. rd says:

    wow! That is cool. I did not know the difference. I will apply what I just learned.

  2. concerto49 says:

    JSP includes is definitely a strange beast. I usually use the static one instead of the dynamic one. Haven’t found it useful.

  3. tapan says:

    if scope=”request”
    output will be
    With @include Fri Oct 25 17:08:53 IST 2013
    With jsp:include Fri Oct 25 17:08:53 IST 2013

    if scope=”page”
    output will be
    With @include Fri Oct 25 17:11:26 IST 2013
    With jsp:include Not defined!

  4. Jafar says:

    JSP include is the clean one. One will will never bump into duplicate variable or random change in variable value. JSP include create a different context for the included JSP and they both share common request. we can pass any parameter through JSP param tag. this approach is much cleaner and IDE friendly.

  5. Eduard Seifert says:

    Thank you very much for this example. That was exactly what i was looking for. Best description on the differences between @include and jsp:include.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]