The Front Controller Pattern
The Front Controller Pattern
As a Jakarta EE web application grows, a common trap appears: every feature gets its own servlet, every servlet duplicates authentication checks, logging, and routing logic, and the codebase turns into a tangle of overlapping responsibilities. The Front Controller pattern is the architectural cure. Instead of mapping URLs directly to individual servlets, a single entry-point servlet receives every request, inspects it, and delegates to a lightweight command handler that knows only about that one use-case. Security, logging, encoding, and other cross-cutting concerns live in exactly one place.
DispatcherServlet, Struts's ActionServlet, and JSF's FacesServlet are all Front Controllers. Learning the raw pattern gives you the mental model to understand and debug any of them.
The Problem Without a Front Controller
Imagine a simple shop application with three servlets: LoginServlet, ProductServlet, and CartServlet. Each one must check whether the user is logged in, set the response encoding, and log the request. The duplication is not just tedious — it is dangerous. When the authentication check changes, you must update three places. When you add a fourth servlet you must remember to add the cross-cutting code. You usually forget.
Structuring the Solution
The pattern has three collaborating pieces:
- Front Controller Servlet — the single servlet mapped to
/*(or a common prefix). It extracts a command name from the request, finds the right handler, and calls it. - Command (Handler) interface — a tiny interface every handler implements. The front controller depends only on this abstraction.
- Concrete Handlers — one class per use-case (login, list products, add to cart). No servlet infrastructure; just business logic and a forward or redirect at the end.
The Command Interface
Keeping the interface this thin means handlers stay focused. They set request attributes, call service-layer methods, and then either request.getRequestDispatcher("/WEB-INF/views/foo.jsp").forward(request, response) or response.sendRedirect(...).
A Concrete Handler
The Front Controller Servlet
service(), not doGet()/doPost(). Overriding service() lets the front controller pass the HTTP method through to the handler unchanged. If your handler needs to differentiate GET from POST it can read request.getMethod() itself, keeping that decision where it belongs.
Authentication in One Place
One of the biggest wins of the Front Controller is centralised authentication. Add the check to service() before dispatch, and every handler in the application is automatically protected:
Handling POST vs GET in Handlers
A handler that manages a form typically responds differently depending on the HTTP method — GET renders the empty form, POST processes the submission and redirects. The handler does this cleanly without any servlet infrastructure:
Trade-offs and When to Use It
- Pro: Cross-cutting concerns (auth, encoding, logging, CSRF) live in exactly one class.
- Pro: Adding a new use-case means adding one handler class and one line in the command registry — no new servlet, no new URL mapping.
- Pro: Handlers are plain Java objects; they are easy to unit-test without a servlet container.
- Con: The command registry in
init()can grow large. In a mature application you would replace the manual map with reflection-based auto-discovery or a dependency-injection container. - Con: Mapping one URL pattern to all commands means the HTTP method semantics of individual endpoints are less explicit to the container. Document your conventions clearly.
FrontControllerServlet starts doing database lookups or building HTML, you have recreated the original problem in a single class. The Front Controller's only job is to route and apply cross-cutting concerns.
Evolving Toward Frameworks
What you have built is a miniature DispatcherServlet. Spring MVC adds annotation scanning (@GetMapping, @PostMapping), argument resolvers, view resolvers, and interceptors — but the dispatch loop in the centre is exactly this pattern. Understanding the raw version means you can read Spring's source code, configure it correctly, and diagnose subtle routing bugs instead of being mystified by them.
Summary
The Front Controller pattern solves the cross-cutting duplication problem by funnelling all requests through a single dispatch servlet. That servlet resolves a command name from the URL, applies shared concerns (authentication, encoding), and delegates to a thin Command handler. The result is a codebase where adding a feature means adding one class, and where security or logging changes happen in exactly one place. In the final lesson of this tutorial you will combine sessions, filters, and the Front Controller into a complete login-and-protected-area project.