Tip for using ECMA Script objects in Designer


ECMA Script objects in Designer:

With the release of Novell Identity Manager 3.5 a new feature was added to the engine. The ability to make calls to ECMAScript functions. ECMAScript is the official name for what used to be called JavaScript.

Previously, the engine supported making calls to Java functionality, but that meant you needed to either have, or write a Java class to do the task.

Otherwise XSLT, and DirXML Script were the other options for working in the policy flow.

With ECMA support all sorts of new worlds have opened up. In fact, one of the first things done was to port the Novell Consulting Advanced Java Class (AJC) that was used by Novell's consulting group at client implementations to provide the same functionality in ECMA. This is available in IDM 3.61 configurations, and with Identity Manager 4 and it's support for Packages, is available as part of the Advanced Java Class package in the Common section of your Package Catalog.

Go take a look and come back, there are something like 100 functions in there to do all sorts of interesting things. Perhaps a Base 64 decoder interests you? (Well not so much since we have such a token, but useful if we need it in our own ECMA function). Perhaps a way to write to a file (appendToFile()) would come in handy, and save you the cost of a Delimited Text driver license? (Which is why I think charging for that one is dumb).

I started an open call for useful ECMA functions that is still there at this article:

Open Call for useful ECMA functions to use in Identity Manager

There are a bunch of additional interesting functions there. One of my favorites is the LDAP implementation in ECMA from Lothar Haeger, author of the truly awesome Password Notification Service driver. (Which by the way he has just recently Packaged to make it more available for Identity Manager 4 users, and to make it easier to offer upgrades and bug fixes. I imagine it ought to be released by the time this is published, if not, sorry for leaking it.)

If you are interested in learning more about Identity Manager and improving your skills, I highly recommend reading a driver configuration and trying to understand WHY a particular approach was taken versus what it is specifically doing.

I usually suggest that the easiest way to get started is probably a common driver like the Active Directory driver. Then for the most complicated driver I know of, the SAP HR driver from the Compliance Management Platform (CMP) (if you have IDM 3.6) which is now considered the basic driver configuration with IDM 4. This is the single most complicated driver I know of. I tried to walk through it to help with this process, since I was interested in learning about it, and I took notes along the way. You can read that long article series here (Note there are actually two drivers for this process, the SAP HR driver itself and the Business Logic).

SAP HR driver:

SAP Business Logic driver:

When looking for a median difficulty driver, that will still teach a lot, I highly recommend the Password Notification Service driver, which you can get from:

One of the coolest things in there, is noticing that the IDM query token has a problem. Its query functionality is really how the IDM engine implements query functionality. That allows for matching attributes and values, but is not complete. It cannot do an absence test. I.e. You cannot say, show me all objects whose DirXML-Associations value is blank. You would have to return every object of interest, with the DirXML-Associations attribute values, loop through, and throw away every object that has a value.

This is as they say, less than optimal.

Worse than event that is a much more common limitation. For date fields, you cannot do a less than or greater than compare. Think how useful it would be to say, show me all the Users whose Password Expiration Time is less than 14 days from now. Now you can do that in IDM out of the box. Query for all users, and probably wise to use max-results of some value to page it into smaller chunks for memory consumption and performance, and then return the Password Expiration Time and compare that inside a loop.

Well that does work, but it sure as heck isn't fast, nor does it scale very well. With 100 users, not even worth thinking about. But what is you have ten thousand users? One hundred thousand users? One million users? Ten million users. We have clients in almost all those cases. (Ok none of our clients have ten million users, but I know they exist, and our largest is about 1.5 million users).

Well Lothar contemplated this problem for his driver, and took a very very cool approach. Lets use LDAP to make the query, since the LDAP query language supports both absence and presence tests in the filter, but also less than and greater than tests on date and other fields.

Well there is no LDAP token in IDM. But there is ECMA! So Lothar went through the work and toil of figuring out the ECMA needed. This turns out to be so useful, that as a sibling of the Advanced Java Class package in IDM 4, you will find an LDAP Library ECMA Package. Novell is now including it, and a number of drivers use it now. Actually, some Packages that are being applied to all the drivers are using it. I know I saw it in my review of the Managed System Gateway and Data Collection Service driver article series, but cannot remember the context. If you are interested in those articles you can find them here:

Data Collection Service:

Managed System Gateway:

Anyway, this LDAP search function is an awesome tool to add to the IDM toolbox. In fact I am working on a package to make a Work Order driver start using the LDAP query instead of the engine query functionality. This really makes a huge difference in performance.

However, when you call this in Policy, you basically get a simple result returned, as the ECMA function defines it to return. Now any function could return almost anything. Any errors need to be provided by the function (usually with an ECMA try() and catch() set of function calls) and if not, you get a somewhat ugly error returned that is useless as I think it is a reference to either a Java thread or memory location.

So how do you troubleshoot this? Well you could definitely iterate through different code examples in policy, push it out, and keep trying.

Maybe you can do it in Designer's Policy Simulator and that might be helpful. But there might be lower level issues or reasons why Simulator will not quite cut the mustard.

If you are interested in reading about the Policy Simulator in Designer, check out this article: Using Simulator in Designer

Well it turns out that the Identity Manager engine uses the Rhino ECMAScript interpreter which is made available as a Java class. It is also available in Designer, but not just in Simulator!

If you open an ECMA Script editor page, you get three window panes. On the far left is a vertical column which lists out function and variable names to allow to jump around the code sample more easily. I do wish all the iconography was better documented. The functions are pretty obvious as a plus sign in a box that expands to show the contents. The blue equilateral triangle widgets represent variable declarations. Be interesting to know what other icons are available and see a list. (I REALLY want this for the new overlays in Packages, since there are so many and they are teeny tiny, and on my 1920 X 1024 resolution screen, I cannot make heads or tails of them. Guess I should drop my res down to 640 X 480 and see if I can find them and visualize them better. I have tried screen shots, but they look terrible and horribly pixilated.)

This seems like overkill, but go open the libAJC ECMA object where there is close to 100 functions and suddenly it becomes clear how useful it really is!

The main top right pane is the text of the ECMA code itself. Pretty obvious that this is where you enter code.

But if you never noticed, there is a lower right horizontal pane, that is actually a console to an ECMA Script interpreter. The giveaway is the > prompt of course.

Try typing a function name, and Rhino is invoked to try and execute it. This can be very helpful for debugging, since you can know work on simulating your ECMA function live.

I ran into this issue troubleshooting the LDAP ECMA function I was describing above. We had a system where everything worked great in the Development and QA (Quality Assurance) environments, but just were not working at all in Production.

First step was to make sure that the servers being used were willing to connect. You know, the usual, eliminate firewalls and connectivity things. The problem in Production is that you really do not want to be experimenting and trying things. The bosses usually frown upon that quite a bit. If you do not have separate systems, I highly recommend you get them. Developing in Production is a recipe for disaster. The simplest mistake that in the Dev lab you say, oops, fix it and move on, can cause huge problems in development.

But the key is to keep the various levels of systems basically identical. In my case, while Dev was running IDM 4 with SP1 and QA and Prod were still running IDM 4 before SP1, the LDAP script was working in Dev and QA, but not Prod, which rules out the Service Pack (or more specifically, the lack thereof) as the likely cause.

Now, in the case of the LDAP ECMA function, it takes a LOT of arguments. Looking at the ECMA object you can see it looks like:

es:ldapSearchLothar($LdapConnect, $LdapPort, $LdapUseTls, $LdapTlsKeystore, $LdapTlsStorepass, $LdapLogin, $LdapPassword, $UserLdapSearchBase, $UserLdapSearchScope, $filter, $attr-list, $LdapMaxResultSet)

One of the awkward bits in testing this, is that in XPATH (which is how you call an ECMA script function, use an XPATH expression with es: namespace which is implicitly defined by default, and knows to use the ECMA processing engine), a single dollar sign before a variable name can refer to a local variable or a Global Configuration Variable (GCV).

I knew that the following were local variables:









And that is list was coming from GCV's:




But for fun, this one is actually a call to variable, getting the value of a Named Password:


So I added a trace into Prod to get the actual values, and was able to make a function call, with everything I needed that looked more like:

ldapSearchLothar("", "389", "false",,, "cn=ldapUser,ou=services,o=system", 'password', "ou=Users,o=system", "sub", "(&(objectClass=DirXML-nwoWorkOrder)(DirXML-DueDate>=20111002112354))", "DirXML-DueDate, DirXML-nwoStatus, DirXML-nwoDeleteDueDate", "0")

This was able to demonstrate that the LDAP server in Production was actually connecting, and responding. Now because the ECMA function is designed to return a nodeset that looks like XDS (Novell's XML dialect used in IDM) the command line tries to show a nodeset which does not really display as text. Instead, I changed the last line from:

     return nodeSet;

to use the serialize() function that converts a nodeset to nice easy to read text, so that it looked like:

     return serialize(nodeSet);

Then I get nice XDS output in Designer. This was helpful in eliminating a possible problem. I still do not have a solution to my problem, we are looking at packet traces now, but this approach really helped in the troubleshooting to eliminate a bunch of possible issues.

You can see how useful this would be in general troubleshooting of ECMA as you move forward.



How To-Best Practice
Comment List