Using annotation on injector getInstance call

1,759 views
Skip to first unread message

Wingnut

unread,
Mar 18, 2008, 7:41:15 AM3/18/08
to google-guice
I saw a rough example somewhere on this, and for the life of me I
cannot get it to work correctly. I have two annotations, let's call
them Apple and Orange (pardon my fruit references, seemed the simplest
to use).

Here's some code showing implementation:

Annotations (both look the same, but different names, I'll show
"Apple"):

@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
@Target(ElementType.LOCAL_VARIABLE)
public @interface Apple { }

Interfaces:

public interface FruitService {
public FruitType getType();
}

Classes that implement the interface:

public class BaseFruitImpl implements FruitService {
public FruitType getType() {
return FruitType.NONE;
}
}

public class AppleFruitImpl implements FruitService {
public FruitType getType() {
return FruitType.APPLE;
}
}

Bindings in "FruitModule":

binder.bind(FruitService.class).to(BaseFruitImpl.class);
binder.bind(FruitService.class).annotatedWith(Apple.class).to(AppleFruitImpl.class);

Client:

Injector injector = Guice.createInjector(new FruitModule());
@Apple FruitService apple = injector.getInstance(FruitService.class);

Now, I know I can call getInstance(AppleFruitImpl.class) but that's
not the point, the thing is I want to use annotations to make the call
and the bindings should know what class I'm really asking for as I
annotated it with @Apple.. but when I call this with the @Apple
annotation up front, it still gives me a BaseFruitImpl, or
FruitType.NONE if you will, and if I remove the BaseFruitImpl binding
Guice throws an Exception telling me I have no binding..

Something is obviously missing in my code, or something I'm doing is
wrong, but according from what I've seen, this way of doing it should
be fine.

Any help will be very much appreciated, thanks!
Wing

Robbie Vanbrabant

unread,
Mar 18, 2008, 8:05:24 AM3/18/08
to google...@googlegroups.com
Injecting local variables does not work. Guice injects fields, methods and constructors (if tagged with @Inject).

So first, have your annotation represent that you will put it on fields or parameters:

@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface Apple { }

Then, change your example to:
FruitService apple = injector.getInstance(Key.get(FruitService.class, Apple.class));

You should only need to get one object from the injector (top level object) directly. Others, lower down the object graph, you can simply @Inject:
public class UsesService {
    @Inject
    public UsesService(@Apple FruitService service) { ... }
}

Hope this helps. Keep an eye out for my book! (http://www.apress.com/book/view/1590599977)

Robbie

Wingnut

unread,
Mar 18, 2008, 10:43:25 AM3/18/08
to google-guice
Ahh, thanks, that clears it up! Good luck on that book, looks
interesting!

On Mar 18, 1:05 pm, "Robbie Vanbrabant" <robbie.vanbrab...@gmail.com>
wrote:
> Injecting local variables does not work. Guice injects fields, methods and
> constructors (if tagged with @Inject).
>
> So first, have your annotation represent that you will put it on fields or
> parameters:
>
> @Retention(RetentionPolicy.RUNTIME)
> @BindingAnnotation
> @Target({ElementType.FIELD, ElementType.PARAMETER})
> public @interface Apple { }
>
> Then, change your example to:
> FruitService apple = injector.getInstance(Key.get(FruitService.class,
> Apple.class));
>
> You should only need to get one object from the injector (top level object)
> directly. Others, lower down the object graph, you can simply @Inject:
> public class UsesService {
> @Inject
> public UsesService(@Apple FruitService service) { ... }
>
> }
>
> Hope this helps. Keep an eye out for my book! (http://www.apress.com/book/view/1590599977)
>
> Robbie
>
Reply all
Reply to author
Forward
0 new messages