(Ugh, I cannot figure out how to prevent/control line-wraps in google
groups.)
Thanks for taking the time to enumerate the differences between the
Appdapter registry and the OSGi service registry. I thought about
using "Registree" as the name, to try to prevent confusion with other
registries, might still go that way, opinions welcome.
It's not intended to wrap the OSGi registry, but it is intended to be
complementary to the OSGi registry. The idea is that a running
application will have some small number (say 1 to 10) of separate
"root" Appdapter registries, which, in an OSGi environment, would be
located using the OSGi registry. If OSGi is not available, then
application components will find root-level Appdapter registries in
some static
variables or whatever the actual container uses.
These separate Appdapter registries might use different
implementations of the Registry interfaces. The "BasicRegistry" we
have so far is a minimal pure-java object registry, which is basically
just a bag that can filter query-by-equal-description results by
type. I see putting an object in there as a lighter-weight operation
than registering an OSGi service. An application might create a
bunch (say 100s or even 1000s, in a multi-user environment) of
BasicRegistrys, only a few of which will be "roots" looked up from
Container, while most are just found as entries in other registries.
> It seems to be an OSGi best practice to avoid using the Service Registry
> directly, and to go through some component/lifecycle manager.
One intent is that most application code can ignore the question of
whether it is in an OSGi environment, because most application code is
just working with the Appdapter Registry interfaces. Only the very
outer shell of a "main()" program or a bundle should need to be aware
of the platform issues. However, the nitty-gritty application code
*does* need to be able to find the registries it needs to do its own
local work, and so here we are currently relying, by convention, on a
single super-directory of root registries accessed through a singleton
static method called RegistryServiceFuncs.getTheWellKnownRegistry().
The current implementation of the
RegistryServiceFuncs.getTheWellKnownRegistry() will try to find an
OSGi context, and if that fails, will fall back to using a static
registry. So, here we have an implicit model of a single root
appdapter registry, called "the well known registry". I don't want
to assume that this single root registry model will be enough for
complex applications, but it is sufficient to work through the current
problems we have in Cogchar, where we sorely need a directory of
goodies.
One could say that "getTheWellKnownRegistry()" is, in fact, a wrapper
for the OSGi registry system, but the assumptions it makes are not
required for compatibility with the rest of the Appdapter Registry
API, and any additional features we layer on top as you have proposed
(I get to those below).
We expect that an application will hide its use of this static method
behind its OWN static/singleton methods, which are then embellished
with the small number (1 to 10) of additional root registry static
methods needed by that application (which can be in different
singletons for each component of the application, if desirable). So,
we might have something like:
org.funzo.common
class FunzoAppFuncs {
// HIDE the assumption about wellKnownRegistry in this protected-
static method.
protected static VerySimpleRegistry getWellKnownRegistry() {
return RegistryServiceFuncs.getTheWellKnownRegistry().
}
}
org.funzo.vision
class FunzoVisionFuncs extends FunzoAppFuncs {
// Make this return type as narrow as it needs to be for
application
// purposes of the VisionRegistry.
public static Registry getVisionRegistry() {
VerySimpleRegistry wellKnownVSR = getWellKnownRegistry();
Registry visionRegistry =
findRequiredUniqueNamedObject(Registry.class, "VISION_REGISTRY");
if (visionRegistry == null) {
visionRegistry = new ... // Could be a BasicRegistry,
or something else.
Description visionRegistryDesc = new ... // Could be a
BasicDescription, or...
wellKnownVSR.register(visionRegistry,
visionRegistryDesc);
}
return visionRegistry;
}
}
So, then all the application code, across all OSGi bundles (or in a
unit-test main program), can always call
FunzoVisionFuncs.getVisionRegistry(), and get a good result
regardless of whether we are in an OSGi environment or not. From
there, we have complete flexibility about what interfaces the
VisionRegistry itself implements. Notice that the application code
(other than FunzoVisionFuncs) does *not* use the naive assumption that
there is a single WellKnownRegistry that rules all others, so we can
relax that assumption later without breaking the application.
Now I'll comment on each of the proposed features:
> 1) Unregister objects.
I'm adding this as an optional "DeletingRegistry" interface, which
BasicRegistry
may be able to implement.
> 2) Notify listeners of registration events
Yes, definitely useful, but adds a layer of complexity that I didn't
want to tackle yet.
If we can cook up a simple version that is sufficient for current
Robokind purposes,
I'd be glad to have that as a mix-in.
> 3) Add registration properties to the Description
I am OK with a properties-based description facility as a mix-in.
This approach
makes use of the agnostic interface structure in the core API.
> 4) Query based on registration properties (This would be quite challenging
> to abstract across various registry implementations).
Like #2 and #3, it's great to have, and should be driven by actual
use cases in our applications. I am OK with duplicating what OSGi
does, and I'm OK with ignoring what OSGi does. I just want my
apps to be decoupled into components that find each other using a
minimal number of well-known names that are compatible with URIs.
See eventual MetadataRepo-backed query features below.
> If you have 1-4, you could use the robokind service lifecycles with the
> appdapter registry. You would have to modify the
> ServiceDependencyTracker and the DynamicServiceLauncher to use appdapter
> rather than OSGi directly.
That sounds great. It seems we could create a set of implementations
of the Appdapter interfaces, extended with the set of register/
unregister/find features that Robokind actually uses in
ServiceDependencyTracker and DynamicServiceLauncher .
We'll have to look at the details to see if it is easiest to do this
by extending Basic*, or creating a new set of implementations. We
*could* possibly create a set of implementations that truly does wrap
the OSGi finding implementation, conceptually the
AppdapterRegistreeImplementedWithOSGiServiceRegistry system, although
I am not really in love with that idea, just yet.
Specifically, I think we need to see how complicated it is to
implement what you actually currently need from #4 - query by
property.
For more complex property queries, the right way to go is possibly
with a SPARQL query against a metadata-backed Registree. Of course,
we already have a MetadataRepo in Appdapter, so the groundwork is
there. But I didn't dive into this area yet, because I wanted to
focus on just getting a basic set of interfaces together that
application objects can use to find each other at run time using
oversimplified assumptions, e.g. "all the most important objects have
unique names and specific types".
> 5) Finders return an object reference which includes the Description.
> 6) Count object use
> (BundleContext has getService and ungetService to keep count of how many
> places the service is used. This is a problem
> with the robokind ClassTracker. It eagerly gets all the services, and
> never releases them. I don't have anything that uses
> that count at the moment.)
Yeah, good stuff for the apps that want to work this way. Totally
fine to have these features mixed-in over the very loose core
interfaces .