Novell Home

Troubleshooting IF-THEN-ELSE Blocks with IDM Code

Novell Cool Solutions: Feature
By Geoffrey Carman

Digg This - Slashdot This

Posted: 24 Oct 2007
 

Problem

I was working on the Publisher Input Transform channel of an eDirectory driver, and the Password (Pub)-Sub rule, which handles sending an email on error synchronizing it to the other system to the end user. By default it sends a generic error message email. I wanted to handle a couple of different error codes. Specifically, I started testing for 16018 errors, which is "Password Minimum Life is triggered" (the UP policy says you have to wait a day between password changes).

So I copied the emailing rule and pasted it into an IF-THEN-ELSE block, having set the local variable ERROR-MESSAGES with text() of the error. This way, I could build a set of IF-THEN's to send a different email based on the actual error message. In the case of a 16018, the message: -16018 0xFFFFC16E NMAS_E_PASSWORD_LIFE_MIN is not very helpful to an end user. So, I created a new email template that explains more clearly that the policy only allows password changes once a day, and because the user tried to soon since the last change, they should please wait and try again tomorrow.

Here is the rule that I ended up with. (I disabled the default send mail rule that comes with the driver and deleted it from the rule below to save space.)

<?xml version="1.0" encoding="UTF-8"?><policy>
<description>Email notifications for failed password
subscriptions</description>
<rule>
<conditions>
  <and>
    <if-global-variable mode="nocase"
name="notify-user-on-password-dist-failure"
op="equal">true
    </if-global-variable>
    <if-operation op="equal">status
    </if-operation>
    <if-xpath op="true">self::status[@level != 'success'][text() !=
'']/operation-data/password-subscribe-status/association[text() !='']
    </if-xpath>
  </and>
</conditions>
<actions>
  <do-set-local-variable name="ERROR-MESSAGE">
    <arg-string>
      <token-xpath expression="self::status/child::text()"/>
    </arg-string>
  </do-set-local-variable>
  <do-if>
    <arg-actions>
      <do-send-email-from-template
notification-dn="cn=security\cn=Default Notification Collection"
template-dn="Security\Default Notification Collection\Password 16018
error">
        <arg-string name="UserFullName">
          <token-dest-attr name="Full Name">
            <arg-association>
              <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
            </arg-association>
          </token-dest-attr>
        </arg-string>
        <arg-string name="UserGivenName">
          <token-dest-attr name="Given Name">
            <arg-association>
              <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
            </arg-association>
          </token-dest-attr>
        </arg-string>
        <arg-string name="UserLastName">
          <token-dest-attr name="Surname">
            <arg-association>
              <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
            </arg-association>
          </token-dest-attr>
        </arg-string>
        <arg-string name="ConnectedSystemName">
          <token-global-variable name="ConnectedSystemName"/>
        </arg-string>
        <arg-string name="FailureReason">
          <token-text/>
            <token-xpath expression="self::status/child::text()"/>
        </arg-string>
<arg-string name="to">
        <token-dest-attr name="Internet EMail Address">
        <arg-association>
          <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
        </arg-association>
        </token-dest-attr>
        </arg-string>
      </do-send-email-from-template>
      <do-break/>
    </arg-actions>
  <arg-conditions>
    <and>
      <if-xpath op="true">contains($ERROR-MESSAGE, "16018")</if-xpath>
    </and>
  </arg-conditions>
  <arg-actions>
    <do-send-email-from-template
notification-dn="cn=security\cn=Default Notification Collection"
template-dn="cn=security\cn=Default Notification
Collection\cn=Password Set Fail">
      <arg-string name="UserFullName">
        <token-dest-attr name="Full Name">
          <arg-association>
            <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
          </arg-association>
        </token-dest-attr>
      </arg-string>
      <arg-string name="UserGivenName">
        <token-dest-attr name="Given Name">
          <arg-association>
            <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
          </arg-association>
        </token-dest-attr>
      </arg-string>
      <arg-string name="UserLastName">
        <token-dest-attr name="Surname">
          <arg-association>
            <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
          </arg-association>
        </token-dest-attr>
      </arg-string>
      <arg-string name="ConnectedSystemName">
        <token-global-variable name="ConnectedSystemName"/>
      </arg-string>
      <arg-string name="FailureReason">
        <token-text/>
          <token-xpath expression="self::status/child::text()"/>
      </arg-string>
      <arg-string name="to">
        <token-dest-attr name="Internet EMail Address">
          <arg-association>
            <token-xpath
expression="self::status/operation-data/password-subscribe-status/association"/>
          </arg-association>
        </token-dest-attr>
      </arg-string>
    </do-send-email-from-template>
    </arg-actions>
  </do-if>
</actions>
</rule>

When I start this driver, I get the following error:

DirXML Log Event -------------------
   Driver:  \ACMEIDVAULT\ACME\services\ACMEFLAT\eDirectory Driver
   Channel: Subscriber
   Status:  Error
   Message: Code(-9127) Error in
vnd.nds.stream://ACMEVAULT/acme/services/ACMEFLAT/eDirectory+Driver/Password%28Pub%29-Sub+Email+Notifications#XmlData:71
: Missing 'arg-conditions' element.

What you should notice is that this block:

<arg-conditions>
<and>
<if-xpath op="true">contains($ERROR-MESSAGE, "16018")</if-xpath>
</and>
</arg-conditions>

is now stuck in between two <arg-actions> blocks. The way an IF-THEN-ELSE action is structured is that first you have a arg-conditions block with your IF test or tests. Then the first arg-actions is the THEN block, and the second one is the ELSE block of actions.

I am not sure how I got there, based on my actions, but it was probably related to cutting and pasting. Regardless, the driver would not start with this ordering, even though iManager could parse the XML back to a valid-looking set of rules. It was only when I looked at the XML itself that this became obvious.

Solution

This was a tricky problem to catch! However, fixing it is simple.

In the XML view, cut the <arg-conditions> block and paste it before the first <arg-actions> block.

A corollary to this: If you are working on an IF-THEN-ELSE action, and you realize you need to switch the order of the THEN and ELSE actions, you can easily do it in the XML view by just changing the order. Of course, you usually could just negate the IF test to get the same effect, but there may be a reason why that would not work for you.


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell