This is a demo application that serves as an executable guideline for migrating a large-ish service written in "Play for Java" framework to a traditional servlet-based Spring MVC service.
- CompanyGuardian aspect guarding "companyId" request header
- CustomerEntity entity representing a simple "customer" record (DTO omitted for brevity)
- CustomerRepository - for manipulating
CustomerEntity
- CustomerQueries and CustomerCommands - service-layer components, logical transaction boundaries
- CustomerReadingController and CustomerWritingController - Spring MVC controllers using queries, commands, and preconditions
- DbContextHolder - keeps track (thread local) about which database to use (master/slave replication)
- RoutingDataSourceTransactionInterceptor - automatically switches master/slave data source based on the logical transaction type (reading/writing)
- PreconditionsAction - invokes all provided preconditions before proceeding/rejecting the main logic call (delegated by the controller)
- ValidPayloadPrecondition - payload-aware precondition that binds the JSON request, and executes any required validations
- RequestLoggingFilter - logs HTTP requests
- ErrorHandler - handles common errors (400s, 5xx)
- SpringHttpContext - adapter between Play's
ctx()
and Spring/Servlet world
Would we write an app like this had we started with Spring MVC straight away? No. But we have a bunch of existing components and we need to mitigate the risks of this migration as much as we can. Therefore we're carrying over some styles/components that are not typically seen in Spring MVC applications:
- Guardians instead of Controller Advices
- manual aspects guarding path variables and query parameters
- Preconditions instead of Controller Advices and/or auto-binding
@ModelAttribute
-like advices are substituted withPreconditionsAction
- Manual validation instead of
@Valid
@Valid
and custom validators are possible (and possibly preferred for the future usages), but this demo also supports manual payload preconditions and JSON request to POJO binding
- Actions
@With(FooAction.class)
are replaced with Controller Advices, see ErrorHandler for example application.conf
is replaced with application.ymlctx()
(hidden behind HttpContext) are replaced by Spring-first binding (@RequestHeader
,@RequestParam
etc.) or adapted usingRequestContextHolder
(for storing request-only data)