Anton Tagunov wrote:
3) The issue may be partially resolved by allowed a component to declare a dependency on its own role. (Probably this has already been done and that's how excalibur-store compiles fortress meta-data, but then why are you having troubles?)
In fact it is quite reasonable to allow a component to look up its own role and not consider it a cyclic dependency. If I want to get myself via a lookup() why not allow me to do this?
Hmmm. I think that a loop is a loop. Roles may be fine. But a component instance should not be able to lookup itself as the returned instance would not yet have been initialized.
Not at all. Your English is much better than my Russian. :-) I can relate when4.2) (I hope my poor knowledge of terminology has not stopped me from being understandable here :)
using my Japanese though :-)
7)Actually, I don't think it should be up to the component to worry about when it can
This section is a sort of "RT" :-)
Are the loops evil after all?
Can there be a legitimate application where two components need to lookup() each other?
Why not?
The real trouble will happen if the components invoke each other during the "warmup" peirod.
("warmup" = contextualize, configure, service, initialize, start)
But if the components do not make any real calls on each other until after "warmup", then its all ok!
actually make use of components that have been obtained via a lookup. So I think
it is good that the Container makes sure that components do no declare any
loops.
The question is how to handle lookups whose lifecycles are managed by the
component. This is how I have handled systems that must contain actual loops.
For example. If you have 4 components CA, CB, CC, and CD. You can declare
that CB depends on CA, CC depends on CB, and CD depends on CA. Fortress
will correctly load CA then CB, then CC, and finally CD. The problem is that
CA also needs to call methods in CD. The declaration that CA depends on CD
will not work because this would create a loop that would prevent the container
from being able to guarantee that all components are initialized before being
looked up.
I have worked around this by wrapping the call to lookup CD in CA in a lookup
release block. This means that the lookup and release must be done for each
call, But if I make sure that CD can not be disposed while a call is being made
CD cd = (CD)sm.lookup( CD.ROLE ); try { cd.doSomething(); } finally { sm.release( cd ); cd = null; }
Even this method is not perfect on its own if doSomething takes a while to execute. Fortress does not wait until all looked up references have been released before disposing a component. It simple guarantees that the components will be disposed in the correct order. Meaning CD->CC->CB->CA in this case.
The problem is that the above will dispose CD while its doSomething method is being called by CA. This can lead to NPE's if CD's dispose method is called before doSomething has completed.
This is a hack, but I have worked around this by implementing a call counter in
all methods of CD that are exposed.
public void doSomething()
{
synchronized(this)
{
m_calls++;
}
try
{
// Actually do something
}
finally
{
synchronized(this)
{
m_calls--;
this.notifyall();
}
}
}
Then in the components dispose method, wait until the m_calls counter has dropped to 0. This will work most of the time, but there is still a slight chance that the thread from CA will lookup the CD component just before it is disposed and the dispose method will be called before the doSomething() is actually called. This is only an issue at application shutdown, so it was an acceptable workaround at the time.
It would be nice if the container handled this kind of thing correctly.
It should be possible to create a lookup counter that tracks the number of times that a component. The counter would then be checked before a component was disposed and the counter would wait up to a timeout limit before disposing the component. The container would prevent any new references to the component from being looked up once the shutdown process was initiated.
Thoughts?
Cheers, Leif
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]