On Wed, May 11, 2011 at 5:14 PM, Guillaume Nodet <gnodet@gmail.com> wrote:
On Wed, May 11, 2011 at 15:42, Alex Karasulu <akarasulu@apache.org> wrote:
> Thanks Guillaume for your thoughts. Responding in this post to both of you
> in line ...
> On Wed, May 11, 2011 at 12:19 PM, Emmanuel Lecharny <elecharny@gmail.com>
> wrote:
>> On 5/11/11 10:47 AM, Guillaume Nodet wrote:
SNIP ...
> By "hide the OSGi stuff", do you mean embed the OSGi container in the
> application?

Looking at the current api, an average user that does not use OSGi
won't see the fact that an embedded Felix is launched and it has no
access to it anyway, so that's what I mean by hidden.

The goal was not to grant programatic access to the OSGi container. The goal was to just expose a directory where the user can drop bundles and on startup they would be used to extend the codec.

>>> that you export the slf4j pacakge in version 1.6.0 from the system
>>> bundle.   What if a user start using a [1.6.1,2) range when importing
>>> that package ?
> Do you mean to say the user, writes and added a new bundle for an extension,
> and the extension bundle depends on slf4j 1.6.1 for example?


Agreed if a bundle supplying the 1.6.1 SLF4J API is not provided we'll get an exception from the container. However if the 1.6.1 API is provided in the bundle loading directory it should work just fine.

However this is not that realistic of a situation because users that are going to use the LDAP API in this standalone scenario to extend it will have to use a specific version of the LDAP API and develop their extensions/plugins according those dependencies. Let's step through the process:

1). The user of the API wants to extend the codec in the LDAP API to handle the encoding and decoding of Foo extended operations present specifically in Bar LDAP server.

2). User creates a Maven project to create the Foo extended operation codec plugin including the dependency for the LDAP API version they're working with. Naturally they would use the SLF4J API dependency that the LDAP API version uses.

In this case the aforementioned scenario does not result. The plugin for the Foo codec extension bundle would naturally have to follow the dependencies used by the LDAP API.
> Again do you [Guillaume] mean embedding a OSGi container when you say
> hiding?

Yes, embedding but not giving the user access to it.

OK I see, we do not intend to give the user access to the container. Is there some reason why you think we should grant user access to the container?
Other possible problems are that OSGi does not work in some
environments like Google App Engine for example, because it needs
access to the file system.

Good point. This might be a good reason to just avoid using OSGi here.
I'm quite sure I haven't fully grasped what the use case is (i.e. when
/ how / who will people develop and use those bundles / extensions),
but a simple URLClassLoader would look like a way easier solution to
me when not in OSGi.   If that cause problem, you could always say:
well, OSGi solves those problems so you should use it and the code is
able to leverage it.

This decision is really about a tradeoff. The codec needs the ability to allow users to extend it to handle new extended req/resp pairs and controls. The server and studio exist in OSGi environments where there's no problem with using OSGi bundles for the modularity mechanism. Plus when used in these two scenarios, the LDAP API extensions can be dynamically loaded, unloaded and/or have new versions loaded, and this is a capability is appealing.

The tradeoff problem appears when the LDAP API is used standalone outside of these environments in a client application or with some command line tool for ldap clients. So having OSGi bundles for codec extensions, how do we re-use those extensions in the standalone scenario?

The simple class loading mechanism should work just fine with the plugin bundles defaulting to regular jars, and this is how the standalone version of the codec factory can work while the OSGi version can be used in the ApacheDS and Studio use cases.

I'm starting to think the classloader based mechanism might be best for standalone usage. 

I guess I'm just missing the use cases to understand that this could
be a good solution, as I don't even see where the bundles loaded are
used at all

The plugin bundles do not contain any services. The activators of the plugin bundles simply register classes in the plugin bundle with the main service exported by the host application: the codec factory service.

Looking at this big fat mess a good rule of thumb is starting to emerge:

Do not embed OSGi containers in APIs, because you cannot be sure of the environments in which that API will be used.

The best way to proceed would be to expose a means to programmatically register new extension components with the API, and leave the mechanism to load and register the plugin components outside the API to be handled by some other component.