So far, I successfully used google guice 2. While migrating to guice 3.0, I had troubles with assisted inject factories. Assume the following code
public interface Currency {}
public class SwissFrancs implements Currency {}
public interface Payment<T extends Currency> {}
public class RealPayment implements Payment<SwissFrancs> {
@Inject
RealPayment(@Assisted Date date) {}
}
public interface PaymentFactory {
Payment<Currency> create(Date date);
}
public SwissFrancPaymentModule extends AbstractModule {
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Payment.class, RealPayment.class)
.build(PaymentFactory.class));
}
}
While creating the injector, I get the following exception:
com.google.inject.CreationException: Guice creation errors:
1) Payment<Currency> is an interface, not a concrete class.
Unable to create AssistedInject factory. while locating Payment<Currency>
at PaymentFactory.create(PaymentFactory.java:1)
With the assisted inject creator from guice 2 my configuration works:
bind(PaymentFactory.class).toProvider(
FactoryProvider.newFactory(PaymentFactory.class, RealPayment.class));
The only workaround I found so far is to remove the generic parameter from the return type of the factory method:
public interface PaymentFactory {
Payment create(Date date);
}
Does anybody know, why guice 3 doesn't like the generic parameter in the factory method or what I generally misunderstood about assisted inject factories? Thanks!
There are two issues with your code above.
First, RealPayment
implements Payment<SwissFrancs>
, but PaymentFactory.create
returns Payment<Currency>
. A Payment<SwissFrancs>
cannot be returned from a method that returns Payment<Currency>
. If you change the return type of create
to Payment<? extends Currency>
, then RealPayment
will work (because it's a Payment
for something that extends Currency
).
Second, you DO need to use the version of implement
that takes a TypeLiteral
as its first argument. The way to do that is to use an anonymous inner class. To represent `Payment' you can use
new TypeLiteral<Payment<? extends Currency>>() {}
See the Javadoc for that TypeLiteral
constructor for more information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With