Reputation: 3290
I have a simple requirement -
This is the service where I want to inject the object of CalledService
.
public class CallingService {
private CalledService service;
@Inject
public CallingService(CalledService svc) {
service = svc;
}
}
The CalledService
looks like this -
public class CalledService {
private String variable_value;
public CalledService(String parameter) {
variable_value = parameter;
}
}
And let's say in the psvm
, I am writing this code for execution -
Injector injector = Guice.createInjector(new AppInjector());
CallingService service = injector.getInstance(CallingService.class);
The issue is if CalledService
had a non-parameterised constructor then it would have worked fine. But since it is a parameterised I don’t know how I can inject the parameter value.
Also, several other services might want to inject the CalledService
with different parameter values. So I don't want to bind any static value to the parameter.
Can anyone suggest the simplest way this can be achieved using Google Guice? Also, I found a lot of answers in this forum but they were not exactly what I was looking for, and some solutions were overly complicated. Thanks in advance.
Upvotes: 3
Views: 6115
Reputation: 3290
Thanks, @Luigi, and @vsbehere for helping me out. I went through the stackoverflow link which you guys shared before also.
The answer that was mentioned there seemed a bit complicated to me, I wished the way to Inject parameters using Google Guice had been a little simpler. One thing which I was very resistant to use was the factory class and I wanted to know if its usage can be avoided. Then I went through this documentation and I made sense to me.
Just to summarize, the purpose of the FactoryInterface
is to help Guice build the objects. AssistedInject
maps the create()
method's parameters to the corresponding @Assisted
parameters in the implementation class's constructor, in this example the implementation class is the CalledService
. The create()
method in the Factory Interface takes only the assisted parameters and, one should make sure they are in the same order as in the constructor.
I hope the above paragraph made sense, which explains why a Factor class is required. And this is how I solved the above-mentioned problem -
The CalledService
now looks like this, there is a @Assisted
keyword now in the parameter -
public class CalledService {
private String variable_value;
@Inject
public CalledService(@Assisted String parameter) {
variable_value = parameter;
}
public void printValue() {
System.out.println(variable_value);
}
}
The CalledServiceFactory is a new addition, whose purpose is to create objects of CalledService. And this is how it looks -
public interface CalledServiceFactory {
CalledService create(String var);
}
The CallingService
now looks like this, we are injecting a CalledServiceFactory
instance to this class now and this will help in creating the instance of CalledService
-
public class CallingService {
@Inject
private CalledServiceFactory factory;
public void callingMethod() {
CalledService service = factory.create("someValue");
service.printValue();
}
}
Inside the Module, I have configured the CalledServiceFactory
-
public class AppInjector extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder()
.build(CalledServiceFactory.class));
}
}
And finally, for executing it, this is how I have executed it in the main function -
private static void main() {
Injector injector = Guice.createInjector(new AppInjector());
CallingService service = injector.getInstance(CallingService.class);
service.callingMethod();
}
This is how I have implemented it, and this is the max simplest I could trim it down to. If anyone has any optimum solution then please let me know.
Upvotes: 1
Reputation: 1079
I'm afraid you took a wrong turn. Look at provides-methods instead (also, use interface binding to unleash Guice' full potential!):
import javax.swing.JOptionPane;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Provides;
public class Main {
public static void main(String[] args) {
CallingService callingService = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(CallingService.class).to(DefaultCallingService.class);
bind(CalledService.class).to(DefaultCalledService.class);
}
@Provides
String provideParameter() {
return JOptionPane.showInputDialog(null);
}
}).getInstance(CallingService.class);
callingService.requestStuffExecution();
}
}
Interface 1:
public interface CallingService {
void requestStuffExecution();
}
Interface 2:
public interface CalledService {
void doStuff();
}
Default Impl1:
import com.google.inject.Inject;
public class DefaultCallingService implements CallingService {
private DefaultCalledService service;
@Inject
public DefaultCallingService(DefaultCalledService svc) {
service = svc;
}
@Override
public void requestStuffExecution() {
service.doStuff();
}
}
Default Impl2:
import com.google.inject.Inject;
public class DefaultCalledService implements CalledService {
private String parameter;
@Inject
public DefaultCalledService(String par) {
this.parameter = par;
}
@Override
public void doStuff() {
System.out.println("Oh boy, always so much stuff to do! Performing: " + parameter);
}
}
Prints: "Oh boy, always so much stuff to do! Performing: <The Input String>".
Upvotes: 0
Reputation: 124
In addition to the suggestion in the comment above - assisted inject You can bind instances in Guice. Please see here for details/examples
Hope this helps
Upvotes: 1