Universal Messaging 10.1 | Concepts | Commonly Used Features | Event Filtering using Subjects and Principals
 
Event Filtering using Subjects and Principals
Universal Messaging provides several mechanisms for directing events to specific consumers:
*Subject-based filtering: This enables publishers to direct events to specific consumers based on the 'subject' of their connection.
*Principal-based filtering: This allows one or more string attributes called principals to be associated with your nSession at initialization. Publishers can also publish events with one or more principals, and your nSession will receive events that have at least one principal that matches one of your nSession's principals.
Subject-based Filtering
Universal Messaging's subject-based filtering enables publishers to direct events to specific consumers based on the 'subject' of their connection. For example, if you initiate a Universal Messaging nSession with the subject / session name of "mrsmith", and your nSession is then used to subscribe to a channel called '/deals', any publisher on the '/deals' channel can publish an nConsumeEvent onto the '/deals' channel directly to "mrsmith" by calling the following:
nConsumeEvent newdeal = new nConsumeEvent("New Deal",
"Free Holiday In Barbados".getBytes();
newdeal.setSubscriberName("mrsmith".getBytes());
channel.publish(newdeal);
This is a powerful concept and one which is used heavily in request/response scenarios, as well as in scenarios for directly streaming events to individuals as required.
Limitations of subject-based filtering
Subject-based filtering has some limitations. If you consider large deployments of Universal Messaging where potentially there are multiple instances of 'services' which connect to Universal Messaging, and where the services would typically use the same UID for the nSession subject, it is difficult to distinguish between specific instances of a service, or have any kind of logical grouping of these services, as they will all appear as the same connected UID to the Universal Messaging server. One example of this would be the use of the Universal Messaging API by webMethods Integration Server (IS), where there could be multiple instances of IS, and within each instance of IS, multiple triggers that consume events from the same channel or queue. In such a case, there would be no possibility to distinguish between specific instances of IS, or specific triggers, or all triggers on an IS instance, since they are all running using the same UID.
For this purpose, Universal Messaging provides a client API feature called Principals to extend the subject-based filtering mechanism. This feature is described below.
Principal-based Filtering
All Universal Messaging Enterprise client APIs support the concept of an nSession object, which is the container for the physical connection to a Universal Messaging server. During initialisation, a handshake mechanism establishes a subject, which defaults to the local user name on the host machine (typically using the format "user@host"), but which can also be overridden to contain any arbitrary string as the UID portion of the subject.
Universal Messaging allows you to treat the subject not just as a single string but as a set of substrings called principals. These in turn can be used as filterable attributes for the nSession.
The Universal Messaging server maintains the subject in its own server-side connection that corresponds to the client nSession, and so any subject and principal list is available at the Universal Messaging server.
The nSession includes a method that enables multiple string principals to be passed during authentication. In addition, the subject filtering mechanism in the Universal Messaging server also checks the list of provided principals during the filtering based on the subscriber name(s) passed in any published events.
So you can do the following:
String[] group1 = {"trigger1","IS1"};
nSessionAttributes sAttr1 = new nSessionAttributes(rname);
nSession subSession1 = nSessionFactory.create(sAttr1, "subscriber1");
subSession1.setAdditionalPrincipals(group1);
subSession1.init();

String[] group2 = {"trigger2","IS1"};
nSessionAttributes sAttr2 = new nSessionAttributes(rname);
nSession subSession2 = nSessionFactory.create(sAttr1, "subscriber2");
subSession2.setAdditionalPrincipals(group2);
subSession2.init();
The nSessions created above now contain several principals. Similarly, a publisher can publish events in the following way:
nConsumeEvent event = new nConsumeEvent(group1[0].getBytes(),
group1[0].getBytes());
event.setSubscriberName(group1[0]);
pubchan.publish(event);

nConsumeEvent event2 = new nConsumeEvent(group1[1].getBytes(),
group1[1].getBytes());
event2.setSubscriberName(group1[1]);
pubchan.publish(event2);
You can see that the first event should go only to subSession1 / subscriber1, since the subscriberName equals the principal "trigger1", and the second will go to both subSession1 and subSession2, since they both have been created with a principal list that contains "IS1".
One extension to this is the ability to send an event to multiple subscriber names, which means that published events can also be delivered to multiple sessions with a matching principal in their list. For example, consider the following additional code:
String[] group3 = {"trigger3","IS2"};
String[] group4 = {"trigger4","IS2"};
String[] group5 = {"trigger1","trigger2","trigger3","trigger4"};

nSessionAttributes sAttr3 = new nSessionAttributes(rname);
nSession subSession3 = nSessionFactory.create(sAttr3, "subscriber3");
subSession3.setAdditionalPrincipals(group3);
subSession3.init();nSessionAttributes sAttr4 =
new nSessionAttributes(rname2);

nSession subSession4 = nSessionFactory.create(sAttr4, "subscriber4");
subSession4.setAdditionalPrincipals(group4);
subSession4.init();
So a publisher can now publish the following events:
nConsumeEvent event3 = new nConsumeEvent("All", "All".getBytes());
event3.setSubscriberNames(group5);
pubchan.publish(event3);
nConsumeEvent event4 = new nConsumeEvent("IS1 and IS2",
"IS1 and IS2".getBytes());
event4.setSubscriberNames(new String[]{group1[1], group3[1]});
pubchan.publish(event4);
Here, event3 will be delivered to all 4 sessions, since all 4 'triggerX' principal names have been added to the event, and event4 will also be delivered to all 4 sessions, since both 'IS1' and 'IS2' are added to the subscriber names. Therefore, all sessions have a matching principal for both events.
This very simple concept greatly enhances the ability to direct events to single connections or to a logical grouping of connections.