How a web request is routed and handled: MVC's actual division of responsibilities, Page Controller versus Front Controller, and Application Controller for flows whose next step is a decision. Use when controllers contain business rules or persistence calls, when the same cross-cutting concern is copied into every handler, when a wizard's navigation logic is spread across handlers as if-chains, when a filter, interceptor and handler contend for one concern, when a controller is tested by star...
Scanned 9/19/2026
Install to Claude Code
npx -y skills add robsonkades/agent-skills --skill mvc-and-request-handling --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Mvc And Request Handling?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/robsonkades-mvc-and-request-handling)More formats (shields.io, HTML) on the badges page.
---
name: mvc-and-request-handling
description: >
How a web request is routed and handled: MVC's actual division of responsibilities, Page
Controller versus Front Controller, and Application Controller for flows whose next step
is a decision. Use when controllers contain business rules or persistence calls, when the
same cross-cutting concern is copied into every handler, when a wizard's navigation logic
is spread across handlers as if-chains, when a filter, interceptor and handler contend for
one concern, when a controller is tested by starting the whole application, or when
classical web patterns are mapped onto a REST API. Does not cover how the response is
rendered (view-and-representation-patterns), the remote operation and its payload
(remote-facade-and-dto), the use-case layer (service-layer-design), or where conversation
state lives across requests (session-state-strategies).
---
# MVC and Request Handling
## Purpose
Keep the web layer to its actual job — turning a request into a call and a result into a
response — and put shared request concerns in one place instead of in every handler. Modern
frameworks implement these patterns for you, so the value here is not in building them but
in **recognising which pattern a piece of code is playing**, and noticing when a
responsibility has landed in the wrong one.
## The vocabulary, disambiguated
"Model" means three different things in a typical discussion, and conflating them causes
real design errors:
```text
Domain model the business objects and rules (domain-logic-organization)
Presentation model what the view needs: already formatted, already decided
Framework model the map of attributes handed to a template (Spring's Model)
```
The separation used here for a web boundary:
```text
Controller interprets the request, invokes the application, selects the response.
Delegates business rules and use-case transaction ownership.
View renders. Owns no decisions beyond presentation.
Model application state/behavior in MVC's broader vocabulary;
prefer a deliberate presentation model at the response boundary.
```
Web MVC is not the original Smalltalk MVC: there is no observer relationship and no
long-lived view. The name persists; the mechanism is request → controller → model → render.
## Page Controller and Front Controller
```text
Page Controller one handler per page or action. Simple, local, and every
shared concern needs a shared mechanism such as filters
or composed collaborators.
Front Controller one entry point receives every request, applies shared
concerns, and dispatches to a handler. Shared concerns
exist once; the handler stays small.
```
Many Java web frameworks provide a Front Controller (for example Spring's `DispatcherServlet`),
and handler methods play the page/action role behind it. These patterns can coexist.
The practical questions are **which
concerns belong in the front controller's chain and which in the handler**, and whether the
chain's stages are being used correctly.
## Workflow
Start with the requested responsibility or ordering question. Reuse existing configuration
and tests; an adequate handler or trivial redirect can close with no change. Apply only the
steps needed for the actual contract, and state specific missing evidence without requiring
a full request-chain redesign or an Application Controller on every review.
1. **Check the handler's contents and runtime.** Inspect routing, security configuration,
Java and framework versions first. Examples use Servlet Spring MVC; `ProblemDetail`
requires Spring 6+ (Java 17+), not an implicit upgrade. A controller should bind input,
invoke application behavior, and map the result. Trace business rules and transaction
ownership; a simple read need not gain a pass-through service (`layering-and-boundaries`).
2. **Find duplicated policy.** Repetition count alone does not justify indirection; shared
authorization, error mapping, correlation, tenant and envelope semantics often belong in the
chain when centralization prevents drift and preserves ordering.
3. **Place it at the right stage.** Filter, interceptor, argument resolver, exception
handler, advice: they see different things and run at different times. Choosing wrongly
produces a concern that works until it does not.
4. **Assess flow decisions.** Repeated or independently changing journey decisions can
justify an HTTP-independent Application Controller. A local response choice may remain
in a handler; authoritative mutation rules still belong to the application/domain contract.
5. **Keep the response shape a deliberate decision**, not the accidental serialisation of
whatever the service returned (`remote-facade-and-dto`).
6. **Test at the right level.** Focused handler tests cover mapping, validation and status
codes with application doubles where useful. Use integration tests when the actual
transaction, security or serialization contract requires them.
## Decision rules
```text
A concern applies to every request (correlation id, security context,
request logging, tenant resolution)
→ an appropriate chain stage, with explicit route/dispatch coverage.
Order it after required identity/validation prerequisites and before
work that depends on it; a filter need not be first to be shared.
A concern applies to a group of handlers and needs to know which handler
was selected (authorisation on an annotation, feature flags per route)
→ enabled method security for authorisation; an interceptor can
handle non-security route metadata. Keep request security in
the security filter chain, with consistent path matching.
A concern turns an exception into a response
→ consistent error mapping at each boundary: MVC advice for MVC
exceptions, security/filter/container handlers for their failures.
Share the contract; avoid duplicated generic catches.
A concern turns request data into a domain-shaped parameter
(the current user, a parsed range, a tenant)
→ an argument resolver. This removes the boilerplate without
hiding a business rule.
The next step of a multi-step flow depends on state, not on a link
→ consider Application Controller when shared or complex journey
decisions need one owner, testable without HTTP. Keep simple
response choices local and mutation legality independently enforced.
A screen is one page, one action, no shared concerns beyond the global
ones
→ a plain handler. Do not build a flow abstraction for it.
The API is REST over resources
→ routing is by resource and method, not by page. Page
Controller and Front Controller both still describe what the
framework does. Choose a deliberate representation; Remote Facade
applies when network granularity needs it, not from the REST label alone.
```
## Rules
- A controller deciding domain policy is a layering defect; `if` itself is not evidence because
protocol negotiation, optional input and response mapping legitimately branch. Trace whether the
condition must hold for non-HTTP callers.
- **A controller with a repository call is not automatically wrong.** For a pure read it can
be the honest design. For writes, trace actual transaction, invariant and actor/resource
authorization ownership, including non-HTTP callers. An existing bounded operation may
already enforce the contract; extract a use-case boundary when coordination or independent
policy ownership requires it (`service-layer-design`).
- Cross-cutting concerns implemented per handler can diverge. Repeated policy plus observed drift or
ordering/security risk is the signal, and
consider a shared chain stage or collaborator before a base controller: Java's single
class inheritance makes independently varying base-class policies awkward to combine.
- **Choose the chain stage by what it must see.** Ordinary Servlet filters run before MVC
handler selection. Interceptors see the selected handler but are not a sufficient security
boundary: Spring warns of path-matching mismatches. Use the security chain and enabled
method security; test uncovered routes and alternate dispatches.
- The framework's model map is a presentation concern. Putting entities in it couples the
template to entity properties and can trigger lazy loading during rendering
(`orm-behavioral-patterns`).
- Validation splits in two and both halves are needed: **syntactic** (required, format,
range) belongs at the boundary, on the request type; **semantic** (this customer may not
order this product) belongs in the domain, where it can be enforced regardless of the
caller.
- One deliberate error contract across the application's HTTP boundaries. RFC 9457 problem details give a standard
target (`rpc-and-api-contracts`).
- **Application Controller is the least-known pattern here and the most useful** where it
applies: multi-step flows, approval chains, state machines. Its value is that the flow
becomes a testable object rather than a set of redirects spread over handlers.
- Do not map classical page-flow patterns onto an HTTP API by analogy. An API may expose resources,
commands, workflows and hypermedia; Remote Facade is useful when network granularity requires it,
not a synonym for every REST endpoint
(`remote-facade-and-dto`).
- Handler tests cover binding, validation, status codes and error shape with application
doubles where useful. Separate integration tests may legitimately include a database to
verify transaction, authorization or serialization behavior (`architecture-testing`).
Return the observed responsibility/ordering issue or supported no-change verdict, its evidence,
and the focused checks performed or still needed. Missing configuration makes claims about
filter coverage, authorization and transaction scope conditional; inspect it before diagnosing.
## References
- [Page Controller versus Front Controller](references/page-vs-front-controller.md) — both
patterns in a modern stack, exactly which shared concern belongs at which stage of the
chain (filter, interceptor, argument resolver, advice) with the ordering that matters, the
base-controller anti-pattern, and how the same reasoning applies to a message consumer or
a scheduled job. Read when placing a cross-cutting concern or reviewing a controller.
- [Application Controller](references/application-controller.md) — flow logic extracted from
handlers: a state machine over an application process, where the flow state lives, how it
is tested without HTTP, and when a flow abstraction is overkill. Read when a wizard,
approval chain or multi-step process is being built or has become unmanageable.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!