bineanzhou / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Assisted inject can't match generics parameters correctly #218

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I have a class with a constructor as:

public class Foo<I extends Baz> {

  public Foo(BarService service,
      FooProcessor<I> processor,
      BazHelper baz,
      Class<I> iClass) {
    ...
  }
}

Three of those paramters are generally gotten from guice, while the fourth
(the class) is a constant depending on where in the code I create a Foo.
(FooProcessor has a zero-arg constructor, so guice can fill it in no matter
what type is used as a parameter)

This would seem like a perfect use case for @AssistedInject, but trying this:

public interface FooFactory {
  <I extends Baz> Foo<I> create(Class<I> iClass);
}

and putting @Assisted in the right place on the constructor led to this
exception while creating the injector:

java.lang.IllegalArgumentException: class test.Foo has no @AssistInject
constructor that takes the @Assisted parameters [java.lang.Class<I>] in
that order. @AssistInject constructors are [public
test.Foo(test.BarService,test.FooProcessor,test.BazHelper,java.lang.Class)]
        at
com.google.inject.assistedinject.FactoryProvider.createMethodMapping(FactoryProv
ider.java:195)
        at
com.google.inject.assistedinject.FactoryProvider.<init>(FactoryProvider.java:102
)
        at
com.google.inject.assistedinject.FactoryProvider.newFactory(FactoryProvider.java
:96)
        at test.FooModule.configure(FooModule.java:138)
        at com.google.inject.AbstractModule.configure(AbstractModule.java:66)
...

(class names changed to obscure internal details)

Original issue reported on code.google.com by d...@google.com on 8 Jul 2008 at 8:12

GoogleCodeExporter commented 9 years ago

Original comment by limpbizkit on 31 Dec 2008 at 1:15

GoogleCodeExporter commented 9 years ago
Attached Ilya Firman's patch to add support for generic factories.

Original comment by limpbizkit on 9 Feb 2009 at 3:41

Attachments:

GoogleCodeExporter commented 9 years ago
Attaching a patch that provides support for generics in both the "compatibility 
mode"
(FactoryProvider) and the new mode (FactoryProvider2). Also, added more 
comprehensive
tests.

Original comment by ilya.fir...@gmail.com on 11 Feb 2009 at 12:28

Attachments:

GoogleCodeExporter commented 9 years ago
Modified the patch to support using parameters of generic types in factory 
methods.
This only affects the "compatibility mode".

Original comment by ilya.fir...@gmail.com on 12 Feb 2009 at 10:37

Attachments:

GoogleCodeExporter commented 9 years ago
I've applied Ilya's patch with r871. We now support parameterized factories 
(Factory<T>) but not parameterized 
methods. I think this is probably good enough.

Original comment by limpbizkit on 27 Feb 2009 at 10:02

GoogleCodeExporter commented 9 years ago

Original comment by limpbizkit on 27 Apr 2009 at 6:24

GoogleCodeExporter commented 9 years ago
I just encountered a case where I need this, but the provided solution does not 
suit
me. Here's the use case (with card games, since that's where I found the issue).

A typical card game (according to my application) has two or more decks; each 
deck is
composed of exactly one type of cards. The application is generic enough not to
decide in the core what composes these decks, and how they are defined.

So my DeckBuilder has this method:

public <C extends Card> Deck<C> buildDeck (Class<C> type);

But to build the deck, I need a provider (or several) in my DeckBuilderImpl.

I've thought about using the MultiBinder (based upon 
Map<Class<?>,Provider<Deck<?>>),
but this is not applicable in my case since so far I can't share the multibinder
between all the known modules (the one I develop for the core) and unknown ones 
(the
modules defining the decks). I can't also give a parameter to these modules, 
since 1)
they are unknown 2) they are instanciated via java.util.ServiceLoader.

So, only the generic-parametered factories can help me, but I need the 
genericity on
the method, and not on the factory-type.

I really think that this kind of factory would be needed for modular 
applications
only. Since in all other circumstances I could find a workaround. This is the 
first
time I can't.

Original comment by ogregoire on 28 May 2009 at 10:45

GoogleCodeExporter commented 9 years ago
Issue 673 has been merged into this issue.

Original comment by sberlin on 9 Dec 2011 at 3:00

GoogleCodeExporter commented 9 years ago
sberlin,

Can you update the documentation to mention this limitation (until it is fixed)?

Original comment by cow...@bbs.darktech.org on 9 Dec 2011 at 8:46

GoogleCodeExporter commented 9 years ago
Sure, can you provide some example documentation that you'd like to see (and 
where)?

Original comment by sberlin on 9 Dec 2011 at 9:08

GoogleCodeExporter commented 9 years ago
I recommend adding the following note on 
http://code.google.com/p/google-guice/wiki/AssistedInject

WARNING: AssistedInject can't handle methods with type parameters unless the 
class itself is generic. See 
http://code.google.com/p/google-guice/issues/detail?id=218 for more information.

Original comment by cow...@bbs.darktech.org on 9 Dec 2011 at 10:22

GoogleCodeExporter commented 9 years ago
I'm facing the same issue as @ogregoire. Rather disappointing that this is 
still an issue years later :-/

Original comment by benjamin...@gmail.com on 23 Sep 2012 at 1:49

GoogleCodeExporter commented 9 years ago
People can always help move things along by a) providing testcases that can be 
integrated into the build and b) suggesting patches. That said supporting 
parameterized methods on a non-generic factory is afaict non-trivial, but there 
may be ways to avoid needing them in the first place (which is also where a 
concrete example/test can help focus the discussion).

Original comment by mccu...@gmail.com on 24 Sep 2012 at 11:07

GoogleCodeExporter commented 9 years ago
I am also facing a situation similar to @ogregoire. Something to the effect of:

class AugmentedQueryFactory {
    public <X> AugmentedTypedQuery<X> createQuery(String query, Class<X> entityType);
}

Original comment by ssk...@qualys.com on 14 Aug 2013 at 5:26

GoogleCodeExporter commented 9 years ago
THe majority of this is fixed with one corner case, so I'm leaving this open, 
but the priority is low, with no milestone. 

Original comment by cgruber@google.com on 18 Nov 2013 at 8:09

GoogleCodeExporter commented 9 years ago

Original comment by cgruber@google.com on 18 Nov 2013 at 9:10