Ok, an example ...

First a service interface:

        public interface Foo {
          String db();
        }

Now we create an implementation that registers the raw underlying db:

        @Component
        public class FooImpl implements Foo {
          public        String db() { return "Hello World";}
        }

The migrator depends on the raw service, we assume that this raw service does 
not have the property state set. So we create a reference to this 'raw' service 
by creating a target filter that checks if the property is NOT set. Notice that 
the activate method is the suitable place to do the migration (or check the 
migration was already done). The activate method should return once the 
migration is done, after which the Foo service will be registered. If you fail 
to migrate, just throw an exception; this will be logged and the service will 
NOT be registered. 

        @Component(property="state=migrated")
        public class FooMigrator implements Foo {
          Foo raw;

          @Activate void activate(){  /* migrate, take your time */ }

          public        String db() { return raw.db();}

          @Reference(target="(!(state=*))")
          void setFoo( Foo raw) { this.raw=raw; }
        }

Now the client. If we can adapt the client, the client should have a target 
filter with the state=migrated. 

@Component
public void Client {
        Foo migrated;
        
        @Activate void activate() { System.out.println(migrated.db()); }

        @Reference(target="(state=migrated)")
        void setFoo( Foo migrated) { this.migrated=migrated; }
}

That's all ... this code actually will not require anything extra except the 
package and import statements. The beauty of it all is that with DS you can 
override the reference target filters. So in the case you cannot change the 
client, you set the Foo.target configuration property to the desired filter. 

This is infinitely simpler than service hooks are other hacks, believe me, I've 
been there. In this model you leverage the surprising large amount of 
guarantees that DS is giving you.

Kind regards,

        Peter Kriens



@Component(property

On 20 mrt. 2014, at 17:53, Bertrand Delacretaz <[email protected]> wrote:

> Hi Peter,
> 
> On Thu, Mar 20, 2014 at 4:32 PM, Peter Kriens <[email protected]> wrote:
>> ...The migrator depends on the raw service and registers a delegate service 
>> after it has
>> migrated the database. You can easily make a pipeline like this. A simple 
>> service property
>> will do the trick. In DS it is easy to use the target filter (that can be 
>> set by config admin
>> so you code is ignorant of the fact) to manage the pipeline.
>> 
>>   db -> migrator -> client
> ...
> 
> Looks very cool, I agree. But how do you hide the raw db service from
> existing clients that currently get it via an @Reference annotation
> with no specific filter?
> 
> My understanding is that a DS client that does not specify a filter
> will get the first service that provides the corresponding interface,
> so as soon as the raw db is available, those clients will see it.
> 
> I'm probably missing something...by "can be set by config admin" do
> you mean that I can setup a default filter so that clients with no
> filter only see the delegate service that the migrator registers,
> because that delegate will have something like a visibleTo=allClients
> service property?
> 
>> ...In general you make things surprisingly complex once you step outside the 
>> standard service dependency model....
> 
> Absolutely agree, so if your suggestion works without any changes to
> existing clients that's fantastic.
> 
> -Bertrand
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to