How to avoid using scriptlets in my JSP page?

I think it helps more if you see with your own eyes that it can actually be done entirely without scriptlets.

Here’s a 1 on 1 rewrite with help of among others JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) core and functions taglib:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <link href="https://stackoverflow.com/questions/2188706/${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a 
    ${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/events/Listing.action">Events</a>
  <a 
    ${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''}
    href="${pageContext.request.contextPath}/people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}">
    <a href="Listing.action">List of Events</a>
    |<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}">
    <a href="Listing.action">List of People</a>
    |<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

Here’s a more optimized rewrite, note that I used c:set to “cache” expression results for reuse and that I use HTML <base> tag to avoid putting the context path in every link (just make all relative URL’s in your webpage relative to it –without the leading slash!):

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" />
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" />

<html>
<head>
  <title>My Events - <decorator:title /></title>
  <base href="https://stackoverflow.com/questions/2188706/${pageContext.request.contextPath}">
  <link href="assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div class="tabs">
  <a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a>
  <a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a>
</div>

<div class="submenu">
  <c:if test="${isEvents}">
    <a href="Listing.action">List of Events</a>|<a href="New.action">New Event</a>
  </c:if>
  <c:if test="${isPeople}">
    <a href="Listing.action">List of People</a>|<a href="New.action">New Person</a>
  </c:if>
  &nbsp;
</div>

It can actually be optimized more if you collect all those “hardcoded” values like events and people and link texts in a Map in the application scope and use under each the JSTL <c:forEach> to display the tabs.

As to your actual question, you can disable scriptlets (and get runtime errors about using it) by adding the following entry in webapp’s web.xml. It may help to spot overseen scriptlets.

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <scripting-invalid>true</scripting-invalid>
    </jsp-property-group>
</jsp-config>

To learn more about EL, check the Java EE tutorial part II chapter 5. Implicit EL objects, such as ${pageContext} are described here. To learn more about JSTL, check the Java EE tutorial part II chapter 7. Note that JSTL and EL are two separate things. JSTL is a standard taglib and EL just enables to access backend data programmatically. Although it is normally used in taglibs like JSTL, it can also be used standalone in template text.

Leave a Comment