2014-02-26 9:13 GMT+01:00 Christian Schneider <ch...@die-schneider.net>:

> On 25.02.2014 17:34, Guillaume Nodet wrote:
>
>> 2014-02-25 14:29 GMT+01:00 Christian Schneider <ch...@die-schneider.net>:
>>
>>  As Achim stated in the roadmap thread Guillaume and me had a lot of
>>> discussions on the irc channel recently. I fully agree that we need to
>>> recapitulate the discussions here on the list to give the other community
>>> members a chance to take part in the discussion.
>>>
>>> Overview
>>> ------------
>>> So I would like to start with a short overview on what we have now:
>>>
>>> Karaf Commands:
>>> - Based on Karaf Action interface
>>> - One Class per command
>>> - Action objects are not thread safe. They need to be created per command
>>> call and are discarded after that
>>>
>>>  Just fyi, the goal was to remove the burden of writing thread safe
>> classes
>> for the user, so it's not really a limitation, it's a feature.  The
>> consequence of this feature is that actions lifecycle is handled by the
>> framework and not the user.
>>
> If you look at felix gogo commands they are also thread safe. As long as
> you
> only store injected services in the attributes the commands are perfectly
> thread safe as the arguments
> are supplied in parameters. So the gogo commands achieve the same as the
> karaf Action but with much simpler means.
> This is why I prefer the gogo model. It is simpler in itself while
> offering the same possible feature set.
>
>  - As Action is not meant to be called we currently do not expose it as a
>>> service so the intermediary either has to be created by a framework
>>> extension (DS plugin or Blueprint namespace handler)
>>> - The blueprint extender and new namespace support safes a lot of xml
>>> configuration but on the other hand introduces some special DI
>>> annotations
>>> that are karaf proprietary
>>>
>>>  Those new annotations are not much different from @Command or @Option /
>> @Argument.  You think they are different because you're looking at what is
>> done inside the implementation.  From a user perspective, it defines the
>> command and the completers and needed services if any, so they're all
>> additional metadata to actions and completers.
>>
> For karaf usage I am really fine with these annotations and the scr
> command plugin. They are easy to use
> and do their job. For externally supplied commands I would prefer to not
> need framework extensions like that.
>
>  So based on the current situation we discussed what can be done to make
>>> using and providing commands easier.
>>>
>>> Target Audience
>>> ---------------------
>>>
>>> So who do we address?
>>> - Karaf developers who write commands for karaf itself
>>> - Developers of external projects that like to provide shell commands for
>>> karaf but also for other environments like Eclipse RCP. Or custom
>>> application with felix + gogo. ( Examples are cxf, camel, activemq,
>>> several
>>> pax projects)
>>>
>>> Goals
>>> -------
>>>
>>> Some goals here:
>>> - We would like to have a simple API for commands that does not expose
>>> the
>>> inner workings to users
>>> - Ideally we would like to be framework agnostic as the external projects
>>> typically already decided about their framework choices or might want to
>>> switch in the future
>>> - For karaf itself we do not absolutely need the framework agnostic goal.
>>> Instead we want to achieve ease of use in Blueprint and DS which are the
>>> main frameworks in karaf. For the future DS is probably even the more
>>> important
>>> - External projects should be able to write one style of commands that
>>> runs in a wide range of environments
>>>
>>> Ideas
>>> -------
>>>
>>> 1. Minimize exposed api
>>> Currently most internals are exposed in DefaultActionPreparator. We could
>>> provide it as a service with the ActionPreparator interface. So instead
>>> of
>>> "new" in AbstractCommand we could look up the service there
>>>
>>>  The API exposed to the user is the Action interface and the @Command,
>> @Option, @Argument, @Completer, @Service, @Reference annotations.  That
>> looks pretty minimal to me.   The fact that some implementation classes
>> (such as AbstractCommand, etc...) are leaking is mostly due to classloader
>> constraints.  If that's really a problem, I think we could easily write an
>> extender.   As a matter of fact, it was in master until a few days ago.
>> See
>> https://github.com/apache/karaf/commit/2bd28679e01f3800a2d686fcc214c8
>> 50f0a3c2c5
>> Maybe we should pursue this way as it should enable us to completely hide
>> the implementation classes.
>>
> For commands inside the karaf source you are right. We can either use the
> blueprint namespace or the
> scr command plugin. Both options are fine for us and make us independent
> of the command impls. Still we can not really
> hide the command impl because of the classloader as you wrote.
>
> People who implement commands outside the karaf source tree (camel, cxf,
> activemq, ...) might have a diffrerent view. They might not use blueprint
> or DS or might not want to use our extensions.
> Then they are exposed to the command impls. This is why I would like to
> improve the situation for these users. Ideally by really encapsulating the
> command impls. I think my idea 3 should allow this.
> I will provide a poc in a branch to show what I mean.
>
> If it works we would not be limited by classloader constraints and even
> our own framework extensions might profit from the better encapsulation.
> Lets wait till I tested it to see how it would work.


The classloader problem is mostly because we don't use an extender.
 Blueprint should be able to hide the internal classes used, and that's
actually the case because no bundle sees the BlueprintCommand which is
used.  DS is slightly different as it can not contribute its own classes,
where blueprint namespace handlers can.

So I really think using an extender would solve the whole problem I think.
  I've just spent a bit of time drafting a cleaner API for commands.  The
main problem with the current state is that there was no clean API written
at the very beginning and things have evolved quite a bit.  In addition,
gogo and jline leak into our API which is not really good.

So I'd like to discuss the following small API which I think would be very
easy to use (it's mostly a different package).

https://github.com/gnodet/karaf/tree/console-api/shell/console/src/main/java/org/apache/karaf/shell/api

The annotations are basically what we have, the main changes are:
  * Action main method has been changed to avoid referencing gogo
  * the gogo CommandSession and jline Terminal / ConsoleReder are hidden by
a minimal api (.api.console.Session and Terminal)
  * Terminal, Session and BundleContext would be injected with @Reference
along any OSGi service
  * bundles containing commands need a Karaf-Command manifest header

The benefits would be the following:
  * clean API, so complete separation of command implementors from the
implementation
  * also abstract gogo and jline
  * no need for blueprint / DS at all
  * complete support for what we have
  * we could start using semantic versioning on those 3 packages (it
doesn't have to be tied to the release cycle)
  * easy enough switch (just a few package changes usually, slightly more
for commands that were using gogo or jline)
  * way easier to support a degraded mode on top of pure gogo



>
>  2. Create generic Actionpublisher using whiteboard model
>>> I created a whiteboard model for an ActionPublisher. In this case the
>>> Action would be published as services. So this would minimize the API the
>>> user sees and be easy to use. Downsides is that we publish an Action
>>> service that is more a template than a real service. So Guillaume had
>>> some
>>> major issues with this attempt.
>>> So probably this is not the way we will proceed
>>>
>>> 3. Create generic ActionPublisher as service
>>> An alternative to the above would be to create a service that can be
>>> called with your Action object as a parameter and that publishes a
>>> suitable
>>> command for it. So in this case the ActionPunlisher is a real service and
>>> still manages to hide our implementations. We could reuse the simple
>>> reflection based action copying form the whiteboard model. This would
>>> allow
>>> to have one ActionPublisher instead of the different commands we use
>>> right
>>> now. (Blueprint, DS, ...). The service could also be reused in the DS
>>> plugin and the blueprint namespace
>>>
>>>  I think this actually make things more complicated, as blueprint and DS
>> are
>> not really meant to call a service from the registry without any user
>> code.
>>
> We could use the service in the blueprint namespace handler. People who do
> not use our namespace could also use the service instead.
> I am not sure about the DS plugin. This is why I would like to test it
> first.
>
>
>>
>>  4. Improve support for gogo commands
>>> The current gogo command model is quite feature rich. Compared to karaf
>>> it
>>> mainly lacks completion support. So I am pretty sure we could make gogo
>>> commands work in karaf with the same feature set like karaf Actions. This
>>> would provide especially external developers a way to create commands
>>> that
>>> is easy to handle and does not expose them to the implementations without
>>> any framework extensions. As gogo commands are real services it is
>>> especially easy in DS as the normal injection model works
>>>
>>
>> I don't really have any problem with that.  It should not be very
>> difficult
>> to improve the console to give visibility to those commands.  For
>> completion, we definitely can't go as far as karaf commands, but at least
>> the name of the command and maybe option names could be completed, and
>> eventually use the same default completers, though it kinda depends how
>> the
>> parsing is done (not sure how boolean options are parsed).
>>
> I hope we can achieve the same feature set but you know more about the
> details than I. Do you see any severe problems to
> deliver a more completer support?
>
>
>>
>>  5. Make karaf commands work in gogo
>>> I prepared a branch where I split the command runtime (api + abstract
>>> command impls) from the console. It should be possible to install this on
>>> top of felix gogo to make karaf commands work outside karaf.
>>>
>>>  Have you tried it in bare felix + gogo yet ?
>>
> Not yet.
>
>
>
> Christian
>
> --
> Christian Schneider
> http://www.liquid-reality.de
>
> Open Source Architect
> http://www.talend.com
>
>

Reply via email to