I have an class with a static interface within it.
public class UserInfo {
private Store userInfoStore;
public static interface Store {
UserInfo save(UserInfo userInfo);
}
public UserInfo save() {
if (userInfoStore == null) return null;
return userInfoStore.save(this);
}
}
I then have an object which implements the above object's interface
public class UserAuditService implements UserInfo.Store {
#Override
public UserInfo save(UserInfo userInfo) {
// code that persists object to disk
}
}
Now say I'm creating an instance of the UserInfo object somewhere else in my application. How do I reference the save method implemented in the UserAuditService class?
UserInfo userInfo = new UserInfo();
??? - Not sure what to do here.
If save method is what you want to call then do the following:
UserInfo userInfo = new UserInfo();
UserInfo.Store userStore = new UserAuditService();
userStore.save(userInfo);
This is one way of using the implemented method.
You mean you don't want to hardcode the UserAuditService class, because there may be many implementations in the future?
There are many solutions, it's what the dependency injection is all about.
You may use Spring or other dependency injection framework, and configure the class to use in xml (or by annotations).
You may do it by hand, for example using constructor dependency injection (you add field of type UserInfo.Store to the UserInfo class, and assign to it a class passed as parameterin a constructor of UserInfo).
Another option is setter dependency injection - you have the same field in UserInfo, but you set it in a setter called from some place after the UserInfo was created.
This makes it clear what happens, but requires to pass the dependencies all the way from the place you configured it to the place they are used, that's why people use dependency injection frameworks to cut the boilerplate.
Related
In my project I have different services. Each service can define its own Permissions. For each permission, a bean will created. This way, the Authorization service can inject all available permission, without actually knowing them.
The Permission definition of ServiceA will look like this:
#Configuration()
public class ServiceAPermissions extends Permissions {
private static final String BASE = "servicea";
public static final String SERVICEA_READ = join(BASE, READ);
public static final String SERVICEA_WRITE = join(BASE, WRITE);
#Bean()
Permission getReadPermission() {
return new Permission(SERVICEA_READ);
}
#Bean()
Permission getWritePermission() {
return new Permission(SERVICEA_WRITE);
}
}
ServiceB will define the following Permissions:
#Configuration()
public class ServiceBPermissions extends Permissions {
private static final String BASE = "serviceb";
public static final String SERVICEB_READ = join(BASE, READ);
#Bean()
Permission getReadPermission() {
return new Permission(SERVICEB_READ);
}
}
Obviously, this will end in a name clash of the defined beans as I have defined a bean with the name getReadPermission twice. If course I can name the methods like getServiceAReadPermission so they will be distinguished, but this only a convention, which might be ignored.
In this situation, Spring doesn't notify me about the duplicate definition, it simply will just instantiate one and ignore the other definition. Is there a way to tell Spring to throw an Exception, if a bean is defined twice? This way one would be always aware of a duplicate definition.
Alternatively, is there a way to tell spring, that it should use a random bean name instead of the method signature? I know that I can give each bean a name manually #Bean(name = "A name"), but I like to avoid that, as a dev will not be forced to do so and still might forget it.
That design does not seem very logical. A bean is supposed to be available only once, you're using it differently.
I'd suggest to provide a PermissionFactory-Bean which does what you need, along the line of
#Component
public class PermissionFactory {
public Permission createFactory() {
// create A or B permission randomly, as you wanted
}
}
I have a validation method in a model class that gets called from code that I don't have control over. This validation method has parameters that come from dependency injection. One of these parameters is a singleton (#Singleton) class.
#Singleton
public class ObjValidation {
#Inject
public ObjValidation() {
objsCache = new HashSet<>();
}
public boolean exists(String obj) {
return objsCache.contains(obj) || lookupObj(obj);
}
...
}
As you can see this singleton does perform a lookup on a database if the object isn't contained in the cache. While testing this database isn't there and should not be tested. Therefore I'm trying to mock the exists() method to return true without being run.
My first thought was, since this is a singleton, if I would inject the singleton into my test case before running it, I would create the singleton instance therefore could spy on it.
ObjValidation objValidation = spy(app.injector().instanceOf(ObjValidation.class));
doReturn(true).when(objValidation).exists(any());
But yes, spy only returns a copy and therefore doesn't spy on the instantiated singleton. I would need to replace the singleton instance with the spy copy to make it work this way.
How can I do this?
Further explanation of the test case:
In my test (method under test is register()) I bind a scala.html view form to a model class via the build in functionality of the play framework.
public Result register() throws ResultMessageException {
...
Form<Registration> filledRegistrationForm = this.formFactory.form(Registration.class).bindFromRequest();
...
}
The model has a validation method that has parameters that get injected as described in the play documentation: https://www.playframework.com/documentation/2.6.x/JavaForms#Custom-class-level-constraints-with-DI-support
#ValidateWithDI
public class Registration implements ValidatableWithDI<ValidationError> {
#Required
private String obj;
#Override
public ValidationError validate(ObjValidation objValidation) {
if (!objValidation.exists(obj)) {
return new ValidationError("obj");
}
return null;
}
}
This validation method gets called by the framework while binding the form.
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);
}
}
Is it possible to perform custom injection with constructor/factory arguments computed based on injection point WITHOUT defining custom annotation ?
Given a code:
class Foo {
public Foo() {}
public Foo(java.lang.reflect.Field field) {}
}
class Bar {
#javax.inject.Inject Foo foo;
}
How can I configure guice to use second constructor of Foo (passing target field) without modifying Bar.
I know that guice can do custom injections of java.util.logging.Logger with standard #Inject but that seems hardcoded and uses internal api.
You can use injection providers to do it. See https://code.google.com/p/google-guice/wiki/ProviderBindings and https://code.google.com/p/google-guice/wiki/ProvidesMethods. You just have to tell Guice how to instantiate the object when it binds it.
For exemple in a project of mine I tried this :
public static class CalendarServiceProvider implements Provider<CalendarService> {
#Inject
GAppsOAuth oauth;
private GCalendarService service;
#Override
public CalendarService get() {
if (service == null) {
service = new GCalendarService(oauth);
}
return service;
}
}
I don't know if it's what you're looking for, but I hope it'll help.
If you want only to use specific constructor, you can use constructor bindings:
bind(Foo.class).toConstructor(Foo.class.getConstructor(java.lang.reflect.Field.class));
If you need something more complex, you have to use custom injections.
I have a Factory Class use case I want to implement with Guice, but not sure how.
I have an Abstract Class named Action which represent different kind of actions the user could perform on my app.
Each of the Actions are subclasses of Action class, and each of them also have an identification of String type.
Because Actions are heavy objects I don't want to have it all instanciated at once, so I provides a Factory to instanciate each of them depending on the ID the client ask for.
The Factory Interface looks like:
public interface ActionFactory {
Action getActionByID(String id);
}
Our implementation of this Factory uses a HashMap to maintain the relationship between the String instance and a so called ActionInstantiator that will provides the concrete Action instance.
Implementation of this looks like:
public class ActionFactoryImpl implements ActionFactory {
private HashMap<String, ActionInstantiator> actions;
private static ActionFactoryImpl instance;
protected ActionFactoryImpl(){
this.actions=new HashMap<String, ActionInstantiator>();
this.buildActionRelationships();
}
public static ActionFactoryImpl instance(){
if(instance==null)
instance=new ActionFactoryImpl();
return instance;
}
public Action getActionByID(String id){
ActionInstantiator ai = this.actions.get(id);
if (ai == null) {
String errMessage="Error. No action with the given ID:"+id;
MessageBox.alert("Error", errMessage, null);
throw new RuntimeException(errMessage);
}
return ai.getAction();
}
protected void buildActionRelationships(){
this.actions.put("actionAAA",new ActionAAAInstantiator());
this.actions.put("actionBBB",new ActionBBBInstantiator());
.....
.....
}
}
So some client that could use this factory and wants ActionAAA instance class calls it like this:
Action action=ActionFactoryImpl.instance().getActionByID(actionId);
Where actionId was obtained at runtime from database.
I found that some kind of annotation injection could do something similar, but in my case I think that that wouldn't work, because I only know the instance that the user will requieres at runtime, so I couldn't annotated on the code.
I'm new to Guice so maybe this is something very common I couldn't found in the docs, I appologies if that is the case.
Any help will be appreciated.
Regards
Daniel
You want to use the Multibindings extension, specifically MapBinder. You probably want your ActionInstantiator type to implement Provider<Action>. Then you can do:
MapBinder<String, Action> mapbinder
= MapBinder.newMapBinder(binder(), String.class, Action.class);
mapbinder.addBinding("actionAAA", ActionAAAInstantiator.class);
// ...
Then you can inject a Map<String, Provider<Action>> where you want. You'll also be able to inject things in to your ActionInstantiators.