You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Pierre De Rop (JIRA)" <ji...@apache.org> on 2018/09/24 12:41:00 UTC

[jira] [Updated] (FELIX-5939) DM annotations enhancements

     [ https://issues.apache.org/jira/browse/FELIX-5939?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Pierre De Rop updated FELIX-5939:
---------------------------------
    Description: 
Some DM annotations improvements have been done regarding DM Annotation in this github project: [https://github.com/pderop/dm.enhanced,] and the intent is to merge the improvements to the felix trunk.

Essentially, the following DM annotations enhancements and modifications have been done:
 * in OSGi R7, declarative service now provides a @ComponentPropertyType annotation that can be used to defined user defined property type annotations. Now this annotation is used by other R7 libraries, like jaxrs whiteboard R7 API. So the DM annotation scanner has been enhanced for the support of the DS @ComponentPropertyType, allowing you to reuse user defined annotations from other r7 libraries (whiteboad, etc ...). The dm annotation plugin has been enhanced by reusing some part of the ds annotation scanner from bndlib, which is full of reusable useful code which has been applied to dm (scanning of property types, PREFIX_, etc ...). For consistency api reasons, a new @PropertyType annotation has also been added to the DM annotation API: this annotation has the same semantics has the DS @ComponentPropertyType annotations.
 * allow ServiceDependency to auto detect the service type when the annotation is applied on a collection class field
 * removed FactoryComponentAdapterService (some attributes have been added in the Component annotation in order to declare factory pid components with the @Component annotation)
 * removed some old annotations / attributes. The attributes and annotations related to metatype have been removed since you can now use the standard metatype annotations. if users need to use old version, then the previous old 4.2.1 annotations can be used, because the dm runtime is compatible with old and new annotations version.
 * removed "dereference" attribute in ServiceDependencyAnnotation, because we can now infer if the service dependency callbacks accepts a ServiceReference or a ServiceObjects parameter

Since some incompatible changes have been made, the major version of the annotation bundle has been bumped to 5.0.0.

*User defined property types examples:*

So far, you could define component service properties using DM @Property annotation, and component configuration could be declared as user defined interfaces. You can now declare user-defined annotations which can be used to specify both service properties and component configuration. It means that instead of declaring service properties using @Property annotation, you can now use your own annotations (which must be annotated with the new @PropertyType annotation, or using the standard @ComponentPropertyType annotation.

For example, let’s assume your write an OSGi r7 jaxrs servlet context which needs the two following service properties:
{code:java}
osgi.http.whiteboard.context.name
osgi.http.whiteboard.context.path
{code}
Then you can first define your own annotation (but you could also reuse the default annotations provided by the new jaxrs whiteboard r7 api, from the org.osgi.service.jaxrs.whiteboard.propertytypes package):

 
{code:java}
import org.apache.felix.dependencymanager.annotation.PropertyType;

@PropertyType
@interface ServletContext {
    String osgi_http_whiteboard_context_name() default AppServletContext.NAME;
    String osgi_http_whiteboard_context_path();
}
{code}
In the above, the underscore is mapped to ".", and you can apply the above annotation on top of your component like this:
{code:java}
 @Component
 @ServletContext(osgi_http_whiteboard_context_path="/game")
 public class AppServletContext extends ServletContextHelper {
 }
{code}
You can also use configuration admin service in order to override the default service properties:
{code:java}
 @Component
 @ServletContext(osgi_http_whiteboard_context_path="/game")
 public class AppServletContext extends ServletContextHelper {
    @ConfigurationDependency(propagate=true, pid="my.pid")
    void updated(ServletContext cnf) {
        // if some properties are not present in the configuration, then the ones used in the
        // annotation will be used.
        // The configuration admin properties, if defined, will override the default configurations
        // defined in the annotations
    }
 }
{code}
 
You can also define multiple property type annotations, and possibly single valued annotation, like it is the case with standard r7 DS. In this case, you can use the standard R7 PREFIX_ constants in order to specify the property prefix, and the property name will be derived from the single valued annotation (using camel case convention):


{code:java}
 @PropertyType
 @interface ContextName {

    // will map to "osgi.http.whiteboard.context.name" property name
    String PREFIX_="osgi.http.whiteboard.";
    String value();
 }
 
 @PropertyType
 @interface ContextPath {

    // will map to "osgi.http.whiteboard.context.path" property name
    String PREFIX_="osgi.http.whiteboard.";
    String value();
 }
 
 @Component
 @ContextName(AppServletContext.NAME)
 @ContextPath("/game")
 public class AppServletContext extends ServletContextHelper {
 }
 \{code}


Now , the following is the same example as above, but also using configuration admin service in order to override default service properties: Here, as in OSGi r7 declarative service, you can define a callback method which accepts as arguments all (or some of) the defined property types:


{code:java}
 @Component
 @ContextName(AppServletContext.NAME)
 @ContextPath("/game")
 public class AppServletContext extends ServletContextHelper {
    @ConfigurationDependency(propagate=true, pid="my.pid")
    void updated(ContextName ctxName, ContextPath ctxPath) {
        // if some properties are not present in the configuration, then the ones used in the annotation will be used.
        // The configuration admin properties, if defined, will override the default configurations defined in the annotations
    }
 }
 \{code}
 
The following is the same example as above, but this time the configuration callback can also define a Dictionary in the first argument (in case you want to also get the raw configuration dictionary:


{code:java}
 @Component
 @ContextName(AppServletContext.NAME)
 @ContextPath("/game")
 public class AppServletContext extends ServletContextHelper {
    @ConfigurationDependency(propagate=true, pid="my.pid")
    void updated(Dictionary<String, Object> rawConfig, ContextName ctxName) {
        // if some properties are not present in the configuration, then the ones used in the annotation will be used.
        // The configuration admin properties, if defined, will override the default configurations defined in the annotations
    }
 }
 \{code}

Empty Marker annotations can also be used: when you define an empty annotation, it will be mapped to a java.lang.Boolean property type with Boolean.TRUE value. For example, the following component will be registered with "osgi.jaxrs.resource" service property with Boolean.TRUE value:

{code:java}
@PropertyType
@interface JaxrsResource {

    // will map to "osgi.jaxrs.resource" property name
    String PREFIX_="osgi.";
}
 
@Component(provides = MyResource.class)
@JaxrsResource 
public class MyResource {
    @Path(“foo”)
    @GET
    public void getFoo() {
        ...
    }
}
{code}
User defined property types can also be applied on factory components, for example, in the following, the service properties are declared using the user-defined annotations (they will be overriden from the factory configuration, if present in the config):
{code:java}
@Component(factoryPid="my.factory.pid")
@ContextName(AppServletContext.NAME)
@ContextPath("/game")
class Hello implements HelloService { 
    void updated(ContextName ctxName, ContextPath ctxPath) {
        // Configure or reconfigure our component. the default service 
        // properties will be overriden by the factory configuration (if the
        // service properties are defined in the config)
    }
} 
{code}
*Not backward compatible annotation changes:*

This sections describes what has been removed in the annotation api:
 * removed FactoryConfigurationAdapterService annotation, which was too verbose. when you need to define some factory pid component, just reuse the @Component annotation and declare the new factoryPid/propagate/updated attributes that have been added in the @Component annotation
 * removed PropertyMetadata annotation: it was related to metatypes, but as of today, osgi metatypes can be defined using standard metatype annotations. No need to support this anymore.
 * removed ResourceAdapterService and ResourceDependency annotations because it was needed to depend on some classes from the dependency manager API. The DM Api should be used directly.
 * removed the following attributes from the Component annotation:
 -- FACTORY_NAME
 -- FACTORY_INSTANCE
 -- factorySet
 -- factoryMethod
 These attributes were used to be able to create component instances multiple times. Now, simply use factoryPid Component attribute and use standard Configuration Admin in order to instantiate multiple instances of a given service (using factory configuration).
 * removed @PropertyMetaData annotation, which was related to osgi metatype. now, you can use standard metatype annotations.

Since some incompatible changes have been made, the major version of the annotation bundle has been bumped to 5.0.0, but the dm runtime is still compatible with previous annotations. 

  was:
Some DM annotations improvements have been done regarding DM Annotation in this github project: [https://github.com/pderop/dm.enhanced,] and the intent is to merge the improvements to the felix trunk.

Essentially, the following DM annotations enhancements and modifications have been done:
 * in OSGi R7, declarative service now provides a @ComponentPropertyType annotation that can be used to defined user defined property type annotations. Now this annotation is used by other R7 libraries, like jaxrs whiteboard R7 API. So the DM annotation scanner has been enhanced for the support of the DS @ComponentPropertyType, allowing you to reuse user defined annotations from other r7 libraries (whiteboad, etc ...). The dm annotation plugin has been enhanced by reusing some part of the ds annotation scanner from bndlib, which is full of reusable useful code which has been applied to dm (scanning of property types, PREFIX_, etc ...). For consistency api reasons, a new @PropertyType annotation has also been added to the DM annotation API: this annotation has the same semantics has the DS @ComponentPropertyType annotations.
 * allow ServiceDependency to auto detect the service type when the annotation is applied on a collection class field
 * removed FactoryComponentAdapterService (some attributes have been added in the Component annotation in order to declare factory pid components with the @Component annotation)
 * removed some old annotations / attributes. The attributes and annotations related to metatype have been removed since you can now use the standard metatype annotations. if users need to use old version, then the previous old 4.2.1 annotations can be used, because the dm runtime is compatible with old and new annotations version.
 * removed "dereference" attribute in ServiceDependencyAnnotation, because we can now infer if the service dependency callbacks accepts a ServiceReference or a ServiceObjects parameter

Since some incompatible changes have been made, the major version of the annotation bundle has been bumped to 5.0.0.

*User defined property types examples:*

So far, you could define component service properties using DM @Property annotation, and component configuration could be declared as user defined interfaces. You can now declare user-defined annotations which can be used to specify both service properties and component configuration. It means that instead of declaring service properties using @Property annotation, you can now use your own annotations (which must be annotated with the new @PropertyType annotation, or using the standard @ComponentPropertyType annotation.

For example, let’s assume your write an OSGi r7 jaxrs servlet context which needs the two following service properties:
{code:java}
osgi.http.whiteboard.context.name
osgi.http.whiteboard.context.path
{code}

Then you can first define your own annotation (but you could also reuse the default annotations provided by the new jaxrs whiteboard r7 api, from the org.osgi.service.jaxrs.whiteboard.propertytypes package):

 
{code:java}
import org.apache.felix.dependencymanager.annotation.PropertyType;

@PropertyType
@interface ServletContext {
    String osgi_http_whiteboard_context_name() default AppServletContext.NAME;
    String osgi_http_whiteboard_context_path();
}
{code}

In the above, the underscore is mapped to ".", and you can apply the above annotation on top of your component like this:

{code:java}
 @Component
 @ServletContext(osgi_http_whiteboard_context_path="/game")
 public class AppServletContext extends ServletContextHelper {
 }
 \{code}


You can also use configuration admin service in order to override the default service properties:


{code:java}
 @Component
 @ServletContext(osgi_http_whiteboard_context_path="/game")
 public class AppServletContext extends ServletContextHelper {
    @ConfigurationDependency(propagate=true, pid="my.pid")
    void updated(ServletContext cnf) {
        // if some properties are not present in the configuration, then the ones used in the
        // annotation will be used.
        // The configuration admin properties, if defined, will override the default configurations
        // defined in the annotations
    }
 }
 \{code}
 
You can also define multiple property type annotations, and possibly single valued annotation, like it is the case with standard r7 DS. In this case, you can use the standard R7 PREFIX_ constants in order to specify the property prefix, and the property name will be derived from the single valued annotation (using camel case convention):


{code:java}
 @PropertyType
 @interface ContextName {

    // will map to "osgi.http.whiteboard.context.name" property name
    String PREFIX_="osgi.http.whiteboard.";
    String value();
 }
 
 @PropertyType
 @interface ContextPath {

    // will map to "osgi.http.whiteboard.context.path" property name
    String PREFIX_="osgi.http.whiteboard.";
    String value();
 }
 
 @Component
 @ContextName(AppServletContext.NAME)
 @ContextPath("/game")
 public class AppServletContext extends ServletContextHelper {
 }
 \{code}


Now , the following is the same example as above, but also using configuration admin service in order to override default service properties: Here, as in OSGi r7 declarative service, you can define a callback method which accepts as arguments all (or some of) the defined property types:


{code:java}
 @Component
 @ContextName(AppServletContext.NAME)
 @ContextPath("/game")
 public class AppServletContext extends ServletContextHelper {
    @ConfigurationDependency(propagate=true, pid="my.pid")
    void updated(ContextName ctxName, ContextPath ctxPath) {
        // if some properties are not present in the configuration, then the ones used in the annotation will be used.
        // The configuration admin properties, if defined, will override the default configurations defined in the annotations
    }
 }
 \{code}
 
The following is the same example as above, but this time the configuration callback can also define a Dictionary in the first argument (in case you want to also get the raw configuration dictionary:


{code:java}
 @Component
 @ContextName(AppServletContext.NAME)
 @ContextPath("/game")
 public class AppServletContext extends ServletContextHelper {
    @ConfigurationDependency(propagate=true, pid="my.pid")
    void updated(Dictionary<String, Object> rawConfig, ContextName ctxName) {
        // if some properties are not present in the configuration, then the ones used in the annotation will be used.
        // The configuration admin properties, if defined, will override the default configurations defined in the annotations
    }
 }
 \{code}

Empty Marker annotations can also be used: when you define an empty annotation, it will be mapped to a java.lang.Boolean property type with Boolean.TRUE value. For example, the following component will be registered with "osgi.jaxrs.resource" service property with Boolean.TRUE value:

{code:java}
 @PropertyType
 @interface JaxrsResource {

    // will map to "osgi.jaxrs.resource" property name
    String PREFIX_="osgi.";
 }
 
 @Component(provides = MyResource.class)
 @JaxrsResource 
 public class MyResource {
    @Path(“foo”)
    @GET
    public void getFoo() {
        ...
    }
}
 \{code}

User defined property types can also be applied on factory components, for example, in the following, the service properties are declared using the user-defined annotations (they will be overriden from the factory configuratinn, if present in the config):
{code:java}
@Component(factoryPid="my.factory.pid")
@ContextName(AppServletContext.NAME)
@ContextPath("/game")
class Hello implements HelloService { 
    void updated(ContextName ctxName, ContextPath ctxPath) {
        // Configure or reconfigure our component. the default service 
        // properties will be overriden by the factory configuration (if the
        // service properties are defined in the config)
    }
} 
{code}

*Not backward compatible annotation changes:*

This sections describes what has been removed in the annotation api:
 * removed FactoryConfigurationAdapterService annotation, which was too verbose. when you need to define some factory pid component, just reuse the @Component annotation and declare the new factoryPid/propagate/updated attributes that have been added in the @Component annotation
 * removed PropertyMetadata annotation: it was related to metatypes, but as of today, osgi metatypes can be defined using standard metatype annotations. No need to support this anymore.
 * removed ResourceAdapterService and ResourceDependency annotations because it was needed to depend on some classes from the dependency manager API. The DM Api should be used directly.
 * removed the following attributes from the Component annotation:
-- FACTORY_NAME
-- FACTORY_INSTANCE
-- factorySet
-- factoryMethod
These attributes were used to be able to create component instances multiple times. Now, simply use factoryPid Component attribute and use standard Configuration Admin in order to instantiate multiple instances of a given service (using factory configuration).
 * removed @PropertyMetaData annotation, which was related to osgi metatype. now, you can use standard metatype annotations.

Since some incompatible changes have been made, the major version of the annotation bundle has been bumped to 5.0.0, but the dm runtime is still compatible with previous annotations. 


> DM annotations enhancements
> ---------------------------
>
>                 Key: FELIX-5939
>                 URL: https://issues.apache.org/jira/browse/FELIX-5939
>             Project: Felix
>          Issue Type: Improvement
>          Components: Dependency Manager, Dependency Manager Annotations
>    Affects Versions: org.apache.felix.dependencymanager-r11
>            Reporter: Pierre De Rop
>            Assignee: Pierre De Rop
>            Priority: Minor
>             Fix For: org.apache.felix.dependencymanager-r12
>
>
> Some DM annotations improvements have been done regarding DM Annotation in this github project: [https://github.com/pderop/dm.enhanced,] and the intent is to merge the improvements to the felix trunk.
> Essentially, the following DM annotations enhancements and modifications have been done:
>  * in OSGi R7, declarative service now provides a @ComponentPropertyType annotation that can be used to defined user defined property type annotations. Now this annotation is used by other R7 libraries, like jaxrs whiteboard R7 API. So the DM annotation scanner has been enhanced for the support of the DS @ComponentPropertyType, allowing you to reuse user defined annotations from other r7 libraries (whiteboad, etc ...). The dm annotation plugin has been enhanced by reusing some part of the ds annotation scanner from bndlib, which is full of reusable useful code which has been applied to dm (scanning of property types, PREFIX_, etc ...). For consistency api reasons, a new @PropertyType annotation has also been added to the DM annotation API: this annotation has the same semantics has the DS @ComponentPropertyType annotations.
>  * allow ServiceDependency to auto detect the service type when the annotation is applied on a collection class field
>  * removed FactoryComponentAdapterService (some attributes have been added in the Component annotation in order to declare factory pid components with the @Component annotation)
>  * removed some old annotations / attributes. The attributes and annotations related to metatype have been removed since you can now use the standard metatype annotations. if users need to use old version, then the previous old 4.2.1 annotations can be used, because the dm runtime is compatible with old and new annotations version.
>  * removed "dereference" attribute in ServiceDependencyAnnotation, because we can now infer if the service dependency callbacks accepts a ServiceReference or a ServiceObjects parameter
> Since some incompatible changes have been made, the major version of the annotation bundle has been bumped to 5.0.0.
> *User defined property types examples:*
> So far, you could define component service properties using DM @Property annotation, and component configuration could be declared as user defined interfaces. You can now declare user-defined annotations which can be used to specify both service properties and component configuration. It means that instead of declaring service properties using @Property annotation, you can now use your own annotations (which must be annotated with the new @PropertyType annotation, or using the standard @ComponentPropertyType annotation.
> For example, let’s assume your write an OSGi r7 jaxrs servlet context which needs the two following service properties:
> {code:java}
> osgi.http.whiteboard.context.name
> osgi.http.whiteboard.context.path
> {code}
> Then you can first define your own annotation (but you could also reuse the default annotations provided by the new jaxrs whiteboard r7 api, from the org.osgi.service.jaxrs.whiteboard.propertytypes package):
>  
> {code:java}
> import org.apache.felix.dependencymanager.annotation.PropertyType;
> @PropertyType
> @interface ServletContext {
>     String osgi_http_whiteboard_context_name() default AppServletContext.NAME;
>     String osgi_http_whiteboard_context_path();
> }
> {code}
> In the above, the underscore is mapped to ".", and you can apply the above annotation on top of your component like this:
> {code:java}
>  @Component
>  @ServletContext(osgi_http_whiteboard_context_path="/game")
>  public class AppServletContext extends ServletContextHelper {
>  }
> {code}
> You can also use configuration admin service in order to override the default service properties:
> {code:java}
>  @Component
>  @ServletContext(osgi_http_whiteboard_context_path="/game")
>  public class AppServletContext extends ServletContextHelper {
>     @ConfigurationDependency(propagate=true, pid="my.pid")
>     void updated(ServletContext cnf) {
>         // if some properties are not present in the configuration, then the ones used in the
>         // annotation will be used.
>         // The configuration admin properties, if defined, will override the default configurations
>         // defined in the annotations
>     }
>  }
> {code}
>  
> You can also define multiple property type annotations, and possibly single valued annotation, like it is the case with standard r7 DS. In this case, you can use the standard R7 PREFIX_ constants in order to specify the property prefix, and the property name will be derived from the single valued annotation (using camel case convention):
> {code:java}
>  @PropertyType
>  @interface ContextName {
>     // will map to "osgi.http.whiteboard.context.name" property name
>     String PREFIX_="osgi.http.whiteboard.";
>     String value();
>  }
>  
>  @PropertyType
>  @interface ContextPath {
>     // will map to "osgi.http.whiteboard.context.path" property name
>     String PREFIX_="osgi.http.whiteboard.";
>     String value();
>  }
>  
>  @Component
>  @ContextName(AppServletContext.NAME)
>  @ContextPath("/game")
>  public class AppServletContext extends ServletContextHelper {
>  }
>  \{code}
> Now , the following is the same example as above, but also using configuration admin service in order to override default service properties: Here, as in OSGi r7 declarative service, you can define a callback method which accepts as arguments all (or some of) the defined property types:
> {code:java}
>  @Component
>  @ContextName(AppServletContext.NAME)
>  @ContextPath("/game")
>  public class AppServletContext extends ServletContextHelper {
>     @ConfigurationDependency(propagate=true, pid="my.pid")
>     void updated(ContextName ctxName, ContextPath ctxPath) {
>         // if some properties are not present in the configuration, then the ones used in the annotation will be used.
>         // The configuration admin properties, if defined, will override the default configurations defined in the annotations
>     }
>  }
>  \{code}
>  
> The following is the same example as above, but this time the configuration callback can also define a Dictionary in the first argument (in case you want to also get the raw configuration dictionary:
> {code:java}
>  @Component
>  @ContextName(AppServletContext.NAME)
>  @ContextPath("/game")
>  public class AppServletContext extends ServletContextHelper {
>     @ConfigurationDependency(propagate=true, pid="my.pid")
>     void updated(Dictionary<String, Object> rawConfig, ContextName ctxName) {
>         // if some properties are not present in the configuration, then the ones used in the annotation will be used.
>         // The configuration admin properties, if defined, will override the default configurations defined in the annotations
>     }
>  }
>  \{code}
> Empty Marker annotations can also be used: when you define an empty annotation, it will be mapped to a java.lang.Boolean property type with Boolean.TRUE value. For example, the following component will be registered with "osgi.jaxrs.resource" service property with Boolean.TRUE value:
> {code:java}
> @PropertyType
> @interface JaxrsResource {
>     // will map to "osgi.jaxrs.resource" property name
>     String PREFIX_="osgi.";
> }
>  
> @Component(provides = MyResource.class)
> @JaxrsResource 
> public class MyResource {
>     @Path(“foo”)
>     @GET
>     public void getFoo() {
>         ...
>     }
> }
> {code}
> User defined property types can also be applied on factory components, for example, in the following, the service properties are declared using the user-defined annotations (they will be overriden from the factory configuration, if present in the config):
> {code:java}
> @Component(factoryPid="my.factory.pid")
> @ContextName(AppServletContext.NAME)
> @ContextPath("/game")
> class Hello implements HelloService { 
>     void updated(ContextName ctxName, ContextPath ctxPath) {
>         // Configure or reconfigure our component. the default service 
>         // properties will be overriden by the factory configuration (if the
>         // service properties are defined in the config)
>     }
> } 
> {code}
> *Not backward compatible annotation changes:*
> This sections describes what has been removed in the annotation api:
>  * removed FactoryConfigurationAdapterService annotation, which was too verbose. when you need to define some factory pid component, just reuse the @Component annotation and declare the new factoryPid/propagate/updated attributes that have been added in the @Component annotation
>  * removed PropertyMetadata annotation: it was related to metatypes, but as of today, osgi metatypes can be defined using standard metatype annotations. No need to support this anymore.
>  * removed ResourceAdapterService and ResourceDependency annotations because it was needed to depend on some classes from the dependency manager API. The DM Api should be used directly.
>  * removed the following attributes from the Component annotation:
>  -- FACTORY_NAME
>  -- FACTORY_INSTANCE
>  -- factorySet
>  -- factoryMethod
>  These attributes were used to be able to create component instances multiple times. Now, simply use factoryPid Component attribute and use standard Configuration Admin in order to instantiate multiple instances of a given service (using factory configuration).
>  * removed @PropertyMetaData annotation, which was related to osgi metatype. now, you can use standard metatype annotations.
> Since some incompatible changes have been made, the major version of the annotation bundle has been bumped to 5.0.0, but the dm runtime is still compatible with previous annotations. 



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)