I have a singleton:
public class MySingleton{
public static getInstance(){//typical singleton getInstance
...
}
//fields
private static volatile instance;
#Inject
private AnotherClassInstanceThatIWantToInjectHere anotherClassInst_BlaBla;
private MySingleton(){
...
anotherClassInst_BlaBla.doSmth();//NullPointerException happens!
...
}
}
What is cause of this NPE? Does it happens because it is constructor or because it is singleton?
When the constructor of MySingleton is invoked, instance is null. Guice has to construct the instance of MySingleton before it has anything to inject into.
Guice has a concept of singletons: either you bind the class in singleton scope in your module, or you annotate the class as #Singleton. Then you just inject like usual:
#Singleton
public class MySingleton {
private AnotherClassInstanceThatIWantToInjectHere anotherClassInst_BlaBla;
#Inject public MySingleton(AnotherClassInstanceThatIWantToInjectHere anotherClassInst_BlaBla) {
this.anotherClassInst_BlaBla = anotherClassInst_BlaBla;
anotherClassInst_BlaBla.doSmth();
}
}
anotherClassInst_BlaBla is an instance variable in this case, I guess that's why you choose setter injection. Since it's an instance variable and also setter injection needs an instance to set this variable to, an instance of MySingleton class needs to be created/constructed to use anotherClassInst_BlaBla.
Shortly, you should call doSmth() method after the constructor MySingleton() is invoked because setter injection happens after an instance is constructed.
Related
I have a class that has been configured to be a Singleton, like this:
#Singleton
public class MySingleton {
public MySingleton(MyDependency dependencyObj) {
// ...
}
}
Is there a way to get a new instance of MyDependency injected into the single instance of MySingleton each time Guice provides it to some other class?
I can't make any changes to MySingleton (e.g., to make it something other than a Singleton)
I have a class as follows
#Component
public abstract class NotificationCenter {
protected final EmailService emailService;
protected final Logger log = LoggerFactory.getLogger(getClass());
protected NotificationCenter(EmailService emailService) {
this.emailService = emailService;
}
protected void notifyOverEmail(String email, String message) {
//do some work
emailService.send(email, message);
}
}
EmailService is a #Service and should be auto-wired by constructor injection.
Now I have a class that extends NotificationCenter and should also auto-wire components
#Service
public class NotificationCenterA extends NotificationCenter {
private final TemplateBuildingService templateBuildingService;
public NotificationCenterA(TemplateBuildingService templateBuildingService) {
this.templateBuildingService = templateBuildingService;
}
}
Based on the above example the code won't compile because there is no default constructor in the abstract class NotificationCenter unless I add super(emailService); as the first statement to NotificationCenterA constructor but I don't have an instance of the emailService and I don't intend to populate the base field from children.
Any idea what's the proper way to handle this situation? Maybe I should use field injection?
NotificationCenter is not a real class but an abstract class, so you can't create the instance of it. On the other hand, it has a field (final field!) EmailService that has to be initialized in constructor! Setter won't work here, because the final field gets initialized exactly once. It's Java, not even Spring.
Any class that extends NotificationCenter inherits the field EmailService because this child "is a" notification center
So, you have to supply a constructor that gets the instance of email service and passes it to super for initialization. It's again, Java, not Spring.
public class NotificationCenterA extends NotificationCenter {
private final TemplateBuildingService templateBuildingService;
public NotificationCenterA(EmailService emailService, TemplateBuildingService templateBuildingService) {
super(emailService);
this.templateBuildingService = templateBuildingService;
}
}
Now spring manages beans for you, it initializes them and injects the dependencies.
You write something that frankly I don't understand:
...as the first statement to NotificationCenterA constructor but I don't have an instance of the emailService and I don't intend to populate the base field from children.
But Spring will manage only a NotificationCenterA bean (and of course EmailService implementation), it doesn't manage the abstract class, and since Java puts the restrictions (for a reason) described above, I think the direct answer to your question will be:
You can't use setter injection in this case (again, because of final, it is Java, not because of Spring)
Constructor injection, being in a general case better than setter injection can exactly handle your case
First point :
#Component is not designed to be used in abstract class that you will explicitly implement. An abstract class cannot be a component as it is abstract.
Remove it and consider it for the next point.
Second point :
I don't intend to populate the base field from children.
Without Spring and DI, you can hardcoded the dependency directly in the parent class but is it desirable ? Not really.
It makes the dependency hidden and also makes it much more complex to switch to another implementation for any subclass or even for testing.
So, the correct way is injecting the dependency in the subclass and passing the injected EmailService in the parent constructor :
#Service
public class NotificationCenterA extends NotificationCenter {
private final TemplateBuildingService templateBuildingService;
public NotificationCenterA(TemplateBuildingService templateBuildingService, EmailService emailService) {
super(emailService);
this.templateBuildingService = templateBuildingService;
}
}
And in the parent class just remove the useless #Component annotation.
Any idea what's the proper way to handle this situation? Maybe I
should use field injection?
Not it will just make your code less testable/flexible and clear.
using field injection would be the way to go since you mentioned you don't want to have the emailService in child class.
The other way you can try is to inject the EmailService bean into NotificationCenterA constructor, and then pass it to super(emailService).
So, it would be something like:
#Autowired
public NotificationCenterA(EmailService emailService, TemplateBuildingService templateBuildingService) {
super(emailService);
this.templateBuildingService = templateBuildingService;
}
You can also achieve this by using #Lookup annotation.
public abstract class NotificationCenter {
protected final Logger log = LoggerFactory.getLogger(getClass());
#Lookup
protected EmailService getEmailService() {
return null; // Spring will implement this #Lookup method using a proxy
}
protected void notifyOverEmail(String email, String message) {
//do some work
EmailService emailService = getEmailService(); // This is return the service bean.
emailService.send(email, message);
}
}
I am using Spring Framework for Dependency Injection. At one point I inject an instance of a certain class into another class and I need to create an additional temporary object of the same class. I probably could change the scope of the injected bean to prototype but I wonder if there's another simple way to do that?
My only idea is to create it using new but wanted to know if there is a proper way to do it with Spring.
Just a general example:
#Inject
private ClassA classA;
public void methodA() {
// here I need another instance of ClassA to be used in the scope of this method
}
Just subclass it and use prototype scope.
#Component
#Scope("prototype")
public class ClassB extends ClassA {
}
Then, to use it:
#Autowired
private ApplicationContext context;
public void methodA(){
// will return a new instance (still a bean) every time its called
ClassB bean = context.getBean(ClassB.class);
...
}
You can also cast down to ClassA and use bean name if you like.
There are two ways you can do this based on the purpose of another instance of ClassA.
First,
you can create a new object using "new" keyword.
public void methodA()
{
ClassA antherClassAInstance = new ClassA();
}
This approch is suitable when you want to use the new instance only for this method.
Second,
Declare global instance using #Autowired annotation.
#Autowired
ClassA antherClassAInstance;
I want to externalize commonly used applicationlogic into a "utility class" called Helper. The applicationlogic needs other CDI beans to work.
Two possibilities:
a)
#SessionScoped
class ControllerWithCdiBean {
#Inject
Helper helper;
public void doIt() {
Object result = helpder.calculate();
}
}
#RequestScoped
class Helper{
#Inject
Service anyService;
public Object calculate() {
return anyService.calc();
}
}
b)
#SessionScoped
class ControllerWithStaticCallsViaDeltaspike {
public void doIt() {
Object result = Helpder.calculate();
}
}
class Helper{
private static Service anyService = BeanProvider.getContextualReference(Service.class);
public static Object calculate() {
return anyService.calc();
}
What about performance? Are there any notable differences? Both solutions are possible for me, is one solutions better than the other?
One disadvantage:
Helpder gets initialized for every Request.
Mark your Helper class as #ApplicationScoped. With this, you will have a single instance per application context.
Still, if it's just an utility class, it shouldn't be a managed bean at all. I would instead mark it as final, define a private constructor and mark all the methods as static. This is because since it's an utility class, it doesn't need to maintain any state.
I'm defining a Java EE bean as follows:
#LocalBean
#Stateless
public class GreetingBean {
private HelloBean helloBean;
#Inject
public void setHelloBean(HelloBean helloBean) {
this.helloBean = helloBean;
}
// ...
}
And:
#Named
public class HelloBean {
public HelloBean() { // ... }
public HelloBean(String hello) { // ... }
}
Now, how can I inject the GreetingBean into another class by also setting an HelloBean instance for it?
Supposing that I've two different constructors for the HelloBean class (the one with an argument, for instance a String, the other without [default]), how can I properly inject either?
If you have two different constructors, this is very different question from this that you are asking here. In this case the default constructor (without arguments) will be called when HelloBean gets instantiated.
To inject a bean instance using arguments you have to use a producer method which will instantiate HelloBean. More info can be found here and here.