Bodyless classes only for carrying annotations... too much magic for my taste.
Spring Boot Done Right: Lessons from a 400-Module Codebase
91–100 of 100 posts
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#92I wonder how many of these rules can be enforced with static analysis and ArchUnit.
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#93Hacker news likes to dunk on Spring Boot, but its usage in enterprises is very very high.
it doesn't mean that usage of something being very high is a clever idea. lots of people take meth - so are you gonna take meth too. ```@EnableConfigurationProperties(CasConfigurationProperties.class) @EnableScheduling @ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.SimpleMFA) @AutoConfiguration @Import({ CasSimpleMultifactorAuthenticationComponentSerializationConfiguration.class, CasSimpleMult…
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#94Hacker news likes to dunk on Spring Boot, but its usage in enterprises is very very high.
Huh, Enterprise usage of Blackberry was very very high and then it was not. And at one point SOA, SOAP/WSDL/XML usage was very very high and now I am told in my very enterprise job I'd be fired if I dared bring those names up. Usage being high doesn't say anything about quality or suitability of a product specially in enterprise settings.
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#95Hacker news likes to dunk on Spring Boot, but its usage in enterprises is very very high.
I'm not that deep into Java, but I was under the impression that things like Quarkus were starting to replace Spring in enterprise use...
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#96There is no right way to do Spring Boot.The entire idea is broken. Dependency injection is good. It makes it possible to test stuff. Automagic wiring of dependencies based on annotations is bad and horrible. If you want to do dependency injection, you should do it the way Go programs do it. Create the types you need in your main method and pass them into the constructors that need them. When you write tests and you w…
The other issue is dynamic configuration. How do you handle replacing certain dependencies, e.g. for testing, or different runtime profiles? You could try to implement your own solution, but the more features you add, the closer you'd get to a custom DI framework. And then you'd have an actual mess, a naive non-standard solution for a solved problem, because you didn't want to read the manual for the standard implementation.
By the way, Spring dependency injection is mainly based on types. Annotations are not strictly necessary, you can interact with the Spring context in a procedural/functional manner, if you think that makes it better. You can also configure MVC (synchronous Servlet-based web) or Webflux (async web) routes functionally.
When a bean is missing, the app will fail to start, and you will get an error message explaning what's missing and which class depends on it. The easiest way to ensure this doesn't happen is to keep the empty @SpringBootTest test case that comes with the template. It doesn't have any assertions, but it will spin up a full Spring context, and fail if there is a configuration problem.
The only complicated part about Spring Boot is how the framework itself can be reconfigured through dependency injection. When you provide a certain "bean", this can affect the auto-configuration, so that other beans, which you might expect, are no longer automatically created. To debug this behavior, check out the relevant AutoConfiguration class (in your IDE, use the "go to class" shortcut and type something like FooAutoConfi..., e.g. JdbcAutoConfiguration).
In a good codebase, the configuration itself would be tested. For instance, if you did something a bit more complicated like connecting two JDBC databases at the same time, you would test that it read the configuration from the right sources and provides the expected beans.
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#97> What makes the CAS codebase impressive is the discipline of applying all of them consistently, across 400 modules, for years. I think this is the main point. You can write good code in any language following this concept.
That's really the whole thesis. None of the patterns in the article are clever or novel - @ConditionalOnMissingBean has been in the Spring Boot docs since day one. What's hard is getting a team to apply it on every single bean, in every single module, for years, without anyone cutting corners. Discipline scales. Cleverness doesn't.
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#98Earlier quoted context omitted.
it saves a lot of reinventing the wheel
And at the same time, gives you a dozen of footguns. This is just a list for the gotchas in the "@Transactional" annotation - https://dev.to/closeup1202/8-spring-transactional-pitfalls-t... Now read up on all the dozen of annotations. But yeah, we did not want to "re-invent the wheel".
Thankfully the company that wrote the article has a linter/warning product to help avoid those pitfalls.
Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#99Earlier quoted context omitted.
Im comparing against node equivalent ORMs and find spring consistently better. Yeah ive got to read up on annotations - but when it comes to transactions its always worth revisiting them to check for changes
Meh... await using cn = await pool.connect(); const records = await cn.query ` SELECT ... FROM ... WHERE ... `; for await (const record of records) { ... } Oh, spring is so much better...
var records = jdbcClient
.sql("select * from posts")
.query(Post.class)
.toList();
records.forEach(p -> ...);Re: Spring Boot Done Right: Lessons from a 400-Module Codebase
#100Earlier quoted context omitted.
Meh... await using cn = await pool.connect(); const records = await cn.query ` SELECT ... FROM ... WHERE ... `; for await (const record of records) { ... } Oh, spring is so much better...
Spring version: var records = jdbcClient .sql("select * from posts") .query(Post.class) .toList(); records.forEach(p -> ...);