Reputation: 131
I have come across a curious scenario in which any attempt of using CDI for managing a singleton has resulted in failure no matter the solutions I tried, and I am not even sure at this point if this is something feasable/that can be done, hence the reason I am posting here.
I'll try to explain to my best the current scenario and I would like to know whether my intention can be done, and if yes, by what way, and if not, is there some alternative to "upgrading" the singleton instances in that jar. If I have missed details/parts of the code, please let me know, as this is something a little bit unusual and I do not if I provided everything needed.
Background:
Intention:
Steps taken:
For one single class, removed the private constructor, getInstance(), created a new interface for the class to expose only certain methods, and the singleton class was implementing the new interface and was marked with the @Singleton annotation from javax.inject.
In the war project, removed the getInstance() call, and set the variable with @Inject as a field in the class that was using it, like so:
@Inject
private Management managementInterface;
...
void someMethod(){
managementInterface.performBusinessLogic();
}
This resulted in a NPE being thrown when calling performSomeBusinessLogic(), for which I found several answers, so I have added a beans.xml to that jar with discovery-mode=all, tried the @Singleton from javax.ejb, but nothing worked to make it possible to inject that singleton.
I have searched quite some time to see how this could be done, but most of the scenarios depicted here/on google are about inter-ejb communication between application deployed in the same container, but this is not the same : we are trying to use CDI to inject a singleton from a jar file that is not an ejb/war project, but rather a simple java library.
Things to consider:
That singleton class was previously used in multiple ejb/war projects with no issues, so the fact that it was put as a custom module in JBoss and a standalone jar means there really is one only instance of that class for all the calling ejb/war projects, and we avoid the whole context/class-loading typical issues that come with this stuff.
That singleton exposed quite a lot of methods, some of which were actually better not exposed, so I would like to put an interface before it so the calling clients will only have access to some methods, but not all of them.
The jar file has access to a lot of libraries/dependencies due to the structure of the project and the way the dependencies are managed, so the intention was to drop the old way of creating and using singletons and migrating it to something more modern.
The IDE (Intellij) is able to resolve the dependency without issues, as can be seen in the following attachment, on clicking the blue mark icon it leads to the class that is marked with @Singleton and that's implementing that interface.
Question:
Upvotes: 2
Views: 452
Reputation: 880
If the Management class is in a jar dependency (provided from JBoss or packaged inside the ear) is not viewed as a CDI bean. It must be insiede an EJB/CDI module packaged at the same level as testing-ejb.
Another way is to use @Remote EJB annotation and deploy the jar as a library, not a simple dependecy.
It's not clear (for me) the purpose of this refactoring but if is to avoid to instantiate the class manually on every bean that need it you could write a simple producer:
@Singleton
public class ManagementProvider() {
@Produces
public Management getInstance() {
return Management.getInstance();
}
}
Then you can use @Inject anytime you want!
Upvotes: 1