Walking through the Oracle EBS HR driver – Part 4

I had noticed the Oracle EBS drivers get added to Designer a few patches ago, but never really had much of a chance to look at them. As I have been doing in my driver walkthrough series, I decided to do the Oracle eBusiness HR driver next.

In the first article I made it through the configuration, GCVs, and the started working through the Subscriber channel.

In the second article I finished the Matching policy in the Subscriber channel and got into the Command Transform.

In the third article I finished the Command Transform and started into the Output Transform.

In this article I will continue through the Output Transform.

When last we left off, I was at the following policy in the Output Transform.


There are two rules in this policy:

  • Convert the DATE attribute to MM-DD-YYYY format during add

  • Convert the DATE attributes to MM-DD-YYYY format during modify

Convert the DATE attribute to MM-DD-YYYY format during add

This rule is interesting. It uses a clever trick, loop (for-each) over the XPATH add-attr. This does not even have a condition since this XML is only ever found in an <add> event. (A <modify> event would have <modify-attr> nodes, and a <instance> event would have <attr> nodes). Inside the loop it sets a variable "attributename" from the XPATH of $current-node/@attr-name which is of course the attribute name. That is if you loop over the nodes that look like <add-attr attr-name="Given Name"> then the XPATH returns Given Name.

Then a If test is performed, on the local variable, attributename being tested with a regular expression of:

That is three things in there, the pipe symbol separates them.

The pattern is, period star, which means 0 to many characters followed by _DATE and then any other characters.
Or anything ending in _DT or in _UPDATED, but not followed by any other characters. So BOB_DT would match but BOB_DT_BOB would not. That is important to keep in mind as well see a bit further on.

This is a neat feature of the Condition tokens. You can do many types of compares. The most common are case sensitive or insensitive. But there are also source DN, destination DN, numeric (integer), and binary. The final one is what is used here, regular expression which adds a lot of power. This allows some very clever compares when you need them. It also allows you to embed a logical OR in the midst an ANDed grouping of conditions, since you can do a regular expression compare to something|other and that is an OR test. Really a powerful simple addition, that is great to have in your back pocket.

It must be nice when your schema is so well defined to have those strings in the name of all time formats, but that does not seem very common or likely in most cases. Looking at the Schema Map for this driver, none of them actually have that in the attribute name, and none of the native eDirectory attributes do either. Interesting, not sure what use case this is for, possibly the TCA/UM drivers have different schema maps, and this might just be residual. Well, the Oracle EBS TCA driver config has START_DATE and END_DATE which will be properly handled, but alas PASSWORD_LIFESPAN_DAYS is not covered by this rule. The Oracle EBS UM driver has the same set of attributes.

One other nice thing you can do, if the driver is properly configured (which this one is, from the base packages) is try to Manage Application Schema. (Right click on the driver line and it is an option). This info is stored in the DirXML-ApplicationSchema attribute, which the driver will try to build on its first (or some on every) startup by issuing a getSchema() call. When you are in the Filter/Schema map and chose to Refresh Application Schema it will restart the driver in a mode that forces a getSchema() call to refresh this data. It can often be interesting to peruse this attribute to see the raw schema that is stored, since it defines a number of bits, like multi valued that can be very helpful if you do not understand your target schema well. Alas not every shim can return the schema in this format, so you get whatever the shim provides, as best it provides it. If you look at the Active Directory driver you will be surprised how much schema there is in Active Directory. (Though to be fair, eDirectory has a ton of schema as well).

Some packages include this which is great for me, reading it without a real connected system to start a driver on. I really like it when they include the DirXML-ApplicationSchema in the base package, since I spend too much time looking at drivers I have no live system to test against. If you were making your own base package, you would import your completed driver which would read back this attribute and would then include this attribute in the Initial Settings I believe.

Looking at the TCA drivers base package, just for fun I see this XML right at the top:
<ds-attribute ds-attr-name="application-schema">
<schema-def hierarchical="true">
<class-def class-name="inetOrgPerson" container="false">
<attr-def attr-name="DESCRIPTION" case-sensitive="false" multi-valued="false" naming="false" read-only="false" required="false" type="string"/>

One minor peeve I had (they fixed it recently after I pointed it out) is that all the mappings of real attributes, like DirXML-ApplicationSchema to the ds-object/ds-attribute naming model of 'application-schema' seems like something you would want. It is now available here in the docs: https://www.netiq.com/documentation/idm45/designer_admin/data/packmaninitialsettings.html

This driver does include it, so looking through the schema, which only has inetOrgPerson as the class, I see the possible attributes of:

LAST_UPDATE_DATE (LAST_UPDATED_BY won't work as the _BY will not match)
P_BACKGROUND_DATE_CHECK (Which does not sound like we want to convert that one)

An amusing attribute in the schema is P_BLOOD_TYPE, which is more info than I think I would want my employer to have about me. How about P_USES_TOBACCO_FLASG? That is an odd one. I guess they really really want to know all your personal details.

Anyway, inside the test, if there is a _DATE at the end, a Reformat Operation Attribute is performed on the attribute held in the attributename variable. (Using the notation $attributename$ to use a variable here). The reformatted string is defined as:

Convert Time, from CTIME to MM/dd/yyyy hh:mm:ss format, but incorrectly applies that to the Operation attribute $attributename$. The correct way to do it would be via the local variable current-value. There are three special variables related to loops and the like:

  • current-node (the current instance of the loop, used only in a for-each loop)

  • current-value which is only used here inside a Reformat Operation Attribute, because then it implicitly loops over any remove-value, add-value, or attr nodes and processes all the possible values in the document.

This will only work on added values which I concede in an <add> case will be the only case, but if 2 or more values are sent, all will be set to the first value. But this shows a fundamental misunderstanding of how the token works, which will become more obvious in the next rule.

Convert the DATE attributes to MM-DD-YYYY format during modify

Here we use a similar approach, looping over the XPATH of modify-attr. This means it only applies to <modify> events, since <add> and <instance> have different nodes to hold attribute data.

Again, the local variable attributename is assigned the value of XPATH $current-node/@attr-name, and again a test for the Regex of:

All that is fine. But here is where things start to show where this approach could be better. Now we have two condition blocks to test for the <add-value> and the <remove-value> cases. Why? A Reformat Op Attr would do both perfectly well with one token. In fact for add, modify, and instance cases as well.

So instead we reinvent the token, and have to handle all the cases it does out of the box (and interestingly miss the <instance> case for query responses which is probably not relevant here).

In fact, both the add, modify, and instance case could be handled simpler, by a single For-Each loop, and a single Reformat Operation Attribute token. It is possible to loop over the XPATH of .//@attr-name which means from the current node (period) search down (//) for any node with an XML attribute named attr-name (The @ sign means XML attribute). Then the current-node variable is the name of the attribute. You could then test inside for any of those three DATE style attribute names, and if you succeed, you could then do a simple Reformat Operation Attribute, where the Operation attribute name is the current-node value, which you would enter as $current-node$ and then Reformat Op Attr as needed, the Local Variable current-value.

A trivial example of this is:

<token-xpath expression=".//@attr-name"/>
<do-reformat-op-attr name="$current-node$">
<arg-value type="time">
<token-local-variable name="current-value"/>

All mine does is convert the @type inside the <value> node from whatever it is to Time syntax.

More completely then, I would replace both these rules, with this simpler one:

<token-xpath expression=".//@attr-name"/>
<if-local-variable mode="regex" name="attributename" op="equal">.*_DATE.*|.*_DT|.*_UPDATED</if-local-variable>
<do-reformat-op-attr name="$current-node$">
<arg-value type="string">
<token-convert-time dest-format="MM/dd/yyyy hh:mm:ss" src-format="!CTIME">
<token-local-variable name="current-value"/>

Which does everything their rules do, but better, more completely, and elegantly, using the tokens the way they were meant to be used. The nice thing about the IDM engine is that there are many ways to accomplish the same task, all vaguely correct, and mostly work the same way. I still think my way is better, but the shipping way should mostly work.


This is part of the standard Account Tracking policy and I have decided I will do a set of articles on just those policies as one of my next projects, so I think I will skip this for the most part now. At a high level, this policy sets some Operation Properties that will be used by the Account Tracking Publish policy I think to decide if something needs to be written back to eDirectory as a DirXML-Accounts attribute.

That about wraps up the Output Transform. Which means the Input Transform is the next policy set to work through.

The Input Transform has 8 Policy objects. Several of which should be moved to Startup Policy set in the IDM 4.02.3 and higher world.

  • NOVLAUDTENTC-itp-SendEntitlementsEvents

  • NOVLORAHENT-itp-InitEntitlementConfigurationResource

  • NOVLEBSMSI-itp-InitManagedSystemInfo

  • NOVLORAHATRK-itp-Publish

  • NOVLORAHATRK-itp-WriteAccounts

  • NOVLORAHDCFG-itp-ConvertTime

  • NOVLORAHDCFG-itp-ModifyDirXML-PersonIdAttribute

  • NOVLORAHENT-itp-EntitlementsImpl

That is a lot to work through so no time like the present to get started digging into them.


This policy sends Audit Events (targeted at Sentinel, primarily, but since the Event Audit Service, part of Reporting is a baby version of Sentinel, the EAS as well) with custom event numbers as follows:

1200 - Account Create by Entitlement Grant
1201 - Account Delete by Entitlement Revoke
1202 - Account Disable by Entitlement Revoke
1203 - Account Enable by Entitlement Grant

In each of the policies to manage these, some variables are set, which are used in the final rules, Generate Event token call which is really what does all the work. The various variables get set for each case, as appropriate in the rules.

<do-generate-event id="$auditEventID$" level="log-info">
<arg-string name="value3">
<token-local-variable name="version"/>
<arg-string name="target">
<token-local-variable name="target"/>
<arg-string name="target-type">
<token-local-variable name="targetType"/>
<arg-string name="subTarget">
<token-local-variable name="subTarget"/>
<arg-string name="value">
<token-local-variable name="status"/>
<arg-string name="text3">
<token-local-variable name="idmEventID"/>
<arg-string name="text1">
<token-local-variable name="identity"/>
<arg-string name="data">
<token-text xml:space="preserve">IDM eventID: </token-text>
<token-local-variable name="idmEventID"/>
<token-text xml:space="preserve">level: </token-text>
<token-xpath expression="@level"/>
<arg-string name="text2">
<token-text xml:space="preserve">Object Class: </token-text>
<token-op-property name="objectClass"/>

Version seems to be statically defined to 1.
target is based on the association value, but from the Op Property set probably in the Output transform Subscribe policy.
targetType is statically defined 4.
subTarget is a string built from Operation Property 'accountAction', an underscore, auditEventId variable (set by each of the rules) an underscore, and then the @level of the status event.
status is the @level value, where success, retry, warning, error, and fatal are remapped to 0, 1, 2, 3, 4 respectively.
idmEventID is the @event-id XML attribute.
identity is the Operation Property 'guid'.

The other rules in this policy set basically set the auditEventID attribute value to one of the 1200, 1201, 1202, 1203 event type values.

That about wraps up this article, stayed tuned for more (sadly, probably many more, only just starting on the Publisher channel, and already 4 articles to get this far. But I do not think it will get as bad as the Office 365 series that took 16 articles to get through).


How To-Best Practice
Comment List