Application developer guide
This guide will provide information on how an application developer can leverage the new Generic Cloud Services APIs, in order to be able to properly use the CloudPublisher/CloudSubscriber API, publish a message, being notified of message delivery and of connection status changes.
The Kura ExamplePublisher will be used as a reference.
The application should bind itself to a CloudPublisher
or CloudSubscriber
instance, this can be done in different ways, such as using OSGi ServiceTracker
s or by leveraging the Declarative Service layer.
The recommended way to perform this operation is choosing the latter and allowing the user to customize the service references through component configuration.
If the component metatype and definition are structured as described below, the Kura Web UI will show a dedicated widget in component configuration that helps the user to pick compatible CloudPublisher
or CloudSubscriber
instances.
-
Write component definition
The first step involves declaring the Publisher or Subscriber references in component definition:
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.kura.example.publisher.ExamplePublisher" activate="activate" deactivate="deactivate" modified="updated" enabled="true" immediate="true" configuration-policy="require"> <implementation class="org.eclipse.kura.example.publisher.ExamplePublisher"/> <!-- If the component is configurable through the Kura ConfigurationService, it must expose a Service. --> <property name="service.pid" type="String" value="org.eclipse.kura.example.publisher.ExamplePublisher"/> <service> <provide interface="org.eclipse.kura.configuration.ConfigurableComponent"/> </service> <reference name="CloudPublisher" policy="static" bind="setCloudPublisher" unbind="unsetCloudPublisher" cardinality="0..1" interface="org.eclipse.kura.cloudconnection.publisher.CloudPublisher"/> <reference name="CloudSubscriber" policy="static" bind="setCloudSubscriber" unbind="unsetCloudSubscriber" cardinality="0..1" interface="org.eclipse.kura.cloudconnection.subscriber.CloudSubscriber"/> </scr:component>
The snipped above shows the definition of Kura ExamplePublisher, this component is capable of sending and receiving messages, and therefore defines two references, the first to a
CloudPublisher
and the second to aCloudSubscriber
.In order to allow the user to customize the bindings at runtime, the
target
attribute of the references should not be specified at this point in component definition, as it will be set by the Web UI.Reference cardinality should be use the
0..1
or0..n
form, as it is not guaranteed that the references will point to a valid service instance during all the lifetime of the application component. For example, references can not be bound if the application has not been configured by the user yet or if the target service is missing. -
Create component metatype
Application metatype should declare an
AD
for each Publisher/Subscriber reference declared in component definition:<MetaData xmlns="http://www.osgi.org/xmlns/metatype/v1.2.0" localization="en_us"> <OCD id="org.eclipse.kura.example.publisher.ExamplePublisher" name="ExamplePublisher" description="Example of a Configuring Kura Application."> <!-- ... --> <AD id="CloudPublisher.target" name="CloudPublisher Target Filter" type="String" cardinality="0" required="true" default="(kura.service.pid=changeme)" description="Specifies, as an OSGi target filter, the pid of the Cloud Publisher used to publish messages to the cloud platform."> </AD> <AD id="CloudSubscriber.target" name="CloudSubscriber Target Filter" type="String" cardinality="0" required="true" default="(kura.service.pid=changeme)" description="Specifies, as an OSGi target filter, the pid of the Cloud Subscriber used to receive messages from the cloud platform."> </AD> <!-- ... --> </OCD> <Designate pid="org.eclipse.kura.example.publisher.ExamplePublisher" factoryPid="org.eclipse.kura.example.publisher.ExamplePublisher"> <Object ocdref="org.eclipse.kura.example.publisher.ExamplePublisher"/> </Designate> </MetaData>
It is important to respect the following rules for some of the
AD
attributes:id
This attribute must have the following form:
where
<reference name>
should match the value of thename
attribute of the corresponding reference in component definition.-
required
must be set totrue
-
default
must not be empty and must be a valid OSGi filter.
The Web UI will renderer a dedicated widget for picking
CloudPublisher
andCloudSubscriber
instances: -
Write the bind/unbind methods in applicaiton code
The last step involves defining some
bind...()
/unbind...()
methods with a name that matches the values of thebind
/unbind
attributes of the references in component definition.public void setCloudPublisher(CloudPublisher cloudPublisher) { ... } public void unsetCloudPublisher(CloudPublisher cloudPublisher) { ... } public void setCloudSubscriber(CloudSubscriber cloudSubscriber) { ... } public void unsetCloudSubscriber(CloudSubscriber cloudSubscriber) { ... }
As stated above, since reference cardinality is declared as
0..
, the application must be prepared to handle the cases where references are not satisfied, and thereforeCloudPublisher
andCloudSubscriber
instances are not available. -
Publish a message
If a
CloudPublisher
instance is bound, the application can publish messages using itspublish()
method: -
Receiving messages using a CloudSubscriber
In order to receive messages from a
CloudSubscriber
, the application must implement and attach aCloudSubscriberListener
to it.This can be done for example during
CloudSubscriber
binding:public class ExamplePublisher implements CloudSubscriberListener, ... { ... public void setCloudSubscriber(CloudSubscriber cloudSubscriber) { this.cloudSubscriber = cloudSubscriber; this.cloudSubscriber.registerCloudSubscriberListener(ExamplePublisher.this); ... } public void unsetCloudSubscriber(CloudSubscriber cloudSubscriber) { this.cloudSubscriber.unregisterCloudSubscriberListener(ExamplePublisher.this); ... this.cloudSubscriber = null; } ... @Override public void onMessageArrived(KuraMessage message) { logReceivedMessage(message); } ... }
The CloudSubscriber will invoke the
onMessageArrived()
method when new messages are received. -
Receiving connection state notifications
If an application is interested in cloud connection status change events (connected, disconnected, etc), it can implement and attach a
CloudConnectionListener
to aCloudPublisher
orCloudSubscriber
instance.public class ExamplePublisher implements CloudConnectionListener, ... { ... public void setCloudPublisher(CloudPublisher cloudPublisher) { this.cloudPublisher = cloudPublisher; this.cloudPublisher.registerCloudConnectionListener(ExamplePublisher.this); ... } public void unsetCloudPublisher(CloudPublisher cloudPublisher) { this.cloudPublisher.unregisterCloudConnectionListener(ExamplePublisher.this); ... this.cloudPublisher = null; } public void setCloudSubscriber(CloudSubscriber cloudSubscriber) { this.cloudSubscriber = cloudSubscriber; ... this.cloudSubscriber.registerCloudConnectionListener(ExamplePublisher.this); } public void unsetCloudSubscriber(CloudSubscriber cloudSubscriber) { ... this.cloudSubscriber.unregisterCloudConnectionListener(ExamplePublisher.this); this.cloudSubscriber = null; } ... @Override public void onConnectionEstablished() { logger.info("Connection established"); } @Override public void onConnectionLost() { logger.warn("Connection lost!"); } @Override public void onDisconnected() { logger.warn("On disconnected"); } ... }
-
Receiving message delivery notifications
If an application is interested in message confirmation events and the underlying cloud connection supports it, it can implement and attach a
CloudDeliveryListener
to aCloudPublisher
instance.public class ExamplePublisher implements CloudDeliveryListener, ... { ... public void setCloudPublisher(CloudPublisher cloudPublisher) { this.cloudPublisher = cloudPublisher; ... this.cloudPublisher.registerCloudDeliveryListener(ExamplePublisher.this); } public void unsetCloudPublisher(CloudPublisher cloudPublisher) { ... this.cloudPublisher.registerCloudDeliveryListener(ExamplePublisher.this); this.cloudPublisher = null; } ... @Override public void onMessageConfirmed(String messageId) { logger.info("Confirmed message with id: {}", messageId); } ... }
The CloudSubscriber will invoke the
onMessageConfirmed()
method when a published message is confirmed.In order to determine which message has been confirmed, the provided
messageId
can be compared with the id returned by thepublish()
call that published the message.Please note that if the underlying cloud connection is not able to provide message confirmation for the published message, the id returned by
publish()
will benull
.