SubscriptionShim execute

Sends eDirectory information to the DirXML driver for the external application.

Syntax

Java

  public XmlDocument execute (
     XmlDocument         doc, 
     XmlQueryProcessor   query)
  
  

C++

  #include "NativeInterface.h"
  
  XmlDocument * METHOD_CALL execute (
     XmlDocument         *document, 
     XmlQueryProcessor   *query);
  
  

Parameters

document
(IN) Points to an XML document.
query
(IN) Points to a callback method that the DirXML driver can call if a command in the document does not contain enough information.

Remarks

The DirXML engine uses the execute method to send commands to the driver, and the driver executes them in the application. For example, the DirXML engine could send an XML document that instructs the driver to create a new user in the application. Other examples include commands to modify an attribute on an application object or to delete an application object. In addition, the DirXML engine can send a query element as part of a document passed to the execute method. The query instructs the driver to query the application for the data contained in the query.

The doc argument is the command document which is an XML document containing one or more commands that must be executed by the driver. This may be any mix of acceptable commands, depending on the rules, and may include any of the following: <add>, <modify>, <delete>, <rename>, <move>, and <query>.

IMPORTANT:Although the DirXML engine usually sends just one command per document, the subscriber must be prepared to handle any number of commands in a single document.

The query argument is an interface that allows the subscriber to query eDirectory for any additional information it may require to complete a command. The XmlQueryProcessor interface has a method named query which accepts an XDS document containing one or more queries.

The return from the execute method is an XML document containing the status of the command processing. For the format of all possible input and output documents, see Section 7.0, eDirectory DTD Commands and Events.

One or more of the commands in the command document might fail. In order to allow the driver to return multiple <status> elements, each corresponding to a single command, both the command elements and the <status> elements have an attribute named event-id. The event-id value is unique in the document and is used to tell DirXML which command element the <status> element refers to. If a <status> element has no event-id attribute, the <status> element is assumed to apply to all commands that were in the command document.

The class names and attribute names contained in the command document will be the application’s names, if a mapping rule is in place for the driver. The examples from the skeleton driver in this section are from a skeleton driver installation with no mapping rule, so the names in the example documents are the eDirectory names.

Add Command

The following sample command document instructs the skeleton driver to add a user.

  <nds dtdversion="1.0" ndsversion="8.5">
     <source>
        <product version="1.0">DirXML</product>
        <contact>Novell, Inc.</contact>
     </source>
     <input>
        <add class-name="User" event-id="0" src-dn="\PERIN-TAO\novell\John" src-entry-id="35868">
           <add-attr attr-name="Surname">
              <value timestamp="965252204#5" type="string">Doe</value>
           </add-attr>
           <add-attr attr-name="Telephone Number">
              <value timestamp="965252229#6" type="teleNumber">(801) 555-5555</value>
           </add-attr>
           <add-attr attr-name="Given Name">
              <value timestamp="965252229#1" type="string">Jonathan</value>
           </add-attr>
        </add>
     </input>
  </nds>
  

The above document tells the skeleton driver to add a user with three attributes. The response to an add command is a status or output document containing either an error status or an <add-association> informing DirXML the object was successfully added to the application and informing DirXML of the application value used for associating the eDirectory and application objects.

The skeleton driver does not actually support an application, so it cannot add a user, but the skeleton subscriber does have code that returns a fake association value telling DirXML that it did add the user. This is so that the skeleton driver can also illustrate how to receive modify and delete commands. The following example is a return document for the add example.

  <nds dtdversion="1.0" ndsversion="8.5">
     <output>
        <add-association dest-dn="\PERIN-TAO\novell\John" event-id="0">7</add-association>
     </output>
  </nds>
  

The above document causes the DirXML engine to write a string ("7") that associates the eDirectory object with the application object. All further commands relating to the application object will contain this association value so that the driver can reference the object in the application.

For more information about the possible elements in an add operation, see add.)

Modify Command

The following command modifies the eDirectory object represented by the <add> command above. It contains a command to change the Given Name attribute.

  <nds dtdversion="1.0" ndsversion="8.5">
     <source>
        <product version="1.0">DirXML</product>
        <contact>Novell, Inc.</contact>
     </source>
     <input>
        <modify class-name="User" event-id="0" src-dn="\PERIN-TAO\novell\John" src-entry-id="35868" timestamp="965252836#6">
           <association state="associated">7</association>
           <modify-attr attr-name="Given Name">
              <remove-value>
                 <value timestamp="965252836#6" type="string">Jonathan
                      </value>
              </remove-value>
              <add-value>
                 <value timestamp="965252836#6" type="string">Johnny
                      </value>
              </add-value>
           </modify-attr>
        </modify>
     </input>
  </nds>
  

The above document instructs the skeleton driver to modify the user with the unique application key of "7" such that the Given Name attribute value changes from "Jonathan" to "Johnny". The skeleton driver pretends the operation succeeds and returns the following status document:

  <nds dtdversion="1.0" ndsversion="8.5">
     <output>
        <status event-id="0" level="success"/>
     </output>
  </nds>
  

For more information about the possible elements in a modify operation, see modify.

Query Command

The command document passed to the execute method may also contain a query. A query is typically issued to the driver due to a matching rule. The DirXML engine sends a query when the following conditions occur:

  • An event occurs for an eDirectory object that matches the subscriber filter for the driver
  • The eDirectory object has not yet been associated with an object in the application
  • A matching rule is present on the subscriber channel

The DirXML engine uses the query to locate a match in the application according to the criteria present in the matching rule.

The following command document, containing a query, was sent to the skeleton driver previous to the <add> command above. The query was generated because a matching rule was in place on the subscriber channel that instructed DirXML to attempt to find an object in the application with the same value for the "Surname" and "Telephone Number" attributes.

  <nds dtdversion="1.0" ndsversion="8.5">
     <source>
        <product version="1.0">DirXML</product>
        <contact>Novell, Inc.</contact>
     </source>
     <input>
        <query class-name="User" event-id="0">
           <search-class class-name="User"/>
           <search-attr attr-name="Surname">
              <value timestamp="965252204#5" type="string">Doe</value>
           </search-attr>
           <search-attr attr-name="Telephone Number">
              <value timestamp="965252229#6" type="teleNumber">
                      (801) 555-5555</value>
           </search-attr>
           <read-attr/>
        </query>
     </input>
  </nds>
  

Because the skeleton driver has no application, it is unable to find a match, and returns the following document.

  <nds dtdversion="1.0" ndsversion="8.5">
     <output>
        <status event-id="0" level="success"/>
     </output>
  </nds>
  

The absence of an <instance> element in the return document indicates no matching objects were found. The <status> element in the return document is success because the query command was successfully executed.

The following examples illustrate a query that returns a matched object. These examples were generated by the VRTest driver.

The DirXML engine sends the following query:

  <nds dtdversion="1.0" ndsversion="8.5">
     <source>
        <product version="1.0">DirXML</product>
        <contact>Novell, Inc.</contact>
     </source>
     <input>
        <query class-name="User Object" event-id="0">
           <search-class class-name="User Object"/>
           <search-attr attr-name="name">
              <value type="string">Jane</value>
           </search-attr>
           <read-attr/>
        </query>
     </input>
  </nds>
  

The VRTest driver returns the following response:

  <nds dtdversion="1.0" ndsversion="8.5">
     <output>
        <instance class-name="User Object" src-dn="\novell\Jane">
           <association>25</association>
        </instance>
     </output>
  </nds>
  

The above query instructed the VRTest driver to query the VRTest application for an object of class "User Object" with an attribute named "name" with the value "Jane". The empty <read-attr/> element instructs the driver that DirXML does not require any attributes to be read.

The response from the driver indicates that a single match was found, and that the unique application key for the object is "25". If more than one matching object had been found, multiple <instance> elements would appear in the result document.

For more information about the possible elements in a query operation, see query.

Sample Code

Java Sample Code

The following code from the skeleton driver code sends a message to DSTrace, searches the document for elements, dispatches them to command handlers, and returns a result document. It also shows how to handle the most common error conditions.

  public XmlDocument execute( XmlDocument doc, XmlQueryProcessor query)
     {
        int   retryCount = 2;
        tracer.trace("execute");
        try
        {
           //setup the return document for use by command handlers
           outputElement = createOutputDocument();
  
           //try and connect with our mythical app
           while (retryCount-- > 0)
           {
              try
              {
                 connect();
                 Document document = doc.getDocument();
  
                 //find the <input> element
                 Element input = (Element)document.getElementsByTagName("input") .item(0);
  
                 //iterate through the children, dispatching commands
                 Node childNode = input.getFirstChild();
                 while (childNode != null)
                 {
  
            //only elements are interesting...ignore any nterspersed
                    //text, comments, etc.
                    if (childNode.getNodeType() == Node.ELEMENT_NODE)
                    {
                       dispatch((Element)childNode);
                    }
                    childNode = childNode.getNextSibling();
                 }
  
                 //return the result of whatever we were told to do
               return new XmlDocument(outputElement.getOwnerDocument());
              } catch (java.io.IOException e)
              {
                 if (retryCount <= 0)
                 {
                    //done trying
                    throw   e;
                 }
              }
           }
           //if we fall through here, we failed to connect
           throw new java.io.IOException("failed to connect");
        } catch (java.io.IOException e)
        {
           //somehow failed in talking to app, tell DirXML to retry later
           return   createStatusDocument(STATUS_RETRY,e.toString());
        } catch (Throwable t)
        {
           //something bad happened...
           return   createStatusDocument(STATUS_ERROR,t.getMessage());
        }
     }
  

In the DirXML sample code, see the execute method in the SolutionSubscriptionShim.java file and the SubscriptionShimImpl.java file. For sample code that processes the commands, see the dispatch method in the SolutionSubscriptionShim.java file and the handler methods (addHandler, modifyHandler, deleteHandler, renameHandler, moveHandler, and queryHandler) in the SkeletonSubscriptionShim.java file.

C++ Sample Code

The following code from the skeleton driver sends a message to DSTrace, searches the document for elements, dispatches them to command handlers, and returns a result document. It also shows how to handle the most common error conditions.

  XmlDocument * METHOD_CALL SkeletonSubscriber::execute(
     XmlDocument * doc, XmlQueryProcessor * queryInterface)
  
  {
     int   retryCount = 2;
     common.tracer->trace("execute");
     try
     {
        //setup the return document for use by command handlers
        outputElement = NdsDtd_newOutputDocument();
  
        //try and connect with our mythical app
        while (retryCount-- > 0)
        {
           try
           {
              //connect may throw a ConnectException
              connect();
              Document * document = doc->getDocument();
  
              //find the <input> element
              Element * input = (Element *)document->getElementsByTagName
             (common.ndsDtd->TAG_INPUT)->item(0);
  
              //iterate through the children, dispatching commands
              Node * childNode = input->getFirstChild();
              while (childNode != 0)
              {
                 //only elements are interesting...ignore any interspersed 
                 //text, comments, etc.
                 if (childNode->getNodeType() == Node::ELEMENT_NODE)
                 {
                    dispatch((Element *)childNode);
                 }
                 childNode = childNode->getNextSibling();
              }
              //return the result of whatever we were told to do
              return common.setReturnDocument(outputElement
               ->getOwnerDocument());
           } catch (ConnectException e)
           {
              if (retryCount <= 0)
              {
                 //done trying
                 throw   e;
              }
           }
        }
        //if we fall through here, we failed to connect,
        //so get the enclosing handler
        throw   ConnectException(MSG_CONNECT_FAILURE);
     } catch (ConnectException e)
     {
        //somehow failed in talking to app, tell DirXML to retry later...
        //"retry" status means the eDirectory event will not be discarded 
       //and that DirXML will resubmit it later (default is 30 seconds
       // later). This status should be used for errors related to
      //connection problems since the event won't be lost. For errors  
      // such  as application errors due to data, etc., use error since
      //it will cause DirXML to discard the event.
        return  common.setReturnDocument(common.createStatusDocument (STATUS_LEVEL_RETRY,e.getMessage()));
     } catch (ShimException e)
     {
        return   common.setReturnDocument(common.createStatusDocument (STATUS_LEVEL_ERROR,e.getMessage()));
     } catch (...)
     {
        //something bad happened...
        return   common.setReturnDocument(common.createStatusDocument( STATUS_LEVEL_FATAL,MSG_BAD));
     }
  }
  

In the DirXML sample code, see the execute method in the SubscriptionShimImpl.cpp file. For sample code that processes the commands, see the dispatch method in the SubscriptionShimImpl.cpp file and the handler methods (addHandler, modifyHandler, deleteHandler, renameHandler, moveHandler, and queryHandler) in the SkeletonSubscriber.cpp file.