[ https://issues.apache.org/jira/browse/FELIX-5941?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Pierre De Rop resolved FELIX-5941. ---------------------------------- Resolution: Fixed committed in revision 1842034. > DM APi enhancements > ------------------- > > Key: FELIX-5941 > URL: https://issues.apache.org/jira/browse/FELIX-5941 > Project: Felix > Issue Type: Improvement > Components: Dependency Manager > Reporter: Pierre De Rop > Assignee: Pierre De Rop > Priority: Minor > Fix For: org.apache.felix.dependencymanager-r12 > > > in [https://github.com/pderop/dm.enhanced,] some enhancements have been done > regarding the dm API, and the intent of this issue is to merge the > improvements into the felix trunk: > * the api to define aspects and adapters have been reworked (but dm API > remains {{backward compatible}}) > * you can now declare multiple property type interfaces when using > Configuration Dependency or Factory Components (this was needed to implement > the enhancements for the annotations) > * configuration dependency using metatypes can now declare property types > * Allow to specify if propagated configuration dependencies must override > service service properties (it was not possible to override service > properties with propagated service properties so far) > * Added the following signatures in Component interface: > ** setInterface(Class serviceName, Dictionary properties) > ** setInterface(Class[] serviceNames, Dictionary properties) > h3. *Aspect/Adapters Api enhancements* > So far, aspects or adapters were defined using many methods from > DependencyManager or DependencyActivatorBase classes: > For example, in DependencyManager.java, we currently have many signatures > {code:java} > public class DependencyManager { > public Component createAdapterService(Class<?> serviceInterface, String > serviceFilter) {...} > public Component createAdapterService(Class<?> serviceInterface, String > serviceFilter, String autoConfig) {...} > public Component createAdapterService(Class<?> serviceInterface, String > serviceFilter, String add, String change, String remove) {...} > public Component createAdapterService(Class<?> serviceInterface, String > serviceFilter, String add, String change, String remove, String swap) {...} > public Component createAdapterService(Class<?> serviceInterface, String > serviceFilter, String autoConfig, Object callbackInstance, String add, String > change, String remove, String swap, boolean propagate) {...} > > public Component createFactoryConfigurationAdapterService(String > factoryPid, String update, boolean propagate) {...} > public Component createFactoryConfigurationAdapterService(String > factoryPid, String update, boolean propagate, Object callbackInstance) {...} > public Component createFactoryConfigurationAdapterService(String > factoryPid, String update, boolean propagate, Class<?> configType) {...} > public Component createFactoryConfigurationAdapterService(String > factoryPid, String update, boolean propagate, Object callbackInstance, > Class<?> configType) {...} > public Component createAdapterFactoryConfigurationService(String > factoryPid, String update, boolean propagate,String heading, String desc, > String localization, PropertyMetaData[] propertiesMetaData) {...} > > public Component createBundleAdapterService(int bundleStateMask, String > bundleFilter, boolean propagate) {...} > public Component createBundleAdapterService(int bundleStateMask, String > bundleFilter, boolean propagate, Object callbackInstance, String add, String > change, String remove) {...} > > public Component createResourceAdapterService(String resourceFilter, > boolean propagate, Object callbackInstance, String callbackChanged) {...} > public Component createResourceAdapterService(String resourceFilter, > boolean propagate, Object callbackInstance, String callbackSet, String > callbackChanged) > public Component createResourceAdapterService(String resourceFilter, > Object propagateCallbackInstance, String propagateCallbackMethod, Object > callbackInstance, String callbackChanged) {...} > public Component createResourceAdapterService(String resourceFilter, > Object propagateCallbackInstance, String propagateCallbackMethod, Object > callbackInstance, String callbackSet, String callbackChanged) {...} > > public Component createAspectService(Class<?> serviceInterface, String > serviceFilter, int ranking, String autoConfig) {...} > public Component createAspectService(Class<?> serviceInterface, String > serviceFilter, int ranking) {...} > public Component createAspectService(Class<?> serviceInterface, String > serviceFilter, int ranking, String add, String change, String remove) {...} > public Component createAspectService(Class<?> serviceInterface, String > serviceFilter, int ranking, String add, String change, String remove, String > swap) {...} > public Component createAspectService(Class<?> serviceInterface, String > serviceFilter, int ranking, Object callbackInstance, String add, String > change, String remove, String swap) {...}{code} > So, we have simplified the usage of the aspect/adapters like this: instead of > having to use some of the many methods from the DependencyManager or > DependencyActivatorBase, we have added some new interfaces for the aspect and > adapters, and these interfaces are extending the Component interface. All > other existing methods have been moved to > DependencyManagerCompat/DependencyActivatorBaseCompat classes and the > DependencyManager/DependencyActovatorBase classes are now extending the > compat classes: this allows to simplify the reading of the javadocs for > DependencyManager/DependencyActovatorBase. > For example, let's first show how an factory pid component was declared so > far (a factory pid component is one which can be instantiated multiple times > using a "factory configuration" created using standard "configuration admin" > service): > {code:java} > public class Activator extends DependencyActivatorBase { > @Override > public void init(BundleContext context, DependencyManager dm) throws > Exception { > dm.add(createFactoryConfigurationAdapterService("my.factory.pid", > "updated", true, MyConfig.class) > .setInterface(MyService.class.getName(), null) > .setImplementation(MyServiceImpl.class) > .add(createServiceDependency().setService(LogService.class))); > } > }{code} > So, now, there is a new FactoryComponent interface which extends the > Component interface and it contains all the various parameters used when > declaring a factory pid component. So the example above becomes: > {code:java} > public class Activator extends DependencyActivatorBase { > @Override > public void init(BundleContext context, DependencyManager dm) throws > Exception { > dm.add(createFactoryComponent() > .setFactoryPid("my.factory.pid") > .setPropagate(true) > .setConfigType(MyConfig.class) > .setInterface(MyService.class.getName(), null) > .setImplementation(MyServiceImpl.class) > .add(createServiceDependency().setService(LogService.class))); > } > }{code} > Now, we explain what the new interfaces look like: Indeed as you can imagine, > there is an issue when you extend the Component interface, because the > various Component setter methods return a Component type. So, what we would > like is to be able to introduce a generic type in the Component interface , > and such generic type can then be used to allow the Component setter methods > to return not the Component type, but instead return the aspect/adapter sub > classes. This is what we have done, let's show a pseudo code, so you can > understand how it works: > First, the Component annotation have been reworked like this: > {code:java} > public interface Component<T extends Component<T>> { > T setInterface(String service, Dictionary properties) > T setImplementation(Object ob); > ... > }{code} > As you can see the Component annotation is now using a recursive generic type > which extends the Component interface. And now we have for example the > following AdapterComponent interface which is defined like this: > {code:java} > public interface AdapterComponent extends Component<AdapterComponent> { > AdapterComponent setAdaptee(Class<?> service, String filter); > AdapterComponent setAdapteeCallbacks(String add, String change, String > remove, String swap); > ... > }{code} > So, now, an adapter component can be defined like this: > {code:java} > Component adapter = createAdapterComponent() > .setAdaptee(Adaptee.class, "(foo=bar)") > .setAdapteeCallbacks("setAdaptee", "changeAdaptee", null, null) > .setImplementation(AdapterImpl.class) > .setInterface(AdapterService.class, null) > .add(createServiceDependency().setService(LogService.class));{code} > > *Support for multiple configuration types in callbacks* > The ConfigurationDependency and Factory components can now support updated > callbacks with multiple configuration types, for example, the following > Activator defines a factory component (using the enhanced api) and multiple > configuration types can now be provided: > {code:java} > public class Activator extends DependencyActivatorBase { > @Override > public void init(BundleContext context, DependencyManager dm) throws > Exception { > Component factoryComponent = createFactoryComponent() > .setFactoryPid(pid). > .setConfigType(MyConfig1.class, MyConfig2.class) > .setImplementation(MyComponent.class); > dm.add(factoryComponent); > } > } > public class MyComponent { > void updated(MyConfig1 cnf1, MyConfig2 cnf2) { ... } > }{code} > Moreover, you can define a Dictionary parameter as the first argument in the > updated callback, because sometimes, it's useful to be injected with the raw > dictionary configuration, as well as with the configuration types. Example: > {code:java} > public class MyComponent { > void updated(Dictionary<String, Object> rawConfig, MyConfig1 cnf1, > MyConfig2 cnf2) { ... } > }{code} > so, the new signatures for the updated callbacks are now the following (for > both ConfigurationDependency and Factory Component): > * updated(Dictionary cnf) > * updated(Component comp, Dictionary cnf) > * updated(Component comp, Property interfaces ...) > * updated(Property interfaces ...) > * updated(Dictionary cnf, Property interfaces ...) > * updated(Component comp, Dictionary cnf, Property interfaces ...) -- This message was sent by Atlassian JIRA (v7.6.3#76005)