Best Practices for Avoiding Scriptlets in JSP 2: From Legacy Code to Modern Alternatives

Nov 22, 2025 · Programming · 10 views · 7.8

Keywords: JSP Scriptlets | JSTL Tag Library | EL Expression Language | Servlet Filters | MVC Design Pattern

Abstract: This article provides an in-depth exploration of techniques to avoid scriptlets in JSP 2, analyzing six major disadvantages of scriptlets and systematically introducing modern alternatives including JSTL tag libraries, EL expressions, Servlet filters, and MVC patterns. Through concrete code examples and architectural comparisons, it demonstrates how to achieve better code reusability, testability, and maintainability while adhering to Oracle's official best practice recommendations.

Analysis of Scriptlet Limitations

In the early stages of JSP development, developers commonly used scriptlets to embed Java code within JSP pages. These code blocks, represented by <% %>, <%= %>, and <%! %> syntax, could implement business logic functionally but introduced significant architectural problems. Since the birth of JSTL (JavaServer Pages Standard Tag Library) and EL (Expression Language) in 2001, industry consensus has formed: scriptlets should be avoided whenever possible.

The main drawbacks of scriptlets manifest in six critical dimensions:

  1. Lack of Reusability: Scriptlets cannot be reused across different JSP pages, leading to duplicated logic code in multiple locations.
  2. Insufficient Replaceability: Scriptlets lack abstraction mechanisms, making unified logic replacement and upgrades difficult.
  3. Limited Object-Oriented Capabilities: Unable to effectively utilize inheritance, composition, and other object-oriented features for code organization.
  4. Debugging Difficulties: When scriptlets throw exceptions during execution, typically only blank pages are returned without detailed error information.
  5. Testing Impracticality: Scriptlets are difficult to unit test, making it hard to ensure code quality and reliability.
  6. High Maintenance Costs: Mixed business and presentation logic creates chaotic code structures requiring more time and effort for long-term maintenance.

Official Specifications and Best Practices

Oracle explicitly recommends in its official JSP coding conventions: when tag classes can provide equivalent functionality, JSP scriptlets should be avoided. The JSP 1.2 specification particularly emphasizes that using JSTL can help significantly reduce the need for scriptlets in JSP pages. Pages employing tag libraries typically offer better readability and maintainability while facilitating the separation of business logic from presentation logic—the core concept of the MVC design pattern.

In the MVC architectural pattern, JSP scriptlets should not be used for writing business logic. Instead, business logic should reside in appropriate Java classes, with JSP pages responsible only for data presentation. Even when data transformation is needed, front controller Servlets or custom tags should be prioritized.

Specific Alternatives and Implementations

Using Servlet Filters for Common Logic

For common logic that needs execution on every request, such as user authentication, Servlet filters should be used. The following example demonstrates session validation in a filter:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
    throws ServletException, IOException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    
    if (httpRequest.getSession().getAttribute("user") == null) {
        httpResponse.sendRedirect("login.jsp");
    } else {
        chain.doFilter(request, response);
    }
}

By configuring appropriate <url-pattern> in web.xml, this logic can be applied to all relevant JSP pages, avoiding code duplication.

Using Servlets for GET Request Processing

For GET requests requiring data preprocessing, such as loading product lists from a database, implementation should occur in the Servlet's doGet() method:

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
    try {
        ProductService service = new ProductService();
        List<Product> products = service.getAllProducts();
        request.setAttribute("products", products);
        request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
    } catch (SQLException e) {
        throw new ServletException("Database query failed", e);
    }
}

This approach separates database access from page rendering, making exception handling easier while allowing flexible response adjustments before JSP display.

Using Servlets for POST Request Processing

For processing form submissions via POST requests, such as user login validation, implementation should occur in the Servlet's doPost() method:

protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    UserService userService = new UserService();
    User user = userService.authenticate(username, password);
    
    if (user != null) {
        request.getSession().setAttribute("user", user);
        response.sendRedirect("home.jsp");
    } else {
        request.setAttribute("errorMessage", "Invalid username or password");
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
    }
}

This architecture provides clearer page navigation logic, allowing flexible choice between redirects and forwards based on business outcomes.

Using JSTL for Page Flow Control

When controlling flow within JSP pages, the JSTL core tag library should be used. The following example demonstrates using c:forEach to iterate through a product list:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<table>
    <tr>
        <th>Product Name</th>
        <th>Description</th>
        <th>Price</th>
    </tr>
    <c:forEach items="${products}" var="product">
        <tr>
            <td>${product.name}</td>
            <td>${product.description}</td>
            <td>${product.price}</td>
        </tr>
    </c:forEach>
</table>

Compared to scriptlets, XML-style tags are clearer and more readable, avoiding complex bracket nesting issues.

Using EL Expressions for Data Access

For simple data access and display, EL expressions should be used. The following example demonstrates echoing form submission values:

<input type="text" name="username" value="${param.username}" />

${param.username} is equivalent to request.getParameter("username") but with more concise syntax.

Using EL Functions for Utility Methods

For utility methods needed in JSP pages, they can be defined as EL functions. JSTL provides a standard function library, and custom functions can also be created. The following example demonstrates using fn:escapeXml to prevent XSS attacks:

<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<input type="text" name="comment" value="${fn:escapeXml(param.comment)}" />

Forced Disabling of Scriptlets

To ensure development teams follow best practices, scriptlets can be forcibly disabled in web.xml configuration:

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

This configuration throws exceptions when scriptlets are detected, forcing developers to use modern alternatives.

Architectural Evolution and Future Directions

Facelets, the successor to JSP and the view technology for JSF, has completely removed support for scriptlets, forcing developers to build web applications "the right way." Modern Java web development increasingly favors complete MVC frameworks like Spring MVC, JSF, or Wicket, which provide stricter separation of concerns and better development experiences.

By adopting the alternatives discussed in this article, developers can build more robust, maintainable, and testable web applications while preparing technically for migration to modern web frameworks.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.