Solace Hello World
16 Minute Read
Assumptions
This tutorial assumes the following:
-
You are familiar with OpenMAMA core concepts.
- If not, see this guide.
- You are familiar with Solace core concepts.
-
You have access to a properly installed OpenMAMA release.
- Solace middleware bridge with its dependencies is also installed
-
You have access to Solace messaging with the following configuration details:
- Connectivity information for a Solace message-VPN
- Enabled client username and password
One simple way to get access to Solace messaging quickly is to create a messaging service in Solace Cloud as outlined here. You can find other ways to get access to Solace messaging below.
Goals
The goal of this tutorial is to demonstrate the most basic messaging interaction using OpenMAMA with the Solace middleware bridge. This tutorial is similar to the OpenMAMA Quick Start Guide and the OpenMAMA Example Walk Through, but with a distinct focus on configuring OpenMAMA with Solace messaging. See the Resources section below for some further links to other OpenMAMA tutorials and examples.
This tutorial will show you how to publish a message with one string field to a specific topic with Solace messaging using OpenMAMA C API.
Installation
Installation instructions for OpenMAMA can be found on OpenMAMA Wiki.
Simplified installation instructions for OpenMAMA with Solace middleware bridge are available here.
For building OpenMAMA from source see OpenMAMA Wiki.
Get Solace Messaging
This tutorial requires access Solace PubSub+ messaging and requires that you know several connectivity properties about your Solace messaging. Specifically you need to know the following:
Resources | Value | Description |
---|---|---|
Host | String | This is the address clients use when connecting to the PubSub+ messaging to send and receive messages. (Format: DNS_NAME:Port or IP:Port ) |
Message VPN | String | The PubSub+ message router Message VPN that this client should connect to. |
Client Username | String | The client username. (See Notes below) |
Client Password | String | The client password. (See Notes below) |
There are several ways you can get access to PubSub+ Messaging and find these required properties.
Option 1: Use PubSub+ Cloud
- Follow these instructions to quickly spin up a cloud-based PubSub+ messaging service for your applications.
-
The messaging connectivity information is found in the service details in the connectivity tab (shown below). You will need:
- Host:Port (use the SMF URI)
- Message VPN
- Client Username
- Client Password
Option 2: Start a PubSub+ Software
-
Follow these instructions to start the PubSub+ Software in leading Clouds, Container Platforms or Hypervisors. The tutorials outline where to download and how to install the PubSub+ Software.
-
The messaging connectivity information are the following:
-
Host: <public_ip> (IP address assigned to the VMR in tutorial instructions)
-
Message VPN: default
-
Client Username: sampleUser (can be any value)
-
Client Password: samplePassword (can be any value)
Note: By default, the PubSub+ Software "default" message VPN has authentication disabled.
-
Option 3: Get access to a PubSub+ Appliance
-
Contact your PubSub+ appliance administrators and obtain the following:
- A PubSub+ Message-VPN where you can produce and consume direct and persistent messages
- The host name or IP address of the Solace appliance hosting your Message-VPN
- A username and password to access the Solace appliance
Hello World
In our first program we’re going to publish one “Hello World” message to a specific topic on Solace messaging using OpenMAMA with the Solace middleware bridge.
The program will consist of two major parts:
- Initialize Solace middleware bridge
- Publish Message
Initialize
Any OpenMAMA program begins with initialization that consists of loading a bridge and opening it, in this particular order:
- load
- open
This is how it is done.
Begin by declaring the bridge pointer:
mamaBridge bridge = NULL;
Then we need to load the bridge, referring to it by its name (“solace”), and open it by calling mama_open()
:
mama_loadBridge(&bridge, "solace");
mama_open();
Opening of the bridge must have a corresponding closing mama_close()
call:
mama_close();
This is already a program that can be compiled and executed, let’s add to it some console messages that would help us to watch it running, and some rudimentary error handling.
#include <stdio.h>
#include <mama/mama.h>
int main(int argc, const char** argv)
{
printf("Solace OpenMAMA tutorial.\nPublishing one message with OpenMAMA.\n");
mama_status status;
mamaBridge bridge = NULL;
// load Solace middleware bridge and open it
if (((status = mama_loadBridge(&bridge, "solace")) == MAMA_STATUS_OK) &&
((status = mama_open()) == MAMA_STATUS_OK))
{
printf("Closing Solace middleware bridge.\n");
mama_close();
// normal exit
exit(0);
}
printf("OpenMAMA error: %s\n", mamaStatus_stringForStatus(status));
exit(status);
}
At this point our program needs to be linked with libmama
(libmamac
or libmamacmdd
on Windows) and it requires OpenMAMA headers to compile.
On Linux, assuming OpenMAMA installed into /opt/openmama
:
$ gcc -o topicPublishOne topicPublishOne.c -I/opt/openmama/include -L/opt/openmama/lib -lmama
On Windows, assuming OpenMAMA is at <openmama>
directory:
$ cl topicPublishOne.c /I<openmama>\mama\c_cpp\src\c /I<openmama>\common\c_cpp\src\c\windows -I<openmama>\common\c_cpp\src\c <openmama>\Debug\libmamacmdd.lib
When we run this program, it seems like nothing happened:
$ ./topicPublishOne
Solace OpenMAMA tutorial.
Publishing one message with OpenMAMA.
2016-07-12 13:58:27: Failed to open properties file.
2016-07-12 13:58:27:
********************************************************************************
Note: This build of the MAMA API is not enforcing entitlement checks.
Please see the Licensing file for details
**********************************************************************************
Closing Solace middleware bridge.
But in fact OpenMAMA has successfully initialized with the Solace middleware bridge and is ready to publish a message.
Publish Message
You have definitely noticed the “Failed to open properties file”
log message (if it appears twice, ignore one of them, it is a well known OpenMAMA pickle.
It means that MAMA at run-time is looking for the properties file and we will create that file a bit later.
At this point we can successfully load the Solace middleware bridge and open it, which means a successful initialization of OpenMAMA. Now we can publish a message.
In order to publish a message we need to do the following in this particular order:
- Create a transport for the Solace middleware bridge
- Create a publisher that uses this transport
- Create a message
- Use the publisher to send the message
Create transport
Creating of transport includes two steps in this particular order:
- allocate
- create
mamaTransport transport = NULL;
mamaTransport_allocate(&transport);
mamaTransport_create(transport, "vmr", bridge);
Notice the name of the transport: “vmr”
. This is the alias we will refer to from the properties file.
Don’t forget to destroy the transport before closing the bridge:
mamaTransport_destroy(transport);
This is how our program looks now, let’s compile and run it.
#include <stdio.h>
#include <mama/mama.h>
int main(int argc, const char** argv)
{
printf("Solace OpenMAMA tutorial.\nPublishing one message with OpenMAMA.\n");
mama_status status;
mamaBridge bridge = NULL;
// load Solace middleware bridge and open it
if (((status = mama_loadBridge(&bridge, "solace")) == MAMA_STATUS_OK) &&
((status = mama_open()) == MAMA_STATUS_OK))
{
// create transport
mamaTransport transport = NULL;
if (((status = mamaTransport_allocate(&transport)) == MAMA_STATUS_OK) &&
((status = mamaTransport_create(transport, "vmr", bridge)) == MAMA_STATUS_OK))
{
printf("Closing Solace middleware bridge.\n");
mamaTransport_destroy(transport);
mama_close();
// normal exit
exit(0);
}
}
printf("OpenMAMA error: %s\n", mamaStatus_stringForStatus(status));
exit(status);
}
Now our program runs with a failure when creating of the Solace middleware bridge transport, the failure error code is STATUS_PLATFORM
:
2016-06-28 14:08:11: Warn SOLACE-MW-Bridge: (mama/c_cpp/src/c/bridge/solace/logging.c:129): [API] solClientOS.c:3394 (7f1192289700) TCP connection failure for fd 7, error = Connection refused (111)
2016-06-28 14:08:11: Warn SOLACE-MW-Bridge: (mama/c_cpp/src/c/bridge/solace/logging.c:129): [API] solClient.c:11775 (7f1192289700) Session '(c0,s1)' error attempting transport connection, client name 'localhost.localdomain/13964/#00000001', peer address 'IP 127.0.0.1:55555', connection 'tcp_TxRx' local address 'IP 127.0.0.1:57885'
2016-06-28 14:08:11: Warn SOLACE-MW-Bridge: (mama/c_cpp/src/c/bridge/solace/logging.c:129): [API] solClient.c:11276 (7f1192289700) Protocol or communication error when attempting to login for session '(c0,s1)'; are session HOST and PORT correct? client name 'localhost.localdomain/13964/#00000001', peer address 'IP 127.0.0.1:55555', connection 'tcp_TxRx' local address 'IP 127.0.0.1:57885'
2016-06-28 14:08:11: Warn SOLACE-MW-Bridge: (mama/c_cpp/src/c/bridge/solace/transport.c:480): Error in solClient_session_connect() - ReturnCode='Not ready', SubCode='SOLCLIENT_SUBCODE_COMMUNICATION_ERROR', ResponseCode=0, Info='solClientOS.c:3394 (7f1192289700) TCP connection failure for fd 7, error = Connection refused (111)'
OpenMAMA error: STATUS_PLATFORM
This means we cannot go on without configuring a transport for the Solace middleware bridge, and that transport is Solace messaging.
Configuring transport for the Solace middleware bridge means creating and editing a configuration file. The recommended name for this file is mama.properties and its location needs to be known to the bridge.
Create a text file named mama.properties and add to it a minimum set of properties for Solace messaging:
mama.solace.transport.vmr.session_host=<host>
mama.solace.transport.vmr.session_username=<client-username>
mama.solace.transport.vmr.session_password=<client-password>
mama.solace.transport.vmr.session_vpn_name=<vpn-name>
mama.solace.transport.vmr.allow_recover_gaps=false
Notice how solace
and vmr
property token names are the same as in mama_loadBridge(&bridge, "solace")
and mamaTransport_create(transport, "vmr", bridge)
calls.
mama.solace.transport.vmr.session_host
isHost
and usually has a value of the host address of your Solace messaging.mama.solace.transport.vmr.session_username
isClient Username
mama.solace.transport.vmr.session_password
is optionalClient Password
mama.solace.transport.vmr.session_vpn_name
isMessage VPN
mama.solace.transport.vmr.allow_recover_gaps
doesn’t have a default value and specifies whether the Solace middleware bridge should override applications settings for recovering from sequence number gaps in subscriptions. Whenallow_recover_gaps
istrue
applications are allowed to specify the gap recovery behaviour. Whenallow_recover_gaps
isfalse
, the gap recovery is disabled for all subscriptions, regardless of applications settings.
Now we need to modify our program to refer to this properties file by its name and location (in the current directory: "."
):
mama_openWithProperties(".","mama.properties");
This is how our program looks now, let’s compile and run it.
#include <stdio.h>
#include <mama/mama.h>
int main(int argc, const char** argv)
{
printf("Solace OpenMAMA tutorial.\nPublishing one message with OpenMAMA.\n");
mama_status status;
mamaBridge bridge = NULL;
// load Solace middleware bridge and open it
if (((status = mama_loadBridge(&bridge, "solace")) == MAMA_STATUS_OK) &&
((status = mama_openWithProperties(".","mama.properties")) == MAMA_STATUS_OK))
{
// create transport
mamaTransport transport = NULL;
if (((status = mamaTransport_allocate(&transport)) == MAMA_STATUS_OK) &&
((status = mamaTransport_create(transport, "vmr", bridge)) == MAMA_STATUS_OK))
{
printf("Closing Solace middleware bridge.\n");
mamaTransport_destroy(transport);
mama_close();
// normal exit
exit(0);
}
}
printf("OpenMAMA error: %s\n", mamaStatus_stringForStatus(status));
exit(status);
}
Now our program runs without any errors and it successfully connects to Solace messaging. If you sleep the main thread before the mamaTransport_destroy(transport)
call, you can see use PubSub+ Manager to see this program as a client connected to Solace messaging.
Create publisher
The only thing we want to happen with this program is to publish the “Hello World” message and for that we need to create a publisher.
A publisher is created for a specific topic (named “tutorial.topic”
in this tutorial) and the already created transport:
mamaPublisher publisher = NULL;
mamaPublisher_create(&publisher, transport, "tutorial.topic", NULL, NULL);
It needs to have a corresponding destroy
call:
mamaPublisher_destroy(publisher);
The publisher is ready, let’s create the message we’re going to publish.
Create message
A message is created with one call, but it is created empty, so we need to add a field with the string "Hello World"
in it.
mamaMsg message = NULL;
mamaMsg_create(&message);
mamaMsg_addString(message, "MyGreetingField", 99, "Hello World");
Notice that our field has a name ("MyGreetingField"
) and a field identifier a.k.a. FID (99
). Both are of arbitrary values in this tutorial, but if your program publishes market data, their values need to be assigned according to the data dictionary.
Send message
At this point the only things left are to send the message and to delete it afterwards to avoid memory leaks:
mamaPublisher_send(publisher, message);
mamaMsg_destroy(message);
This is the final look of our program.
#include <stdio.h>
#include <mama/mama.h>
int main(int argc, const char** argv)
{
printf("Solace OpenMAMA tutorial.\nPublishing one message with OpenMAMA.\n");
mama_status status;
mamaBridge bridge = NULL;
// load Solace middleware bridge and open it
if (((status = mama_loadBridge(&bridge, "solace")) == MAMA_STATUS_OK) &&
((status = mama_openWithProperties(".","mama.properties")) == MAMA_STATUS_OK))
{
// 1\. create transport and 2\. create publisher
mamaTransport transport = NULL;
mamaPublisher publisher = NULL;
if (((status = mamaTransport_allocate(&transport)) == MAMA_STATUS_OK) &&
((status = mamaTransport_create(transport, "vmr", bridge)) == MAMA_STATUS_OK) &&
((status = mamaPublisher_create(&publisher, transport, "tutorial.topic", NULL, NULL)) == MAMA_STATUS_OK))
{
// 3\. create message and add a string field to it
mamaMsg message = NULL;
if (((status = mamaMsg_create(&message)) == MAMA_STATUS_OK) &&
((status = mamaMsg_addString(message, "MyGreetingField", 99, "Hello World")) == MAMA_STATUS_OK))
{
// 4\. send the message
if ((status = mamaPublisher_send(publisher, message)) == MAMA_STATUS_OK)
{
// notice that "destroy" calls are in the opposite order of "create" calls
mamaMsg_destroy(message);
printf("Message published, closing Solace middleware bridge.\n");
mamaPublisher_destroy(publisher);
mamaTransport_destroy(transport);
mama_close();
// normal exit
exit(0);
}
}
}
}
printf("OpenMAMA error: %s\n", mamaStatus_stringForStatus(status));
exit(status);
}
Summarizing
Combining the example source code shown above results in the following source code files:
Building
To build on Linux, assuming OpenMAMA installed into /opt/openmama
:
$ gcc -o topicPublishOne topicPublishOne.c -I/opt/openmama/include -L/opt/openmama/lib -lmama
To build on Windows, assuming OpenMAMA is at <openmama>
directory:
$ cl topicPublishOne.c /I<openmama>\mama\c_cpp\src\c /I<openmama>\common\c_cpp\src\c\windows -I<openmama>\common\c_cpp\src\c <openmama>\Debug\libmamacmdd.lib
Running the application
On Linux:
$ ./topicPublishOne
On Windows:
$ topicPublishOne.exe
Sample output
This is the program’s console output (on Linux):
$ ./topicPublishOne
Solace OpenMAMA tutorial.
Publishing one message with OpenMAMA.
2016-07-13 11:46:10:
********************************************************************************
Note: This build of the MAMA API is not enforcing entitlement checks.
Please see the Licensing file for details
**********************************************************************************
2016-07-13 11:46:10: mamaTransport_create(): No entitlement bridge specified for transport vmr. Defaulting to noop.
Message published, closing Solace middleware bridge.
You can see the message published by listening for it on Solace messaging with the sdkperf_c
utility:
$ ./sdkperf_c -cip=192.168.1.75 -cu=default@default -stl=">" -md
CPU mask currently set to: 0x0003\. To modify use linux cmd: taskset
CPU Speed calculated (Hz): 2980249271
Client naming used:
logging ID = 000001
username = default
vpn = default
client names = sdk generated.
APP NOTICE Wed Jul 13 11:45:59.762 2016 PerfClientCollection.cpp:95 (7f65461f9740) Master random seed used : 261933454
APP NOTICE Wed Jul 13 11:45:59.786 2016 AbstractClientCollection.cpp:1744 (7f65461f9740) Router capabilities: (PFG=1, SFG=1, TEMP=1, JNDI=1, Z=1)
Receiving messages. Ctrl-c to exit.
^^^^^^^^^^^^^^^^^^ Start Message ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Destination: Topic 'tutorial/topic'
Class Of Service: COS_1
DeliveryMode: DIRECT
User Property Map:
Key 'U' (STRING) dfedorov
Key 'H' (STRING) localhost.localdomain
Key 'P' (INT32) 5086
Binary Attachment: len=44
31 01 2f 00 00 00 2a 0c 04 00 63 18 13 65 4d 79 1./...*. ..c..eMy
47 72 65 65 74 69 6e 67 46 69 65 6c 64 00 1c 0e Greeting Field...
48 65 6c 6c 6f 20 57 6f 72 6c 64 00 Hello Wo rld.
^^^^^^^^^^^^^^^^^^ End Message ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Between the Start Message and End Message console output you can see the published message topic 'tutorial/topic'
as Destination and the message with the string field “Hello World” as Binary Attachment.
Congratulations! You have now successfully published a message on Solace messaging using OpenMAMA with the Solace middleware bridge.
Resources
For more information about OpenMAMA:
- The OpenMAMA website
- The OpenMAMA code repository on GitHub
- Chat with OpenMAMA developers and users at Gitter OpenMAMA room
For more information about Solace technology:
- The Solace Developer Portal website
- Get a better understanding of Solace technology
- Ask the Solace community
Other tutorials and related links: