The domain module was supposed to be framework-free. That was the whole premise of the module split back when the project moved to a multi-module Maven layout: domain objects and use cases in one module, persistence and web concerns in others, a dependency arrow pointing one direction only. Nobody was supposed to be able to import Spring into domain code, because domain code wasn't supposed to know Spring existed.
Nobody enforced that on purpose. It was a convention, documented once in an architecture decision record nobody had reread in over a year, and conventions without enforcement decay exactly as fast as you'd expect. A new engineer needing a bean somewhere reached for @Component because that's what got autowired correctly, and it worked, because the domain module still had spring-context on its classpath as a transitive dependency from something else. Nothing broke, nothing failed review, because nobody was specifically looking for it, and the annotation looked completely at home next to everything else in the class.
The point where this stopped being theoretical was a routine cleanup: pulling spring-context off the domain module's dependency list entirely, on the assumption that removing an unused transitive dependency was a safe, boring change. The build didn't just fail, it failed in 30 places, scattered across use case classes, domain services, even two places inside what were supposed to be pure value objects.
Each of those 30 was a small decision that had made sense in isolation. A @Value here to inject a configuration property directly into a domain service instead of passing it through a constructor from the application layer. A @Component there because Spring's classpath scanning was easier than manually wiring a dependency. None of them were dramatic, and none of them showed up in code review as anything worth blocking, because reviewers were reading for correctness, not for which module a symbol was imported from.
The cost wasn't abstract. Domain logic that imports Spring can't be unit tested without a Spring context spinning up somewhere in the test, even for a pure business rule that has nothing to do with dependency injection. It can't be reused in a different delivery mechanism without dragging a framework along with it. And it quietly breaks the one guarantee the module boundary was supposed to provide, that the rules governing a claim, a payout, or an account state don't depend on which web framework happens to be serving the request.

Fixing the 30 was a day of mechanical refactoring. Making sure it stayed fixed was the part that mattered: an ArchUnit rule added to the build that fails any test run where a class in the domain package imports anything from org.springframework, with the dependency itself removed from the module's POM so it can't come back in silently through someone else's transitive import. The convention that used to live in a document nobody read now lives in the build, which is the only place a convention survives contact with a deadline.
More like this?
I write short production war stories like this one, plus a deep-dive architecture series. Subscribe here if you want both in your inbox.
Recommended Resources for Java & Spring Boot Engineers
If you are preparing for Senior/Lead Java interviews or looking to solidify your Spring Boot & Architecture skills, check out these highly-rated resources from the Javarevisited publication (Use promo code friends20 for an exclusive 20% discount automatically applied at checkout):
- Grokking the Java Interview Prepare for core Java, concurrency, JVM internals, and design pattern questions. Get Full Book (Paid) | Download Free Sample Copy
- Grokking the Spring Boot Interview Master Spring Core, Auto-configuration, Spring Data JPA, Security, and Microservices. Get Full Book (Paid) | Download Free Sample Copy
- Grokking the SQL Interview Deep-dive into query optimization, indexing, joins, and complex SQL window functions. Get Full Book (Paid) | Download Free Sample Copy
- The Complete Java + Spring + SQL Interview Bundle Get all three interview guides in a single heavily discounted package. Get the Ultimate Interview Bundle
- Spring Professional Certification Practice Questions (250+ Questions) Validating your skills? Practice with real exam-style questions before taking the Spring Professional certification. Get the Spring Professional Questions | Download Free Sample Copy

Top comments (0)