Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

JSP in Moderation: Keeping Views Thin

Posted on October 16, 2010 By Luis Fernandez

Are your JSPs carrying more weight than they should? Do you feel that every small tweak needs a hunt across five files and a guess about what the controller is secretly doing? Are you copy pasting error handling and formatting logic in every view, hoping it will not bite you next week? With Oracle now steering Java after the Sun deal and Servlet 3.0 features landing in containers like Tomcat 7, this is a good time to ask a simple question that saves teams a lot of pain: how thin can a JSP be while still doing its job well?

Short answer: thinner than what most apps ship today.

Why keep JSP views thin

JSP is a view technology. That means its primary duty is to present the model that controllers and services prepare. When JSP gets stuffed with branching, calculations and data access, the page becomes a mini application that is hard to read and harder to test. Thin views are easier to cache, faster to tweak, and friendlier to new teammates. Tools like JSTL and the Expression Language are mature and fast, and with Java EE 6 in the wild there is no excuse to keep pouring Java code inside your pages. Keep the separation of concerns clean and your future self will thank you.

Less guessing, more shipping.

Scriptlets are a code smell you can smell from space

Scriptlets were fine around the time when jQuery was not even a thing. Today it is different. We have tag libraries, the Expression Language, and better controllers. Scriptlets mix Java into HTML and turn code review into archaeology. They tempt you to hit a DAO or parse dates in the view. That path is slow and brittle. Prefer JSTL for loops and conditions, fmt for i18n and dates, and small custom tags for repeated view pieces. Your JSP should read like a template, not like a servlet wearing lipstick.

<%-- Bad: business logic in the view --%>
<% 
  User user = (User) request.getAttribute("user");
  if (user == null) {
    user = userDao.findById(Long.parseLong(request.getParameter("id"))); // yikes
  }
  List<Order> orders = orderService.recentOrders(user.getId());
%>

<h3>Hello <%= user.getName() %></h3>
<% for (Order o : orders) { %>
  <p>Order #<%= o.getId() %></p>
<% } %>

That work belongs in the controller.

JSTL and EL carry the load

JSTL gives you clean iteration, conditions, and formatting without leaking Java code into the page. EL lets you reach the model in a tidy way. If your JSP uses only c, fmt, and maybe a custom tag or two, you are on the right track. Reserve Java for controllers and services. Keep the view a template that pulls data already shaped for display. That keeps your HTML readable and makes designers and developers both happy.

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

<h3>Hello ${user.name}</h3>

<c:if test="${empty orders}">
  <p>No recent orders.</p>
</c:if>

<c:forEach var="o" items="${orders}">
  <p>Order #${o.id} 
    on <fmt:formatDate value="${o.date}" pattern="yyyy MMM dd"/>
  </p>
</c:forEach>

Readable and safe.

Push logic to controllers and services

Controllers should gather data, prepare view models, and choose the JSP. With Servlet 3.0 you can use annotations and avoid web xml clutter. Populate request attributes with ready to render data. No DAOs in JSP. No try catch in JSP. Keep that stuff where it belongs. The view should only concern itself with HTML and small decisions about presentation. This also opens the door for unit tests on controllers where it is easier to test logic.

// Servlet 3.0 style controller
@WebServlet("/account")
public class AccountServlet extends HttpServlet {
  @Inject private OrderService orderService;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    User user = (User) req.getAttribute("user"); // set by auth filter
    List<OrderSummary> summaries = orderService.recentSummaries(user.getId(), 5);
    req.setAttribute("user", user);
    req.setAttribute("orders", summaries); // view friendly data
    req.getRequestDispatcher("/WEB-INF/views/account.jsp").forward(req, resp);
  }
}

Views love pre cooked data.

When JSTL is not enough, use tag files or simple tags

If you repeat markup and tiny bits of logic across pages, write a tag file or a simple tag instead of dumping logic in each JSP. Tag files are quick and live under WEB INF tags. They keep your markup tidy and your view rules consistent. This is perfect for common widgets like pagers or alerts.

<%-- /WEB-INF/tags/alert.tag --%>
<%@ tag body-content="scriptless" %>
<%@ attribute name="type" required="true" %>
<div class="alert ${type}">
  <jsp:doBody />
</div>

<%-- usage in a JSP --%>
<%@ taglib prefix="ui" tagdir="/WEB-INF/tags" %>
<ui:alert type="warning">Card on file is expiring soon.</ui:alert>

Small tag. Big win.

Spring MVC and Struts 2 play nice with thin JSPs

Most teams I meet are on Spring 3 or Struts 2. Both make thin views natural. In Spring MVC you return a model and a view name and let the resolver pick the JSP. You can use Spring form tags to reduce noise around forms and binding. In Struts 2 you pass an action value stack to the view and keep markup free of Java. Either way the principle is the same. Push logic out, keep display in.

// Spring 3 controller
@Controller
@RequestMapping("/profile")
public class ProfileController {
  @RequestMapping(method = RequestMethod.GET)
  public String show(Model model, @AuthenticationPrincipal User user) {
    model.addAttribute("user", user);
    model.addAttribute("orders", orderService.recentSummaries(user.getId(), 5));
    return "profile"; // /WEB-INF/views/profile.jsp
  }
}
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<h3>Edit profile</h3>
<form:form modelAttribute="user">
  <label>Name</label> <form:input path="name"/>
  <input type="submit" value="Save"/>
</form:form>

Frameworks help. Discipline finishes the job.

Keep performance and caching in mind from day one

Thin JSPs are faster to render and easier to cache. Precompile JSPs in your build if your container supports it, or warm up on startup to avoid the first hit penalty. Use tag files or includes to avoid repeating expensive fragments. Let Tomcat 7 handle gzip and set sane cache headers for static files. For dynamic views, cache small computed chunks in the controller or service layer where you have control. Pair this with a front end diet using jQuery, fewer requests and compressed assets. Less work for the JSP means happier users.

Fast pages get read. Slow pages get closed.

Team rules that keep JSP in moderation

Make thin views a team rule and back it with quick checks. A simple grep in your pre commit hook can block scriptlets. Code reviews should call out Java in JSP, unreachable branches, and raw database calls. Favor EL, JSTL and small tags. Keep helpers in services. Use fmt for dates and i18n. If a JSP grows past a few small decisions move logic out. If a template repeats across pages extract a tag file. When in doubt ask yourself whether a designer could edit the JSP without breaking the app. If the answer is no, move logic out.

# pre-commit example to block scriptlets
if git diff --cached --name-only | grep -E '\.jsp$' > /dev/null; then
  if git diff --cached | grep -n '<%[^@=!]' > /dev/null; then
    echo "Blocked: scriptlet found in JSP. Use JSTL or tags."
    exit 1
  fi
fi

Guardrails beat heroics.

A simple checklist for thin JSPs

– The JSP uses only EL, JSTL, and custom tags.
– The controller sets all attributes needed for display.
– No data access or service calls in the view.
– Repeated markup lives in tag files.
– Formatting uses fmt and messages bundles.
– The JSP is readable by someone who does not write Java daily.

Keep the view a view.

Thin JSPs age well.

Software Architecture Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes