Do all the things like ++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatarSign Up
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple APILearn More
On a side note, I was having a sheets nervous breakdown for an HR thinking about all the tasks I am supposed to finish and not having enough time.
On the other hand, when I think about stuff like this, technical/conceptual, I find it interesting and sorta calming.
First off, there are 2 types of singletons: Spring-managed beans and your own managed singletons.
Secondly, Spring does not only operate in Singletons. Spring's dependency injection also supports PROTOTYPE (see the @Bean() params).
Thirdly, yes, that's how it works. However, there are a few things you should consider:
- Field injection (@Autowired private MyService service;) has become an antipattern. Use constructor/setter injections.
- The "global collection" is usually referred to as Spring's context in general.
- It is not bad is used correctly. It saves you from lots of boilerplate code, it enables you to easily plug in new services/controllers/etc to your application; other Spring modules as well.
- It might be bad if abused (e.g. field injections hide bad arch problems)
- you are marrying Spring, because @Autowired is only supported by Spring. JSR330 would be a solution but it is only partially supported by Spring.
@donuts Oh, and Spring can only inject dependencies into Spring-managed beans. It means you must register your controllers, services, repos and other components into the Spring context if you want Spring to do the injection for you. And these dependencies must also be in the context as well.
What Spring does nicely, it works out the sequence of the beans' initialization really well. I.e. it figures out which bean depend on which ones and initializes dependencies first.
@netikras what about in the case of multithreading, like SpringBoot.
Multiple requests come at once but if a Bean can only be used by one at a time?
Also I guess this goes into a issue I had with an existing app someone else wrote. For one of the classes it creates a new one per request by returning: new AppContext(...).getBean("helper");
Problem is after the request finishes, the object is not disposed and eventually causes memory and socket leaks but to a network connection created in the bean/context. And finally hangs the machine.
Is there some sort of kill-switch basically "get rid of everything it created immediately".
@donuts one doesn't normally create a separate context for each thread/request. Normally a single app uses a single context to cover it all.
Also, querying the context manually is not the preferred way to get/register a bean. If possible, use the Spring's annotations. Yes, it sounds weird, but it actually is a better approach. I like to see Spring like a proprietary product that hopefully knows what it's doing.
No, getting rid of all the beans is not possible. Spring is using its own beans in the same context, so nuking them is as good as System.exit(). Unless you go ahead and juggle multiple contexts all the time, which is a performance killer and a good way to create random ans hard to solve bugs.
I don't think there are concurrency issues in the context, since a singletone is only 1 instance and other beans are querying it, not writing. Anyways, if you encounter any - they should be easy to work around with custom synchronizers using some Factory pattern as a bean.
@netikras well whoever wrote this code thought it was a good idea... shortcut.
And sort back to the issue with global collections. The structure is Spring class -> many spring classes -> many spring classes.
And of course all have parameter less constructors and a ton of AutoWired...
So I guess a team of monkeys that never learned how to use spring the right way...
Then junior devs copy the code and just make it worse...
One of those inner classes causes the leak due to some lib that can't close itself...
So guess only way is system.exit();
The work I did was create a pool for the first class.
The problem and reason why the original code needed to create new contexts is because the super class it creates has a initialize(requestSpicificArgs) method... So can't have 2 requests using the same one at once....
@donuts I know there is a lot more to it than what you've just said and the devs probably had a good reason to do what they did.
But I can't help but think: WTF? All the webapps have request-speciffic methods and practically none of them need a separate Spring context created for each request. Sounds like either singletons done wrong (stateful) or someone misread (if read at all) Spring docs.
@netikras tried that but this lib can't close... Calling close() just hangs the thread or does it in background but doesn't really close.
Our team there's sr devs and jr devs. Senior devs do things because that's how they always did it.
Jr devs do things bc that's how the existing code does it.
And then there's me. When something fcks up that no one can fix, it goes to me and well the root cause everytime is "some incompetent monkey fcked up"... And it will keep on happening until I stop saving their asses...
Maybe next time something like this happens... I'll just reject helping them
@netikras u close the app. The root cause it's that lib resource should've been a Singleton except it's so nestsd in the code but it can't be fix easily.
And the inner classes is used by other "apps" or Spring contexts.
Anyway root cause it's bad design and the Sr devs are part of the problem and I think next time will let them few am with their own mess....
Main reason why I really want to change teams... I don't like being the global error handler...
But no team to change to. Tried last year the team I was joining got restructured away somehow...
Can't do external for health reasons and well COVID
@donuts I think even a reflection-based workaround (with some fields/methods caching if possible) would be a poor way to sovle the problem, but it would solve it for now. Unless, ofc, the code you are using is native (i.e. the methods have 'native' modifier).
Fire up your idea and use that built-in java decompiler to track down the mechanics of that lib and find a way to release your resources. Then summon some reflection for the job to clean all the mess. It'll be slow-ish, but it'd save you from restarts.
Or log a week-long Story to fix the architectural mess they've created. Hopefully, you do have unittests to have your back!
GoGetMeAJob21Let's see if this kitty survives the code review and makes it to production.
Crazed11So I tried to start learning Spring 5 How the fuck do you guys do it? Holy shit. 30 seconds in: "Spring r...
starrynights8913HOLY. CHRIST. MAVEN. Where has this thing been all my life. I can manage my Java web projects from a singl...