TL;DR: Don’t surprise your fellow developers.
Yesterday I learned – or realized again, don’t know – that one can add @CompenenScan
to all Spring components and not only to @Configuration
components:
TIL A @ComponentScan on a @Service class in #Spring actually works and contributes to the application context. 🤯
— Michael Simons (@rotnroll666) May 16, 2019
It’s also ok to annotated methods of standard components with @Bean
and turn them into weird factory components (Those being processed in “light” though, as Marten reminded us.)
I see several issues here, the dilution of concern’s being my primary. I can get a quick overview of all services of an application with my IDE looking for @Service
or whatever. The same with configuration. That helps me a lot not to have to think about things.
I spent a considerable amount of time yesterday helping a friend debugging a weird @SpringBootTest
. He wanted to exclude some services from being started and only test some. The first impression was: He tried this by specifying them on the classes
attribute of @SpringBootTest
. That’s not what that attribute does. That attribute is used to point the test context to configuration classes.
To include or exclude components from being started, one uses @ContextConfiguration
, also from the test package. It has include
and exclude
.
So we added this and removed the classes from @SpringBootTest
attribute. And: Nothing worked anymore. Wtf? After some digging it turned out, that those services mentioned on that attribute – while clearly named and annotated service – also configured more component scanning and the module did not have a @SpringBootApplication
, so the test context couldn’t figure out about the components without being explicitly told to.
Given the fact that the project in question was just a bit older than a year, I think it’s already legacy and not in a good sense: A new developer joining that team would be have a super hard time figuring out what’s happening and why? Things are being named in one way and do something else or something in addition.
Go figure what happens next: It’s always Springs fault, of course.
Well, this time I’d say it’s quite dangerous indeed that all components contribute to the application context and not only @Configuration
classes.
Imagine a library, containing some cool services. When you add this library via a custom starter, you would be hopefully aware, that the starter can add many things to your context. You could however be explicit and write down your own @Configuration
and return new AwesomeLibraryService()
from within a @Bean
method. The AwesomeLibraryService
could be annotated with an arbitrary @ComponentScan
and scan the kitchen sink, the JDK and all the rest, including a blockchain mining library. Probably not what you want.
Anyway, we all are responsible developers, everyone does DDD and writes nice, clean micro services.
My impression of real world projects, especially in big cooperates, is a another. I always stumble upon the same issues:
- Issues with dependencies
- Incompatibile versions
- Cargo cult: A configuration hacked together from various sources is passed on all the time
People are gonna reuse the stuff the find somehow working in projects, whether it’s good or bad.
It’s a seniors developers responsibility to make sure that things have well defined concerns. I am sure that it is impossible to prevent cargo cult, but one can make it a bit safe.
Title photo by Franck V. on Unsplash.
No comments yet
One Trackback/Pingback
[…] >> Separation of Concerns in Spring Applications [info.michael-simons.eu] […]
Post a Comment