On Aug 17, 2009, at 10:15 AM, James Strachan wrote:
>>
>> Guice's approach to custom injections using a TypeListener has
>> limitations because it means one cannot integrate cleanly with the
>> parameters associated with @Inject on constructors, fields or
>> methods.
>
> Agreed
>
>> I would like to do something like:
>> MetaProvider mp = ...
>> bind(QueryParam.class).toMetaProvider(mp);
>> Where a meta provider has access to the injection type, the
>> annotations on
>> the type, and the target class. The meta provider is responsible for
>> creating a provider with the appropriate scope.
>> I am very very tempted to modify Guice to support this concept.
>
> I'd love this too! Basically being able to use the binding annotation
> as a parameter in a provider method along with the injection point
> (method/field); so you can have a single provider (class/method) which
> takes the binding annotation as a parameter - then you can use its
> attributes to create the value.
>
> This came up recently on the guice list though unfortunately didn't
> seem to get much traction from guice committers
> http://groups.google.com/group/google-guice/msg/aafaad43d9433bbd
>
It seems Guice has gone to great lengths to provide plugin points
after construction but is missing one very obvious sweet spot that
could benefit Guice developers so they do not have to resort or lower-
level approaches utilizing reflection. Basically it is the use case of
injecting when some context of where one is injecting is required.
The example of injecting a Log4J Logger could work "correctly" in the
Guice way (also one does not have to always key of an annotation for
this to be of benefit). Thus the example would become:
import org.apache.log4j.Logger;
import com.publicobject.log4j.InjectLogger;
public class PaymentService {
@Inject Logger logger;
...
}
@Override protected void configure() {
bind???(Logger.class, new Log4JMetaProvider());
}
public class Log4JMetaProvider implements MetaProvider<Logger> {
public Provider<Logger> getProvider(final Class target, ...) {
return new Provider<Logger>() {
public Logger get() {
return Logger.getLogger(target);
}
};
}
}
Hmm... perhaps even better one could inject the contextual information
for a provider e.g.:
@Provides
public Logger providerLogger(InjectionContext ic) {
return Logger.getLogger(ic.getTarget());
}
or:
public class LoggerProvider implements Provider<Logger> {
Logger l;
@Inject
public LoggerProvider(InjectionContext ic) {
l = Logger.getLogger(ic.getTarget());
}
public Logger get() {
return l;
}
}
What does Dhanji mean by:
http://groups.google.com/group/google-guice/msg/e3dcb7b788247088
"But you can achieve the same result with a TypeListener +
InjectionListener. "
He may have misunderstanding you because TypeListener +
InjectionListener cannot be used to do:
public class Foo {
@Inject
public Foo(@StringResource("blah") String xyz) {
Or does he mean you can achieve what GuiceFruit does? which is of
course what GuiceFruit uses :-), but makes it easier for the developer.
How about if we could do it like this:
bindAnnotation(StringResource.class).
typedWith(String.class).
toProvider(StringResourceProvider.class);
public class StringResourceProvider implements Provider<String> {
@Inject
public StringResourceProvider(InjectionContext ic) {
StringResource sr = ic.getAnnotation(StringResource.class);
}
...
}
Then i might be able to do something for Jersey/JAX-RS like the
following:
bindAnnotation(QueryParam.class).
toProvider(QueryParamProvider.class).
inScope(RequestScoped.class);
public class QueryParamProvider implements Provider<?> {
@Inject
public QueryParamProvider(InjectionContext ic) {
// Analyze type and annotations, throw exception if it cannot
be supported.
// Store state on the provider
}
...
}
> FWIW GuiceyFruit provides something like this; you create a
> implementation of this interface...
> http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-core/src/main/java/org/guiceyfruit/support/AnnotationMemberProvider.java
>
OK.
In your experience how hard would it be to modify Guice to support
this for @Inject?
Paul.
> which then has access to the annotation and the method/field for
> creating the value. The only downside is this takes place at
> field/method injection points (not constructors) as its a separate
> injection mechanism to @Inject such as to support @Resource,
> @Autowired and so forth.
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>