2

I am doing some basic templating in my JSP-based webapp. For example, I want to have a standard header and footer (basic HTML) that I pull into each of my JSPs.

My content JSP is at /WEB-INF/jsp/home.jsp, and I have template JSPs at /WEB-INF/jsp/template/, such as /WEB-INF/jsp/template/Body-Footer.jsp.

So now, within home.jsp, I want to pull in my template files. First, I try the jsp:include action:

<jsp:include page="template/Body-Footer.jsp"></jsp:include>

It generates the error javax.servlet.ServletException: File &quot;/template/Body-Footer.jsp&quot; not found

Strange to me, considering that Eclipse says that the path is valid.

Okay, so then I switch to the include directive:

<%@ include file="template/Body-Footer.jsp" %>

This works just fine, pulls in my footer HTML.

But why does the jsp:include not work? After some experimentation, I find that putting in the absolute path does get it to work:

<jsp:include page="/WEB-INF/jsp/template/Body-Footer.jsp"></jsp:include>

Now it works fine, no errors.

So here's my question: why? Why do I (apparently) need to use an absolute path with the jsp:include action, but not with the include directive?

Matt Mc
  • 8,882
  • 6
  • 53
  • 89

3 Answers3

6

/WEB-INF/jsp/template/Body-Footer.jsp is not an absolute path. Its also a relative path. The problem is that template/Body-Footer.jsp is an incomplete relative path, whereas the other is complete. That is, the paths are relative to your app path. Since /WEB-INF/ is under your app path, you have to include it. Absolute path means like C:/program files/tomcat/webapps/yourapp/WEB-INF/jsp/template/Body-Footer.jsp

developerwjk
  • 8,619
  • 2
  • 17
  • 33
  • 1
    The other path is absolute regarding the application context URL. – Luiggi Mendoza Feb 17 '14 at 20:36
  • Its absolute RELATIVE to the application context, thus not really absolute at all. There's a clear confusion in terminology going on. Of course your relative paths have to be complete, otherwise, how would they work? – developerwjk Feb 17 '14 at 20:47
  • That's what I've said. I don't negate the fact that they are relatives paths after all. – Luiggi Mendoza Feb 17 '14 at 20:49
0

Answer to WHY - The jsp:include is a runtime directive unlike the <%@ include ... %> directive which happens to be a compile time directive (translation time, actually).

See more on: JSP Performance using jsp:include

Bottom line - directives are run against different folders as a base.

Btw. JSP pages should be outside of WEB-INF folder, if you want to follow official recommendation:

The Java EE 6 Tutorial - Web Module Structure

Community
  • 1
  • 1
dejanmr
  • 47
  • 2
  • 8
  • 2
    This is helpful, thanks. However, on your recommendation of putting the JSPs outside of the WEB-INF folder, maybe I missed it but I couldn't see something in that link that recommended that. In support of putting the JSPs in WEB-INF, we have this: http://stackoverflow.com/questions/6825907/why-put-jsp-in-web-inf – Matt Mc Mar 20 '15 at 23:08
  • Placing your JSP files under `/WEB-INF/` is a common practice which "hides" the pages from direct-requests, allowing you to ensure that all requests are directed e.g. through a controller or other mechanism that protects your scripts from casual browsing. – Christopher Schultz Jun 19 '20 at 20:18
0

I read JSP 2.0 spec and here:

 Relative URL Specifications

 * A context-relative path is a path that starts with a slash (/).
 It is to be interpreted as relative to the application to which
 the JSP page or tag file belongs. That is, its ServletContext
 object provides the base context URL.

 * A page relative path is a path that does not start with a
 slash (/). It is to be in- terpreted as relative to the current
 JSP page, or the current JSP file or tag file, depending on where
 the path is being used.

For now javax.servlet.ServletContext.getRealPath("/WEB-INF/test/test.jsp") is null for security reason.

Assume that context-relative path is path from your WAR root.

gavenkoa
  • 45,285
  • 19
  • 251
  • 303