[rhetorical] Should AttributeResolver implement the Resolver interface ?
Rod Widdowson
rdw at steadingsoftware.com
Sun Nov 10 08:05:33 EST 2013
Scott said:
> Not hung up on details, but yes, I would expect something like that.
That’s where my mind is going, but sadly getting into the details flushes
an architectural call we need to make (although I suspect it is made for
us). So here goes...
Tom's suggestion
>interface ReloadableService<T extends ServiceableComponent>
> start()
> stop()
> reload()
> ...
> T getServiceableComponent()
>
Is pretty close to where I was going, but it needs more work in the in the
case of destroyable, reloadable components - otherwise once you have called
getServiceableComponent() you lose track of it and there is no
synchronization between you and the destroy.
There are two ways around this, what V2 does is:
class FooService implements Foo, ReloadableService
And wrap the calls to the methods in (just) enough logic to handle the
synchronization. The actual implementation is not something I'd port
through to V3 though - it makes dangerous use of locks. This also has the
disadvantage that we need a class for everything (FilterService,
ResolverService and so on).
The other solution is to add a:
doneWithServiceableComponent()
to the ServiceableComponent interface and to wrap the call to
getServiceableComponent in a try{} and the doneWithServiceableComponent()
in the finally{}.
Neither of these deals with the case in which the same configuration file
supports two different operations. We already have this in V2 (Attribute
resolution and Attribute encoding coming from attribute-resolver.xml) and in
V3 I am proposing that there be three (Attribute mapping, resolution and
encoding). There is definite timing window during a reload during which an
inflight operation can see two version of the configuration.
If we care about this (and I do since I spend most of my life dealing with
the outcomes of this sort of thing) then the second solution (the
get/doneWith() pairing) offers an out. We can grab the component at the
start of the flow and call doneWith () it at the end. Meantime we can cast
the ServiceableComponent to whatever we want it to be and then use as
appropriate. It's always the same component and it is proof against
reloading.
Against this I have two concerns, one technical and the other vaguely
visceral.
My technical concern lies in the fact that we absolutely *must* always call
doneWithServiceableComponent(), otherwise destruction will not take place.
It's easy to do this within the confines of a try/finally, but given the
complexity of a webflow can we easily guarantee this?
I use reference counted subsystems (which is what this is) all the time to
deal with exactly this sort of situation, but I'll admit that debugging
reference count leaking can be a bear, and by their very nature bugs in
these systems are not something you can easily test for. Maybe Spring's
lifecycle can help use here? If the SWF is a bean which implements
DisposableBean - does it suffice to call doneWithServiceableComponent() in
the destroy() method?
The absolutely guarantee is to use finalize()as a final defence, but I have
read enough to be leery of that (and we would certainly want to use it only
as the final fail-safe).
The other concern is really no more than an observation: if you do have a
service which can implement a number of different Operations the obvious
thing to do is to add a
<S extends ServiceableComponent> queryInterface(Class<S>)
method to allow you to turn one sort of component (say an attribute
resolver) into another (say attribute encoder). And hey presto you have
invented IUnknown!! I have enough COM wounds (some of them as recent as
last Thursday) for this to provoke the aforementioned visceral reaction. Of
course you don't need to do it that way - it's just that that solution leapt
out at me.
My overall instinct is that if we are to implement safe reload then we need
to go for the refcounted model. But I am very leery of the pitfalls of
adopting it.
Thoughts?
More information about the dev
mailing list