Solace Systems – Managing Subscriptions on Behalf of Clients


Like most messaging products, once you start distributing data, you need to lock down who can access the data. In the case of Solace Systems this can be nicely handled by the “Managing of Subscriptions on Behalf of Other Clients” functionality (see Solace Systems Feature Guide). What follows are some notes and code snippets that provide one view on how to leverage subscriptions.

Before starting out your Solace Systems appliance needs to have a least one user that has the “Subscription Manager” privilege. This user will essentially facilitate the managing of client subscriptions, and hence should be thought of as an admin user for all intents and purposes. All “client” users should be setup with an ACL profile that prevents the addition of subscriptions – effectively and on-boarding process.

With the above in place, we can now effectively begin to explore managed subscriptions. One important point before proceeding, a client must be connected to the appliance before subscriptions can be managed on their behalf. So essentially the following would be one possible work flow to subscription management:

  1. Business server application (assume running a OS service) is connected to Solace System appliance with a username that has “Subscription Management” privilege.
  2. “Client” start desktop application, logs onto Solace System appliance, and makes a remote call to a server to logon to business application
  3. Business server on receipt client “logon” request, adds appropriate subscriptions to client based on entitlements
  4. “client” desktop application begins to see appropriate message flow

In addition what is nice is that the Solace System API offers the ability for subscriptions to be added/removed on demand based on user actions by the client application sending a request to the Subscription Manager who dynamically adds/removes a messaging system subscription(s) matching the content being requested.

Given the above workflow, point 1 would do something similar to:

            using (ISession session = ConnectToAppliance(managerUser))
            {
                Debug.Assert(session.Connect() == ReturnCode.SOLCLIENT_OK, "Should  have logged in to Solace Systems Appliance");
                Debug.Assert(session.IsCapable(CapabilityType.SUBSCRIPTION_MANAGER), string.Format("{0} Not Supported. Exiting", CapabilityType.SUBSCRIPTION_MANAGER));
            }
        private ISession ConnectToAppliance(string clientName)
        {
            var contextProps = new ContextProperties();
            var sessionProps = new SessionProperties
            {
                VPNName = "???",
                Host = "???",
                UserName = "???",
                ClientName = ???,
                Password = string.Empty,
                ReconnectRetries = 3,
                ReapplySubscriptions = true
            };

            _context = null;

            try
            {
                Debug.WriteLine("Creating the context ...");
                _context = ContextFactory.Instance.CreateContext(contextProps, null);

                Debug.WriteLine(string.Format("Creating the {0} session ...", clientName));
                return _context.CreateSession(sessionProps, HandleMessageEvent, HandleSessionEvent);
            }
            catch (Exception ex)
            {
                var sb = new StringBuilder();
                sb.Append(string.Format("Encountered an exception: {0}n", ex.Message));
                sb.Append(string.Format("tType = {0}n", ex.GetType().ToString()));
                sb.Append(string.Format("tStack = {0}n", ex.StackTrace));
                Debug.WriteLine(sb.ToString());
            }

            return null;
        }

Point 2 would leverage something similar to the following code:

            using (ISession session = ConnectToAppliance(clientUser))
            {
                if (session.Connect() == ReturnCode.SOLCLIENT_OK)
                {
                }
            }

Point 3 would subscribe on behalf of the client using the following code.

Server steps are

  • Login to solace router
  • Receive client login request
  • Add subscriptions on behalf of client in #2
            // Following code runs on the server - effectively a Subscription Manager process
            // Login as manager, add topic for a user, and check user can now login

            using (ISession session = ConnectToAppliance(managerUser))
            {
                session.Connect();
                if (session.IsCapable(CapabilityType.SUBSCRIPTION_MANAGER))
                {
                    ContextFactory cf = ContextFactory.Instance;

                    // Following code is really client code in a client process
                    // Client (in another process) connects to Solace System Appliance
                    using (ISession userSession = ConnectToAppliance(clientUser))
                    {
                        userSession.Connect();  

                        // Request comes to business server, passing clientUser as a parameter
                        // server process execute following code
                        using (IClientName clientName = cf.CreateClientName(clientUser))
                        {
                            using (ITopic serviceTopic = ContextFactory.Instance.CreateTopic(Topic))
                            {
                               // Grants subscription on behalf of client.  Assume here that serviceTopic is say a topic providing currency pair prices
                                session.Subscribe(clientName, serviceTopic,
                                                  SubscribeFlag.RequestConfirm | SubscribeFlag.WaitForConfirm, null);


                                // Send message from server via serviceTopic.  Client should now receive this message, as subscription has been granted
                                using (var message = ContextFactory.Instance.CreateMessage())
                                {
                                    message.Destination = serviceTopic;
                                    message.DeliveryMode = MessageDeliveryMode.Direct;
                                    message.BinaryAttachment = Encoding.ASCII.GetBytes("Hello client");
                                    session.Send(message);
                                }
                                Thread.Sleep(2000);
                            }
                        }
                    }
                }
            }

~ by mdavey on January 22, 2011.

2 Responses to “Solace Systems – Managing Subscriptions on Behalf of Clients”

  1. Great post. You could further expand point 2 to use the Solace API’s request/response mechanism to send the logon request to the business server. The request is sent to the well known/configured topic of the business server. The implication of this is that the architecture can have many business servers listening to a client logon topic for these logon events and each can manage the entitlements of their own topic spaces. When one request is sent to the topic all servers receive and each can choose to respond or ignore.

    Using request/response in this way helps keep the clients and business servers decoupled allowing for better modularity and scaling.

    Cheers, Greg.

  2. Any idea how to include the Send message on a Transaction? (with the .net API?) the API documentation only refers to Java in this regard. Commit and Rollback methods that is.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: