Just a second...

Sending request messages to a message path

A client session can send a request message containing typed data to a message path. One or more client sessions can register to handle messages sent to that message path. The handling client session can then send a response message containing typed data. The response message is sent to the requesting client session directly, through the same message path.

A client session on the left. Diffusion in the centre. A control client session that has registered a handler for the message path on the right. An arrow representing the request message goes from the client session through a shape representing the message path inside the Diffusion server and continues to the handling client session. An arrow representing the response message goes from the handling client session back through the message path on the Diffusion server to the requesting client session.
When a request message is sent to a message path and a client session that handlers that message path responds, the following events occur:
  1. A client session sends a request message to a message path.
  2. The control client session receives the request message through a request handler.
  3. The session client session uses sends a response to the request message.
  4. The client session receives the response.

Both the request message and the response message contain typed values. The messages can contain data of one of the following types: JSON, binary, string, 64-bit integer, or double. The response message is not required to be the same data type as the request it responds to.

Sending to a message path

Required permissions: send_to_handler permission for the specified message path

Send the request message specifying the following information:
  • The message path to send the request to and receive the response through
  • The request message
  • The datatype of the request message
  • The datatype of the response message
JavaScript
// Example with json topic type.
var jsonType = diffusion.datatypes.json();
// Create a JSON object to send as a request.
var requestJson = jsonType.from("hello");

// Send the request to a message path "foo".
session.messages.sendRequest('foo', requestJson, jsonType).then(function(response) {
console.log(response.get());
}, function(error) {});
Apple
[session.messaging sendRequest:[PTDiffusionPrimitive requestWithLongLong:42]
                        toPath:message_path
  int64NumberCompletionHandler:^(NSNumber *response, NSError *error)
{
    if (error) {
        NSLog(@"Failed to send to %@. Error: %@", message_path, error);
    } else {
        NSLog(@"Received response: %@", response);
    }
}];
                    
Java and Android
    //Establish client sesssion
    final Session session = Diffusion.sessions().principal("client").password("password").open("ws://localhost:8080");
    
    //Obtain the Messaging feature
    final Messaging messaging = session.feature(Messaging.class);
    
    //Create a JSON object to send as a request
    final JSON request = Diffusion.dataTypes().json().fromJsonString("\"hello\"");
    
    //Send the request to a message path "foo" and wait for (at most) 5 seconds until the response is received.
    final JSON response = messaging.sendRequest("foo", request, JSON.class, JSON.class).get(5, TimeUnit.SECONDS);

Responding to request messages sent to a message path

Required permissions: send_to_session permission for the specified message path, register_handler permission, and view_session permission to register to receive session property values with the request message

Define a request handler to receive and respond to request messages that have a specific data type.

JavaScript
var jsonType = diffusion.datatypes.json();
    var requestJson = jsonType.from({ "foo": "bar"});
    var responseJson = jsonType.from({ "ying": "yang"});
    // Define a request handler for json topic type
    var handler = {
        onRequest: function(request, context, responder) {
            responder.respond(responseJson, jsonType);
        },
        onError: function() {},
        onClose: function() {}
    };
Apple
@interface NumberRequestDelegate : NSObject<PTDiffusionNumberRequestDelegate>
@end

@implementation NumberRequestDelegate

-(void)diffusionTopicTreeRegistration:(PTDiffusionTopicTreeRegistration *)registration
          didReceiveRequestWithNumber:(nullable NSNumber *)number
                              context:(PTDiffusionRequestContext *)context
                            responder:(PTDiffusionResponder *)responder;
{
    // Do something when a request is received.
}

- (void)diffusionTopicTreeRegistration:(nonnull PTDiffusionTopicTreeRegistration *)registration
                      didFailWithError:(nonnull NSError *)error
{
    // Do something if the registration fails.
}

- (void)diffusionTopicTreeRegistrationDidClose:(nonnull PTDiffusionTopicTreeRegistration *)registration
{
    // Do something if the registration closes.
}
                    
Java and Android
private final class JSONRequestHandler implements MessagingControl.RequestHandler<JSON, JSON> {                      
    @Override
    public void onClose() {
        ....
    }

    @Override
    public void onError(ErrorReason errorReason) {
        ....
    }

    @Override
    public void onRequest(JSON request, RequestContext context, Responder<JSON> responder) {
        ....
        responder.respond(response);
    }
}

Register the request handler against a message path. You can only register one request handler against each message path.

JavaScript
var handler = {
    onRequest: function(request, context, responder) {},
    onError: function() {},
    onClose: function() {}
};
session.messages.addRequestHandler('topic', handler);
Apple
// Ensure to maintain a strong reference to your delegate as it
// is referenced weakly by the Diffusion client library.
NumberRequestDelegate *const delegate = [NumberRequestDelegate new];
PTDiffusionRequestHandler *const handler = [PTDiffusionPrimitive int64RequestHandlerWithDelegate:delegate];

[session.messagingControl addRequestHandler:handler
                                    forPath:path
                          completionHandler:^(PTDiffusionTopicTreeRegistration *registration, NSError *error)
{
    // Check error is `nil`, indicating success.
}];
                    
Java and Android
messagingControl.addRequestHandler(messagePath, JSON.class, JSON.class, new JSONRequestHandler());

One-way messaging to a path

Note: One-way messaging was deprecated in Diffusion™ Cloud 6.2 and will be removed in a future release. Use request-response messaging instead.

Diffusion Cloud also provides a capability to send one-way messages to a message path. This message is not typed. The handling session cannot respond directly to this message.

Send a one-way message specifying the following information:
  • The message path to send the message through
  • The request message
  • Any additional options, such as headers or a message priority
JavaScript
session.messages.send('message_path', content);
Apple
PTDiffusionContent *const content = [[PTDiffusionContent alloc] initWithData:data];

[session.messaging sendWithPath:message_path
                          value:content
                        options:[PTDiffusionSendOptions new]
              completionHandler:^(NSError *const error)
{
    if (error) {
        NSLog(@"Failed to send. Error: %@", error);
    } else {
        NSLog(@"Sent");
    }
}];
Java and Android
messaging = session.feature(Messaging.class);
messaging.send(message_path, message_content, messaging.sendOptionsBuilder().headers(headers).build());
.NET
var messaging = session.Messaging;
messaging.Send( message_path, message_content, messaging.CreateSendOptionsBuilder().SetHeaders( headers ).Build() );
C
SEND_MSG_PARAMS_T params = {
        .topic_path = message_path,
        .payload = *content,
        .headers = headers,
        .priority = CLIENT_SEND_PRIORITY_NORMAL,
        .on_send = on_send,
        .context = context
};

/*
 * Send the message and wait for the callback to acknowledge
 * delivery.
 */
send_msg(session, params);

To receive a message sent to a message path, a client session must define a message handler:

JavaScript
// Create a message handler
var handler = {
    onMessage : function(message) {
         console.log(message); // Log the received message
    },
    onActive : function(unregister) {
     
    },
    onClose : function() {
     
    }
};
Apple
@interface MessageDelegate : NSObject <PTDiffusionMessageDelegate>
@end

@implementation MessageDelegate

-(void)diffusionTopicTreeRegistration:(PTDiffusionTopicTreeRegistration *)registration
              hadMessageFromSessionId:(PTDiffusionSessionId *)sessionId
                                 path:(NSString *)path
                              content:(PTDiffusionContent *)content
                              context:(PTDiffusionReceiveContext *)context
{
    // Do something when a message is received.
}

-(void)diffusionTopicTreeRegistrationDidClose:(PTDiffusionTopicTreeRegistration *)registration
{
    // Do something if the registration closes.
}

-(void)diffusionTopicTreeRegistration:(PTDiffusionTopicTreeRegistration *)registration didFailWithError:(NSError *)error
{
    // Do something if the registration fails.
}
Java and Android
private class MyHandler extends MessageHandler.Default {
    @Override
    public void onMessage(
        SessionId sessionId,
        String topicPath,
        Content content,
        ReceiveContext context) {
            // Do something when a message is received.
    }
}
.NET
private class MyHandler : MessageReceiverDefault {
    public override void OnMessage(
        SessionId sessionId,
        string topicPath,
        IContent content,
        IReceiveContext context) {
            // Take action when a message is received.
    }
}
C
/*
 * Function called on receipt of a message from a client.
 *
 * We print the following information:
 *   1. The message path on which the message was received.
 *   2. A hexdump of the message content.
 *   3. The headers associated with the message.
 *   4. The session properties that were requested when the handler was
 *      registered.
 *   5. The user context, as a string.
 */
int
on_msg(SESSION_T *session, const SVC_SEND_RECEIVER_CLIENT_REQUEST_T *request, void *context)
{
        printf("Received message on path %s\n", request->topic_path);
        hexdump_buf(request->content->data);
        printf("Headers:\n");
        if(request->send_options.headers->first == NULL) {
                printf("  No headers\n");
        }
        else {
                for(LIST_NODE_T *node = request->send_options.headers->first;
                    node != NULL;
                    node = node->next) {
                        printf("  Header: %s\n", (char *)node->data);
                }
        }

        printf("Session properties:\n");
        char **keys = hash_keys(request->session_properties);
        if(keys == NULL || *keys == NULL) {
                printf("  No properties\n");
        }
        else {
                for(char **k = keys; *k != NULL; k++) {
                        char *v = hash_get(request->session_properties, *k);
                        printf("  %s=%s\n", *k, v);
                }
        }
        free(keys);

        if(context != NULL) {
                printf("Context: %s\n", (char *)context);
        }

        return HANDLER_SUCCESS;
}

Register the message handler against a message path and its descendants:

JavaScript
// Register the handler
session.messages.addHandler('message_path', handler).then(function() {
    // Registration happened successfully
}, function(error) {
    // Registration failed
});
Apple
// Ensure to maintain a strong reference to your message delegate as it is
// referenced weakly by the Diffusion client library.
MessageDelegate *const messageDelegate = [MessageDelegate new];

// Use the Messaging Control feature to send a registration request to the
// server.
[session.messagingControl addMessageHandlerForPath:message_path
                                      withDelegate:messageDelegate
                                 completionHandler:
^(PTDiffusionTopicTreeRegistration* registration, NSError* error)
{
    // Check error is `nil`, indicating success.
    // Optionally store a strong reference to registration in order to allow the
    // handler to be unregistered at the server.
}];
Java and Android
session.feature(MessagingControl.class).addMessageHandler(message_path, new MyHandler());
.NET
session.MessagingControl.AddMessageHandler( message_path, new MyHandler() );
C
 /*
         * Register a message handler, and for each message ask for
         * the $Principal property to be provided.
         */
        LIST_T *requested_properties = list_create();
        list_append_last(requested_properties, "$Principal");

        MSG_RECEIVER_REGISTRATION_PARAMS_T params = {
                .on_registered = on_registered,
                .topic_path = topic,
                .on_message = on_msg,
                .session_properties = requested_properties
        };
        list_free(requested_properties, free);

        register_msg_handler(session, params);

To respond to this message, the receiving client session sends a separate message to the session that sent the message. For more information, see One-way messaging to a session.