Multiple configurations

69 views
Skip to first unread message

Brad Micholson

unread,
Oct 1, 2014, 6:38:56 PM10/1/14
to google...@googlegroups.com
I'm wondering if there's a better way to do this than I'm currently doing...

I want to, essentially, bind multiple configurations of a class, based on an annotation. I don't want a separate class binding for different annotations; I just want different parameters in the constructor. Right now, I'm creating multiple providers, which contain differently annotated parameters.
However, I'd love to be able to use AssistedInject, as I find I'm creating a ton of factory classes. There doesn't really seem to be a way to do that. I'd initially thought I could maybe create multiple abstract implementations of the factory, and annotate the parameters, but it seems the factory must be an interface...

Nate Bauernfeind

unread,
Oct 1, 2014, 8:42:58 PM10/1/14
to google...@googlegroups.com
Can you explain what you mean with a small amount of code? Can you annotate the assisted inject factories? Maybe you can mix PrivateModule's along with AssistedInject factories to get the effect you're looking for (and potentially exposing the factory with an annotation?).

Nate

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-guice/b8e3782d-53f9-42a4-b0d4-8e148c56323d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Brad Micholson

unread,
Oct 2, 2014, 11:31:17 AM10/2/14
to google...@googlegroups.com
public class Example implements ExampleInterface {
 
private final int moduleId;
 
public Example(int moduleId){
   
this.moduleId = moduleId;
 
}
}

In my Guice module, I do

@Provides @Module1
private ExampleInterface provideModule1Example(@Module1 int moduleId){
 
return new Example(moduleId);
}

@Provides @Module2
private ExampleInterface provideModule2Example(@Module2 int moduleId){
 
return new Example(moduleId);
}

So, injecting an ExampleInterface, annotated with either @Module1 or @Module2, uses the same implementation, just with a different parameter. If I want to add an AssistedInject parameter to the constructor, and create a factory for it, I'd have something like

public interface ExampleInterfaceFactory {
 
ExampleInterface create(Object someParameter);
}

I'd want to annotate someParameter, but the annotation would depend on how the ExampleInterface is annotated where it's injected.

I hope that all makes sense. I'm still fairly new to Guice...

Brad Micholson

unread,
Oct 2, 2014, 12:58:06 PM10/2/14
to google...@googlegroups.com
Actually, that doesn't make any sense at all. Forgive me, I've never used AssistedInject before. I wouldn't want to annotate someParameter at all; that's what I want to explicitly pass in...
I guess the issue is that Example doesn't have an @Inject annotation, so I can't really use AssistedInject on it.

Nate Bauernfeind

unread,
Oct 2, 2014, 2:05:00 PM10/2/14
to google...@googlegroups.com
Ok, I see. I've found most of my uses cases of assisted injection are summed up here:

1. You have single class that you want to create and manage multiple instances. This class also uses objects that are already part of your guice object graph (shared services, etc). I prefer assisted injection for these.
class Foo {
@Inject
public Foo(FooService fooService, @Assisted String name) { ... }
public static interface Factory {
Foo createFoo(String name);
}
}
public class FooManager {
private final Foo.Factory _fooFactory;
@Inject
public FooManager(Foo.Factory factory) {
_fooFactory = factory;
}
public Foo onFooSubscribed(String subscriptionName) {
Foo foo = _fooFactory.create(subscriptionName);
// TODO: save foo for later.
return foo;
}
}

2. You have many classes that you want to create and manage as a group, and you want to create multiple groups. Many of these classes will use objects that are already part of your guice object graph. I prefer using childInjectors for these and create my own factory (which seems similar to assisted inject). Usually you'll want the one object you pull out of this graph be able to start and stop the entire sub-graph (so that you can clean up when it's time for that object graph to disappear).
public class ClientFactory {
private final Injector _injector;
 
@Inject
public ClientFactory(Injector injector) {
_injector = injector;
}
 
public Client create(ClientConfiguration config) {
return _injector.createChildInjector(new ClientModule(config)).getInstance(Client.class);
}
 
private static class ClientModule extends AbstractModule {
...
}
}
public class ClientManager {
private final ClientFactory _clientFactory;
@Inject
public ClientManager(ClientFactory factory) {
_clientFactory = factory;
}
public Client onClientSubscribed(ClientConfiguration clientConfig) {
Client client = _clientFactory.create(clientConfig);
client.start();
// TODO: save client for later.
return client;
}
}

3.  If you have a simple object like Bar here, then I wouldn't bother using Guice for it at all as there is no gain (unless, of course!, you've got some injection listener that MUST be aware of instances of Bar).
class Bar {
public Bar(String name) { ... }
}
public class BarManager {
public Bar onBarSubscribed(String barName) {
Bar bar = new Bar(barName);
// TODO: save bar for later.
return bar;
}
}

From your example, I can't tell if you actually are trying to figure out how to inject many instances of Bar or if you're just trying to be simple for the sake of the email thread. So, if this is not helpful at all, please say so and I'll try again.

Nate





Brad Micholson

unread,
Oct 2, 2014, 2:42:03 PM10/2/14
to google...@googlegroups.com
Well, I was trying to make the example simple, but I think this makes sense. I've been looking at the child injector thing, but I was unaware that you could inject an Injector like that (am I right in assuming that'll be the same Injector that creates the ClientFactory?). I think that might be exactly what I need. Thanks!
Reply all
Reply to author
Forward
0 new messages