Groovy Identity Manager: integrating IdM and Groovy

I'm actively doing Identity Manager projects for about 4 years now. I really like the product because of its flexibility. There is one obstacle: the XPress language. With respect to its language features, XPress is comparable to Shell script (bash, tcsh etc.). Here is a sample of Xpress code:

<block trace=true>
   <set name="foo">
     <concat>
        <s>Hello, </s>
        <ref>input</ref>
        <s>!</s>
     </concat>
  </set>
  <ref>foo</foo>
</block>

The variable foo will contain the value "Hello, world!" (assuming that input has a vlue of "world").

You can also call any Java class from XPress code

<invoke class="com.sun.idm.Hello" name="print">
   <ref>input</ref>
</invoke>

which leads to the same result.

The good thing about XPress is that you can change the code while your IdM is running (i.e. you don't have to redeploy IdM if you change the code. The bad thing is that XPress suffers from XML-bola (tags, brackets etc): the code becomes easily unreadable. Given the fact, that everything in IdM needs to be serializble in order to write it to the persistent storage (SQL database), it is propably difficult to fully replace XPress.

If you want to have both, readable code plus the agility of a scripting language, you can use e.g. Groovy (the trick basically is to invoke your own class loader). Suppose you have a Java class "GroovyWrapper" that has a method "run(String groovyScript)". You can call this method (e.g. with a workflow):

<Activity id='10' name="groovyTest">
        <Action>
          <invoke name="run" >
            <new class="com.sun.idm.GroovyWrapper"></new>
            <s>/Users/steffo/CodeWarrior/helloWorld.groovy</s>
          </invoke>
       </Action>
</Activity>

You can now change your groovyScript from

def name='World'; println "Hello $name!"

to

def name='Sun'; println "Hello $name!"

without redeploying IdM.

GroovyWrapper is very simple. First you need to download Groovy from groovy.codehouse.org. There
is also a nice Section on how to integrate Groovy which can be the basis for your GroovyWrapper

/\*
\* GroovyWrapper.java
\*
\* Created on March 5, 2007, 11:11 AM
\*
\* To change this template, choose Tools | Template Manager
\* and open the template in the editor.
\*/


/\*
\* The following JARs must be copied to $WSHOME/WEB-INF/lib
\*
\* antlr-2.7.5.jar
\* asm-2.2.jar
\* asm-analysis-2.2.jar
\* asm-attrs-2.2.jar
\* asm-tree-2.2.jar
\* asm-util-2.2.jar
\* groovy-1.0.jar
\* groovy-starter.jar
\* groovy-xmlrpc-0.3.jar
\*/

package com.sun.idm;

import java.io.File;
import java.io.IOException;
import groovy.lang.GroovyObject;
import groovy.lang.GroovyClassLoader;

import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
import groovy.util.ResourceException;
import groovy.util.ScriptException;

/\*\*
\*
\* @author steffo
\*/
public class GroovyWrapper {

/\*\* Creates a new instance of GroovyWrapper \*/
private GroovyClassLoader loader;
private Class groovyClass;

public GroovyWrapper() {

}
public Object run(String groovySrc){
ClassLoader parent = getClass().getClassLoader();
loader = new GroovyClassLoader(parent);

Object obj = null;

try {
groovyClass = loader.parseClass(new File(groovySrc));
} catch (IOException e) {
System.out.println("File " + groovySrc + "does not exists or is unreadabl");
}

try {
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Object[] args = {};
obj = groovyObject.invokeMethod("run", args);

} catch (Exception e) {
System.out.println("Cannot instantiate Groovy object");

}

return obj;

}

The problem with the run method is that is does not return any object. This can be achieved by the following method:

/\*\* Runs the script 'script'. This script must have an output variable 'outputVariable' \*/
public Object runScript(String script, String outputVariable) {
Object obj = null;
String root = new String("/Users/steffo/CodeWarrior");

try {
GroovyScriptEngine gse = new GroovyScriptEngine(root);
Binding binding = new Binding();
binding.setVariable("input", "world");
gse.run(script, binding);

obj = binding.getVariable(outputVariable);
} catch (IOException e) {
System.out.println("Path " + root + " does not exist");
} catch (ResourceException e) {
System.out.println("Error running " + script);
} catch (ScriptException e) {
System.out.println("Error running " + script);
}

return obj;


}

You can use this method via:

<block>
<set name="groovyResult">
<invoke name="runScript" >
<new class="com.sun.idm.GroovyWrapper"></new>
<s>helloWorldScript.groovy</s>
<s>output</s>
</invoke>
</set>
<ref>groovyResult</ref>
</block>

The veriable groovyResult contains the object that is passed from Groovy to IdM.


A last remark: I currently have no idea of the potential drawbacks (e.g. performance) of this approach. What I know is that our support stuff says: try to use XPress, if that doesn't work use JavaScript. If that doesn't work, use Java. Please take this into account when developing IdM solutions or opening support cases.

Comments:

What do you think of JRuby or Ruby as an alternative to XPress? As with XPress, it does not require any compilation or restart. Given the momentum behind the Ruby/JRuby, even with in Sun, I think JRuby is a much better alternative than Groovy. Once JRuby 1.0 is out, expected to be around JavaOne, I think its adaption would bypass Groovy with in 6 months. IMO....Groovy may have had the early starter adavantage, but with huge Ruby/ROR crowd, JRuby would make Groovy disappear from the scene within a year or two. - Ram

Posted by ram on April 17, 2007 at 11:20 PM CEST #

Good post Steffo. Is it possible to use groovy with jdbc-scripting rather than bean shell?

Posted by Eamonn O'Connell on August 09, 2007 at 04:39 AM CEST #

Eamonn,

not sure what you mean by JDBC scripting, but sure you can use any scripting language. The trick is the class-loader. From an implementation perspective: choose whatever you feel is the right tool for you. Sun of course will not be able to support anything but what's in the docs (XPRESS, JS, Java).

Posted by Steffo on September 24, 2007 at 04:20 PM CEST #

Did you see this post http://duckdown.blogspot.com/2008/07/active-directory-20.html

Great insight into Active Directory. Too bad Sun is not at the table...

Posted by Roger on July 22, 2008 at 07:44 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

steffo

Search

Top Tags
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today