> DNU home > online course > DirXML Driver Development
April 2001
DeveloperNet University Course

Implementing Queries


Module Objective: After studying the concepts in this section, you should be able to describe the elements of basic query processing in general terms.

Queries are sent by either DirXML or the driver to gain more information about an object or objects in either NDS or the external application. Often, this is because the information given in an XDS event document is insufficient for the system to perform a specified operation.

For example, imagine a system where the PBXSimulator application is run for some time on another platform before being connected to the driver by a secure socket.

While the driver and the external application were disconnected, the PBXSimulator administrator at the remote site created some accounts. Of course, since the connection was unavailable, the driver received no notification of these add operations.

Now, imagine that after the connection is established, the administrator modifies one of the new accounts somehow (a new phone number or something like that).

Since the driver is now connected, it would now be receiving event notifications. So, the Publisher shim creates an object modify XDS document something like the one below and sends it to the engine.


<input>   
<modify class-name="User" src-dn="0065">
<association>0065</association>
<modify-attr attr-name="phone">
<remove-all-values/>
<add-value>
<value type="teleNumber">123.456.7890</value>
</add-value>
</modify-attr>
</modify>
</input>

Of course, the XDS document contains the unique association value assigned by the driver to identify the source object. But, the problem is that the DirXML driver never got the chance to create the object in NDS. So, the association is meaningless to DirXML.

But, does the engine give up?

No, the engine sends a query to the Publisher shim requesting values for every attribute listed in the Publisher's filter so that it can obtain the information necessary to create a corresponding object in NDS.

But, how is the query sent to the Publisher shim?

Below is the declaration of the Publisher shim class.


public class Lab1PublicationShim implements PublicationShim, XmlQueryProcessor

You can see that the Publisher shim implements the XmlQueryProcessor interface. Shown below is the XmlQueryProcessor interface.


public interface XmlQueryProcessor
{
public XmlDocument query(XmlDocument queryDoc);
}

Since the engine knows that the Publisher shim implements the XmlQueryProcessor interface, it knows that it can send an XDS query document to the shim's query( ) method and that the shim should then parse the query and do the right thing to obtain the requested information from the external application (we'll describe how this is done later).

Below is an example of the query built for PBXSimulator by the engine.


<nds dtdversion="1.0" ndsversion="8.5">
<source>
<product asn1id="2 16 840 1 113719 1 x" version="1.0">PBXSimulator</product>
<contact>PBXs_R_Us</contact>
</source>
<input>
<query class-name="User" event-id="0" scope="entry">
<association>0065</association>
<read-attr attr-name="department"/>
<read-attr attr-name="location"/>
<read-attr attr-name="lastName"/>
<read-attr attr-name="CN"/>
<read-attr attr-name="phone"/>
<read-attr attr-name="title"/>
</query>
</input>
</nds>

Note: You can get more detail about the composition of the query element from NDS.DTD just as you have done for other XDS elements in previous labs.

The engine gets the information needed to build the query from the original modify event XDS document (where it gets the association value 0065) and from the list of attribute names in the Publisher's filter.

Assuming that the Publisher shim receives the query and handles it appropriately by interrogating the external application for the specified information. It would then return query results in an XDS document to the engine, similar to the one below.


<nds dtdversion="1.0" ndsversion="8.5">
<output>
<instance class-name="User" src-dn="0065">
<association>0065</association>
<attr attr-name="department">
<value>engineering</value>
</attr>
<attr attr-name="location">
<value>provo</value>
</attr>
<attr attr-name="lastName">
<value>Schmoe</value>
</attr>
<attr attr-name="CN">
<value>Joe Schmoe</value>
</attr>
<attr attr-name="phone">
<value>123-456-7890</value>
</attr>
<attr attr-name="title">
<value>programmer</value>
</attr>
</instance>
</output>
</nds>

You can see that the query results contain all of the attributes defined in the query which is all of the attributes in the PBXSimulator's Publisher filter (this of course would include the information required for object creation by the create rule).

However, the driver doesn't know that there were pre-existing objects in PBXSimulator. So, it thinks that there is still a possibility that an NDS object corresponding to the event really does exist, but without an association.

This is where the Publisher matching rule comes in. The purpose of the matching rule is to help positively identify an object in a target system when the target object of an operation is unclear. The matching rule defines the attribute values in the target class, which are to be read from potential target objects and compared with the source information for the purpose of identification.

For example, in the output document resulting from the query to PBXSimulator we have loads of information about the PBXSimulator object. But, which of these attribute values can be used to identify a corresponding object in NDS? This is the job of the PBXSimulator's Publisher matching rule.

Below is a matching rule that could be used to identify NDS objects for the PBXSimulator Publisher.


<?xml version="1.0" encoding="UTF-8" ?>
<matching-rules>
<matching-rule>
<!-- for users, match on Surname and Given Name -->
<match-attr attr-name="Surname"/>
<match-attr attr-name="L"/>
<match-attr attr-name="OU"/>
</matching-rule>
</matching-rules>

Note: All names in all rules except the input and output transformation stylesheets are NDS names, regardless of the channel.

PBXSimulator's mapping rule maps the attribute names thusly:
Surname "last name"
L "location"
OU "department"

In the case of the output document above, the engine would compose a query to NDS looking for an object containing:

  • a Surname of "Schmoe"
  • an L of "Provo"
  • an OU of "engineering"

There are three possible outcomes to this matching query:

  1. If the engine is able to find an object matching these values, it will perform the modify on it as the target object and update its association with the appropriate value.
  2. If the engine finds multiple objects matching these values, it will throw an error for the ambiguous matching result and abandon the modify operation.
  3. If the engine finds no object that matches these values, it will perform an add operation to create an NDS object corresponding to the source object from the external application.

In our example, there are no NDS objects corresponding to the object sourcing the modify event from PBXSimulator. So, option three is taken and the engine creates a new object in NDS to correspond with the source object in PBXSimulator.

The engine can also send queries to the external application through the Subscriber shim. In fact, for every add operation the engine reads information from the NDS object and refers to the Subscriber matching rules (if any) to generate a query to the external application to verify that the object doesn't already exist, much like the matching query described above.

Below is the declaration of the Subscriber shim class.


public class Lab1SubscriptionShim implements SubscriptionShim

You can see that the Subscriber shim implements the SubscriptionShim interface. Shown below is the SubscriptionShim interface.


public interface SubscriptionShim
{
public XmlDocument init( XmlDocument initParameters );
public XmlDocument execute( XmlDocument eventDoc,
XmlQueryProcessor ndsQueryProcessor );
}

As you should remember, the engine sends XDS documents to the Subscriber shim in the eventDoc parameter of its execute method. This is also the way that the engine sends a query to the external application. The engine installs the query element in a document and sends it to execute( ). The execute( ) method parses out the query element and sends it as a document fragment to the driver's code which handles queries.

Note: The purpose of the XmlQueryProcessor parameter to the execute( ) method is to provide a way for your shim to send a query for NDS information to the engine.

Basically, a query from the engine to the Publisher and the Subscriber channels can often be handled in the same way with the same code (as it is done with PBXSimulator's Lab1QueryHandler class).

Implementing a Query Handler in Your Driver

So, now that you know what a query is and how it is sent, do the following to learn how to implement query handling in your driver:

  1. Locate the source code for the query( ) method in the Lab1QueryHandler class in Lab1QueryHandler.java and read its comments for a detailed description of how queries are generally handled in a driver.
  2. Compare the description in the Lab1QueryHandler.java's comments with the source code in the file to see how queries are implemented in PBXSimulator.

Once you feel that you understand how queries are handled in PBXSimulator, proceed to the self-check for this topic.

Previous Contents Next
download sample file