On circular dependencies

47 views
Skip to first unread message

Jonathan

unread,
Mar 19, 2009, 8:18:28 PM3/19/09
to google-guice
Looking over the way Guice handles circular dependencies, it looks
like the resulting object for some expected type is inserted into each
of the delegating proxies that were created as a result of a circular
dependency. I know this is just one solution to a nasty problem, but I
was hoping to find that each of the circular dependencies would get
their own instance of the expected type. Is this possible?

Regards -
jonathan

Bob Lee

unread,
Mar 19, 2009, 8:32:47 PM3/19/09
to google...@googlegroups.com
I assume you're talking about circular deps between constructors. This is a tough problem. Injecting proxies was an experiment that I don't really like to advertise. We can't just keep injecting new instances because we'd go into an infinite loop. In the long run, I think the best solution will be to generate an error when we encounter a circular dep. The solution to the error will be to inject a Provider<X> into one of the constructors or to move the dep into an injected method instead (not currently supported).

Bob

Sam Berlin

unread,
Mar 19, 2009, 8:38:05 PM3/19/09
to google...@googlegroups.com
Perhaps if circular dependencies are disabled, then a new
@AllowCircular annotation can be added to explicitly enable circular
dependencies (on certain parameters) so that they can be allowed on a
case-by-case basis. As much as I dislike circular dependencies,
sometimes they're incredibly hard to fix properly.

Sam

Jonathan

unread,
Mar 19, 2009, 9:03:26 PM3/19/09
to google-guice
That's fair enough. Thanks for the response.

jonathan

On Mar 19, 5:32 pm, Bob Lee <crazy...@crazybob.org> wrote:
> I assume you're talking about circular deps between constructors. This is a
> tough problem. Injecting proxies was an experiment that I don't really like
> to advertise. We can't just keep injecting new instances because we'd go
> into an infinite loop. In the long run, I think the best solution will be to
> generate an error when we encounter a circular dep. The solution to the
> error will be to inject a Provider<X> into one of the constructors or to
> move the dep into an injected method instead (not currently supported).
>
> Bob
>

Endre Stølsvik

unread,
Mar 19, 2009, 10:07:38 PM3/19/09
to google...@googlegroups.com
On Fri, Mar 20, 2009 at 01:32, Bob Lee <craz...@crazybob.org> wrote:
> I assume you're talking about circular deps between constructors. This is a
> tough problem. Injecting proxies was an experiment that I don't really like
> to advertise.

Good!

But as a user of your tool, one will most certainly be bitten by them
at some point, so you will learn about them - the hard way.

> In the long run, I think the best solution will be to
> generate an error when we encounter a circular dep. The solution to the
> error will be to inject a Provider<X> into one of the constructors or to
> move the dep into an injected method instead (not currently supported).

Hear, hear!!

I never liked those proxies, and one have no idea of them existing
until one suddenly get an error about accessing such a proxy. They are
not stable either, so those proxy-problems kinda come and go with
module-configuration changes. And amazingly, they cannot be resolved
by making a setter (what about field-injection?). Is this 3.0 stuff?

Endre.

Stuart McCulloch

unread,
Mar 23, 2009, 2:23:14 PM3/23/09
to google...@googlegroups.com
2009/3/20 Endre Stølsvik <stol...@gmail.com>

I would've thought more likely 2.1 (or 2.x) as this wouldn't require a major API change

do you perhaps have a test-case where you wouldn't expect a proxy, but do get one?
You could then open an issue on the Guice project page and attach your test-case.
 
Endre.


--
Cheers, Stuart

Endre Stølsvik

unread,
Mar 23, 2009, 2:49:07 PM3/23/09
to google...@googlegroups.com
On Mon, Mar 23, 2009 at 19:23, Stuart McCulloch <mcc...@gmail.com> wrote:
> 2009/3/20 Endre Stølsvik <stol...@gmail.com>
>>
>> On Fri, Mar 20, 2009 at 01:32, Bob Lee <craz...@crazybob.org> wrote:
>> > I assume you're talking about circular deps between constructors. This
>> > is a
>> > tough problem. Injecting proxies was an experiment that I don't really
>> > like
>> > to advertise.
>>
>> Good!
>>
>> But as a user of your tool, one will most certainly be bitten by them
>> at some point, so you will learn about them - the hard way.
>>
>> > In the long run, I think the best solution will be to
>> > generate an error when we encounter a circular dep. The solution to the
>> > error will be to inject a Provider<X> into one of the constructors or to
>> > move the dep into an injected method instead (not currently supported).
>>
>> Hear, hear!!
>>
>> I never liked those proxies, and one have no idea of them existing
>> until one suddenly get an error about accessing such a proxy. They are
>> not stable either, so those proxy-problems kinda come and go with
>> module-configuration changes. And amazingly, they cannot be resolved
>> by making a setter (what about field-injection?). Is this 3.0 stuff?
>
> I would've thought more likely 2.1 (or 2.x) as this wouldn't require a major
> API change

Failing to start if proxies would be needed are a kind of invasive API
change, wouldn't you think? I guess this have to be configurable, with
default on as in "do create proxies".

>
> do you perhaps have a test-case where you wouldn't expect a proxy, but do
> get one?

No, I don't - but I don't think this issue in any way isn't fully
understood. I just said "Yes!" and elaborated slightly on what I as a
user find un-good with it: It is not as I "wouldn't expect a proxy",
because the reason for getting it is very simple. It is that /where/
you get it is indeterministic: If A depends on B that needs A, then
where is the proxy inserted? Maybe one config would work, and another
not: By adding some pretty much unrelated bindings into the system,
you all of a sudden get a proxy-access-error because the order got
changed (the proxy is created for the other place). Also it is not
possible to break the cycle by inserting a setter on either A or B -
Guice blatantly still creates the proxy.

This is all "as I've understood it", but Bob effectively, IIUC, said
as much, which means that he know exactly where the situation lies.

Endre.

Stuart McCulloch

unread,
Mar 23, 2009, 4:46:56 PM3/23/09
to google...@googlegroups.com
2009/3/24 Endre Stølsvik <stol...@gmail.com>
On Mon, Mar 23, 2009 at 19:23, Stuart McCulloch <mcc...@gmail.com> wrote:
> I would've thought more likely 2.1 (or 2.x) as this wouldn't require a major
> API change

Failing to start if proxies would be needed are a kind of invasive API
change, wouldn't you think? I guess this have to be configurable, with
default on as in "do create proxies".

as you say, this could be configurable... waiting until v3 sounds like a long time :)
 
> do you perhaps have a test-case where you wouldn't expect a proxy, but do
> get one?

No, I don't - but I don't think this issue in any way isn't fully
understood. I just said "Yes!" and elaborated slightly on what I as a
user find un-good with it: It is not as I "wouldn't expect a proxy",
because the reason for getting it is very simple. It is that /where/
you get it is indeterministic: If A depends on B that needs A, then
where is the proxy inserted? Maybe one config would work, and another
not: By adding some pretty much unrelated bindings into the system,
you all of a sudden get a proxy-access-error because the order got
changed (the proxy is created for the other place).

indeterminism isn't good, so at least I (personally) would be interested in an
example where adding an unrelated binding introduced a proxy... especially
wrt. a proxy-access-error (are you perhaps using OSGi?)

Also it is not possible to break the cycle by inserting a setter on either A or B -
Guice blatantly still creates the proxy.

again an example of this would be useful as that would help people develop
a solution - again speaking personally, while I don't have time to create such
examples, having an existing example to play around with would help focus
my mind on contributing a patch ;)

This is all "as I've understood it", but Bob effectively, IIUC, said
as much, which means that he know exactly where the situation lies.

yes, I think Bob and Jesse have a good understanding of this

last time I checked Guice was supposed to only use proxies where necessary
(or for method interception) but this might have changed in the latest code...

Endre.

--
Cheers, Stuart
Reply all
Reply to author
Forward
0 new messages