Log4JMembersInjector for Constructor injection?

47 views
Skip to first unread message

Gili

unread,
Jul 24, 2009, 12:12:49 AM7/24/09
to google-guice
Hi,

Is it possible to implement Log4JMembersInjector -- as found here:
http://code.google.com/p/google-guice/wiki/CustomInjections -- but for
constructor injection instead? That is, I'd like Guice to be smart
enough to inject the correct Logger instance into the constructor
automatically. I took a look at InjectionListener but it seems to hook
instances that have already been injected. Another approach that comes
to mind is:

@Provides
public Logger getLogger(Class<?> outerClass);

If I could somehow get Guice to pass in the correct Class... Any
ideas?

Gili

Dhanji R. Prasanna

unread,
Jul 24, 2009, 12:15:43 AM7/24/09
to google...@googlegroups.com
You can already do this with jdk loggers.

Dhanji.

Adrian Cole

unread,
Jul 24, 2009, 3:49:42 AM7/24/09
to google...@googlegroups.com
In jclouds, we use a similar approach, but don't bind ourselves to
java or log4j:
http://code.google.com/p/jclouds/wiki/LogDesign

Here's the configuration class that may help you do what you are looking for:
http://code.google.com/p/jclouds/source/browse/trunk/core/src/main/java/org/jclouds/logging/config/BindLoggersAnnotatedWithResource.java

I hope this helps,
-Adrian
jclouds

Dhanji R. Prasanna

unread,
Jul 24, 2009, 4:51:01 AM7/24/09
to google...@googlegroups.com
You can also write a trivial injection listener that looks for whatever logging class you like and set it after construction.

Dhanji.

Adrian Cole

unread,
Jul 24, 2009, 5:00:17 AM7/24/09
to google...@googlegroups.com
If just injecting a log class, you're right: that's trivial. The
less trivial part is setting the log scope relevant to the object
being constructed.

-Adrian

Gili Tzabari

unread,
Jul 24, 2009, 8:22:37 AM7/24/09
to google...@googlegroups.com
Guys,

I don't understand your answers. It sounds to me like you're talking
about field injection, not constructor injection.

I don't want to inject a log into an already-constructed object. I want
to inject a log directly into the class constructor:

class Foo
{
private final Logger log;

@Inject
public Foo(Logger log)
{
this.log = log;
}
}

Also, I am not necessarily doing this for jdk loggers so please provide
more detail on how to write a custom injection listener to do this.

Thanks,
Gili

Adrian Cole

unread,
Jul 25, 2009, 5:23:53 AM7/25/09
to google...@googlegroups.com
Hi, Gili.

I've just coded this for you.. I hope you digg it ;)

http://digg.com/d3yXEh

Cheers,
-Adrian
jclouds

Gili Tzabari

unread,
Jul 25, 2009, 10:51:09 AM7/25/09
to google...@googlegroups.com
Hi Adrian,

If I understand your code directly, you always inject
Logger.getRootLogger() into the constructor, then use reflection to
alter the field after-the-fact to the current type. Is this correct?

I'm looking for a way to set the Constructor argument to the right
value in the first place, instead of fixing it after the fact. It seems
to me that Guice 2.0 is missing a facility for this sort of thing. Are
there any plans for adding one in Guice 2.1 or 3.0?

Adrian Cole

unread,
Jul 25, 2009, 1:17:13 PM7/25/09
to google...@googlegroups.com
Indeed you are correct. I believe this is the only way to accomplish
the goal with the current version of guice without hacking core
classes. I don't think this was possible at all in Guice 1.0.

For this to be accomplished natively, one way could be to add a
context to providers. In this context, one could reach the injectee
like below:

@Provider Logger providerLogger(InjectionContext context){
return Logger.getLogger(context.getInjectee().getClass().getName());
}

I'm interested in other opinions on how to accomplish this.

Regards,
-Adrian
jclouds

Rodrigo Couto

unread,
Jul 26, 2009, 10:30:09 AM7/26/09
to google-guice
One could take this problem to another direction. The problem, it
seems, is the fact that you must pass a parameter to the Logger about
the class (or type) of the injectee. There is a way to accomplish
this, but it won't be pretty :)

public class LoggerFor<T> {
@Inject private TypeLiteral<T> injectee;
public Logger passMeTheLogger() { return Logger.getLogger
(injectee.getRawType()); }
}

Then, suppose you want to use a logger in the following class:

public class LoggerUser {
@Inject private LoggerFor<LoggerUser> please;
public void doesSomething() {
Logger logger = please.passMeTheLogger();
logger.debug("thanks!");
}
}

There is the obvious drawback: now you have to bind a LoggerFor<T> for
every of its clients.

-- Rodrigo Couto

On 25 jul, 14:17, Adrian Cole <fernc...@gmail.com> wrote:
> Indeed you are correct.  I believe this is the only way to accomplish
> the goal with the current version of guice without hacking core
> classes.  I don't think this was possible at all in Guice 1.0.
>
> For this to be accomplished natively, one way could be to add a
> context to providers.  In this context, one could reach the injectee
> like below:
>
> @Provider Logger providerLogger(InjectionContext context){
>    return Logger.getLogger(context.getInjectee().getClass().getName());
>
> }
>
> I'm interested in other opinions on how to accomplish this.
>
> Regards,
> -Adrian
> jclouds
>
> On Sat, Jul 25, 2009 at 4:51 PM, Gili Tzabari<gili.tzab...@gmail.com> wrote:
>
> > Hi Adrian,
>
> >        If I understand your code directly, you always inject
> > Logger.getRootLogger() into the constructor, then use reflection to
> > alter the field after-the-fact to the current type. Is this correct?
>
> >        I'm looking for a way to set the Constructor argument to the right
> > value in the first place, instead of fixing it after the fact. It seems
> > to me that Guice 2.0 is missing a facility for this sort of thing. Are
> > there any plans for adding one in Guice 2.1 or 3.0?
>
> > Thanks,
> > Gili
>
> > Adrian Cole wrote:
> >> Hi, Gili.
>
> >> I've just coded this for you..  I hope you digg it ;)
>
> >>http://digg.com/d3yXEh
>
> >> Cheers,
> >> -Adrian
> >> jclouds
>
> >> On Fri, Jul 24, 2009 at 2:22 PM, Gili Tzabari<gili.tzab...@gmail.com> wrote:
> >>> Guys,
>
> >>>        I don't understand your answers. It sounds to me like you're talking
> >>> about field injection, not constructor injection.
>
> >>>        I don't want to inject a log into an already-constructed object. I want
> >>> to inject a log directly into the class constructor:
>
> >>> class Foo
> >>> {
> >>>   private final Logger log;
>
> >>>   @Inject
> >>>   public Foo(Logger log)
> >>>   {
> >>>     this.log = log;
> >>>   }
> >>> }
>
> >>>        Also, I am not necessarily doing this for jdk loggers so please provide
> >>> more detail on how to write a custom injection listener to do this.
>
> >>> Thanks,
> >>> Gili
>
> >>> Adrian Cole wrote:
> >>>> If just injecting a log class, you're right: that's trivial.   The
> >>>> less trivial part is setting the log scope relevant to the object
> >>>> being constructed.
>
> >>>> -Adrian
>
> >>>> On Fri, Jul 24, 2009 at 10:51 AM, Dhanji R. Prasanna<dha...@gmail.com> wrote:
> >>>>> You can also write a trivial injection listener that looks for whatever
> >>>>> logging class you like and set it after construction.
> >>>>> Dhanji.
>
> >>>>> On Fri, Jul 24, 2009 at 5:49 PM, Adrian Cole <fernc...@gmail.com> wrote:
> >>>>>> In jclouds, we use a similar approach, but don't bind ourselves to
> >>>>>> java or log4j:
> >>>>>>    http://code.google.com/p/jclouds/wiki/LogDesign
>
> >>>>>> Here's the configuration class that may help you do what you are looking
> >>>>>> for:
>
> >>>>>>http://code.google.com/p/jclouds/source/browse/trunk/core/src/main/ja...
>
> >>>>>> I hope this helps,
> >>>>>> -Adrian
> >>>>>> jclouds
>
> >>>>>> On Fri, Jul 24, 2009 at 6:15 AM, Dhanji R. Prasanna<dha...@gmail.com>
> >>>>>> wrote:
> >>>>>>> You can already do this with jdk loggers.
> >>>>>>> Dhanji.
>
> >>>>>>> On Fri, Jul 24, 2009 at 2:12 PM, Gili <gili.tzab...@gmail.com> wrote:
> >>>>>>>> Hi,
>
> >>>>>>>> Is it possible to implement Log4JMembersInjector -- as found here:
> >>>>>>>>http://code.google.com/p/google-guice/wiki/CustomInjections-- but for

Adrian Cole

unread,
Jul 26, 2009, 2:48:27 PM7/26/09
to google...@googlegroups.com
Very clever, Rodrigo.   Thanks for sharing this.  Although I'm not sure I'd use it for Loggers, it is an interesting example of TypeLiteral use.

Cheers,
-Adrian

Gili Tzabari

unread,
Jul 27, 2009, 1:00:17 PM7/27/09
to google...@googlegroups.com
Rodrigo,

Cute example but the fact that LoggerFor<T> takes in the name of the
enclosing class defeats the entire purpose.

I like the "InjectionContext" proposal quite a bit. Any chance that
being added?

Gili

Gili

unread,
Aug 13, 2009, 10:01:05 PM8/13/09
to google-guice
I filed a RFE for injection context: http://code.google.com/p/google-guice/issues/detail?id=412

Gili

On Jul 25, 1:17 pm, Adrian Cole <fernc...@gmail.com> wrote:
> Indeed you are correct.  I believe this is the only way to accomplish
> the goal with the current version of guice without hacking core
> classes.  I don't think this was possible at all in Guice 1.0.
>
> For this to be accomplished natively, one way could be to add a
> context to providers.  In this context, one could reach the injectee
> like below:
>
> @Provider Logger providerLogger(InjectionContext context){
>    return Logger.getLogger(context.getInjectee().getClass().getName());
>
> }
>
> I'm interested in other opinions on how to accomplish this.
>
> Regards,
> -Adrian
> jclouds
>
> On Sat, Jul 25, 2009 at 4:51 PM, Gili Tzabari<gili.tzab...@gmail.com> wrote:
>
> > Hi Adrian,
>
> >        If I understand your code directly, you always inject
> > Logger.getRootLogger() into the constructor, then use reflection to
> > alter the field after-the-fact to the current type. Is this correct?
>
> >        I'm looking for a way to set the Constructor argument to the right
> > value in the first place, instead of fixing it after the fact. It seems
> > to me that Guice 2.0 is missing a facility for this sort of thing. Are
> > there any plans for adding one in Guice 2.1 or 3.0?
>
> > Thanks,
> > Gili
>
> > Adrian Cole wrote:
> >> Hi, Gili.
>
> >> I've just coded this for you..  I hope you digg it ;)
>
> >>http://digg.com/d3yXEh
>
> >> Cheers,
> >> -Adrian
> >> jclouds
>
> >> On Fri, Jul 24, 2009 at 2:22 PM, Gili Tzabari<gili.tzab...@gmail.com> wrote:
> >>> Guys,
>
> >>>        I don't understand your answers. It sounds to me like you're talking
> >>> about field injection, not constructor injection.
>
> >>>        I don't want to inject a log into an already-constructed object. I want
> >>> to inject a log directly into the class constructor:
>
> >>> class Foo
> >>> {
> >>>   private final Logger log;
>
> >>>   @Inject
> >>>   public Foo(Logger log)
> >>>   {
> >>>     this.log = log;
> >>>   }
> >>> }
>
> >>>        Also, I am not necessarily doing this for jdk loggers so please provide
> >>> more detail on how to write a custom injection listener to do this.
>
> >>> Thanks,
> >>> Gili
>
> >>> Adrian Cole wrote:
> >>>> If just injecting a log class, you're right: that's trivial.   The
> >>>> less trivial part is setting the log scope relevant to the object
> >>>> being constructed.
>
> >>>> -Adrian
>
> >>>> On Fri, Jul 24, 2009 at 10:51 AM, Dhanji R. Prasanna<dha...@gmail.com> wrote:
> >>>>> You can also write a trivial injection listener that looks for whatever
> >>>>> logging class you like and set it after construction.
> >>>>> Dhanji.
>
> >>>>> On Fri, Jul 24, 2009 at 5:49 PM, Adrian Cole <fernc...@gmail.com> wrote:
> >>>>>> In jclouds, we use a similar approach, but don't bind ourselves to
> >>>>>> java or log4j:
> >>>>>>    http://code.google.com/p/jclouds/wiki/LogDesign
>
> >>>>>> Here's the configuration class that may help you do what you are looking
> >>>>>> for:
>
> >>>>>>http://code.google.com/p/jclouds/source/browse/trunk/core/src/main/ja...
>
> >>>>>> I hope this helps,
> >>>>>> -Adrian
> >>>>>> jclouds
>
> >>>>>> On Fri, Jul 24, 2009 at 6:15 AM, Dhanji R. Prasanna<dha...@gmail.com>
> >>>>>> wrote:
> >>>>>>> You can already do this with jdk loggers.
> >>>>>>> Dhanji.
>
> >>>>>>> On Fri, Jul 24, 2009 at 2:12 PM, Gili <gili.tzab...@gmail.com> wrote:
> >>>>>>>> Hi,
>
> >>>>>>>> Is it possible to implement Log4JMembersInjector -- as found here:
> >>>>>>>>http://code.google.com/p/google-guice/wiki/CustomInjections-- but for

Nicholas Clare

unread,
Aug 14, 2009, 1:12:15 AM8/14/09
to google...@googlegroups.com

Nicholas Clare

unread,
Aug 14, 2009, 1:14:33 AM8/14/09
to google...@googlegroups.com
Sorry about that, pesky iPhone!
Reply all
Reply to author
Forward
0 new messages