registry api requests

2 views
Skip to first unread message

Matt Stevenson

unread,
Feb 10, 2012, 1:44:49 PM2/10/12
to appdapt...@googlegroups.com
I looked through the appdapter registry api, I'm not sure if it's intended to be an abstraction to wrap and the OSGi Service Registry.
If it is, there are a few things that should be added:

1) Unregister objects.

2) Notify listeners of registration events

3) Add registration properties to the Description

4)  Query based on registration properties (This would be quite challenging to abstract across various registry implementations).

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.)

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.

It seems to be an OSGi best practice to avoid using the Service Registry directly, and to go through some component/lifecycle manager.

--
Matt Stevenson.
Message has been deleted

stub22

unread,
Feb 10, 2012, 4:33:27 PM2/10/12
to appdapter-users
(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 .

Matt Stevenson

unread,
Feb 10, 2012, 7:10:01 PM2/10/12
to appdapt...@googlegroups.com
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.
 
OSGi uses the LDAP filter syntax: http://www.selfadsi.org/ldap-filter.htm
I use it, but not much.  I only do full name matches, no wildcards, and I only use the "&" (and) operation.  But I provide a way for people to use their own filters if they have a more complex setup.
Here's a couple places I use it:
In the motion service lifecycles (org.robokind.api.motion.osgi) I add the Parameterized Type for the JointPositionMap used.  It doesn't give full type safety, but it gives some generics support and lets me find blender components which use the same map type (Blender, FrameSources, FrameCombiner, and BlenderOutput need to agree on a PositionMap).  I also make all the Blender components agree on a robot id to avoid confusion with multiple robots.
I use the properties to specify the speech service for a viseme service to use.

Another issue is allowing a single class for registration.  I set things up this way and I ran into problems.  My AnimationJobFrameSource is a perfect example.  It needs to be discovered separately as an AnimationJob, FrameSource, and Playable, but registered and unregistered as a single instance.  OSGi handles this by adding the registration class class names as properties to be queried.

As far as my service lifecycle goes, I may switch to the felix Dependency Manager.  (I don't know how closely you've been following the robokind list, but I was talking about it yesterday.)  I have some ideas on how to work around the things I dislike, but I don't have the time to test it out so I'll be using what I have for at least a few months.  Switching to Dependency Manager could mean digging in deeper with OSGi...

I was thinking about this a lot the past couple days, and I'm about ready to go all in behind OSGi and give it first class status in robokind.  My problem has been that I've been treating it more as a runtime environment to insulate from, rather than a set of specs to adopt.  The more I insulate myself from it, the more likely I am to run into community scaling issues.  Other things we want to use have to be adapted to the RK abstractions, which has to be maintained along with RK.  And the worst part is all that work is only good within RK.

Rather than (in some uses) hiding OSGi, the registry would depend on the BundleContext and be vocal about it, flaunt what it uses in the OSGi pride parade.  Rather than implementing a registry with other object repositories, have them implement a BundleContext.  That way you could use other OSGi tools with it for free.  The registry doesn't need the whole BundleContext and we want to enforce some sort of contract.  Create an AppdapterContext which is a subset of the BundleContext needed, and then implement an AppdapterBundleContext to wrap an AppdapterContext as a BundleContext.
You could create a DynamiceServiceLauncher and give it an AppdapterBundleContext or a BundleReference (the default osgi implementation), and it doesn't know the difference. If we decide Dependency Manager is the way to go, we do the same thing.
In the end OSGi will always be the bigger community, and it has a lot more to offer than we do.

--
Matt Stevenson.
Reply all
Reply to author
Forward
0 new messages