user guide -...

26
User Guide Release 2.3.1

Upload: others

Post on 22-May-2020

9 views

Category:

Documents


0 download

TRANSCRIPT

User GuideRelease 2.3.1

Contents1 Introduction 1

2 Apache Maven archetypes for your Gateway projects 3

3 The Camel DDS Component 53.1 Maven configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53.2 The Vortex Gateway opensplice-idl-plugin for Maven . . . . . . . . . . . . . . . . . . . . . . . 63.3 Endpoint configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.4 Content of Camel Exchanges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.5 Example of route . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.6 Dynamic DDS QoS changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.7 Camel Messages mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.8 DDS Polling Consumer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133.9 Additional Apache Camel Processors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4 The Camel DDSI Component 164.1 DDSI Maven configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164.2 DDSI Endpoint configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174.3 Content of Camel Exchanges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204.4 Example of route . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204.5 DDSI message’s body . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204.6 DDSI messages marshalling/unmarshalling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214.7 DDSI over TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

5 Troubleshooting 23

6 Contacts & Notices 246.1 Contacts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246.2 Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

i

1Introduction

Vortex Gateway addresses the problem of making data seamlessly flow across systems and technologies whileadapting format, content and QoS. The Vortex Gateway is the best choice for integrating DDS-based systems withother messaging technologies, such as JMS, as well as for integrating with proprietary and Web Technologies suchas W3C Web Services and RESTful Web Services.

By leveraging Apache Camel, the Vortex Gateway comes with off-the-shelf support for more than eighty connec-tors including the Vortex OpenSplice Real-Time Networking Wire Protocol, as well as transports that are standardin Enterprise Conputing and Web applications.

In v2.x of Vortex Gateway an OMG DDSI protocol connector was introducted.

Fig. 1.1: The Vortex Gateway architecture

For more information about Apache Camel, please refer to:

• http://camel.apache.org/

• http://camel.apache.org/manual.html (Apache Camel manuals)

• http://camel.apache.org/components.html (list of available protocols)

Below is an illustration of a typical use case of Vortex Gateway.

Here, Vortex Gateway is used to get Radar Tracks data from different radars via DDS or JMS.

1

User Guide, Release 2.3.1

Fig. 1.2: A Vortex Gateway Use Case

Radar Tracks from JMS are routed to DDS and all Tracks are received and classified by Classifier. The Classifierwill publish Classification data on DDS.

Vortex Gateway also routes Radar Tracks and Classification data from DDS to an external Ajax-based display viaa REST endpoint.

2

2Apache Maven archetypes for yourGateway projects

Vortex Gateway provides two archetypes to quickly generate a Maven project configured with Gateway usage andwith a Java class to be completed with your Camel routes definition.

Those archetypes are automatically added to your local archetype catalog during Vortex Gateway installation.

To create your project, run the following command and follow the instructions below:

mvn archetype:generate -DarchetypeCatalog=local

Select the archetype you want, depending on the Vortex Gateway component you want to use in your project:

• gateway-archetype-camel-ospl for a project using the camel-ospl component (see std,std-refThe CamelDDS Component)

• gateway-archetype-camel-ddsi for a project using the camel-ddsi component (see std,std-refThe CamelDDSI Component)

Then follow the instructions, defining the groupId , artifactId and version of your project.

Here is an example of output and user’s input (end of each “Define value for property...” line):

demo@hao:~$ mvn archetype:generate -DarchetypeCatalog=local[INFO] Scanning for projects...[INFO][INFO][INFO] Building Maven Stub Project (No POM) 1[INFO][INFO][INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) @standalone-pom >>>[INFO][INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) @standalone-pom <<<[INFO][INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @standalone-pom ---[INFO] Generating project in Interactive mode[INFO] No archetype defined. Using maven-archetype-quickstart(org.apache.maven.archetypes:maven-archetype-quickstart:1.0)Choose archetype:1: local -> com.prismtech.gateway.archetypes:gateway-archetype-camel-ospl(Creates a new Gateway project using camel-ospl component.)

2: local -> com.prismtech.gateway.archetypes:gateway-archetype-camel-ddsi(Creates a new Gateway project using camel-ddsi component.)

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1Define value for property 'groupId': : org.acmeDefine value for property 'artifactId': : MyProjectDefine value for property 'version': 1.0-SNAPSHOT: : 0.0.1-SNAPSHOTDefine value for property 'package': org.acme: : org.acme[INFO] Using property: project-version = 2.0.0

3

User Guide, Release 2.3.1

Confirm properties configuration:groupId: org.acmeartifactId: MyProjectversion: 0.0.1-SNAPSHOTpackage: org.acmeproject-version: 2.0.0Y: : Y[INFO][INFO] Using following parameters for creating project from Archetype:gateway-archetype-camel-ospl:2.0.0[INFO][INFO] Parameter: groupId, Value: org.acme[INFO] Parameter: artifactId, Value: MyProject[INFO] Parameter: version, Value: 0.0.1-SNAPSHOT[INFO] Parameter: package, Value: org.acme[INFO] Parameter: packageInPathFormat, Value: org/acme[INFO] Parameter: package, Value: org.acme[INFO] Parameter: version, Value: 0.0.1-SNAPSHOT[INFO] Parameter: project-version, Value: 2.0.0[INFO] Parameter: groupId, Value: org.acme[INFO] Parameter: artifactId, Value: MyProject[INFO] project created from Archetype in dir: /home/demo/MyProject[INFO][INFO] BUILD SUCCESS[INFO][INFO] Total time: 31.345s[INFO] Finished at: Wed Jul 02 15:01:26 CEST 2014[INFO] Final Memory: 10M/207M[INFO]

With this example the following hierarchy of directories and files are created:

MyProject/|-- pom.xml|-- README.txt`-- src/

`-- main/|-- idl/| `-- your_dds_types_definition.idl`-- java/

`-- org/`-- acme/

`-- GatewayRoutesDefinition.java

The generated Maven pom.xml file is already configured with appropriate dependencies, depending the VortexGateway component you selected (see std,std-refMaven configuration for camel-ospl , or see std,std-refDDSIMaven configuration for camel-ddsi ).

All you have to do is:

1. Copy or create your IDL files with DDS types definition in src/main/idl .

2. Update the GatewayRoutesDefinition.java adding your own Camel routes definition.

3. Compile your project with this command:

mvn package

4. Run your project with this command:

mvn exec:java

(For camel-ospl projects, if Vortex OpenSplice is not configured in Single Process mode, don’t forget to start theVortex OpenSplice daemon at first)

4

3The Camel DDS Component

The Camel DDS component (named camel-ospl) allows messages to be written to a DDS Topic via a Camelroute; or messages to be received from a DDS Topic via a Camel route using Vortex OpenSplice RT Networkingprotocol.

The message exchanged by DDS could be either the IDL-typed DDS sample (default mode), or any Java serializ-able object (using the std,std-refCamel Messages mode).

3.1 Maven configuration

If you look at the pom.xml file generated by the Vortex Gateway’s archetype for camel-ospl , you will see thefollowing declarations, which are required for your Maven project:

<dependencyManagement><dependencies>

<!-- Import Gateway's dependencyManagement. --><!-- Thus all dependencies used by Gateway are --><!-- referenced with appropriate version numbers. --><dependency>

<groupId>com.prismtech.gateway</groupId><artifactId>parent-pom</artifactId><type>pom</type><scope>import</scope><version>${gateway-version}</version>

</dependency></dependencies>

</dependencyManagement>

This is to import all version numbers of dependencies the Gateway might use. Thus, when your project requires adependency that Gateway has been tested with, you don’t have to specify its version number again.

<dependencies><!-- Gateway's Camel OpensSpliceDDS endpoint --><dependency>

<groupId>com.prismtech.gateway</groupId><artifactId>camel-ospl</artifactId><version>${gateway-version}</version>

</dependency>

<!-- Vortex OpenSplice --><dependency>

<groupId>org.opensplice</groupId><artifactId>dcpssaj</artifactId>

</dependency></dependencies>

These are your project’s explicit dependencies on Vortex Gateway’s camel-ospl component and Vortex Open-Splice’s dcpssaj.jar file.

Dependencies on Apache Camel’s artefacts are implied, since camel-ospl depends on those artefacts.

5

User Guide, Release 2.3.1

Note that the scope of Vortex OpenSplice’s dcpssaj dependency is ‘system‘, because this jar has to be found in the$OSPL_HOME/jar/ directory. This is configured in the imported Vortex Gateway’s parent-pom:

<build><plugins>

<!-- OpenSplice IDL compilation plugin --><plugin>

<groupId>com.prismtech.gateway</groupId><artifactId>opensplice-idl-plugin</artifactId><version>${gateway-version}</version><executions>

<execution><phase>generate-sources</phase><goals>

<goal>idl-compile</goal></goals>

</execution></executions>

</plugin></plugins>

</build>

The Vortex Gateway’s opensplice-idl-plugin is used by Maven at the ‘generate-sources‘ phase, to process all IDLfiles placed in the src/main/idl directory and generate Java classes for DDS types, DataReaders and DataWriters.Those classes will be used at runtime by your Gateway project.

More configuration options for this plugin are described in std,std-refThe Camel DDSI Component.

3.2 The Vortex Gateway opensplice-idl-plugin for Maven

The opensplice-idl-plugin for Maven drives the Vortex OpenSplice idlpp command to process IDL files and gen-erate corresponding code (DDS types and typed DDS DataReaders and DataWriters).

By default ( i.e. without additional configuration) this plugin searches for files with an ‘.idl‘ extension in thesrc/main/idl/ directory, and generates Java code in the target/generated-sources/idl/ directory.

The generated Java files are automatically added to the list of Java source files to be compiled by Maven duringthe ‘compile‘ phase.

In addition, the following optional parameters can be configured:

Name Type DescriptionoutDir File The directory to output the generated sources to.

Default value is: ${project.build.directory}/ generated-sources/idlincludeDirs File[] Additional include directories containing additional *.idl files required for

compilation.idlDir File The source directory containing *.idl files.

Default value is: ${basedir}/src/main/idlmacros String[] Preprocessing macros definitions (used with -D options)idlc String The compiler executable.

Default value is: idlclanguage String The language of generated code. Should be one of ‘java’, ‘c’, ‘c++’ or ‘cs’.

Default value is: ‘java‘mode String Standalone or CORBA mode. Should be either ‘-S’ or ‘-C’.

Default value is: ‘-S‘

3.3 Endpoint configuration

An Apache Camel endpoint using Vortex OpenSplice is configured using following URI format:

3.2. The Vortex Gateway opensplice-idl-plugin for Maven 6

User Guide, Release 2.3.1

dds:topicName:domainID/[topicClass][?options]

Where topicName is the DDS topic name to publish or subscribe, domainID is the DDS domain identifier, andtopicClass is the generated class for the topic type (optional in the case of Camel Messages mode; see std,std-refCamel Messages mode).

Options is a list of optional parameters, separated by ‘&‘ characters; for example:

?option1=value1&option2=value2&...

The following options are accepted:

Name Type DescriptionreadMode Boolean Only applies to a consumer endpoint

(from(“dds:...’)).By default the DDS DataReader of a consumerendpoint uses the take() operation. Setting thisoption to true makes it to use the read() opera-tion instead.The advantage is that in case of a DISPOSE orWRITEDISPOSE message the data will be valid (i.e. the latest-read data). The drawback is that theDataReader consumes more memory to keep thelatest data in a cache.

ignoreLocalPublishers Boolean Only applies to a consumer endpoint(from(“dds:...’)).Indicate if a consumer must ignore the data pub-lished by a local producer (i.e. in the same JVM).By default this option is set to true, avoiding loopfor bridge patterns using 2 routes in opposite di-rections. For instance with a DDS/JMS bridge,you configure 2 routes:

• a route from JMS to DDS• a route from DDS to JMS

If this option is set to false, the 2nd route will re-ceive the publications from the 1st route, sendingback to JMS data which are coming from JMS.

partition String Corresponds to DDSPartitionQosPolicy.name.A list of DDS partitions, separated by , charac-ters.

contentFilter String Corresponds to a DDS filter expression to be usedon topic (actually a ContentFilteredTopic is cre-ated by the endpoint). This is a SQL-like expres-sion as defined in the DDS specification.WARNING : the expression must use percent-encoding for URI reserved and unsafe characters(e.g. = = %3D , > = %3E , ..)

deadlinePeriod Double Corresponds to DDSDeadlineQosPolicy.period.A float representing a time in seconds.

destinationOrder String Corresponds to DDSDestinationOrderQosPolicy.kind.Possible values:

• BY_RECEPTION_TIMESTAMP• BY_SOURCE_TIMESTAMP

Continued on next page

3.3. Endpoint configuration 7

User Guide, Release 2.3.1

Table 3.1 – continued from previous pageName Type DescriptiondurabilityKind String Corresponds to DDS

DurabilityQosPolicy.kind.Possible values:

• VOLATILE• TRANSIENT• TRANSIENT_LOCAL• PERSISTENT

durabilityServiceCleanupDelay Double Corresponds to DDSDurabilityServiceQosPolicy.service_cleanup_delayA float representing a time in seconds.

durabilityServiceDepth Int Corresponds to DDSDurabilityServiceQosPolicy.history_depthAn integer representing the history depth.

durabilityServiceKind String Corresponds to DDSDurabilityServiceQosPolicy.history_kindPossible values:

• KEEP_ALL• KEEP_LAST

durabilityServiceMaxInstances Int Corresponds to DDSDurabilityServiceQosPolicy.max_instancesAn integer representing the maximum number ofinstances.

durabilityServiceMaxSamples Int Corresponds to DDSDurabilityServiceQosPolicy.max_samplesAn integer representing the maximum number ofsamples.

durabilityServiceMaxSamplesPerInstance Int Corresponds to DDSDurabilityServiceQosPolicy.max_samples_per_instanceAn integer representing the history depth.

historyDepth String Corresponds to DDSHistoryQosPolicy.depth.An integer representing the maximum number ofsamples per instance.

historyKind String Corresponds to DDSHistoryQosPolicy.kind.Possible values:

• KEEP_ALL• KEEP_LAST

latencyDuration Double Corresponds to DDSLatencyBudgetQosPolicy.duration.A float representing a time in seconds.

lifespanDuration Double Corresponds to DDSLifespanQosPolicy.duration.A float representing a time in seconds.

livelinessDuration Double Corresponds to DDSLivelinessQosPolicy.lease_duration.A float representing a time in seconds.

Continued on next page

3.3. Endpoint configuration 8

User Guide, Release 2.3.1

Table 3.1 – continued from previous pageName Type DescriptionlivelinessKind String Corresponds to DDS

LivelinessQosPolicy.kind.Possible values:

• AUTOMATIC• MANUAL_BY_PARTICIPANT• MANUAL_BY_TOPIC

ownershipKind String Corresponds to DDSOwnershipQosPolicy.kind.Possible values:

• SHARED• EXCLUSIVE

ownershipStrength String Corresponds to DDSOwnershipStrengthQosPolicy.value.An integer representing the ownership strength.

presentationAccessScope String Corresponds to DDSPresentationQosPolicy.access_scope.Possible values:

• INSTANCE• TOPIC• GROUP

presentationCoherentAccess Boolean Corresponds to DDSPresentationQosPolicy.coherent_access

presentationOrderedAccess Boolean Corresponds to DDSPresentationQosPolicy.ordered_access

readerDataLifecycleAutopurgeDisposedDelayDouble Corresponds to DDSReaderDataLifecycleQosPolicy.autopurge_disposed_samples_delayA float representing a time in seconds.

readerDataLifecycleAutopurgeNowriterDelayDouble Corresponds to DDSReaderDataLifecycleQosPolicy.autopurge_nowriter_samples_delayA float representing a time in seconds.

reliabilityBlockingTime Double Corresponds to DDSReliabilityQosPolicy.max_blocking_timeA float representing a time in seconds.

reliabilityKind String Corresponds to DDSReliabilityQosPolicy.kind.Possible values:

• RELIABLE• BEST_EFFORT

resourceLimitsMaxInstances Int Corresponds to DDSResourceLimitsQosPolicy.max_instancesAn integer representing the maximum number ofinstances.

resourceLimitsMaxSamples Int Corresponds to DDSResourceLimitsQosPolicy.max_samples.An integer representing the maximum number ofsamples.

resourceLimitsMaxSamplesPerInstance Int Corresponds to DDSResourceLimitsQosPolicy.max_samples_per_instanceAn integer representing the maximum number ofsamples per instance.

Continued on next page

3.3. Endpoint configuration 9

User Guide, Release 2.3.1

Table 3.1 – continued from previous pageName Type DescriptiontimebasedFilter Double Corresponds to DDS

TimeBasedFilterQosPolicy.minimum_separationA float representing a time in seconds.

transportPriority Int Corresponds to DDSTransportPriorityQosPolicy.value.An integer representing the transport priority.

writerDataLifecycleAutodispose Boolean Corresponds to DDSWriterDataLifecycleQosPolicy.autodispose_unregistered_instances

3.4 Content of Camel Exchanges

Each Camel Exchange produced by the DDS endpoint contains the data as body of the IN message. The data hasfor its type the Java class representing the Topic Type.

Note that this data might be ‘invalid’ ( i.e. with some members not set, or with dummy values), if the instancestate changes. See the Vortex OpenSplice reference guide for more details (ReaderDataLifecycleQos chapter).This can be checked with the SampleInfo.valid_data boolean (see below).

The IN message contains the following information as headers:

Name Type DescriptionDDS_SAMPLE_INFO DDS.SampleInfo The SampleInfo object read

by the DDS Reader with thedata.

DDS_DISPOSE com.prismtech.gateway.camelospl.DdsDisposeHeader This header is present onlyif the instance was disposed.In such a case it’s set eitherto DISPOSE if the body ofthe message contains invaliddata, or to WRITEDISPOSEif the body of the messagecontains the last valid datasent by the publisher beforethe disposal.

3.5 Example of route

Below is an example of a simple Camel route definition from a DDS endpoint to a Processor displaying the data:

final String fromURI ="dds:ChatMessage:0/Chat.ChatMessage?ReliabilityKind=RELIABLE&Partition=ChatRoom";

final CamelContext ctx = new DefaultCamelContext();ctx.addRoutes(new RouteBuilder() {

public void configure() {// from DDS endpoint to a Processor displaying the received message.from(fromURI).process(new Processor() {

public void process(Exchange e) {Chat.ChatMessage msg = (Chat.ChatMessage) e.getIn().getBody();String content = msg.content;System.out.println(content);

}});

}});

ctx.start();

3.4. Content of Camel Exchanges 10

User Guide, Release 2.3.1

In this example the DDS endpoint subscribes to the ‘ChatMessage‘ topic in DDS Domain ‘0‘ using DDS partition‘ChatRoom‘. The topic Reliability QoS is set to ‘RELIABLE‘.

3.6 Dynamic DDS QoS changes

The camel-ospl component offers the possibility to change at runtime some of the DDS QoS which are used bythe Vortex OpenSplice entities (Publisher, Subscriber, DataWriter or DataReader).

3.6.1 Publisher / DataWriter changeable QoS

The Publisher and DataWriter DDS entities are managed by a com.prismtech.gateway.camelospl.DdsProducerclass which implements the org.apache.camel.Producer interface.

The following operations can be used at runtime to change some of the DDS QoS used for subsequent Camelexchanges:

• public void changeDeadlinePeriod(double period) throws DdsException;

• public void changeLatencyDuration(double duration) throws DdsException;

• public void changeOwnershipStrength(int strength) throws DdsException;

• public void changeTransportPriority(int priority) throws DdsException;

• public void changeLifespanDuration(double duration) throwsDdsException;

• public void changePartition(String partitionStr) throws DdsException;

Example of usage:

final String toURI ="dds:ChatMessage:0/Chat.ChatMessage?Partition=ChatRoom-1";

final CamelContext ctx = new DefaultCamelContext();final DdsProducer toProducer =(DdsProducer) ctx.getEndpoint(toURI).createProducer();ctx.addRoutes(new RouteBuilder() {

public void configure() {from("...") // from any endpoint.process(toProducer); // equivalent to: .to(toUri);

}});

// ... later, change the partition used by the DdsProducer's entitiestoProducer.changePartition("ChatRoom-2");

3.6.2 Subscriber / DataReader changeable QoS

The Subscriber and DataReader DDS entities are managed by the classcom.prismtech.gateway.camelospl.DdsConsumer which implements the org.apache.camel.Consumer inter-face.

The following operations can be used at runtime to change some of the DDS QoS used for subsequent Camelexchanges:

• public void changeDeadlinePeriod(double period) throws DdsException;

• public void changeLatencyDuration(double duration) throws DdsException;

3.6. Dynamic DDS QoS changes 11

User Guide, Release 2.3.1

• public void changeTimebasedFilter(double timebasedFilter) throwsDdsException;

• public void changePartition(String partitionStr) throws DdsException;

Example of usage:

final String toURI ="dds:ChatMessage:0/Chat.ChatMessage?Partition=ChatRoom-1";

final CamelContext ctx = new DefaultCamelContext();ctx.addRoutes(new RouteBuilder() {

public void configure() {from(fromURI).routeId("ChatRoute") //give an ID to the Route for later retrieval.process(new Processor() {

public void process(Exchange e) {Chat.ChatMessage msg = (Chat.ChatMessage)e.getIn().getBody();String content = msg.content;System.out.println(content);

}});

}});

// ... later, change the partition for the DdsConsumer's entitiesDdsConsumer ddsConsumer =

(DdsConsumer) ctx.getRoute("ChatRoute").getConsumer();ddsConsumer.changePartition("ChatRoom-2");

3.6.3 Per-message changes

It is also possible to change some of the Producer QoS on-the-fly for a single message. To do this, add thefollowing headers to the Camel message sent to a DDS Producer:

Header name Header valuedds.ownershipStrength An integer representing the ownershipStrength value to be used for this

message.dds.transportPriority An integer representing the transportPriority value to be used for this

message.dds.lifespanDuration A float representing the lifespanDuration value (in seconds) to be used

for this message.

Example of usage:

// A route publishing Alarms to DDS and changing the// transportPriority QoS depending the alarm levelfrom("...").choice()

.when().groovy("request.body.alarmLevel == 'LOW'").setHeader("dds.transportPriority", constant(1))

.when().groovy("request.body.alarmLevel == 'HIGH'").setHeader("dds.transportPriority", constant(3))

.endChoice()

.to("dds:Alarms:0/com.prismtech.demo.AlarmType");

3.7 Camel Messages mode

This mode allows Camel Messages to be exchanged via DDS. This includes the Message’s headers, attachmentsand body, providing they contain only Serializable Java objects.

This mode is activated when you don’t specify a topicClass in the endpoint URI.

3.7. Camel Messages mode 12

User Guide, Release 2.3.1

Below is an example of Camel Messages mode usage, with a Java String as the message body:

final String fromURI = "dds:ExampleStrTopic:0/?target=stringTarget";final CamelContext ctx = new DefaultCamelContext();Endpoint endpoint = ctx.getEndpoint(fromURI);// Define the route from DDS endpoint to a Processor// displaying the received data.ctx.addRoutes(new RouteBuilder() {

public void configure() {from(fromURI).process(new Processor() {

public void process(Exchange e) {System.out.println((String)e.getIn().getBody());

}});

}});

// create a ProducerTemplateProducerTemplate template = ctx.createProducerTemplate();

// use ProducerTemplate to send Exchange to DDS endpointtemplate.send(endpoint, new Processor() {

public void process(Exchange exchange) {exchange.getIn().setBody("Hello World!");

}});

The ‘target‘ option used in the URI is specific to the Camel Messages mode. This extra value is sent through DDSwith the Camel message and allows consuming routes to filter messages according to this ‘target‘ value.

3.8 DDS Polling Consumer

The Vortex OpenSplice endpoint provides a DDSPollingConsumer implementation allowing it to wait for incom-ing DDS data. Hence the caller can poll for messages when it is ready.

The DDSPollingConsumer implements the three polling methods of the Camel PollingConsumer interface inaddition to three other polling methods that allow the caller to specify some DDS specific options in order toselect the set of data to be read.

Method Name Descriptionreceive() Waits until a message is available

and then returns it; potentiallyblocking forever.

receive(Map<String, Object> options)receive(long timeout) Waits up to the given timeout and

returns null if no message is receivedwithin the given timeout.

receive(Map<String, Object> options,long timeout)receiveNoWait() Reads a message immediately without

waiting and returns null if no messageis received.

receiveNoWait(Map<String, Object>options)

The ‘options‘ parameter can express the states of the DDS messages to be read as well as a condition that allowsit to read the messages with content-based filtering. The options map keys correspond to the headers namesdescribed in the table in DynamicPollEnricher.

Note that the DDSPollingConsumer performs a DDS read() operation and not a take() operation. It meansthat the data is kept in the DDS middleware and can be read again if necessary.

Below is an example of how to use the DDS PollingConsumer.

// Getting the DDS topicA endpointEndpoint ddsEndpointA = camelContext.getEndpoint("dds:topicA:0/TypeA");

3.8. DDS Polling Consumer 13

User Guide, Release 2.3.1

// Create PollingConsumer to poll data from topicADynamicPollingConsumer pollConsumer =

(DynamicPollingConsumer) ddsEndpointA.createPollingConsumer();

// Setting the polling options : only not read and alive samples

Map<String, Object> conditions = new HashMap<String, Object>();conditions.put("DDS_SAMPLE_STATE", NOT_READ_SAMPLE_STATE.value);conditions.put("DDS_INSTANCE_STATE", ALIVE_INSTANCE_STATE.value);

long wait_timeout = 3000; // milliseconds

// Polling for topicA messages with the given optionsExchange e = pollConsumer.receive(conditions, wait_timeout);if (e != null) {

// to process the message} else {

// TIMEOUT}

3.9 Additional Apache Camel Processors

3.9.1 DynamicPollEnricher

Apache Camel already provides a pollEnrich pattern (see http://camel.apache.org/content-enricher.html ) allowing in a Camel route to enrich an incoming message with data froma PollingConsumer.

But with current Camel versions (2.7.0 and older), the pollEnrich pattern is not able to extract information fromcurrent exchange to influence the polling ( e.g. to poll data with the same key as in the received message). Seehttps://issues.apache.org/jira/browse/CAMEL-4163 for more information about this limita-tion.

We have therefore introduced a new class com.prismtech.gateway.camelext.DynamicPollEnricher which can beused as a Camel Processor. This Processor implements the missing feature of pollEnricher , passing incomingmessages’ headers to a specific implementation of PollingConsumer for DDS endpoint creating a DDSQueryCon-dition according to the headers’ options and calling DataReader.read_w_condition() .

Note that the DynamicPollEnricher uses a non blocking operation of the PollingConsumer to receive the messages.If no message is available yet, it returns immediately with a null exchange.

By default the DynamicPollEnricher class uses the reply from PollingConsumer as outgoing message. But anotherAggregationStrategy can be set to merge the reply with original incoming message. Use the operation PollingCon-sumer.setAggregationStrategy() to set another strategy.

The accepted header options are:

Name Type DescriptionDDS_SAMPLE_STATE int A mask of matching SampleStates.

Default value is DDS.ANY_SAMPLE_STATE.valueDDS_VIEW_STATE int A mask of matching ViewStates.

Default value is DDS.ANY_VIEW_STATE.valueDDS_INSTANCE_STATE int A mask of matching InstanceStates.

Default value is DDS.ANY_INSTANCE_STATE_valueDDS_QUERY_EXPRESSION String A query expression.

Default value is null (meaning a ReadCondition is usedinstead of a QueryCondition ).

DDS_QUERY_PARAMETERS String[] An array of query parameters.Default value is an empty array.

3.9. Additional Apache Camel Processors 14

User Guide, Release 2.3.1

Below is an example of the DynamicPollEnricher class:

// Some DDS endpoints. Messages come from topicA and have to be enriched// by matching data from topicB.Endpoint ddsEndpointA = camelContext.getEndpoint("dds:topicA:0/TypeA");Endpoint ddsEndpointB = camelContext.getEndpoint("dds:topicB:0/TypeB");

// Create PollingConsumer to poll data from topicBDynamicPollingConsumer pollConsumer =

(DynamicPollingConsumer) ddsEndpointB.createPollingConsumer();

// Create PollEnricher to be used on route from topicA,// thus getting matching data from topicBDynamicPollEnricher pollEnricher = new

DynamicPollEnricher(pollConsumer);

// Set custom strategy, creating a TypeC from a TypeA + TypeBpollEnricher.setAggregationStrategy(new AggregationStrategy() {

@Overridepublic Exchange aggregate(Exchange oldExchange, Exchange newExchange){

// get TypeA and TypeBTypeA a = (TypeA) oldExchange.getIn().getBody();TypeB b = (TypeB) newExchange.getIn().getBody();// create TypeCTypeC c = new TypeC(a,b);// replace oldExchange's body with TypeC and return itoldExchange.getIn().setBody(c);return oldExchange;

}});

// Route from TopicA topic to the PollEnricher getting a TopicB sample// with TopicA.index = TopicB.index and aggregating both as a NamedMessage.from(ddsEndpointA)// Query expression to get TopicB with index = first param.setHeader("DDS\_QUERY\_EXPRESSION", constant("index=%0"))// Query param: use Groovy to get TopicA.index and create String array.setHeader("DDS\_QUERY\_PARAMETERS").groovy("[request.body.index.toString()]")// send message with headers to pollEnricher.process(pollEnricher)// now display resulting message (TypeC is expected).process(new Processor() {

public void process(Exchange e) {System.out.println((TypeC)e.getIn().getBody());

}});

For another example of DynamicPollEnricher usage, look at Vortex Gateway’s examples/shape-java code. Itcontains an example of a route from a Circle topic, polling correlated data from a Square topic (the same color)and computing an average position between circle and square shapes.

3.9. Additional Apache Camel Processors 15

4The Camel DDSI Component

As the camel-ospl component, the Camel DDSI component (named camel-ddsi) allows messages to be written toa DDS Topic via a Camel route; or messages to be received from a DDS Topic via a Camel route.

This component doesn’t require Vortex OpenSplice. It uses a Java implementation of the DDSI standard protocolto exchange DDS messages with any DDS participant. Using this component, it is possible to deploy Gateway ina pure-Java environment or to a platform not supported by Vortex OpenSplice.

Moreover, with camel-ddsi you can easily create bridges across multiple DDS Domains (see the example in SeeDDSI Endpoint configuration).

4.1 DDSI Maven configuration

If you look at the pom.xml file generated by the Vortex Gateway’s archetype for camel-ddsi, you will see thefollowing declarations which are required for your Maven project:

<dependencyManagement><dependencies>

<!-- Import Gateway's dependencyManagement. --><!-- Thus all dependencies used by Gateway are --><!-- referenced with appropriate version numbers. --><dependency>

<groupId>com.prismtech.gateway</groupId><artifactId>parent-pom</artifactId><type>pom</type><scope>import</scope><version>${gateway-version}</version>

</dependency></dependencies>

</dependencyManagement>

This is to import all version numbers of dependencies the Gateway might use. Thus, when your project requires adependency that Gateway has been tested with, you don’t have to specify its version number again.

<dependencies><!-- Gateway's Camel DDSI endpoint --><dependency>

<groupId>com.prismtech.gateway</groupId><artifactId>camel-ddsi</artifactId><version>${gateway-version}</version>

</dependency></dependencies>

This is an explicit dependency of your project on Vortex Gateway’s camel-ddsi component. Dependencies onApache Camel’s artefacts are implied, since camel-ddsi depends on those artefacts.

<build><plugins>

<!-- Sun's JDK IDL compilation plugin --><plugin>

16

User Guide, Release 2.3.1

<groupId>org.codehaus.mojo</groupId><artifactId>idlj-maven-plugin</artifactId><version>1.1</version><executions>

<execution><goals>

<goal>generate</goal></goals>

</execution></executions>

</plugin></plugins>

</build>

The idlj-maven-plugin is used by Maven at the ‘generate-sources’ phase to process all IDL files placed in thesrc/main/idl directory and generate Java classes for DDS types. This plugin dependency is not required whenusing the camel-ddsi component. It should be used only if you want to marshal/unmarshal the DDSI messagesreceived from or sent to a camel-ddsi endpoint (see DDSI messages marshalling/unmarshalling).

4.2 DDSI Endpoint configuration

An Apache Camel endpoint using DDSI is configured using following URI format:

ddsi:topicName:domainID/topicClass[?options]

Where topicName is the DDS topic name to publish or subscribe, domainID is the DDS domain identifier, andtopicClass is the java-scoped name of the topic type.

Options is a list of optional parameters, separated by ‘&‘ characters; for example:

?option1=value1&option2=value2&...

The following options are accepted:

Name Type DescriptionregisterType String Specify the name to use for type registration.

If not specified, the type is registered with the topicClass namename, replacing all . with ::. E.g. for class com.foo.MyTypethe name is com::foo::MyType

partition String Corresponds to DDS PartitionQosPolicy.name.A list of DDS partitions, separated by , characters.

reliabilityKind String Corresponds to DDS ReliabilityQosPolicy.kind.Possible values:

• RELIABLE• BEST_EFFORT

networkInterface String Configure the DDSI protocol to use a specific network interface.Possible values are:

• auto: Let the softwareautomatically choose a suitable network interface (this is the defaultvalue). - a short ‘Unix-like’ interface name ( e.g. eth0 , wlan1 ,etc. ) - the IP address of the network interface. - on Windows plat-forms : a connection name (e.g. Local Area Connection).

TCP Boolean Activate DDSI over TCP protocol.See DDSI over TCP.

TCPPort Int Configure the discovery port for DDSI over TCP protocol.See DDSI over TCP.

TCPRemoteHosts String Configure the remote hosts to discover for DDSI over TCP protocol.See DDSI over TCP.

4.2. DDSI Endpoint configuration 17

User Guide, Release 2.3.1

In addition, the following options are also available to set QoS at topic level, but only for creation of new topics inthe system. I.e.: the camel-ddsi endpoint will first try to find an existing topic with the specified name and type. Ifthe topic is found, its QoS are not changed (meaning the options below are not applied). If the topic is not found,it is created with the specified topic QoS.

4.2. DDSI Endpoint configuration 18

User Guide, Release 2.3.1

Name Type DescriptiondurabilityKind String Corresponds to DDS

DurabilityQosPolicy.kind.Possible values:

• VOLATILE• TRANSIENT• TRANSIENT_LOCAL• PERSISTENT

TopicDeadlinePeriod Double Corresponds to DDSDeadlineQosPolicy.period.A float representing a time in seconds.

TopicDestinationOrder String Corresponds to DDSDestinationOrderQosPolicy.kind.Possible values:

• BY_RECEPTION_TIMESTAMP• BY_SOURCE_TIMESTAMP

TopicDurabilityKind String Corresponds to DDSDurabilityQosPolicy.kind.Possible values:

• VOLATILE• TRANSIENT• TRANSIENT_LOCAL• PERSISTENT

TopicDurabilityServiceCleanupDelay Double Corresponds to DDSDurabilityServiceQosPolicy.service_cleanup_delayA float representing a time in seconds.

TopicDurabilityServiceDepth Int Corresponds to DDSDurabilityServiceQosPolicy.history_depthAn integer representing the history depth.

TopicDurabilityServiceKind String Corresponds to DDSDurabilityServiceQosPolicy.history_kindPossible values:

• KEEP_ALL• KEEP_LAST

TopicDurabilityServiceMaxInstances Int Corresponds to DDSDurabilityServiceQosPolicy.max_instancesAn integer representing the maximum numberof instances.

TopicDurabilityServiceMaxSamples Int Corresponds to DDSDurabilityServiceQosPolicy.max_samplesAn integer representing the maximum numberof samples.

TopicDurabilityServiceMaxSamplesPerInstance Int Corresponds to DDSDurabilityServiceQosPolicy.max_samples_per_instanceAn integer representing the history depth.

TopicHistoryDepth String Corresponds to DDSHistoryQosPolicy.depth.An integer representing the maximum numberof samples per instance.

TopicHistoryKind String Corresponds to DDSHistoryQosPolicy.kind.Possible values:

• KEEP_ALL• KEEP_LAST

TopicLatencyDuration Double Corresponds to DDSLatencyBudgetQosPolicy.duration.A float representing a time in seconds.

TopicLifespanDuration Double Corresponds to DDSLifespanQosPolicy.duration.A float representing a time in seconds.

TopicLivelinessDuration Double Corresponds to DDSLivelinessQosPolicy.lease_duration.A float representing a time in seconds.

TopicLivelinessKind String Corresponds to DDSLivelinessQosPolicy.kind.Possible values:

• AUTOMATIC• MANUAL_BY_PARTICIPANT• MANUAL_BY_TOPIC

TopicOwnershipKind String Corresponds to DDSOwnershipQosPolicy.kind.Possible values:

• SHARED• EXCLUSIVE

TopicOwnershipStrength String Corresponds to DDSOwnershipStrengthQosPolicy.value.An integer representing the ownershipstrength.

TopicReliabilityBlockingTime Double Corresponds to DDSReliabilityQosPolicy.max_blocking_timeA float representing a time in seconds.

TopicReliabilityKind String Corresponds to DDSReliabilityQosPolicy.kind.Possible values:

• RELIABLE• BEST_EFFORT

TopicResourceLimitsMaxInstances Int Corresponds to DDSResourceLimitsQosPolicy.max_instancesAn integer representing the maximum numberof instances.

TopicResourceLimitsMaxSamples Int Corresponds to DDSResourceLimitsQosPolicy.max_samples.An integer representing the maximum numberof samples.

TopicResourceLimitsMaxSamplesPerInstance Int Corresponds to DDSResourceLimitsQosPolicy.max_samples_per_instanceAn integer representing the maximum numberof samples per instance.

TopicTransportPriority Int Corresponds to DDSTransportPriorityQosPolicy.value.An integer representing the transport priority.

4.2. DDSI Endpoint configuration 19

User Guide, Release 2.3.1

4.3 Content of Camel Exchanges

Each Camel Exchange produced by the DDSI endpoint contains a byte buffer as the body of the IN message. Thisbyte buffer is the serialized form of the data (see DDSI message’s body, for more details).

Note that this data might be ‘invalid’ ( i.e. with a null body), if the received DDSI message indicates an instancestate change ( e.g. instance disposal). This can be checked with the DdsiMessage.IS_BODY_VALID header (seethe table below).

The IN message contains the following information as headers:

Name Type DescriptionDdsiMessage.TYPE_NAME String The Java class name of the data type.DdsiMessage.IS_BODY_VALID boolean

• True if the message’sbody contains serialized data.

• False if the messageindicates an instance state change.

DdsiMessage.CHANGE_KIND com.prismtech.cafe.ddsi.ChangeKind_t

An enum which can have the followingvalues:

• ALIVE if theinstance is alive

• NOT_ALIVE_DISPOSEDif the instance was disposed

• NOT_ALIVE_UNREGISTEREDif the instance was unregistered

• NOT_ALIVE_DISPOSED_UNREGISTEREDif the instance was disposed and unregis-tered

DdsiMessage.READER_TIME org.omg.dds.core.Time The time at which the DataReader receivedthe DDSI message.

4.4 Example of route

Below is an example of DDS Domain bridging using DDSI. For the specified topic with RELIABLE QoS, the DDSsamples are transferred from Domain 0 to Domain 1:

ctx = new DefaultCamelContext();ctx.addRoutes(new RouteBuilder() {

public void configure() {// from DDSI endpoint on Domain 0 to DDSI endpoint on Domain 1.from("ddsi:MyTopic:0/com.foo.MyType?ReliabilityKind=RELIABLE").to("ddsi:MyTopic:1/com.foo.MyType?ReliabilityKind=RELIABLE");

}});ctx.start();

4.5 DDSI message’s body

The DDSI specification (Chapter 10) describes how the DDS data are serialized in a byte buffer:

1.............8..............16..............24..............32+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| encoding flag | encoding options |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| |~ Serialized Data ~

4.3. Content of Camel Exchanges 20

User Guide, Release 2.3.1

| |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Where ‘encoding flag‘ is either of:

• 0x0000 for CDR_BE (Serialized Data is encoded with OMG CDR Big Endian)

• 0x0001 for CDR_LE (Serialized Data is encoded with OMG CDR Little Endian)

The ‘encoding options‘ bytes are not used yet.

The camel-ddsi endpoint uses this format as Camel message’s body.

In Consumer mode (using from(“ddsi:...”) statement) the Camel exchange sent on the Camel route contains aserialized byte buffer as IN body.

In Producer mode (using to(“ddsi:...”) statement) the Camel exchange is expected to contain a serialized bytebuffer as IN body.

For easier usage, Vortex Gateway provides the Camel TypeConverters from/to the following types:

• java.nio.ByteBuffer

• org.jboss.netty.buffer.ChannelBuffer

Both are utility classes wrapping a byte array. The TypeConverters are zero-copy and set the correct endian-nessvalue to the Buffer object depending on the ‘encoding flag‘ value.

Example of usage:

from("ddsi:MyTopic:0/com.foo.MyType").process(new Processor() {

@Overridepublic void process(Exchange exchange) throws Exception {

ByteBuffer buf = exchange.getIn().getBody(ByteBuffer.class);// We want to change the value of the first data member with is an int// Skip the 4-bytes for encoding flagsbuf.position(buf.position()+4);// mark position to overwrite valuesbuf.mark();// read color lengthint val = buf.getInt();// go back to mark and write modified valuesbuf.putInt(val+1);

}}).to("ddsi:MyModifiedTopic:0/com.foo.MyType");

4.6 DDSI messages marshalling/unmarshalling

Vortex Gateway also provides the way to marshal/unmarshal DDSI messages from/to Java types generated fromthe IDL definition of DDS types.

To use such marshal/unmarshal feature, you have to copy your IDL files into the src/main/idl directory of yourMaven project, and the idlj-maven-plugin (see DDSI Maven configuration) will generate the corresponding Javaclasses.

Then you can use the Camel marshal(“cdr”) and unmarshal(“cdr”) statements as in following example:

from("ddsi:MyTopic:0/com.foo.MyType").unmarshal("cdr") // unmarshal the received buffer to com.foo.MyType.process(new Processor() {

@Overridepublic void process(Exchange exchange) throws Exception {

// the IN body is now a com.foo.MyType object

4.6. DDSI messages marshalling/unmarshalling 21

User Guide, Release 2.3.1

MyType t = exchange.getIn().getBody(MyType.class);// modify some value of the datat.my_param += 1;

}})// re-marshal the com.foo.MyType object to be sent on DDSI.marshal("cdr").to("ddsi:MyModifiedTopic:0/com.foo.MyType");

4.7 DDSI over TCP

Vortex Gateway also provides an implementation of the DDSI protocol using TCP instead of UDP, and thus notusing multicast.

NOTE : The DDSI over TCP protocol is not yet standardized by the O.M.G., and this implementationis experimental. It is subject to changes in future releases and we can’t guarantee that the currentversion will inter-operate with future versions or with other implementations of a DDSI over TCPprotocol. However, all the products of a same version of the Vortex family will inter-operate usingthe DDSI over TCP protocol.

This implementation does not provide dynamic discovery. Each endpoint has to be configured with the addressesand ports of all remote endpoints that might be started in the system.

The following options can be used to configure a DDSI endpoint to use DDSI over TCP:

Name Type DescriptionTCP Boolean Activate DDSI over TCP protocol.

Default value is falseTCPPort Int If you create several DDSI endpoints using TCP on the same host,

they need to use different port numbers. Use this option to configurethe port number of your endpoint.Default value is 7400

TCPRemoteHosts String Configure a list of remote addresses/ports the endpoint will try todiscover. Addresses must be in <IP>:<port> format and must beseparated by , characters.Default is an empty list ( i.e. the DDSI endpoint will not try todiscover other endpoints. It will only communicate with endpointswhich are configured to discover it).

Below is an example of two routes configured to communicate via DDSI over TCP:

// On host 10.10.10.1: a route publishing to DDSI// the endpoint uses port 123456, and will communicate with// 10.10.10.2:45678from("...").to("ddsi:MyTopic:1/com.foo.MyType?TCP=true&TCPPort=123456&TCPRemoteHosts=10.10.10.2:45678");// on host 10.10.10.2: a route subscribing to DDSI// the endpoint uses port 45678, and will not try to discover any onefrom("ddsi:MyTopic:1/com.foo.MyType?TCP=true&TCPPort=45678").to("...");

4.7. DDSI over TCP 22

5Troubleshooting

If you experience any problems with Vortex Gateway installation or usage then you can contact PrismTech support.

Please provide a full description of your platform, including the versions of tools you are using (such as JDK,Maven, Camel, etc. ).

23

6Contacts & Notices

6.1 Contacts

PrismTech Corporation400 TradeCenterSuite 5900Woburn, MA01801USATel: +1 781 569 5819

PrismTech LimitedPrismTech House5th Avenue Business ParkGatesheadNE11 0NGUKTel: +44 (0)191 497 9900

PrismTech France28 rue Jean Rostand91400 OrsayFranceTel: +33 (1) 69 015354

Web: http://www.prismtech.com

E-mail: [email protected]

6.2 Notices

copyright 2015 PrismTech Limited. All rights reserved.

This document may be reproduced in whole but not in part. The information contained in this document is subjectto change without notice and is made available in good faith without liability on the part of PrismTech Limited orPrismTech Corporation. All trademarks acknowledged.

24