Proposal: Identity Injection

69 views
Skip to first unread message

Noctarius

unread,
Aug 8, 2011, 1:05:16 PM8/8/11
to google-guice
Hi guys,

the last days I worked on a new way to use Guice for injection. The
reason for starting this was a request to do similar things at the
german Java forums. So I started experimenting with it and recognized
that Guice 4 trunk has exactly the last missing key implemented to do
what was requested, ProvisionListener.

So what does Identity Injection?
Well Identity Injection takes place for the ID (identity) of object,
for example entites. Instead of just bind one special instance you can
bind a special ID. It can be seen as a special version of @Named
binding but that can be retrieved dynamically. The ID is given as one
or more properties of binding annotations. Compared to normal Guice
binding with annotation bindings you not bind a static instance but
the IdentityProvider retrieves the actual annotation instance (at the
provision point) and can return the value dynamically (for example
retrieve it from database by an EntityManager). In combination with an
RequestScope or Transactional-Scope you can directly bind special
instances.

<pre>public class UserInjectable2 {
@User(byId = 1)
private UserEntity user1;

@User(byId = 2)
private UserEntity user2;
}</pre>

It can be bound by the new IdentityModule:
<pre>final Injector injector = Guice.createInjector(new
IdentityModule() {
@Override
protected void configure() {
bindIdentity(UserEntity.class).annotatedWith(User.class)
.toIdentityProvider(new UserValueInjector());
}
});</pre>

A IdentityProvider is a new interface which works very similar to the
Provider interface but it has a parameter according to the actual
annotation instance:
<pre>public class UserValueInjector implements
IdentityProvider<UserEntity, User> {
@Override
public UserEntity buildValue(final User annotation) {
switch (annotation.byId()) {
case 1:
return new UserEntity("User1", 1);

case 2:
return new UserEntity("User2", 2);
}

throw new IllegalArgumentException("No user found for Id "
+ annotation.byId());
}

@Override
public Class<UserEntity> getInjectionType() {
return UserEntity.class;
}
}</pre>


I would love to discuss the idea and possibly contribute the code to
the official Guice extensions codebase. At the moment the code is
located at bitbucket and can be reviewed at
https://bitbucket.org/noctarius/guiceannotationextender/src.

Looking into an inspiring discussion I will answer all further
questions.

Greeting from Germany,
Noctarius

Noctarius

unread,
Aug 19, 2011, 6:38:32 AM8/19/11
to google-guice
Is there really no interest in responding?

Vance Maverick

unread,
Aug 20, 2011, 1:00:16 PM8/20/11
to google...@googlegroups.com
Hi -- my attention was drawn to this recently by a colleague. I'm not sure I understand your use case: it looks like you expect to have object IDs baked into your code, where more typically (I think) one would write a given method to work on objects of one type but various IDs.

In any case, I've been doing something somewhat similar with Guice, which might interest you or others. There's a binding annotation @Config, which is used to inject the value of a configuration parameter:

  @Inject
  @Config("myConfigParam")
  int myValue;

The injection is done by a ConfigModule, which is initialized with a set of configuration parameters -- anything that looks like a Map<String, String>. It doesn't require any extensions to Guice.

By the way, does your ProvisionListener work correctly for Provider injection? I experimented with this some, and in the Provider case, I couldn't figure out how to get at the annotation value (your byId).

    Vance

Noctarius

unread,
Aug 21, 2011, 3:28:25 AM8/21/11
to google-guice
Hi Vance,

this could be a case for using this. Config keys are known at time of
coding stuff. You can build a @Config annotation without bind all
possible values by using unique annotation bindings.

The ProvisionListener is introduced in Guice 4, so it's not mine
interface and that was the missing part to get Provider injection
working (with some ThreadLocal magic).

Noctarius

unread,
Aug 22, 2011, 1:26:07 PM8/22/11
to google-guice
Another idea where you can use it would be injection of loggers :)

@interface Logger {
Class<?> value();
}

class Foo {
@Logger(Foo.class)
private Logger logger;
}

This are values you know at compile time but could be injected by
using identity providers.

Noctarius

unread,
Aug 25, 2011, 10:05:57 AM8/25/11
to google-guice
Reply all
Reply to author
Forward
0 new messages