Getting annotation value from within a Provider

65 views
Skip to first unread message

Michael Burton

unread,
Jul 17, 2009, 3:40:46 PM7/17/09
to google-guice
I would like to create a Provider that can provide a particular string
based on the value of an Annotation.

In particular (since I'm using Android), I would like to do something
like the following:

@Inject
public void setString( @StringResource(R.string.foobar) String foobar)
{ ... }

If you're not familiar with Android, R.string.foobar is an int value
generated at compile time as part of the android build process. It's
a unique integer that you can use to call into a Resouce object in
order to retrieve the corresponding String.

I see some conversations in the google group from 2007 regarding
various hacky ways to do this, and some suggestions that a less hacky
way is imminent, but I don't see any actual solutions yet.

Is there a way my provider can obtain the value of the resource in
order to determine which String to inject?

Cheers,
Mike

PS. see http://groups.google.com/group/google-guice/browse_thread/thread/24f0a4793f6957ef/56f040b93124cac2
and http://code.google.com/p/google-guice/issues/detail?id=27 for
related conversations I've found so far.

Michael Burton

unread,
Jul 21, 2009, 1:27:36 PM7/21/09
to google-guice
Just thought I'd check in and see if anyone had any suggestions for
how to work around the following issue.

Cheers,
Mike



On Jul 17, 12:40 pm, Michael Burton <m...@niskala.org> wrote:
> I would like to create a Provider that can provide a particular string
> based on the value of an Annotation.
>
> In particular (since I'm using Android), I would like to do something
> like the following:
>
> @Inject
> public void setString( @StringResource(R.string.foobar) String foobar)
> { ... }
>
> If you're not familiar with Android, R.string.foobar is an int value
> generated at compile time as part of the android build process.  It's
> a unique integer that you can use to call into a Resouce object in
> order to retrieve the corresponding String.
>
> I see some conversations in the google group from 2007 regarding
> various hacky ways to do this, and some suggestions that a less hacky
> way is imminent, but I don't see any actual solutions yet.
>
> Is there a way my provider can obtain the value of the resource in
> order to determine which String to inject?
>
> Cheers,
> Mike
>
> PS. seehttp://groups.google.com/group/google-guice/browse_thread/thread/24f0...
> andhttp://code.google.com/p/google-guice/issues/detail?id=27for

Aleksey Didik

unread,
Jul 22, 2009, 9:16:21 AM7/22/09
to google-guice
Hello, I asked about this feature early.

See here:
http://groups.google.com/group/google-guice/browse_frm/thread/1d61052ce6c46bc4/32e7c46604df958c#32e7c46604df958c

Best regards,
Aleksey

Michael Burton

unread,
Jul 22, 2009, 8:18:25 PM7/22/09
to google-guice
Thanks for the link, Aleksey.

Yeah, it seems like binding every configuration constant to an
instance a viable workaround for some situations, but it doesn't seem
like it's really the right solution.

In particular, on Android I don't want to load all of the resources at
the time the module is started. Some of them can be memory intensive
(eg. bitmaps), and many of my Android activities will never use most
of them at all.

I can understand the arguments I've read elsewhere (eg. Dhanji here
http://bit.ly/1FPeAq ) that configuration data doesn't belong in code,
but every once in awhile we all have to work with frameworks that
force you to jump through hoops, and it seems like Guice could make
this sort of thing a lot easier with just a small tweak...

That being said, perhaps someone knows a way to do this already? Is
it possible to get access to the Annotation instance from within a
provider? I've been trying to follow the discussions here, but
haven't really been able to figure out what's supported and what
isn't.

http://code.google.com/p/google-guice/issues/detail?id=258
http://code.google.com/p/google-guice/issues/detail?id=27

Can I get this sort of capability with something like Guiceyfruit?
(And if so, can I use Guiceyfruit without AOP since AOP's not
supported on Android)

Cheers,
Mike





On Jul 22, 6:16 am, Aleksey Didik <aleksey.di...@gmail.com> wrote:
> Hello, I asked about this feature early.
>
> See here:http://groups.google.com/group/google-guice/browse_frm/thread/1d61052...

Witold Szczerba

unread,
Jul 23, 2009, 2:54:39 AM7/23/09
to google...@googlegroups.com
2009/7/23 Michael Burton <mi...@niskala.org>:

> In particular, on Android I don't want to load all of the resources at
> the time the module is started.  Some of them can be memory intensive
> (eg. bitmaps), and many of my Android activities will never use most
> of them at all.

Registering a provider of some resource R does not load R when module
is started. It will be loaded when you inject R, when you inject
something which depends on R or when you inject Provider<R> and invoke
its #get method.

James Strachan

unread,
Jul 30, 2009, 5:36:49 AM7/30/09
to google...@googlegroups.com
2009/7/23 Michael Burton <mi...@niskala.org>:

>
> Thanks for the link, Aleksey.
>
> Yeah, it seems like binding every configuration constant to an
> instance a viable workaround for some situations, but it doesn't seem
> like it's really the right solution.
>
> In particular, on Android I don't want to load all of the resources at
> the time the module is started.  Some of them can be memory intensive
> (eg. bitmaps), and many of my Android activities will never use most
> of them at all.
>
> I can understand the arguments I've read elsewhere (eg. Dhanji here
> http://bit.ly/1FPeAq ) that configuration data doesn't belong in code,
> but every once in awhile we all have to work with frameworks that
> force you to jump through hoops, and it seems like Guice could make
> this sort of thing a lot easier with just a small tweak...

I agree; it would be really nice to be able to write a @Provides
method which has the binding annotation instance as a parameter; so
that you can write a single method which extracts values from the
annotation instance & uses those to create the required object to
inject - rather than having to explicitly bind every permutation of
values of the annotation to instances/providers.


> That being said, perhaps someone knows a way to do this already?  Is
> it possible to get access to the Annotation instance from within a
> provider?  I've been trying to follow the discussions here, but
> haven't really been able to figure out what's supported and what
> isn't.
>
> http://code.google.com/p/google-guice/issues/detail?id=258
> http://code.google.com/p/google-guice/issues/detail?id=27
>
> Can I get this sort of capability with something like Guiceyfruit?
> (And if so, can I use Guiceyfruit without AOP since AOP's not
> supported on Android)

Unfortunately not in the example you show....

@Inject
public void setString( @StringResource(R.string.foobar) String foobar)

GuiceyFruit currently focusses on using an annotation to specify a
parameterised injection point (like @Resource) which only tends to
work on a field or property injection point - not on annotations on
parameters at a regular @Inject injection point.

If you did it more like this...

@StringResource(R.string.foobar)
public void setString( String foobar)

then you could bind the StringResource annotation as an injection
point like the way @Resource is supported; you can then write a kind
of provider which takes the StringResource annotation and uses its
values to create an object.

e.g.

http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-core/src/main/java/org/guiceyfruit/jsr250/ResourceMemberProvider.java

for code sharing reasons much of the heavy lifting is actually in this
base class

http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-core/src/main/java/org/guiceyfruit/jsr250/NamedProviderSupport.java

So in GuiceyFruit you'd implement a class which extends
AnnotationMemberProviderSupport<StringResource> then you bind it in
your GuiceyFruitModule via the bindAnnotationInjector() method
http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-core/src/main/java/org/guiceyfruit/jsr250/Jsr250Module.java

--
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/

Michael Burton

unread,
Jul 30, 2009, 2:44:32 PM7/30/09
to google...@googlegroups.com
Great James, it looks like that's very much along the lines of what
I'm looking for. I'll try it out sometime in the next few weeks.

It seems like I've been reading a lot of "yeah that would be nice"
posts about being able to read attribute values from within
providers. It certainly would help me for Android and other
projects. Guice maintainers, any thoughts about incorporating this
into Guice?

Cheers,
Mike

Michael Burton

unread,
Jul 30, 2009, 4:44:10 PM7/30/09
to google-guice
Well, I couldn't wait, so I walked through what guiceyfruit was doing
and managed to accomplish what I needed using a custom TypeListener
and MembersInjector (without guiceyfruit).

Works great! I'm quite pleased with the result. For anyone looking
to solve this problem in the future, I recommend using this solution
(or guiceyfruit, which is more polished). It would be grand if Guice
supported it directly, but as a workaround this solution seems
scalable and pretty efficient. I had thought it wasn't possible
previously, but now at least I know it is even if it's not as
convenient as a standard Provider.

Thanks James,

Mike





On Jul 30, 11:44 am, Michael Burton <m...@niskala.org> wrote:
> Great James, it looks like that's very much along the lines of what  
> I'm looking for.  I'll try it out sometime in the next few weeks.
>
> It seems like I've been reading a lot of "yeah that would be nice"  
> posts about being able to read attribute values from within  
> providers.  It certainly would help me for Android and other  
> projects.  Guice maintainers, any thoughts about incorporating this  
> into Guice?
>
> Cheers,
> Mike
>
>
>
> > GuiceyFruit currently focusses on using an annotation to specify a
> > parameterised injection point (like @Resource) which only tends to
> > work on a field or property injection point - not on annotations on
> > parameters at a regular @Inject injection point.
>
> > If you did it more like this...
>
> > @StringResource(R.string.foobar)
> > public void setString(  String foobar)
>
> > then you could bind the StringResource annotation as an injection
> > point like the way @Resource is supported; you can then write a kind
> > of provider which takes the StringResource annotation and uses its
> > values to create an object.
>
> > e.g.
>
> >http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-...
>
> > for code sharing reasons much of the heavy lifting is actually in this
> > base class
>
> >http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-...
>
> > So in GuiceyFruit you'd implement a class which extends
> > AnnotationMemberProviderSupport<StringResource> then you bind it in
> > your GuiceyFruitModule via the bindAnnotationInjector() method
> >http://code.google.com/p/guiceyfruit/source/browse/trunk/guiceyfruit-...

Dhanji R. Prasanna

unread,
Jul 30, 2009, 7:12:05 PM7/30/09
to google...@googlegroups.com
Yea, we considered this very early on, with providing the InjectionPoint itself to a provider. But it didn't materialize then and there hasn't been much demand since (InjectionListeners also solve the problem orthogonally, as you note).

Dhanji.

Aleksey Didik

unread,
Jul 31, 2009, 3:02:47 AM7/31/09
to google-guice
That great Michael, but one problem exists.
You couldn't use guiceyfruit (TypeListener) solution for constructor
injection...
But (for me), it's most useful injection type...

If you are using field or method (setter) injection, type listener
works great!

As to me, all who want to read anotation parameters in providers, need
to join forces and argue guice owners into this functionality
necessity.
Or may be create patch by ourselves.

As I understand Bob Lee position, he want to be sure that all binding
could be resolved, application is consistent. But if we will bind a
set of possible annotations to one provider, it can't guarantee
application consistence. (Sorry Bob, if I have corrupted your
opinion).

Any cases, it will be the great to read guice owners position on this
question again.

Best regards,
Aleksey.

James Strachan

unread,
Jul 31, 2009, 3:34:34 AM7/31/09
to google...@googlegroups.com
2009/7/31 Dhanji R. Prasanna <dha...@gmail.com>:

> Yea, we considered this very early on, with providing the InjectionPoint
> itself to a provider. But it didn't materialize then and there hasn't been
> much demand since (InjectionListeners also solve the problem orthogonally,
> as you note).

Though InjectionListeners can only be used to create new injection
points not using @Inject. Its not possible to use them with @Inject
injection points such as this

public class Foo {
@Inject
public Foo(@StringResource("blah") String xyz) {
...

Dhanji R. Prasanna

unread,
Jul 31, 2009, 8:34:21 AM7/31/09
to google...@googlegroups.com
On Fri, Jul 31, 2009 at 5:34 PM, James Strachan <james.s...@gmail.com> wrote:

2009/7/31 Dhanji R. Prasanna <dha...@gmail.com>:
> Yea, we considered this very early on, with providing the InjectionPoint
> itself to a provider. But it didn't materialize then and there hasn't been
> much demand since (InjectionListeners also solve the problem orthogonally,
> as you note).

Though InjectionListeners can only be used to create new injection
points not using @Inject. Its not possible to use them with @Inject
injection points such as this

But you can achieve the same result with a TypeListener + InjectionListener.

I agree, however, I would have liked to see InjectionPoint-aware providers. We discussed this at length early on, but I suppose as these things happen there wasn't enough community pressure and things went in a different direction...

Dhanji.

Reply all
Reply to author
Forward
0 new messages