felix-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Pierre De Rop (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (FELIX-5320) Dependency Manager: adapter service propagates adaptee properties *after* the init (and start) callbacks are called
Date Tue, 16 Aug 2016 11:57:22 GMT

    [ https://issues.apache.org/jira/browse/FELIX-5320?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15422636#comment-15422636

Pierre De Rop commented on FELIX-5320:

Hello Andrea;

You normally use an Adapter in order to create another component on top of an existing one.
Typically, for example you want to create a management component (like a servlet, or an amdatu
restful web service) on top of an existing service component. 

say you are developing a nosql database, and you have for instance a "MyNoSqlDatabase" service

    .setInterface(MyNoSqlDatabase.class.getName(), null));

Now, assume you wan to make a restful web service which allows to administer your database.
To do so, you wan to be modular and you want to make (for example) a jax rs web component,
which would allow for example to display the number of transactions performed, or tune your
nosql database from the web. 
So, you would in this case write an adapter component, like the following, which creates an
amdatu web service component on top of the existing MyNoSqlDatabase service component:

dm.add(createAdapterService(MyNoSqlDatabase.class, null)
    .setInterface(Object.class.getName(), null));

and your jax rs amdatu web service used to aminister your no sql database:

class MyNoSqlDatabaseAdmin {
    volatile MyNoSqlDatabase database; // original database component, injected

    public int transactions()  {
          return database.getTransactions();

I don't know if you need or not adapter, but let's assume that yes, you need an adapter. 
So, getting back to your initial question: your want to add a dynamic dependency for your
adapter, based on the adaptee.

So, in our example, the adaptee is "MyNoSqlDatabase". Now, assume that the  MyNoSqlDatabase
has some services properties. These service properties are by default propagated to the adaptee
service properties (MyNoSqlDatabaseAdmin). 
Now, if you want to get access to the adaptee service properties, you can simply define a
callback for the adaptee, instead of inject it in a compatible map field.
And the callback may then use a signature which takes the adaptee, as well as a map for the
adaptee service properties. You can then just keep the adaptee service properties and use
it from your adapter init method in order to decide to add (or not) an additiona adapter dependency.

let's see this a a concrete example. First, let's redefine the adapter Activator:

dm.add(createAdapterService(MyNoSqlDatabase.class, null, "setDatabase", null /* no change
callback */, null /* no remove callback */)
    .setInterface(Object.class.getName(), null));

and let's refactor the adapter with the "setDatabase" callback

class MyNoSqlDatabaseAdmin {
    volatile MyNoSqlDatabase database; // original database component
    volatile Map databaseProperties; // original database service properties
    volatile SomeOtherService otherService; // dependency dynamically added from init method

    void setDatabase(MyNoSqlDatabase, Map properties) {
        this.database = database;
        this.databaseProperties = properties;

   void init(Component comp) {
       // at this point, the database and database properties have been injected: then depending
on the database service properties (which are by default 
       // propagated to our adapter service properties), then possibly add one more service

       if (databasePropertiesRequiresAnotherDependency(this.databaseProperties)) {
          DependencyManager dm = c.getDependencyManager();
          String filter = getFilter(databaseProperties);
          comp.add(dm.createServiceDependency().setService(SomeOtherService.class, filter).setRequired(true));

    public int transactions()  {
          return database.getTransactions();

so, in the above example, the database (adaptee) is injected using the setDatabase method
and the service properties are kept in the "databaseProperties", which is then reused in the
init method, in order to possibly add an extra dependency.

Notice that if you don't need an adapter at all, you can do the same with a regular Component.

does this help ?

> Dependency Manager: adapter service propagates adaptee properties *after* the init (and
start) callbacks are called
> -------------------------------------------------------------------------------------------------------------------
>                 Key: FELIX-5320
>                 URL: https://issues.apache.org/jira/browse/FELIX-5320
>             Project: Felix
>          Issue Type: Bug
>          Components: Dependency Manager
>    Affects Versions: org.apache.felix.dependencymanager-r8
>            Reporter: Andrea Leofreddi
> In an adapter service, created using the createAdapterService method of DependencyManager
class, one would expect to find the adaptee's properties being propagated to the adapter service
itself, as stated in the documentation (http://felix.apache.org/documentation/subprojects/apache-felix-dependency-manager/reference/component-adapter.html).
> Instead no propagation happens, and both init and start methods won't see any propagated
> After investigating I've found that propagations indeed happens (via AdapterServiceImpl's
propagateAdapteeProperties) only after the callbacks are called.

This message was sent by Atlassian JIRA

View raw message