Search Results

TIBCO FTL® Java Quick Start

Quick Start Contents


This quick start guide focuses on a pair of TIBCO FTL sample applications written specifically for TIBCO Cloud Messaging (TCM): one publisher and one subscriber. The two applications also work with the TCM Demo.

Getting Started

Follow the steps below to use the sample applications:

  • Download and install the TIBCO FTL Messaging SDK and Java TCM Samples. This guide will refer to your FTL installation location as <ftl> and the sample location as <ftl-sample-path>.
  • The sample download contains two Java class and source files.
  • Download and install Java 1.8+.
  • Download your tcm-config.yaml (look for this icon ). This guide will refer to the tcm-config.yaml download locations as <tcm-config>. The sample applications do not take any arguments, instead they require your tcm-config.yaml to be present in the current working directory.
  • On Linux and macOS, add the <ftl>/<version>/bin and <ftl>/<version>/lib directories to your path and library path respectively. On Windows you only need to add <ftl>/<version>/bin to your path.
  • Add <ftl>/<version>/lib/tibftl.jar to your CLASSPATH.

Running samples

Below are the instructions for running the pre-built CLASS files included in the samples download.

Linux and macOS

> cd <ftl-sample-path>/java
> cp <tcm-config> $PWD
> java -Djava.library.path=<ftl>/<version>/lib -cp <ftl>/<version>/lib/tibftl.jar:. TcmDemoPub


> set PATH=<ftl>/<version>/bin;%PATH%
> cd <ftl-sample-path>\java
> copy <tcm-config> %CD%
> java -cp <ftl>\<version>\lib\tibftl.jar;. TcmDemoPub

Building samples

Below are the instructions for building the samples from the source files included in the samples download.

Linux and macOS

> cd <ftl-sample-path>/java
> javac -cp <ftl>/<version>/lib/tibftl.jar
> cp <tcm-config> $PWD
> java -Djava.library.path=<ftl>/<version>/lib -cp <ftl>/<version>/lib/tibftl.jar:. TcmDemoPub


> set PATH=<ftl>/<version>/bin;%PATH%
> cd <ftl-sample-path>\java
> javac -cp <ftl>\<version>\lib\tibftl.jar
> copy <tcm-config> %CD%
> java -cp <ftl>\<version>\lib\tibftl.jar;. TcmDemoPub

Description of sample applications


Basic publisher program that demonstrates the use of publishing FTL messages.


Basic subscriber program that demonstrates the use of subscribing to FTL messages.

Run the Subscriber and Publisher at the same time to demonstrate real-time messaging. Stop the Subscriber, run the Publisher, and restart the Subscriber to demonstrate persistence.

Using the FTL SDK

To use the FTL SDK include the library and any third-party dependencies in your source files:

import com.tibco.ftl.*;
import com.tibco.ftl.exceptions.*;

Client Configuration

The data required to configure a connection to the TCM server is available for download from your account Authentication Keys page as a YAML configuration file tcm-config.yaml. A trivial tcm-config.yaml file parser is provided below for illustration purposes.

public static Map<String, String> parseAppConfig(String filename) throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader(new File(filename)));
        Map<String, String> options = new HashMap<String, String>();

        // Parse the tcm-config.yaml file as name: value options. This can be
        // replaced with a YAML parsing library for full features.
        String line;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            if (!line.startsWith("#")) {
                String[] nameValue = line.split(":", 2);
                if (nameValue.length != 2) {
                    throw new Exception(line + " did not split into a name/value pair");
                String name = nameValue[0].trim();
                String value = nameValue[1].trim();
                options.put(name, value);

        // Take the options parsed from tcm.yaml to create the realm properties
        if (options.get("tcm_authentication_id") == null || options.get("tcm_authentication_id").equals("")) {
            throw new Exception("The tcm_authentication_id option is required to connect to TCM");
        if (options.get("tcm_authentication_key") == null || options.get("tcm_authentication_key").equals("")) {
            throw new Exception("The tcm_authentication_key option is required to connect to TCM");
        if (options.get("ftl_certificate") == null || options.get("ftl_certificate").equals("")) {
            throw new Exception("The ftl_certificate option is required to connect to TCM");
        if (options.get("ftl_application") == null || options.get("ftl_application").equals("")) {
            throw new Exception("The ftl_application option is required to connect to TCM");
        if (options.get("ftl_url") == null || options.get("ftl_url").equals("")) {
            throw new Exception("The ftl_url option is required to connect to TCM");
        return options;

Configuring Realm Properties

A properties object allows the client application to set attributes (or properties) for an object when the object is created. Declare realm property variables:

TibProperties   props = null;
props = FTL.createProperties();

A unique client label for each application will make tracking and monitoring easier.


Configuring TCM authentication and server verification

Authentication using TCM specific authentication keys is required. The authentication id and key are located in the tcm-config.yaml.

props.set(Realm.PROPERTY_STRING_USERNAME, options.get("tcm_authentication_id"));
props.set(Realm.PROPERTY_STRING_USERPASSWORD, options.get("tcm_authentication_key"));

Use the trust file PEM certificate included in the tcm-config.yaml to verify the server you are Connect too.

String ftlCert = options.get("ftl_certificate");

The PEM string contained in the tcm-config.yaml is modified to fit on a single line. Replace the ‘\n’ substring with a newline character to obtain a legal PEM string.

ftlCert = ftlCert.replace("\\n", "\n");

Establishing a connection

Establish a connection to TCM. Specify a string containing the realm service URL, a string containing the application name, and the properties object created above. All values required for a FTL realm connection are contained in the tcm-config.yaml

Realm realm = null;
realm = FTL.connectToRealmServer(options.get("ftl_url"), options.get("ftl_application"), props);

Publishing a message

Before a message can be published, the publisher must be created on the previously-created realm. Specify the endpoint onto which the messages will be published. In this example we are using the “default” endpoint.

Publisher pub = null;
pub = realm.createPublisher("default");

In order to send a message, the message object must first be created via a call to realm.CreateMessage(). Specify the format name. Here the format “demo_tcm” is used. TCM only supports dynamic formats.

msg = realm.createMessage("demo_tcm");

A newly-created message is empty - it contains no fields. The next step is to add one or more fields to the message. msg.SetString() adds a string field. In this example a string field named “demo_tcm” is added, with the value “message seq”.

msg.setString("demo_tcm", "message " + seq);

Once the message is complete, it can be sent via pub.Send(). Specify the message to be sent.


Subscribing and receiving messages

Event Queue

For messages to be delivered to a client application, two things are required: 1) A subscriber object must be created on a particular endpoint 2) The created subscriber object must be added to an event queue to dispatch the received messages Before the subscriber object can be added to an event queue, the event queue must exist. So that is the first step. realm.CreateEventQueue() creates an event queue. A properties object can optionally be specified.

queue = realm.CreateEventQueue();


Create the subscriber object by specifying the endpoint name, an optional content matcher, and an optional properties object.

sub = realm.CreateSubscriber("default", contentMatcher, subscriberProps);

The last step is to add the subscriber object to the event queue. This allows the event queue to dispatch messages sent to that subscriber. Specify the subscriber object, and an object which implements SubscriberListener and provides the MessagesReceived method.

queue.addSubscriber(sub, this);


TIBCO Cloud messaging only supports a fixed set of endpoints: default, shared, last-value and map. Each endpoint is associated with a durable type of the same name. If your application does not need persistence use the default endpoint.

Content Matcher

A content matcher is used to limit which messages are delivered to a client application based on the content of the message. The string passed to realm.CreateContentMatcher() contains JSON which specifies the field name in the message, and the required value of that field. In this case, {"demo_tcm":true} matches any message which contains the field demo_tcm.

contentMatcher = realm.CreateContentMatcher("{\"demo_tcm\":true}");

Subscriber Properties

A shared durable essentially acts like a queue. Messages are stored in the persistent server, and apportioned among active subscribers to the durable in a round-robin fashion. Each subscriber must specify the same durable name. The durable name is defined by properties specified when the subscriber is created. If your application does not need persistence do not supply a durable name.

subscriberProps = FTL.createProperties();
subscriberProps.set(Subscriber.PROPERTY_STRING_DURABLE_NAME, "");


For an event queue to dispatch messages, it must be run on a thread. That thread may be separately created and managed, or it may be the main program thread - as it is in this sample.

The dispatch method call on previously-created event queue is the FTL API function that actually dispatches messages. It should wait for messages to be available for dispatch before returning.

Since messages arrive asynchronously, the dispatch method call is contained in a loop, which terminates only when the finished flag is true, indicating the message has been received.

Console.WriteLine("Waiting for message(s)");
while (!finished)

Message Callback

MessagesReceived() is the message delivery callback method for this sample. Callbacks are associated with a subscriber via queue.AddSubscriber(). The callback must be named MessagesReceived(), be a member of a class which implements SubscriberListener, return void, and take three arguments:

  • an array of messages (Message) being delivered to the callback in this invocation
  • an integer indicating the number of messages delivered to the callback in this invocation
  • an event queue (EventQueue), the event queue which dispatched the messages More than one message may be delivered in a single invocation. The number of messages is contained in the count argument. Each message is an element in the messages argument. The callback must be able to handle the delivery of multiple messages.

Since more than one message may be delivered to this callback in a single invocation, loop through the messages and process them.

public void messagesReceived(List<Message> messages, EventQueue eventQueue)
    int i;
    int msgNum = messages.size();

    for (i = 0;  i < msgNum;  i++)
        if (messages.get(i) != null){
            System.out.print("Received message");
            System.out.println(" " + messages.get(i).toString());

Subscribing to Notifications

Register a notification handler which is invoked when an administrative action occurs which requires the client application to be notified. Specify an object which implements NotificationHandler, and provides an OnNotification() method.


OnNotification is the notification handler callback. In some situation, FTL must notify a client application of a condition which can’t be delivered through an event queue. Instead of sending an advisory (which would require an event queue), FTL uses an out-of-band mechanism to notify the client application. The notification callback must be named OnNotification, be a member of a class which implements NotificationHandler, return void, and take two arguments:

  • an integer (notification code) which indicates the type of condition being notified
  • a string describing the reason for the notification
public void onNotification(int type, String reason)
    if (type == NotificationHandler.CLIENT_DISABLED)
        System.out.println("Application administratively disabled: " + reason);
        finished = true;
        // But just in case additional notification types are added, handle the rest of them.
        System.out.println("Notification type " + type + ": " + reason);


Once objects are no longer needed, they should be disposed of - and generally in reverse order of creation.




// First remove the subscriber from the event queue.

To permanently destroy a durable subscription, including any messages stored by TIBCO Cloud Messaging for that durable, first close the subscription and then call unsubscribe using the realm object. Supply the unsubscribe call with the endpoint name and durable name used to create the durable subscription.

realm.unsubscribe("default", "");