I am new to Guice and have done a lot of reading on this but I have not hand any success with this. I am basically creating a DAO and want to use Guice and the AssistedInjection. Effectively the end goal is create the Injected factory in other classes throughout the application.
Intended use in a actual class that would have the injection of the factory to then get classes from it
public class TestAllModelBootstrap {
#Inject private DAOFactory factory;
public TestAllModelBootstrap() {
}
#Test
public void testGettingDAO() {
Injector injector = Guice.createInjector(new HibernateDAOModule());
Token oToken = new OperTokenV1();
AccountingDAO accountingDAO = factory.create(oToken);
}
}
This is based on Guice-based code of:
public interface DAOFactory {
public AccountingDAO create(Token oTicket);
}
The concrete class has a constructor annoated
#Inject
public HibernateAccountingDAO(#Assisted Token oTicket) {
this.oTicket = oTicket;
}
And the actual Module:
#Override
protected void configure() {
install(new FactoryModuleBuilder()
.implement(AccountingDAO.class, HibernateAccountingDAO.class)
.build(DAOFactory.class));
bind(SessionFactoryInterface.class)
.toProvider(HibernateSessionProvider.class);
}
Each time I try to run this:
java.lang.NullPointerException -> indicating that the:
factory.create(oToken);
has factory as a null. In reading up on the problem I was lead to believe that the injection will not work like I am using it in the "test" class. It needs to be put in an "injected" class itself. But this doesn't work either - if I wrapper the Factory injection in another class and then try to use it, it doesn't work.
Any help would be appreciated...
TestAllModelBootstrap did not come from an Injector—JUnit created it instead—so Guice hasn't had a chance to inject it yet. Guice can only inject into objects that it creates via getInstance (and those objects' dependencies, recursively), or objects passed into injectMembers, or existing instances as requested using requestInjection.
You can manually get a factory instance:
factory = injector.getInstance(DAOFactory.class);
Or ask Guice to inject your members using injectMembers:
injector.injectMembers(this); // sets the #Inject factory field
Or use a tool like Guiceberry to inject your test cases across your app.
Related
I have a class that is instantiated by 3rd party code (it uses reflection to create the object.) I provide the implementation of their interface and they create the object. In my implementation I want to use CDI to inject a service that performs logic. What is the correct way to do this?
public interface ThirdPartyInterface {
public void DoSomething();
}
public class InjectedService {
public void DoSomeLogic() { ... }
}
public class MyImplementation implements ThirdPartyInterface {
#Inject InjectedService service;
#Override
public void DoSomething() {
service.DoSomeLogic();
}
}
I originally thought this would work through the magic of CDI, but found my service object to be null.
The only thing I've come up with so far is to inject the service manually in the constructor
public MyImplementation() {
CDI<Object> cdi = CDI.current();
service = cdi.select(InjectedService.class).get();
}
Is this the correct/only/best way of obtaining the instance? I am using Weld for my CDI implementation.
I have also found this to work in the constructor:
public MyImplementation() {
CDI<Object> cdi = CDI.current();
BeanManager bm = cdi.getBeanManager();
AnnotatedType<MyImplementation> myType = bm.createAnnotatedType(MyImplementation.class);
Set<Bean<?>> beans = bm.getBeans(MyImplementation.class);
Bean<?> bean = bm.resolve(beans);
#SuppressWarnings("unchecked")
CreationalContext<MyImplementation> cc = (CreationalContext<MyImplementation>)bm.createCreationalContext(bean);
bm.createInjectionTarget(myType).inject(this, cc);
}
So long as someone creates the object manually, CDI will not, by default, inject anything into it.
You approach with the constructor injection is probably going to work, unless you get into EARs and such where CDI.current() may not do what you would expect.
There is a way to make CDI inject into manually created objects - the 3rd party would have to take this step to make it work. You need BeanManager and an instance you want to inject into:
BeanManager beanManager = ...; // get hold of bean manager, can be injected
CreationalContext<Object> ctx = beanManager.createCreationalContext(null);
#SuppressWarnings("unchecked")
InjectionTarget<MyImplementation> injectionTarget = (InjectionTarget<MyImplementation>) beanManager
.getInjectionTargetFactory(beanManager.createAnnotatedType(myImplementationInstance.getClass())).createInjectionTarget(null);
injectionTarget.inject(myImplementationInstance, ctx);
Note - by doing this you take responsibility to clean up after the object once you no longer need it. Store the CreationContext somewhere and call release() method on it in order to dispose of it properly (with all possible pre destroy calls and such).
Alternatively, since you are already using CDI, why doesn't 3rd party simply #Inject the bean you provide?
I am building a library based on Spring Framework and I want to allow users invoke Library's methods in parallel.
In my main class I autowire Service class:
#Autowired
private ExportListCommand exportList;
And that's implementation for Library's method:
public ResponseContainer<ExportListResponse> exportList(ExportListOptions options) {
exportList.setoAuthClient(oAuthClient);
ResponseContainer<ExportListResponse> result = exportList.executeCommand(options);
return result;
}
ExportListCommand is defined as a Bean:
#Bean
#Scope("prototype")
public ExportListCommand exportList() {
return new ExportListCommand();
}
When I as a Library user run 2 exportList's methods in parallel Spring creates only single ExportListCommand bean since it autowired only once. But in reality I need 2 independent ExportListCommand beans. I also tried to change #Scope(value="prototype") to #Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS), but that also does not work as I need: Spring creates ExportListCommand bean for each method invocation and I lose oAuthClient value since I get new object.
I made it work only with AnnotationConfigApplicationContext.getBean() approach which I would like to avoid.
What my options are? Thanks.
I believe you are looking to work with a 'factory' object.
There are two primary ways I would consider this from a Spring standpoint.
The 'Java' way: Create a factory object that will return instances of ExportListCommand
This factory would look something like this:
class ExportListCommandFactory {
ExportListCommand newInstance() {
return new ExportListCommand();
}
}
and would be used in your method like this:
#Autowire
private ExportListCommandFactory commandFactory;
public ResponseContainer<ExportListResponse> exportList(ExportListOptions options) {
final ExportListCommand exportList = commandFactory.newInstance();
exportList.setoAuthClient(oAuthClient);
ResponseContainer<ExportListResponse> result = exportList.executeCommand(options);
return result;
}
Of course, doing this would require that you change your configuration to contain a bean that is an ExportListCommandFactory rather than an ExportListCommand.
Alternatively, you could consider...
The 'Spring' way: Use FactoryBean
The only thing you should need to do here is, in your main class, #Autowire a FactoryBean<ExportListCommand> instead of the ExportListCommand, and in your method where you need to invoke the method, consult the factory to get your instance.
#Autowire
private FactoryBean<ExportListCommand> commandFactory;
public ResponseContainer<ExportListResponse> exportList(ExportListOptions options) {
final ExportListCommand exportList = commandFactory.getObject();
exportList.setoAuthClient(oAuthClient);
ResponseContainer<ExportListResponse> result = exportList.executeCommand(options);
return result;
}
You shouldn't need to change your configuration, as FactoryBean is a special bean that will consult the ApplicationContext/BeanFactory for the instance at each invocation of getObject().
My class depends on some services which needs to take few parameters and then make network call, currently I am passing those parameters and then creating those services via a factory injected into my class. I need to inject those services as a dependency instead, I know that I can create providers for them but in most of the examples I see that the providers are often bound to the fixed values like serveraddres etc. but I need to give then values during run time.
Below is my example code:
public SomeClass {
private final SomeFactory someFactory;
#Inject
SomeClass(SomeFactory factory) {
someFactory = factory;
}
public Foo getFoo(String fooId) {
FooService fooService = someFactory.getFooService(fooId);
return fooService.getFoo();
}
}
What I need to do is:
public SomeClass {
private final FooService fooService;
#Inject
SomeClass(FooService fooService) {
this.fooService = fooService;
}
public Foo getFoo(String fooId) {
return fooService.getFoo();
}
}
Update 1
Making the use case more clear:
#Provides
#RequestScoped
public SomeService provideSomeService(Dep1 dep1, String code) throws IOException {
return new SomeService.Builder()
.withApplicationName("Foo")
.setCode(code)
.build();
}
Here, code can be null by default and when needed I can give some value in it.
Can I somehow pass arguments to the provider before its created?
If you have a binding for your value (here, code is a String without a binding annotation), then your Update 1 is exactly what the code would look like.
In practice, there are a few differences:
Constants like int and String values are generally annotated with a binding annotation, either #Named or a custom annotation.
If you need to inject a value into an object graph after Guice initialization, but have a deep enough object graph that dependency injection is still a good idea, you can create a child injector. This way you can make a #Named("code") String accessible within one action or object, but not across your entire Guice application.
If your value for code is dynamic enough that it can't be provided through Guice as a key of its own, then you'll have to pass it in using a factory of some sort. For a Builder-based object, I'd say that your SomeFactory implementation is the best that I would come up with in your case.
If you don't need to use a Builder, and can let Guice create the object based on your fields or constructor parameters, you can code-generate a Factory.
Guice can generate a factory for you through FactoryModuleBuilder, in a feature known as "assisted injection".
Google's other tool, AutoFactory, will code-generate a factory implementation that works in both Guice and Dagger. (It's bundled as "Auto", which includes a model object generator called AutoValue that also generates annotation implementations.)
I put a small demonstration of a child injector and assisted injection in my other SO answer here.
The best approach here is to parameterize the module and pass the parameter through to a provider that you create at runtime:
public class MyModule extends AbstractModule {
private final String code;
public MyModule(String code) {
this.code = code;
}
#Override public void configure() {
Provider<Dep1> depProvider = getProvider(Dep1.class);
bind(SomeService.class)
.toProvider(() -> new SomeService.Builder()
.withApplicationName("Foo")
.withDep(depProvider.get())
.setCode(code)
.build())
.in(RequestScoped.class);
}
}
What is the Spring Framework equivalent to FactoryModuleBuilder, #AssistedInject, and #Assisted in Google Guice? In other words, what is the recommended approach using Spring to create factory objects whose methods accept arguments that the application (not the container) must provide?
The Spring static factory method is not the same as FactoryModuleBuilder. FactoryModuleBuilder builds a Guice module that generates "factories" that implement the Factory Method Pattern. Unlike a Spring static factory method, the methods of these factory objects are instance methods, not static methods. The problem with a static factory method is that it is static and doesn't implement an interface so it cannot be replaced with an alternative factory implementation. Different FactoryModuleBuilder instances, however, can build different factories that implement the same interface.
Spring has no equivalent to the Guice FactoryModuleBuilder. The closest equivalent would be a Spring #Configuration class that provides a factory bean that implements a factory interface whose methods accept arbitrary arguments from the application. The Spring container could inject dependencies into the #Configuration object that it, in turn, could supply to the factory constructor. Unlike with FactoryModuleBuilder, the Spring approach produces a lot of boilerplate code typical of factory implementations.
Example:
public class Vehicle {
}
public class Car extends Vehicle {
private final int numberOfPassengers;
public Car(int numberOfPassengers) {
this.numberOfPassengers = numberOfPassengers;
}
}
public interface VehicleFactory {
Vehicle createPassengerVehicle(int numberOfPassengers);
}
#Configuration
public class CarFactoryConfiguration {
#Bean
VehicleFactory carFactory() {
return new VehicleFactory() {
#Override
Vehicle createPassengerVehicle(int numberOfPassengers) {
return new Car(numberOfPassengers);
}
};
}
}
I'm not entirely certain that this question is a dupe, (only 90% sure), but this answer:
https://stackoverflow.com/a/13243066/1768232
Seems to have the information you need. Specifically, you should do this:
I got it working by fetching an instance of the bean used in the constructor-arg out of the context and then populating it with the values that you are working with at run-time. This bean will then be used as the parameter when you get your factory-generated bean.
public class X {
public void callFactoryAndGetNewInstance() {
User user = context.getBean("user");
user.setSomethingUsefull(...);
FileValidator validator = (FileValidator)context.getBean("fileValidator");
...
}
}
I recommend reading the entire answer.
I need a suggestion for how to code for multiple implementations for a service using Google-guice. Below is the example
TestService testService =new TestServiceImplOne();
TestService testService =new TestServiceImplTwo();
As Guice doesn't allow binding a type to more than one implementations as the below code results in error
binderObject.bind(SomeType.class).to(ImplemenationOne.class);
binderObject.bind(SomeType.class).to(ImplemenationTwo.class);
we can solve this with named annotations as below
binder.bind(Player.class).annotatedWith(Names.named("Good")).to(GoodPlayer.class);
binder.bind(Player.class).annotatedWith(Names.named("Bad")).to(BadPlayer.class);
#Named("Good") Player goodPlayer = (Player)injector.getInstance(Player.class);
#Named("Bad") Player badPlayer = (Player)injector.getInstance(Player.class);
But the application which iam working is something like this. We are binding all the modules in the init() method and creating the injector modules:
//separate method to bind
protected void configure() {
bind(new TypeLiteral<List<Service>>() {}).toInstance(serviceSets);
}
//separate method to inject
Injector i = Guice.createInjector(modules);
But with the above process I can just bind one implementation class to the interface (service class)
Could you please provide me a way to do this with providers. I would like to do something like this below
class TestServiceProvider extends Provider{
// some code where it returns the instance of impl class needed. In my case TestServiceImplOne and TestServiceImplTwo and provider returns the corresponding instance of service class
}
and bind service class with provider class. Something like this
bind(TestService.class).toProvider(TestServiceProvider.class);
I would appreciate if someone suggests a good example using providers or some other way that I can inject whatever implementation I want in the client.
Note: I am using webservices and I am not sure how I can inject different implementations when a webservice is called to a service class.
First of all thanks very much for responding . Coming straight to the point
Iam working on webservices . Heres's the Flow
// GET URI
GET http://www.google.com:8182/indi/provide/organizations/{ou}
OrganizationsResource -------->OrganizationService------>OrganizationServiceImpl
Iam binding OrganizationService with OrganizationServiceImpl and injecting the OrganizationService in OrganizationsResource
#Inject
public void setOrganizationService(OrganizationService orgService) {
this.orgService= orgService;
}
Its fine till here but i have two implementations for OrganizationService ------>OrgDeatilsServiceImpl which does some other job
Now i want to bind both OrganizationServiceImpl and OrgDeatilsServiceImpl to OrganizationService
Confusions:
1) What procedure i have to use in Guice to bind two implementaions?
2) How exactly i can code in OrganizationsResource to dynamically decide which implementation to call.
I would appreciate if you give a sample example for the above requirement.
As Vladimir noted, you can use binding annotations with Providers...
// in YourModule.configure():
bind(TestService.class)
.annotatedWith(Names.named("foo")
.toProvider(TestServiceProvider.class);
...and generic types using TypeLiterals...
bind(new TypeLiteral<List<Service>>() {})
.annotatedWith(Names.named("bar")
.toInstance(serviceSets);
...as long as you ask for an annotated instance using getInstance(Key<T>)...
List<Service> servicesOne = injector.getInstance(
new Key<List<Service>>(Names.named("bar")) {});
// or
List<Service> servicesTwo = injector.getInstance(
Key.get(new TypeLiteral<List<Service>>() {}, Names.named("bar"));
...or, preferably, keep them as fields and let Guice do the injecting, because Guice can't inject local variables. Remember that Guice can only inject classes that it creates, or that you request specifically.
class MyInjectorCreator {
#Inject #Named("foo") Provider<TestService> fooServiceProvider;
#Inject #Named("bar") List<Service> barServices;
// Guice will also wrap/unwrap Providers automatically.
#Inject #Named("foo") TestService fooService;
#Inject #Named("bar") Provider<List<Service>> barServicesProvider;
public void createInjector() {
Injector injector = Guice.createInjector(getListOfModules());
injector.injectMembers(this);
}
}
Now, that answers the question as you phrased it in the title. That said, it sounds like you actually want to choose between implementations at runtime, which is a slightly different but easy-to-solve problem:
class TestServiceProvider extends Provider<TestService> {
// Injection is allowed here!
#Inject ApplicationSettings settings;
#Inject Provider<TestServiceImplOne> oneProvider;
#Inject Provider<TestServiceImplTwo> twoProvider;
#Override public TestService get() {
if (settings.isInTestMode()) {
return new TestTestServiceImplImpl(); // without injection!
} else if (settings.useNewService()) {
return twoProvider.get(); // with injection!
} else {
return oneProvider.get(); // also with injection!
}
}
}
But I should warn you that if you know at injector creation time which service to use, you should probably just bind it correctly then for the sake of code cleanliness and ease of readability:
// in YourModule.configure():
if (settings.isInTestMode()) {
bind(TestService.class).toInstance(new TestTestServiceImplImpl());
} else if (settings.useNewService()) {
bind(TestService.class).to(TestServiceImplTwo.class);
} else {
bind(TestService.class).to(TestServiceImplOne.class);
}