Upload
bjhargrave
View
1.065
Download
0
Embed Size (px)
Citation preview
Field injection, type safe configuration, and more new goodies in Declarative
ServicesBJ Hargrave, IBM
a ComponentImpl
a Service Impl
ServiceComponentRuntime Impl
a Servicea ComponentInstance
ComponentDescription
a ComponentConfguration
registered service
tracksdependencies
declares component
created by
controls 0..n
0..n
0..n
references
1..n1
ConfigurationAdmin
0..n
1
0..n
1
1
<<service>>Service ComponentRuntime
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
@Componentpublic class ExampleImpl implements Example {
private Map<String, Object> properties;private LogService log;@Activatevoid activate(Map<String, Object> map) {
properties = map;}@Overridepublic boolean say(String message) {
log.log((int) properties.get("loglevel"), message);return false;
}@Referencevoid 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
@Referencevoid setLog(LogService log) {
this.log = log;}
Field Injection
• Scalar cardinality
• Static policy
• Dynamic policy
@Referenceprivate Example target;
@Referenceprivate 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
@Referenceprivate List<Example> targets;
https://github.com/bjhargrave/osgice2015/blob/master/2MultipleFieldRef/src/example/command/ExampleCommand.java#L20
@Referenceprivate 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<>();
@ReferenceServiceReference<Example> sr;@ReferenceComponentServiceObjects<Example> so;@Reference(service=Example.class)Map<String,Object> props;@ReferenceMap.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;@Activatevoid 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;
}@Componentpublic class ExampleImpl implements Example {private int myport;@Activatevoid 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)@Componentpublic class ExampleImpl implements Example {private int myport;@Activatevoid 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;@Activatevoid 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;@Activatevoid 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