User Tools

Site Tools


sensorweaver:developer-guide

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
sensorweaver:developer-guide [2014-12-23 10:12] – [SensorWeaver Developer Guide] luigi.fortunatisensorweaver:developer-guide [2015-11-10 16:46] (current) – [Testing your app] luigi.fortunati
Line 5: Line 5:
 General requirements: General requirements:
   * Knowledge of Java, OSGi, Maven.   * Knowledge of Java, OSGi, Maven.
-  * Java Development Kit 7+  * Java Development Kit 8
   * An IDE, preferably with Maven support   * An IDE, preferably with Maven support
   * For testing/deployment   * For testing/deployment
Line 12: Line 12:
  
 A project containing most of the examples shown in this guide can be downloaded at this [[http://ala.isti.cnr.it/svn/wnlab/SensorWeaver/sample-sensor/trunk/|location]] A project containing most of the examples shown in this guide can be downloaded at this [[http://ala.isti.cnr.it/svn/wnlab/SensorWeaver/sample-sensor/trunk/|location]]
-==== Project and development environment setup ====+==== Development environment setup ====
  
-You'll need Java JDK to compile and run your project. [[http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html|Download]] and install one for your system.+You'll need Java JDK to compile and run your project. [[http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html|Download]] and install one for your system.
  
 SensorWeaver components are distributed using Maven [[http://ala.isti.cnr.it:8081/nexus/index.html#welcome|WNLab repositories]].  SensorWeaver components are distributed using Maven [[http://ala.isti.cnr.it:8081/nexus/index.html#welcome|WNLab repositories]]. 
 +
 In order to access released and development JARs you need to configure your development environment. In order to access released and development JARs you need to configure your development environment.
 +
 The best way to achieve this is to add third-party repos to your global maven //settings.xml// in the //default profile//. This removes the need of configuring each maven project. The best way to achieve this is to add third-party repos to your global maven //settings.xml// in the //default profile//. This removes the need of configuring each maven project.
  
Line 25: Line 27:
 <profiles> <profiles>
    <profile>    <profile>
-      <id>default</id>+      <id>wnlab</id>
       <repositories>       <repositories>
          <!-- WNlab Repos -->          <!-- WNlab Repos -->
Line 59: Line 61:
    </profile>    </profile>
 </profiles> </profiles>
 +<activeProfiles>
 +   <activeProfile>wnlab</activeProfile>
 +</activeProfiles>
 </file> </file>
  
-As an alternative, you can include the //repositories// tag inside of your maven project //pom.xml//.+As an alternative, you can include just the //repositories// tag listed above, inside of your Maven project //pom.xml//.
  
 Maven repositories include documentation and source code artifacts. Maven repositories include documentation and source code artifacts.
 +
 Source code can be accessed in read-only in [[http://ala.isti.cnr.it/svn/wnlab/SensorWeaver/|WNLab Subversion]] repository if needed. Source code can be accessed in read-only in [[http://ala.isti.cnr.it/svn/wnlab/SensorWeaver/|WNLab Subversion]] repository if needed.
  
-=== Project setup ===+==== Project setup ====
 Create a Maven project using the IDE of choice. Create a Maven project using the IDE of choice.
  
 The project must generate an OSGi bundle, so: The project must generate an OSGi bundle, so:
   *Set packaging type to //bundle//   *Set packaging type to //bundle//
-  *Set Java compiler with [[http://maven.apache.org/plugins/maven-compiler-plugin/|maven compiler plugin]]+  *Set Java compiler with [[http://maven.apache.org/plugins/maven-compiler-plugin/|maven compiler plugin]]
   *Include the [[http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html|maven bundle plugin]] in order to produce a jar bundle with OSGi manifest.   *Include the [[http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html|maven bundle plugin]] in order to produce a jar bundle with OSGi manifest.
  
Line 86: Line 92:
          <version>3.1</version>          <version>3.1</version>
          <configuration>          <configuration>
-            <source>1.7</source> +            <source>1.8</source> 
-            <target>1.7</target>+            <target>1.8</target>
          </configuration>          </configuration>
       </plugin>       </plugin>
Line 111: Line 117:
 **Tip**: You can find a list of manifest headers on the [[http://wiki.osgi.org/wiki/Category:Manifest_Header|OSGI wiki]] **Tip**: You can find a list of manifest headers on the [[http://wiki.osgi.org/wiki/Category:Manifest_Header|OSGI wiki]]
  
-Add the //middleware-api// dependency to your //pom.xml//.+Then add the //middleware-api// dependency to your project //pom.xml//:
 <file xml pom.xml> <file xml pom.xml>
 <dependencies> <dependencies>
Line 117: Line 123:
       <groupId>it.cnr.isti.sensorweaver.middleware</groupId>       <groupId>it.cnr.isti.sensorweaver.middleware</groupId>
       <artifactId>middleware-api</artifactId>       <artifactId>middleware-api</artifactId>
-      <version>2.0.0</version>+      <version>2.1.0</version>
    </dependency>    </dependency>
 </dependencies> </dependencies>
 </file> </file>
  
-Tip: Check the latest //middleware-api// version on [[http://ala.isti.cnr.it:8081/nexus/index.html#nexus-search;gav~it.cnr.isti.sensorweaver.middleware~middleware-api~~~|WNLab Nexus Repo]] or use [[https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html|maven version ranges]] to be up-to-date with the latest API.+Tip: Check the latest //middleware-api// version on [[http://ala.isti.cnr.it:8081/nexus/index.html#nexus-search;gav~it.cnr.isti.sensorweaver.middleware~middleware-api~~~|WNLab Nexus Repo]] or use [[https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html|maven version ranges]] to be up to date with the latest API.
 ==== Getting an instance of the Middleware service ==== ==== Getting an instance of the Middleware service ====
 Inside of the OSGi runtime environment, the Middleware stands as an OSGi service.  Inside of the OSGi runtime environment, the Middleware stands as an OSGi service. 
Line 128: Line 134:
 There are several ways to achieve this. Here we list two solutions: There are several ways to achieve this. Here we list two solutions:
     * Querying the service registry programmatically using //BundleActivator//     * Querying the service registry programmatically using //BundleActivator//
-    * Blueprint+    * Blueprint (strongly recommended)
  
-=== Bundle Activator === 
- 
-You'll need OSGi dependencies in your pom: 
-<file xml pom.xml> 
-<dependency> 
-   <groupId>org.osgi</groupId> 
-   <artifactId>core</artifactId> 
-   <version>4.3.0</version> 
-</dependency> 
-</file> 
- 
-Then create a java class for your bundle activator: 
-<file java MySensorPublisherActivator.java> 
-package it.cnr.isti.sample; 
- 
-import it.cnr.isti.sensorweaver.middleware.api.Middleware; 
- 
-import org.osgi.framework.BundleActivator; 
-import org.osgi.framework.BundleContext; 
-import org.osgi.framework.ServiceReference; 
- 
-public class MySensorPublisherActivator implements BundleActivator { 
- 
- private ServiceReference<Middleware> middlewareReference; 
- private MySensorPublisher publisher; 
- 
- public void start(BundleContext context) throws Exception { 
- middlewareReference = context.getServiceReference(Middleware.class); 
- Middleware middleware = context.getService(middlewareReference); 
-                //Middleware instance can be passed to other components at this point   
- publisher = new MySensorPublisher(middleware); 
- publisher.start(); 
- } 
- 
- public void stop(BundleContext context) throws Exception { 
- publisher.stop(); 
- context.ungetService(middlewareReference); 
- } 
- 
-} 
-</file> 
- 
-Declare your bundle activator in your Manifest by configuring the //maven bundle plugin//: 
-<file xml pom.xml> 
-<plugin> 
-   <groupId>org.apache.felix</groupId> 
-   <artifactId>maven-bundle-plugin</artifactId> 
-   <version>2.3.7</version> 
-   <extensions>true</extensions> 
-   <configuration> 
-      <instructions> 
-         <!-- ... Other manifest headers ... --> 
-         <Bundle-Activator>it.cnr.isti.sample.MySensorPublisherActivator</Bundle-Activator> 
-      </instructions> 
-   </configuration> 
-</plugin> 
-</file> 
  
 === Blueprint === === Blueprint ===
Line 221: Line 170:
 </file> </file>
  
-Assuming that you're following Maven conventions on project structure, create folder under ''src/main/resources'': ''OSGI-INF/blueprint''.+Assuming that you're following Maven conventions on project structure, create the folder ''src/main/resources/OSGI-INF/blueprint''.
  
 Create a ''services.xml'' file inside of this folder with this content: Create a ''services.xml'' file inside of this folder with this content:
Line 231: Line 180:
  xsi:schemaLocation="  xsi:schemaLocation="
  http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd   http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd 
- http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd+ http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd">
- default-activation="lazy">+
  
  <reference id="middleware"  <reference id="middleware"
Line 244: Line 192:
 </file> </file>
 This configuration basically tells the blueprint runtime to This configuration basically tells the blueprint runtime to
-  * create an instance of ''MySensorPublisher'' when the bundle starts (activation=eager) by wiring it with a proxy reference of the Middleware +  * create an instance of ''MySensorPublisher'' when the bundle starts (activation=eager) by wiring it with a proxy reference of the Middleware using the constructor 
-  * call the method ''start'' of the instance when it is initialized+  * call the method ''start'' of the instance when the bundle is started and the bean is initialized
   * call the method ''stop'' of the instance when the bundle gets stopped   * call the method ''stop'' of the instance when the bundle gets stopped
  
Line 251: Line 199:
 ==== API and usage ==== ==== API and usage ====
  
-Middleware service methods executes asynchronous tasks when called. Whenever a method is called a ''Future'' object is returned ([[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html|documentation]]).+Middleware service methods executes asynchronous tasks when called. Whenever a methodis called a ''Future'' object is returned ([[http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html|documentation]]).
 This solution removes the need to implement callbacks for every method call, improving code readability. This solution removes the need to implement callbacks for every method call, improving code readability.
 The client can synchronize with the end of the middleware task by calling the ''get'' method on the ''Future'' instance, retrieving a result of the computation, when expected, or an asynchronous task execution exception. The client can synchronize with the end of the middleware task by calling the ''get'' method on the ''Future'' instance, retrieving a result of the computation, when expected, or an asynchronous task execution exception.
Line 272: Line 220:
  
   * ''announceDataFeed'' allows to announce the availability of a new //data feed// on the Middleware. It returns, asynchronously, a ''DataFeedClient'' instance that is used for sending data feed messages and unregister the datafeed.   * ''announceDataFeed'' allows to announce the availability of a new //data feed// on the Middleware. It returns, asynchronously, a ''DataFeedClient'' instance that is used for sending data feed messages and unregister the datafeed.
-  * ''registerDiscoverer'' allows to register a ''DataFeedDiscoverer'' instance, a callback object that is notified about lifecycle events related to a set //data feeds//+  * ''registerDiscoverer'' allows to register a ''DataFeedDiscoverer'' instance, a callback object that is notified about lifecycle events related to a set of //data feeds//
   * ''registerListener'' allows to register a ''DataFeedListener'' instance, a callback object that is notified each time a message is produced by a ''data feed''   * ''registerListener'' allows to register a ''DataFeedListener'' instance, a callback object that is notified each time a message is produced by a ''data feed''
  
Line 286: Line 234:
 import it.cnr.isti.sensorweaver.middleware.api.datafeed.descriptor.DataFeedDescriptor; import it.cnr.isti.sensorweaver.middleware.api.datafeed.descriptor.DataFeedDescriptor;
 import it.cnr.isti.sensorweaver.middleware.api.datafeed.descriptor.DataFeedBuilder; import it.cnr.isti.sensorweaver.middleware.api.datafeed.descriptor.DataFeedBuilder;
 +import it.cnr.isti.sensorweaver.middleware.api.common.descriptor.Property;
  
 /** ... **/ /** ... **/
Line 294: Line 243:
  builder.property("sensorType", "temperatureSensor");  builder.property("sensorType", "temperatureSensor");
  builder.parameter("temperature", new Property("Unit of Measure","Celsius"));  builder.parameter("temperature", new Property("Unit of Measure","Celsius"));
- builder.parameter("timestamp", new Property("Format","ISO8601")); + return builder.build();
- DataFeedDescriptor descriptor = builder.build()+
- return descriptor;+
 } }
 </code> </code>
Line 322: Line 269:
  MessageBuilder messageBuilder = dataFeedClient.buildMessage();  MessageBuilder messageBuilder = dataFeedClient.buildMessage();
  messageBuilder.entry("temperature", Integer.toString(datasource.getValue()));  messageBuilder.entry("temperature", Integer.toString(datasource.getValue()));
- messageBuilder.entry("timestamp", DateTime.now().toString());+ messageBuilder.timestamp(Calendar.getInstance().getTimeInMillis());
  messageBuilder.send();  messageBuilder.send();
 } }
 </code> </code>
 +
 +In order to publish a message for a given //data feed// you must produce values for all of the message elements defined previously in the //data feed descriptor//.
 +
 +The datafeed client includes a method //timestamp// for setting the timestamp of the message. If not used, the middleware will set the timestamp at the time of the invocation of the send method.
  
 === Unregistering a Data Feed === === Unregistering a Data Feed ===
Line 339: Line 290:
 === Discover Data Feeds === === Discover Data Feeds ===
 In order to discover new //data feeds// you need to define a ''DataFeedDiscoverer'' first, like the following: In order to discover new //data feeds// you need to define a ''DataFeedDiscoverer'' first, like the following:
- 
  
 <code java> <code java>
Line 363: Line 313:
 </code> </code>
 The discoverer provides a filter which tells the Middleware about which data feeds the discoverer has to be notified on data feed lifecycle events. The discoverer provides a filter which tells the Middleware about which data feeds the discoverer has to be notified on data feed lifecycle events.
 +The filter matches with announced data feed descriptors that have the same property values.
  
 To activate a discoverer you must register it on the Middleware; To activate a discoverer you must register it on the Middleware;
Line 377: Line 328:
  
 In order to start listening for a //data feed// the middleware client must provide a ''DataFeedListener'' In order to start listening for a //data feed// the middleware client must provide a ''DataFeedListener''
-Each listener will listen to messages sent by a //data feed//+ 
 +Each listener will listen to messages sent by a specific //data feed//.
  
 <code java> <code java>
 +    RegistrationToken registrationToken;
 +    
 +    /** ... **/
 +    
 private void startListening(DataFeedDescriptor descriptor) throws InterruptedException, ExecutionException { private void startListening(DataFeedDescriptor descriptor) throws InterruptedException, ExecutionException {
- RegistrationToken registrationToken; +    registrationToken = middleware.registerListener(new LoggingListener(descriptor)).get();
- registrationToken = middleware.registerListener(new LoggingListener(descriptor)).get(); +
- listenerTokens.put(descriptor, registrationToken);+
 } }
   
-private void stopListening(DataFeedDescriptor descriptor) throws InterruptedException, ExecutionException { +private void stopListening() throws InterruptedException, ExecutionException { 
-    RegistrationToken registrationToken = listenerTokens.remove(descriptor); +    registrationToken.unregister().get();
-    if (registrationToken != null) registrationToken.unregister().get();+
 } }
 </code> </code>
 +The same unregistration mechanisms of ''DataFeedDiscoverer'' applies to ''DataFeedListener''.
 +
 +==== Testing your app ====
 +
 +Applications can be easily tested in the [[http://karaf.apache.org/|Karaf]] OSGi environment, using provided logging and debugging tools.
  
-==== Integration testing ====+You can download your preferred Apache Karaf release (latest version is strongly recommended) and install the ''middleware'' feature from the latest [[http://ala.isti.cnr.it:8081/nexus/index.html#nexus-search;quick~sensorweaver-features|SensorWeaver karaf feature repository]] to start up your container.
  
-Applications can be directly tested in Karaf OSGi environment using the middleware-dev feature. please refer to the administrator guide in order to setup the test environment.+Deafult feature configuration assumes that you have an MQTT broker online on port 1883 on your local machine.
  
 +Please refer to the [[sensorweaver:admin-guide|Administrator Guide]] in order to setup and configure your OSGI environment.
sensorweaver/developer-guide.1419329541.txt.gz · Last modified: 2014-12-23 10:12 by luigi.fortunati

Donate Powered by PHP Valid HTML5 Valid CSS Run on Debian Driven by DokuWiki