Automatic bind to no-arg constructor

502 views
Skip to first unread message

Eric Anderson

unread,
Oct 17, 2007, 12:25:49 PM10/17/07
to google...@googlegroups.com
I understand why it is handy to have Guice find parameterless constructors and use them when it hasn't been explicitly told to use something else.  However, this has bitten me SEVERAL times lately as I have added collection classes that should really be setup with a provider.

Is there any way to disable this auto-wire behavior?  I would much rather Guice throw an exception than have it silently swallow the missing binding.  In other words, for this current project, I would prefer Guice to require explicit bindings for everything.  Is there any way to do this?

Thanks.

Eric

Dhanji R. Prasanna

unread,
Oct 17, 2007, 4:41:15 PM10/17/07
to google...@googlegroups.com
Sort of an optionExplicit to use blasphemous terminology ;) There
isn't I'm afraid.

But if you follow a good design pattern you can avoid this problem:
don't bind to concrete implementations!

Instead of:

@Inject MyCollectionImpl<Object> my;

use:

@Inject @My Collection<Object> my;

This way you can't shoot yourself in the foot if there is no binding
to (Collection<Object>, @My).

Eric Anderson

unread,
Oct 17, 2007, 10:21:27 PM10/17/07
to google...@googlegroups.com
Yes, this would work.  Although, as much as I love interfaces, there are some times when the implementation is so simple that having an interface over it would be an unnecessary abstraction.  Typically, when I do the bindings for those types of dependencies, they are bound to a provider or sometimes a singleton.  Either way, the last thing that I want to have happen is for Guice to make me a new one.

We're working on other parts of our process (writing acceptance tests first) so that the development process will give us quick feedback for the times when we've forgotten to specify the bindings.  I was just hoping there would be a safety net such that I could disable this automagic binding.

I'm thinking about looking into providing a mechanism for disabling this automatic behavior.  If someone knows a good reason why I shouldn't look into this, I'd love to get a heads-up before I invest my time here.

Thanks.

Eric

Bob Lee

unread,
Oct 17, 2007, 10:40:04 PM10/17/07
to google...@googlegroups.com
On 10/17/07, Eric Anderson <d.eric....@gmail.com> wrote:
Yes, this would work.  Although, as much as I love interfaces, there are some times when the implementation is so simple that having an interface over it would be an unnecessary abstraction.  Typically, when I do the bindings for those types of dependencies, they are bound to a provider or sometimes a singleton.  Either way, the last thing that I want to have happen is for Guice to make me a new one.

We're working on other parts of our process (writing acceptance tests first) so that the development process will give us quick feedback for the times when we've forgotten to specify the bindings.  I was just hoping there would be a safety net such that I could disable this automagic binding.

I'm thinking about looking into providing a mechanism for disabling this automatic behavior.  If someone knows a good reason why I shouldn't look into this, I'd love to get a heads-up before I invest my time here.

It would be really easy to disable this behavior (a one line change), but before we go adding a mysterious flag, your real problem may already be solved in the next version. In 1.0, Guice will call any no-arg constructor, even if it's private. Bad, bad, bad. In the next version, we plan to restrict this so Guice will only call public no-arg constructors. If you want it to call a private constructor, you will have to explicitly annotate it.

In the case of your singleton, you would just make the constructor private, and so long as you don't annotate it with @Inject, Guice won't call it.

This will break compatibility somewhat, but I think it's worth the risk.

Bob

Dhanji R. Prasanna

unread,
Oct 17, 2007, 10:44:40 PM10/17/07
to google...@googlegroups.com
On 10/18/07, Eric Anderson <d.eric....@gmail.com> wrote:
> Yes, this would work. Although, as much as I love interfaces, there are
> some times when the implementation is so simple that having an interface
> over it would be an unnecessary abstraction. Typically, when I do the
> bindings for those types of dependencies, they are bound to a provider or
> sometimes a singleton. Either way, the last thing that I want to have
> happen is for Guice to make me a new one.

If all you want to do is avoid scoping and provision bypasses by an
implicit binding, you should annotate your implementation class with a
scoping annotation (@Singleton) or a provider indicator:
@ProvidedBy(...).

Then you can tolerate the implicit behavior because your class is
documented with its default scoping and provision use-case and you
never "accidentally" get an alternate instance via nullary ctor.

Dhanji.

Eric Anderson

unread,
Oct 17, 2007, 10:54:53 PM10/17/07
to google...@googlegroups.com
Unfortunately, if I was remembering to add those annotations, I'd be remembering to do what really needs to be done in setting up the bindings in the first place.  As I said before, there are plenty of ways to improve our development process so that I quit getting bitten by this.  The problem is that they all involve stopping work on the class under test and doing something somewhere else.  I tend to code completely to my interface using TDD and then, once the consumer is completely finished, write the implementation.  I only code against concrete classes when they are painfully simple to instantiate in a test harness.  Things that DDD would refer to as "entities" are a good example.  Putting an interface over those is typically a bad idea, IMHO.  Entities are easy to construct in a test harness.  It's these cases when I have forgotten to put in the proper bindings.

On 10/17/07, Dhanji R. Prasanna <dha...@gmail.com> wrote:

Eric Anderson

unread,
Oct 17, 2007, 11:07:50 PM10/17/07
to google...@googlegroups.com
Bob,

Indeed.  The private one was what caught me most by surprise.

What I was thinking of was some sort of way to put a call in the module itself that would disable the auto-wiring behavior.  Perhaps something that could allow the auto-binding to be set to one of:  AutoBind.NEVER (only use those bindings explicitly defined in the module, fail otherwise), AutoBind.PUBLIC (the behavior you described for the next version), AutoBind.ANY(the behavior as exists now).  While having a default of say... PUBLIC would still technically cause a breaking change in that you couldn't simply drop in the next version and be off to the races, a simple change in the module could revert the behavior to the legacy ( 1.0) behavior.

Just a thought.

Btw, I wouldn't be having these issues if I wasn't leaning on the tool pretty hard as is.  I love using Guice and I love not being burried in XML-hell.

Eric
Reply all
Reply to author
Forward
0 new messages