How can I customize binding lookup ?

173 views
Skip to first unread message

David Nouls

unread,
May 4, 2015, 9:05:08 AM5/4/15
to google...@googlegroups.com
In my applications I need to be able to have some influence on how Guice searches for bindings.

The problem that I am trying to solve:
I have a system to generate alerts. The code that generates these alerts need to declare an interface that extends a marker interface and all the methods use annotations to declare the actual text with placeholders for the parameters. The actual implementation of this interface is done by one single dynamic proxy implementation. For example

public interface Alerts {}

public interface TestAlerts extends Alerts {
  @Alert( "Hello {0}" )
  public void hello( String text );
}

In the application code I inject the TestAlerts and use it like a regular object. The advantage of this approach is that I get nice compiler warnings whenever a change to parameters is done, or a message has been removed from the Alerts interface. I can also do decent formatting and type conversion without complicating the code that uses my Alert system.

Right now I have 2 possibilities in Guice:
1) bind all interfaces that extends Alerts with a provider that can create the dynamic proxy specific to the requested interface.
2) Inject an AlertFactory that has a <V extends Alerts> V create(Class<V> typeClass ) method.

Solution 1 becomes tedious because in my case we are talking about hundreds of injections (large enterprise system with lots of independent components).
Solution 2 exposes the fact that you need to use a factory to send a simple alert. Somehow this feels a bit like an anti-pattern because I am not interested in how to create these objects, I just want on instance by magic as I am used in injection frameworks.

I've read and tried the documentation section on custom Custom Injections. But is very incomplete, since it only allows injection into members, not constructors and it requires you to use a custom annotation, not @Inject which basically already requires the class to know that what he is depending on needs some kind of extension - which sounds like an anti-pattern to me.

I would like to be able to somehow register that Guice should use a Factory that takes an argument of type class<V extends Alerts>. Or someway to register a TypeListener that gets invoked when some unknown type is requested for injection. 

Any ideas how to do this ? Any chance of getting some extra extension point in Guice to go a step further with extensions ?


Sam Berlin

unread,
May 4, 2015, 9:07:26 AM5/4/15
to google...@googlegroups.com
The lack of this feature is by design.  See the discussion @ https://github.com/google/guice/issues/49.

sam

--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-guice/d3e36ad3-c49b-4cbb-9640-6527877491bd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

David

unread,
May 4, 2015, 9:54:41 AM5/4/15
to google...@googlegroups.com
Thanks for the link, I did not find that one before.

From what I read in the bug report they need a compelling use case. Assuming that there is no need for this because after 4 years of discussions nobody joined the discussions is an easy answer. Most people just don't bother joining in the discussion for various reasons. 

For me my example is a compelling case. Requiring duplication of bindings (in my case 100+) is very tedious. Injecting a Factory instead is also no so nice (but workable at this moment). And my case does not ask for a complete freedom, I need to register with some base class or matcher that would allow me to construct the required binding.

How did the Custom Injections get accepted in Guice ? It is a very limited scope and it actually is a bit of an anti pattern in that the class actually knows that the fields will be injected by some custom injector. You could argue the same about assisted injects - although those have a bit more broader use.

Various other projects like Jukito/gwtmockito offer a possibility to "auto-mock" undefined bindings. So those could actually also use such an extension mechanism.


Sam Berlin

unread,
May 4, 2015, 10:40:09 AM5/4/15
to google...@googlegroups.com

The reason for the lack of feature is because it would make code using it harder to understand. There's a 1:1 ratio right now with bind statements (or @Provides methods) and injectable types right now. That's relaxed to 0:1 for just-in-time bindings (so if you don't see a bind statement for a type, it must be a just-in-time binding).  Allowing 1:many would make understanding what is being injected much harder.  Guice is already confusing enough... no need to add more features that complicate the basic injection model even more.

TypeListeners are somewhat different because they require using different annotations. The rules for @Inject stay the same, but Guice can be leveraged to supply data to other annotations.

sam


Vyacheslav Rusakov

unread,
May 4, 2015, 3:28:48 PM5/4/15
to google...@googlegroups.com
I faced almost the same problem: I was writing a kind of spring-data repositories, where queries supposed to be defined with annotations on interface methods and in runtime proxies should be created.

The solution I found is a bit hacky: I used @ProvidedBy with generic provider, which could simply generate proxy class from provided interface.
It was important for me to generate proxy class, because guice aop doesn't work for binded instances, and I was going to implement all annotations on interfaces with aop (+reuse @Transactional logic).

As a result, I can now simply annotate interface (or abstract class) with @ProvidedBy(DynamicClassProvider.class) and it will generate required proxy (using javassist) in runtime (during jit resolution)


I think, it perfectly fits for your case. You will just need to implement @Alert annotation support with guice AOP.
Or you could write your own hacky provider the same way :)

понедельник, 4 мая 2015 г., 20:40:09 UTC+6 пользователь Sam Berlin написал:

David

unread,
May 5, 2015, 4:03:35 AM5/5/15
to google...@googlegroups.com
Thanks for the info, I will try that approach. Sounds like fun.

David

unread,
May 7, 2015, 5:10:18 AM5/7/15
to google...@googlegroups.com
I only realize this now, I need to put my code in the com.google.inject.internal package.
Does Guice not offer a way to get info about the type a provider is supposed to be creating (the type on which the ProvidedBy is put) ?

On Mon, May 4, 2015 at 9:28 PM, Vyacheslav Rusakov <vya...@gmail.com> wrote:

Vyacheslav Rusakov

unread,
May 7, 2015, 5:46:29 AM5/7/15
to google...@googlegroups.com
I did not find a way to workaround this limitation. To be honest, I'm glad this api is accessible at least this way. 

четверг, 7 мая 2015 г., 15:10:18 UTC+6 пользователь David Nouls написал:

Sam Berlin

unread,
May 7, 2015, 9:00:40 AM5/7/15
to google...@googlegroups.com
Providers are intended to be 1:1 with what they're providing, so there's no information to supply.

sam

David

unread,
May 7, 2015, 9:39:45 AM5/7/15
to google...@googlegroups.com
Sam,

Providers already get extra information since you can inject dependencies in the Provider, it is not exposed in the interface - which is great.

The 1:1 rule is about the binding to a type of provider, but once you have a Provider then there is no guarantee that it will always return the same instance. Certainly if you combine it with scoped bindings.

What I need is a n:1 binding without needing to write out n lines of bind operation - as is the case right now. 
something like:
bind(Matchers.subTypeOfAlert.class)).toProvider( AlertProvider.class );
or
bind(Types.subtypeOf(Alert.class)).toProvider(AlertProvider.class);

where the AlertProvider has a way to know the key it is actually trying to resolve when a dependency is resolved.
Right now that requires the use of internal code, as demonstrated by Mr Rusakov, 

But why not support @Inject @BindKey Key<?> to avoid making changes to the Provider interface ?

This kind of binding is not something you need very often but for certain kind of situations it is a nice solution. It certainly beats the solution of repeating the bind for every possible subtype with the same target type or to inject a custom made factory everywhere I need to be able to send alerts. 



Sam Berlin

unread,
May 7, 2015, 9:44:30 AM5/7/15
to google...@googlegroups.com
Providers are intended to create something regardless of where it is injecting that thing into and what type the provider was bound to.

Exposing either of those bits of information to the provider makes understanding what is going on much harder.  This is why it's intentionally not exposed.

My prior reply explained why one binding statement to create many bindings isn't supported.

sam

Jens

unread,
May 7, 2015, 10:04:20 AM5/7/15
to google...@googlegroups.com

What I need is a n:1 binding without needing to write out n lines of bind operation - as is the case right now. 

Haven't followed the full discussion but I am pretty sure you could also use annotation processor to generate code required to make your alerts work without using any internal Guice API.

-- J.

Nate Bauernfeind

unread,
May 7, 2015, 10:04:24 AM5/7/15
to google...@googlegroups.com
David,

When I find myself wanting functionality such as one to many binding, I usually realize what I want to accomplish doesn't really need Guice. Have you thought about writing your own alert factory?

Something like:

public interface AlertFactory {
  <T extends Alert> T newAlert(Class<T> cls);
}

Your alert factory impl could have the injector injected into it and then call injector.injectMembors(theNewAlert) if you must have objects injected into them.

Your alerts would be forced to use setter-injection. I imagine they're supposed to be tiny token classes, so that is probably a reasonable restriction anyways (i.e. you don't want them to hold references to them anyways, do you?).

This pattern breaks down a little bit if you have scoped object graphs and you want to inject objects that are bound only in child or private contexts. If that is what you need, then you would also need to provide the injecting context (i.e. pass the injector into the newAlert method). I don't know if Java8's default methods are sufficient to handle abstracting the use of the local-context injector or not should you need it, but it might be worth looking into.

What do you think of a solution like/similar-to this?

Nate

On Thu, May 7, 2015 at 9:39 AM David <david...@gmail.com> wrote:

David

unread,
May 7, 2015, 3:14:27 PM5/7/15
to google...@googlegroups.com
I know how to solve the issue with and without Guice. That is not the point. 

I think Guice is lacking certain functionality that could allow certain injection patterns not possible right now. I have come across many situtations where I needed something like this.

If I have to start creating factories like Nate says (which is what I am doing right now), then what is the point of an injection framework ? Its core reason of being is that is allows you to avoid writing all that boilerplate code to create factories or hand-code singletons and other factory patterns. Additionally, if I want to have a singleton Alert instance then I will have to implement it in the factory somehow. And what about other kind of scoping ?
 
I could experiment with annotation processors ... it seems to be the trend right now. But isn't this making stuff complicated for a simple need ?

Anyway, I spend already too much time on this., thanks for the help. 
 

Tim Boudreau

unread,
May 18, 2015, 3:18:31 PM5/18/15
to google...@googlegroups.com
For what it's worth, I've done something vaguely like what you're after with a ProvisionListener:


I.e. use ProvisionInvocation.getBinding().getKey() to find out what type is being injected into, set that in a ThreadLocal and have the Provider check the value and do something based on it.  That being said, I regret writing this feature - it was a lot of complexity for comparatively minimal utility.

If there is enough information to infer what kind of Alert is needed by introspecting the type you're injecting the Alert into (say, looking at some annotations on that), then that approach might do the job.

Or if some code up the stack has enough information to decide what Alert to create, you could use a custom scope, bind the Alert in there and put it in for later code to retrieve and use.

That said, I'd question the utility of having lots of empty Alert subinterfaces that exist just be the bearer of a runtime annotation.  If you're stuck with it, it is what it is, but there are simpler and more intuitive ways to solve that problem with far less boilerplate.

-Tim

David

unread,
May 20, 2015, 4:47:17 AM5/20/15
to google...@googlegroups.com
Thanks for the suggestions. I kinda decided to go for the unsupported approach. It only took me a few lines of code to get access to the context when inside a Provider it just means I need to access package privates. I would have preferred to do it in a supported way, but It clashes with the Guice philosophy. 

Adding extra "power" features certainly come with a risk of people abusing it, I can certainly respect that. It is just a shame that because of risk of abuse that certain features are not even remotely considered.

As for my use case. Well, it is just a trimmed down version of what I really need. The interface mechanism with annotations does a lot more than what I show here. The huge advantage is that I get compile time checks that all my alerts are properly used, it supports i18n, severity, routing info, can be used both in GWT on the client and on the server in J2EE or OSGI ... etc. The design is clean and easily mockable for testing as well.
 
Reply all
Reply to author
Forward
0 new messages