Field injection, type safe configuration,
and more new goodies in Declarative
Services
BJ Hargrave, IBM
a Component
Impl
a Service Impl
Service
Component
Runtime Impl
a Servicea Component
Instance
Component
Description
a Component
Confguration
registered service
tracks
dependencies
declarescomponent
createdby
controls 0..n
0..n
0..n
references
1..n
1
Configuration
Admin
0..n
1
0..n
1
1
<<service>>
Service Component
Runtime
Declarative Services
• A declarative model for publishing and
consuming OSGi services

• Introduced in Release 4 in 2005, it greatly
simplified programming OSGi services

• Service Component Runtime, SCR, is the
runtime which implements the spec and
manages the service components
Service Component
• A Java class which can optionally be registered as a service and can optionally
use services
• Described by XML in the bundle which is processed at runtime by SCR
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="example.provider.ExampleImpl" activate="activate">
<implementation class="example.provider.ExampleImpl"/>
<service>
<provide interface="example.api.Example"/>
</service>
<reference name="Log" interface="org.osgi.service.log.LogService" bind="setLog"/>
</scr:component>
Service Component using annotations
• But who wants to write XML?
• So DS 1.2 added support for
programming with annotations
• Tools, like , process the
annotations into the XML used by
SCR at runtime
@Component
public class ExampleImpl implements Example {
private Map<String, Object> properties;
private LogService log;
@Activate
void activate(Map<String, Object> map) {
properties = map;
}
@Override
public boolean say(String message) {
log.log((int) properties.get("loglevel"), message);
return false;
}
@Reference
void setLog(LogService log) {
this.log = log;
}
}
Pretty
cool!
So what is new in Declarative Services 1.3?
• Field Injection
• Type Safe Configuration with MetaType integration
• Configuration Admin integration improvements
• Multiple PIDs
• Introspection
• And more small improvements we don’t have time to discuss today
• See 112.17 “Changes” in the DS 1.3 spec
Field Injection
Injection
• Method injection
• Constructor injection
• Field injection
@Reference
void setLog(LogService log) {
this.log = log;
}
Field Injection
• Scalar cardinality
• Static policy
• Dynamic policy
@Reference
private Example target;
@Reference
private volatile Example target;
https://github.com/bjhargrave/osgice2015/blob/master/1ScalarFieldRef/src/example/command/ExampleCommand.java#L17
Field Injection
• Multiple cardinality
• Service type from generic signature
• SCR-managed collection implementation
• Static policy
• Dynamic policy
@Reference
private List<Example> targets;
https://github.com/bjhargrave/osgice2015/blob/master/2MultipleFieldRef/src/example/command/ExampleCommand.java#L20
@Reference
private volatile List<Example> targets;
Field Injection
• User managed collection
• Can also inject fields of types
related to services and
collections of those types
@Reference(policy = ReferencePolicy.DYNAMIC)
private final List<Example> targets = new
CopyOnWriteArrayList<>();
@Reference
ServiceReference<Example> sr;
@Reference
ComponentServiceObjects<Example> so;
@Reference(service=Example.class)
Map<String,Object> props;
@Reference
Map.Entry<Map<String,Object>,Example> tuple;
Type Safe Configuration
Component Properties
• Component properties come from
• Component description
• Configuration Admin configuration
• ComponentFactory.newInstance
<property name=“myport" type="Integer"
value="8080"/>
Dictionary<String, Object> props = new Hashtable<>();
props.put("myport", Integer.valueOf(8081));
cm.getConfiguration("Example").update(props);
Dictionary<String, Object> props = new Hashtable<>();
props.put("myport", Integer.valueOf(8082));
cf.newInstance(props);
Getting the property values
• Activate method
• But what if the configuration value for myport was of type String? Or type Long?
• Type safety failure in your code
• You also need to handle the case where the property is not set
private int myport;
@Activate
void activate(Map<String, Object> props) {
myport = props.containsKey("myport")
? ((Integer) props.get("myport")).intValue() : 8080;
}
Component Property Types
• Define and use your component properties in a type safe manner using
annotations!
@interface Props {
int myport() default 8080;
}
@Component
public class ExampleImpl implements Example {
private int myport;
@Activate
void activate(Props props) {
myport = props.myport();
}
}
https://github.com/bjhargrave/osgice2015/blob/master/3TypeSafeConfig/src/example/provider/ExampleImpl.java#L14
Type Safe Configuration
and MetaType
Component Property Types integrate with MetaType Service
• Use the new MetaType annotations to define metatype resources and
associate them with your component
https://github.com/bjhargrave/osgice2015/blob/master/4TypeSafeConfigWithMetatype/src/example/provider/ExampleImpl.java#L14
@ObjectClassDefinition
@interface Props {
int myport() default 8080;
}
@Designate(ocd=Props.class)
@Component
public class ExampleImpl implements Example {
private int myport;
@Activate
void activate(Props props) {
myport = props.myport();
Multiple Configurations
Component properties from Configurations
• DS integrates with Configuration Admin and will get component properties
from a configuration with the configuration pid of the component
@ObjectClassDefinition(pid = "Example")
@interface Name {
String name() default "Default Name";
}
@Component(configurationPid = "Example")
public class ExampleImpl implements Example {
private String name;
@Activate
void activate(Name name) {
this.name = name.name();
}
}
Sometimes we need to use multiple configurations
• A component may want to use a “system” configuration as well as a specific
configuration
@ObjectClassDefinition(pid = “System")
@interface Name {
String name() default "Default Name";
}
@ObjectClassDefinition(pid = "Example")
@interface Words {
String hello() default "Hello";
String goodbye() default "Goodbye";
}
@Component(configurationPid = {“System", "Example"})
public class ExampleImpl implements Example {
private String name;
private Words words;
@Activate
void activate(Name name, Words words) {
this.name = name.name();
this.words = words;
}
https://github.com/bjhargrave/osgice2015/blob/master/6MultiplePIDs/src/example/provider/ExampleImpl.java#L13
Introspection
Introspecting the Service Components
• SCR now registers a ServiceComponentRuntime service which provides APIs
to introspect the service components managed by SCR
public interface ServiceComponentRuntime {
Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles);
ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name);
Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO
description);
boolean isComponentEnabled(ComponentDescriptionDTO description);
Promise<Void> enableComponent(ComponentDescriptionDTO description);
Promise<Void> disableComponent(ComponentDescriptionDTO description);
}
https://github.com/bjhargrave/osgice2015/blob/master/5Introspection/src/example/command/ExampleCommand.java#L25
SCR Data Transfer Objects
• DTOs are defined for
• Component descriptions - ComponentDescriptionDTO
• Component configurations - ComponentConfigurationDTO
• References - ReferenceDTO, SatisfiedReferenceDTO,
UnsatisfiedReferenceDTO
Why isn’t my component active?
• You can use the DTOs to figure out why
• It might be missing a required configuration or have an unsatisfied reference to
a service
public class ComponentConfigurationDTO extends DTO {
public static final int UNSATISFIED_CONFIGURATION= 1;
public static final int UNSATISFIED_REFERENCE = 2;
public static final int SATISFIED = 4;
public static final int ACTIVE = 8;
public ComponentDescriptionDTO description;
public int state;
public long id;
public Map<String, Object> properties;
public SatisfiedReferenceDTO[] satisfiedReferences;
public UnsatisfiedReferenceDTO[] unsatisfiedReferences;
}
Fin https://github.com/bjhargrave/osgice2015
Field injection, type safe configuration, and more new goodies in Declarative Services

Field injection, type safe configuration, and more new goodies in Declarative Services

  • 1.
    Field injection, typesafe configuration, and more new goodies in Declarative Services BJ Hargrave, IBM
  • 2.
    a Component Impl a ServiceImpl Service Component Runtime Impl a Servicea Component Instance Component Description a Component Confguration registered service tracks dependencies declarescomponent createdby controls 0..n 0..n 0..n references 1..n 1 Configuration Admin 0..n 1 0..n 1 1 <<service>> Service Component Runtime Declarative Services • A declarative model for publishing and consuming OSGi services • Introduced in Release 4 in 2005, it greatly simplified programming OSGi services • Service Component Runtime, SCR, is the runtime which implements the spec and manages the service components
  • 3.
    Service Component • AJava class which can optionally be registered as a service and can optionally use services • Described by XML in the bundle which is processed at runtime by SCR <?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="example.provider.ExampleImpl" activate="activate"> <implementation class="example.provider.ExampleImpl"/> <service> <provide interface="example.api.Example"/> </service> <reference name="Log" interface="org.osgi.service.log.LogService" bind="setLog"/> </scr:component>
  • 4.
    Service Component usingannotations • But who wants to write XML? • So DS 1.2 added support for programming with annotations • Tools, like , process the annotations into the XML used by SCR at runtime @Component public class ExampleImpl implements Example { private Map<String, Object> properties; private LogService log; @Activate void activate(Map<String, Object> map) { properties = map; } @Override public boolean say(String message) { log.log((int) properties.get("loglevel"), message); return false; } @Reference void setLog(LogService log) { this.log = log; } }
  • 5.
  • 6.
    So what isnew in Declarative Services 1.3? • Field Injection • Type Safe Configuration with MetaType integration • Configuration Admin integration improvements • Multiple PIDs • Introspection • And more small improvements we don’t have time to discuss today • See 112.17 “Changes” in the DS 1.3 spec
  • 7.
  • 8.
    Injection • Method injection •Constructor injection • Field injection @Reference void setLog(LogService log) { this.log = log; }
  • 9.
    Field Injection • Scalarcardinality • Static policy • Dynamic policy @Reference private Example target; @Reference private volatile Example target; https://github.com/bjhargrave/osgice2015/blob/master/1ScalarFieldRef/src/example/command/ExampleCommand.java#L17
  • 10.
    Field Injection • Multiplecardinality • Service type from generic signature • SCR-managed collection implementation • Static policy • Dynamic policy @Reference private List<Example> targets; https://github.com/bjhargrave/osgice2015/blob/master/2MultipleFieldRef/src/example/command/ExampleCommand.java#L20 @Reference private volatile List<Example> targets;
  • 11.
    Field Injection • Usermanaged collection • Can also inject fields of types related to services and collections of those types @Reference(policy = ReferencePolicy.DYNAMIC) private final List<Example> targets = new CopyOnWriteArrayList<>(); @Reference ServiceReference<Example> sr; @Reference ComponentServiceObjects<Example> so; @Reference(service=Example.class) Map<String,Object> props; @Reference Map.Entry<Map<String,Object>,Example> tuple;
  • 12.
  • 13.
    Component Properties • Componentproperties come from • Component description • Configuration Admin configuration • ComponentFactory.newInstance <property name=“myport" type="Integer" value="8080"/> Dictionary<String, Object> props = new Hashtable<>(); props.put("myport", Integer.valueOf(8081)); cm.getConfiguration("Example").update(props); Dictionary<String, Object> props = new Hashtable<>(); props.put("myport", Integer.valueOf(8082)); cf.newInstance(props);
  • 14.
    Getting the propertyvalues • Activate method • But what if the configuration value for myport was of type String? Or type Long? • Type safety failure in your code • You also need to handle the case where the property is not set private int myport; @Activate void activate(Map<String, Object> props) { myport = props.containsKey("myport") ? ((Integer) props.get("myport")).intValue() : 8080; }
  • 15.
    Component Property Types •Define and use your component properties in a type safe manner using annotations! @interface Props { int myport() default 8080; } @Component public class ExampleImpl implements Example { private int myport; @Activate void activate(Props props) { myport = props.myport(); } } https://github.com/bjhargrave/osgice2015/blob/master/3TypeSafeConfig/src/example/provider/ExampleImpl.java#L14
  • 16.
  • 17.
    Component Property Typesintegrate with MetaType Service • Use the new MetaType annotations to define metatype resources and associate them with your component https://github.com/bjhargrave/osgice2015/blob/master/4TypeSafeConfigWithMetatype/src/example/provider/ExampleImpl.java#L14 @ObjectClassDefinition @interface Props { int myport() default 8080; } @Designate(ocd=Props.class) @Component public class ExampleImpl implements Example { private int myport; @Activate void activate(Props props) { myport = props.myport();
  • 18.
  • 19.
    Component properties fromConfigurations • DS integrates with Configuration Admin and will get component properties from a configuration with the configuration pid of the component @ObjectClassDefinition(pid = "Example") @interface Name { String name() default "Default Name"; } @Component(configurationPid = "Example") public class ExampleImpl implements Example { private String name; @Activate void activate(Name name) { this.name = name.name(); } }
  • 20.
    Sometimes we needto use multiple configurations • A component may want to use a “system” configuration as well as a specific configuration @ObjectClassDefinition(pid = “System") @interface Name { String name() default "Default Name"; } @ObjectClassDefinition(pid = "Example") @interface Words { String hello() default "Hello"; String goodbye() default "Goodbye"; } @Component(configurationPid = {“System", "Example"}) public class ExampleImpl implements Example { private String name; private Words words; @Activate void activate(Name name, Words words) { this.name = name.name(); this.words = words; } https://github.com/bjhargrave/osgice2015/blob/master/6MultiplePIDs/src/example/provider/ExampleImpl.java#L13
  • 21.
  • 22.
    Introspecting the ServiceComponents • SCR now registers a ServiceComponentRuntime service which provides APIs to introspect the service components managed by SCR public interface ServiceComponentRuntime { Collection<ComponentDescriptionDTO> getComponentDescriptionDTOs(Bundle... bundles); ComponentDescriptionDTO getComponentDescriptionDTO(Bundle bundle, String name); Collection<ComponentConfigurationDTO> getComponentConfigurationDTOs(ComponentDescriptionDTO description); boolean isComponentEnabled(ComponentDescriptionDTO description); Promise<Void> enableComponent(ComponentDescriptionDTO description); Promise<Void> disableComponent(ComponentDescriptionDTO description); } https://github.com/bjhargrave/osgice2015/blob/master/5Introspection/src/example/command/ExampleCommand.java#L25
  • 23.
    SCR Data TransferObjects • DTOs are defined for • Component descriptions - ComponentDescriptionDTO • Component configurations - ComponentConfigurationDTO • References - ReferenceDTO, SatisfiedReferenceDTO, UnsatisfiedReferenceDTO
  • 24.
    Why isn’t mycomponent active? • You can use the DTOs to figure out why • It might be missing a required configuration or have an unsatisfied reference to a service public class ComponentConfigurationDTO extends DTO { public static final int UNSATISFIED_CONFIGURATION= 1; public static final int UNSATISFIED_REFERENCE = 2; public static final int SATISFIED = 4; public static final int ACTIVE = 8; public ComponentDescriptionDTO description; public int state; public long id; public Map<String, Object> properties; public SatisfiedReferenceDTO[] satisfiedReferences; public UnsatisfiedReferenceDTO[] unsatisfiedReferences; }
  • 25.