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/2bd28679e01f3800a2d686fcc214c850f0a3c2c5
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.
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