Hacker News new | ask | show | jobs
by lmm 2101 days ago
Spring boot specifically; regular Spring is relatively ok. I'm using it professionally at the moment. It's just impossible to find where anything is coming from or understand how your application is wired up, because everything magically appears based on what's on the classpath - it's like the COME FROM statement joke. Even just changing your dependency versions can suddenly radically change your application's behaviour (e.g. now it's suddenly running a webserver).
2 comments

I don't understand why is it better to have something wired up by annotations than explicitly writing java code. Is 'new' obsolete? At least tools (including IDE) can look for method calls, annotation strings not so much. I'm completely baffled by the popularity of Spring.
> I don't understand why is it better to have something wired up by annotations than explicitly writing java code.

The argument is that most of your services will be global-ish singletons, and so the details of which services are used from which other services are ceremony rather than business logic; if you've made a code change that means service A now calls service C instead of service B, you want the diff to be about the actual code change in A rather than the plumbing of where it's getting service C from. Since there are problems with language-level singletons (e.g. testability) you want to use plain objects passed to the constructor, but since 99.9% of the time the FooService is always going to be the FooServiceImpl, you don't want the trouble of explicitly wiring it all up yourself. I don't necessarily think Spring is worth it, but wiring by hand certainly does involve writing a lot of code that's more or less irrelevant to your actual business logic.

> At least tools (including IDE) can look for method calls, annotation strings not so much.

Actually one of the things that makes Spring almost tolerable is that IDEs generally do have integration with it, and so "find references" will work properly even for things that are reflectively instantiated by Spring.

(That only applies as long as your wiring is "static" though. With Spring Boot's conditional bean annotations all that goes out of the window and you have no hope of understanding where anything is coming from or where anything is used).

I am not sold on the premise that plumbing code is bad or not business logic, being explicit is no trouble, it is part of the story. How is writing a factory method worse than writing Spring configurations? Personally I prefer to write Java to Spring DSL.
The point is you don't have to write the Spring configuration (except in the rare cases where you need to override with something specific). Just mark each class's constructor as @Autowired, make an AnnotationConfiguredApplicationContext passing the list of all your classes, and you don't have to manually keep track of which services need which other services - Spring takes care of instantiating everything in order and passing dependencies into the things that need them.
Annotations make dependency injection simpler. If you have a Controller that has a Service autowired into the constructor then you can test it by passing a mock service into the constructor.

An alternative would be to have a Main method construct all of the objects and pass them into each other, but @Autowired takes care of that for you.

I don't see any problem with that, in fact, being explicit is a huge plus. I would take that any day of the week over untraceable code. To be more precise, I'm not just baffled by the popularity of Spring, I don't even comprehend how any of that is a good idea to begin with. It solves a non problem and brings in enormous baggage.
That is true, there's a lot of "magic" that comes with boot. It can be helpful to take a look at what all of that auto-configuration code is actually doing, but reading that stuff is pretty difficult as well.
> It can be helpful to take a look at what all of that auto-configuration code is actually doing

You can't tell by reading it either, because it's all dynamic: all of the autoconfigurations create beans conditionally only if other beans of that type aren't defined, if certain classes are present on the classpath, if particular values are defined in the configuration that's written in magical self-transforming YAML, or all three. The only way I've found is to breakpoint at the point where something is wired in to see what the concrete class is, then breakpoint again in the constructor of that class to find where it's being constructed from, so you have to restart your application and run the (slow) spring boot startup twice for each thing you care about. And even that doesn't always work because spring encourages doing AOP with bytecode-manipulation-based proxies.