Yup, AssistedInject in Guice 3.0 requires a little more coordination between the implementation & the factory, especially when more than one parameter is of the same type. The benefits are large, though:
>From the Guice 3.0 Wiki, these are the changes since 2.0: * New FactoryModuleBuilder for building assisted factories * Injection is done through child injectors and can participate in AOP * Performance improvements * Multiple different implementations can be created from a single factory * Incorrect implementations or factories are detected in Stage.TOOL, and more error-checking with better error messages * Work better with parameterized types * Expose details through new extensions SPI I don't think any of those are applicable if you continue to use FactoryProvider and leave the implementation annotated with @AssistedInject. (However, if you change the implementation to @Inject, you'll see the new behavior regardless of whether or not you use FactoryProvider of FactoryModuleBuilder. Also, if you use FactoryModuleBuilder, you'll always get the new behavior regardless of using @Inject or @AssistedInject). Long story short... you're really better off using FactoryModuleBuilder. sam On Tue, Apr 12, 2011 at 8:53 AM, dhoffer <[email protected]> wrote: > I had got it working with I guess it's the 2.0 way of doing > things...with this style binding: > > bind(IMyClassFactory.class).toProvider( > FactoryProvider.newFactory(IMyClassFactory.class, > MyClass.class)); > > but FactoryProvider is deprecated. > > So now that I see your post saying that I need to used 'named' > annotations I changed it to use this approach. > > install(new FactoryModuleBuilder() > .implement(IMyClass.class, MyClass.class) > .build(IMyClassFactory.class)); > > however with this approach I have to used named Assisted annotations > in MyClass and I have to add named Assisted annotations to > IMyClassFactory where none was needed with the 2.0 approach. (Seems > like order of parameters could be used.) > > Both seem to work but the 2.0 approach as less intrusive to the code > (interfaces). ...just my two-cents. > > Thanks much! > -Dave > > On Apr 12, 3:08 pm, Fred Faber <[email protected]> wrote: > > On Tue, Apr 12, 2011 at 2:28 AM, dhoffer <[email protected]> wrote: > > > Yeah, that's what I was missing. This should do exactly what I need > > > but I can't get it to work yet. It compiles but at runtime it fails. > > > I find the documentation on this feature too sparse. Instead of > > > giving one full example they jump between two separate partial > > > examples. > > > > > In particular the docs don't make clear which module it is referring > > > to. In my case the class to be dynamically created has no non- > > > assisted parameters. I.e. the constructor of that class has 5 > > > parameters and they all have the @Assisted annotation. > > > > > So then question 1 is...should this class have the @Inject annotation > > > or the @AssistededInject annotation? > > > > It should use @Inject....@AssistedInject was used in the initial version > of > > the library, which uses reflection and not a child injector to create the > > factory-created objects. > > > > > The docs aren't real clear on > > > this, I think the later is needed only if I have overloaded > > > constructors which I do not. Question 2 is...do I even need a module > > > for this class? Since it has no injected parameters it seems it has > > > nothing to do. > > > > You'll need to bind the Factory as you show below (I'm unclear what > "class" > > you mean in this question). You won't bind the class being created by > the > > factory, if that's the question. > > > > > > > > > Now for the class(s) that need to inject the factory interface I > > > assume these are the modules that need this: > > > install(new FactoryModuleBuilder() > > > .implement(IMyClass.class, MyClass.class) > > > .build(IMyClassFactory.class)); > > > > > And this would be positioned in the module to line up with the > > > IMyClassFactory injected parameter (which in my case is after the bind > > > methods). > > > > Ok. > > > > > > > > > > > > > However at runtime I get this error: > > > > > com.google.inject.CreationException: Guice creation errors: > > > > > 1) A binding to com.app.MyParam annotated with > > > @com.google.inject.assistedinject.Assisted(value=) was already > > > configured at com.app.IMyClassFactory.create(). > > > at com.app.IMyClassFactory.create(IMyClassFactory.java:1) > > > at > > > > > > com.google.inject.assistedinject.FactoryProvider2.initialize(FactoryProvider2.java: > > > 539) > > > at com.google.inject.assistedinject.FactoryModuleBuilder > > > $1.configure(FactoryModuleBuilder.java:335) > > > > > Where MyParam is one of the 5 parameters in the IMyClassFactory create > > > method (i.e. MyClass constructor). > > > > I am guessing that more than one parameter has type "MyParam." > > > > If this is the case, then you need to distinguish param of the same type > by > > "naming" them, e.g., > > > > @Inject ClassCreatedByFactory( > > @Assisted("usedAsUsername") String username, > > @Assisted("usedAsPassword") String password) { ... } > > > > > > > > > Any idea what is wrong? Is there a full example of this someplace? > > > > Generally there are some examples in the test classes, such as here: > > > > http://code.google.com/p/google-guice/source/browse/trunk/extensions/... > > > > Fred > > > > > > > > > -Dave > > > > > On Apr 11, 6:17 pm, Sam Berlin <[email protected]> wrote: > > > > Take a look at the AssistedInject extension @ > > >http://code.google.com/p/google-guice/wiki/AssistedInject. > > > > > > sam > > > > > > On Mon, Apr 11, 2011 at 11:07 AM, David Hoffer <[email protected]> > > > wrote: > > > > > Nope, my factories are as plain as they get, i.e. > > > > > > > public class MyClassFactory implements IMyClassFactory { > > > > > > > public MyClass createMyClass(String param1, String param2, > String > > > > > param3, int param4, double param5) { > > > > > return new MyClass(param1, param2, param3, param4, param5); > > > > > } > > > > > } > > > > > > > The whole purpose of this factory is so I can inject > IMyClassFactory > > > into > > > > > other classes that need to 'new' MyClass so that class is mock > > > testable. > > > > > > > I'd love to use Guice so I don't need to write these factories but > how > > > do I > > > > > pass param1, param2, param3, param4 & param5 into MyClass's > > > constructor? > > > > > > > -Dave > > > > > > > On Mon, Apr 11, 2011 at 6:00 PM, Fred Faber <[email protected]> > wrote: > > > > > > >> This is similar to a question from earlier this week... > > > > > > >> Guice will help you remove invocations of "new" on service > objects. > > > > > > >> It won't be a replacement for your domain-level factory objects > i.e., > > > > >> objects that do more work on an object than simply instantiate it. > > > > > > >> Such a factory might look like: > > > > > > >> class YourFactory { > > > > >> private final Provider<Foo> fooProvider; > > > > > > >> @Inject YourFactory(Provider<Foo> fooProvider) { > > > > >> ... > > > > >> } > > > > > > >> Foo createFoo(ArgType1 arg1, ArgType2 arg2, ...) { > > > > >> Foo foo = fooProvider.get(); > > > > >> ... manipulate foo, probably using the args given above > > > > >> } > > > > >> } > > > > > > >> Note that AssistedInject can remove the boilerplate if all the > factory > > > is > > > > >> doing is to use the argument it gets as constructor arguments to > the > > > thing > > > > >> it is creating. But it sounds like your requirements are more > > > in-depth in > > > > >> that the Factory seems to be doing more work than simply > instantiating > > > an > > > > >> object. > > > > > > >> Fred > > > > > > >> On Mon, Apr 11, 2011 at 10:45 AM, dhoffer <[email protected]> > wrote: > > > > > > >>> I'm taking a look at Guice to see how it would work for us, > currently > > > > >>> we code the IoC manually (giant main that wires everything up) > and > > > use > > > > >>> factories to create dynamic objects so all methods are mock > testable, > > > > >>> i.e. no 'new' in the code (just in the main and factories). > > > > > > >>> I get how Guice solves the IoC part with @Inject & modules, > however > > > > >>> how does it help with the factories that generate dynamic > objects? > > > > >>> I.e. a method that calculates values, creates an object with > those > > > > >>> values, and does some work on and/or returns the object. How > does > > > > >>> Guice stop us from needing to write the class factory that > generates > > > > >>> the object? It looks like I could inject a typed Provider but > that > > > > >>> doesn't let me create the object with the values just created > > > > >>> dynamically. (Also it would tie my code to the Guice APIs.) > > > > > > >>> So it seems Guice solves the static part of the app but not the > > > > >>> dynamic part or am I missing something? > > > > > > >>> -- > > > > >>> You received this message because you are subscribed to the > Google > > > Groups > > > > >>> "google-guice" group. > > > > >>> To post to this group, send email to > [email protected]. > > > > >>> To unsubscribe from this group, send email to > > > > >>> [email protected]. > > > > >>> For more options, visit this group at > > > > >>>http://groups.google.com/group/google-guice?hl=en. > > > > > > > -- > > > > > You received this message because you are subscribed to the Google > > > Groups > > > > > "google-guice" group. > > > > > To post to this group, send email to [email protected] > . > > > > > To unsubscribe from this group, send email to > > > > > [email protected]. > > > > > For more options, visit this group at > > > > >http://groups.google.com/group/google-guice?hl=en. > > > > > -- > > > You received this message because you are subscribed to the Google > Groups > > > "google-guice" group. > > > To post to this group, send email to [email protected]. > > > To unsubscribe from this group, send email to > > > [email protected]. > > > For more options, visit this group at > > >http://groups.google.com/group/google-guice?hl=en. > > -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/google-guice?hl=en. > > -- You received this message because you are subscribed to the Google Groups "google-guice" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.
