cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Dumping the BeanShell namespace in a rule

Dumping the BeanShell namespace in a rule

Many times, in a rule, you have no idea what are all the variables that are available to you. The following code snippet will dump all the variables available in the beanshell namespace for the currently executing rule:

 

UPDATE (1/14/2015): Added check for transient variable name which is a reserved word in Java. See red below.

 

<Rule name='Namespace'>

  <Source>

 

 

 

System.out.println("Beanshell namespace:");

 

for (int i=0; i&lt; this.variables.length; i++){

   String name = this.variables[i];

if ("transient".equals(name)) { continue; }

   Object value = eval(name);

 

   if (value == void)

       print(name + " = void");

   else if (value == null)

       print(name + " = null");

    else

       print (name + ":" + value.getClass().getSimpleName() + " = " + value);

}

 

  </Source>

</Rule>

 

 

As an example, when adding the code above to a buildmap rule, I see the following printed out:

 

Beanshell namespace:

state: HashMap = {}

context: InternalContext = sailpoint.server.InternalContext@ceb3c0

schema: Schema = sailpoint.object.Schema@630f2f[id=ff8080813fcad43c013fcad460590017,name=<null>]

log: Log4JLogger = org.apache.commons.logging.impl.Log4JLogger@1158f9e

record: ArrayList = [TEST01, 20080211, ADMINISTRATORS, DR System:YY-Function Control:YY-BackupControl:YY,  Administrators Group for PAM]

application: Application = sailpoint.object.Application@87d5ce[id=ff8080813fcad43c013fcad460550015,name=PAM]

cols: ArrayList = [Database Name, Report Date, Permission Group, Permission Rights, Description]

bsh: XThis = 'this' reference (XThis) to Bsh object: NameSpace: Bsh Object (bsh.NameSpace@1e43069)

bsf: BSFManager = org.apache.bsf.BSFManager@48702

Labels (2)
Comments

I use this all the time. Thank you for posting Chris!

I use it all the time too! In fact, just yesterday I used it to answer another compass post.

An update to the rule. This version will check each variable in the beanshell namespace, and if the variable is a SailPoint XML object, it will print the xml version of it.

System.out.println("Beanshell namespace:");

for (int i=0; i&lt; this.variables.length; i++){

                String name = this.variables[i];

        // skip variable named "transient" since transient is a java reserved word and fails eval()

                if ("transient".equals(name)) { continue; }

        Object value = eval(name);

    if (value == void)

        System.out.println(name + " = void");

    else if (value == null)

                                System.out.println(name + " = null");

    else

        if (value instanceof sailpoint.object.SailPointObject) {

                                        // print xml if it's a sailpointobject...

                                        System.out.println(name + "(" + value.getClass().getSimpleName() + ") = " + value.toXml());

        } else {

                                        // print value if it's not....

                                        System.out.println(name + "(" + value.getClass().getSimpleName() + ") = " + value );

        }

}

import org.apache.log4j.Logger;

Logger logger = Logger.getLogger("com.package.myRule");

logger.debug("Beanshell namespace:");
for
(int i=0; i < this.variables.length; i++) { // In rules &lt;
  String name = this.variables[i];

  // skip variable named "transient" since transient is a java reserved word and fails eval()
  if
("transient".equals(name)) {
    continue;
  }
  Object value = eval(name);
  if (value == void) {
    logger.debug(name + " = void");
  } else if (value == null) {
    logger.debug(name + " = null");
  } else if (value instanceof sailpoint.object.SailPointObject) {       // print xml if it's a sailpointobject...
    logger.debug(name + "(" + value.getClass().getSimpleName() + ") = " + value.toXml());
  } else {     // print value if it's not....   
    logger.debug(name + "(" + value.getClass().getSimpleName() + ") = " + value);
  }
}

You may want to place the following method in a java class and call it from your rules/workflows/forms when you need it.

Has sombody a idea how to call it from an email template?

//Use Thsi to call

//at.your.package.class.dumpBsh(this.interpreter.getNameSpace(),clog,false,true,java.util.Arrays.asList("plan","b"));

public static void dumpBsh(NameSpace bsh,org.apache.log4j.Logger clog, boolean dumpXml,boolean forceTraceLevel,List<String> dontDumpfor)

{

    Level oldlevel=null;

       //benutze unseren Logger falls wir keinen bekommen haben

       if(clog==null)clog=log;

       if(forceTraceLevel) {

             oldlevel=clog.getLevel();

             clog.setLevel((Level) Level.TRACE);

    }

       if(!clog.isTraceEnabled())return;

       clog.debug("Bsh.namespace start");

    String [] variables=bsh.getVariableNames();

       for (int i = 0; i < variables.length; i++)

    {

       String varName = variables[i];

       Object varValue = null;

             try {

                    if ("transient".equals(varName))  varValue = "[reserved word]";

                    else varValue = bsh.getVariable(varName);

       } catch (Exception ex) { 

                    varValue = "[eval exception]"

       }

             if(varValue instanceof Primitive)

       {

           Primitive p=(Primitive)varValue;

                    if(p==Primitive.VOID) clog.info("Beanshell namespace: "+varName + " = void");

                    else varValue=p.getValue();

       }

            if (varValue == null) clog.info("Beanshell namespace: "+varName + " = null");

             else  clog.info("Beanshell namespace: "+varName + ": " + varValue.getClass().getSimpleName() + " = " + varValue);

             if(dumpXml) {

                    if(varValue instanceof AbstractXmlObject) {

                           if((dontDumpfor!=null && !dontDumpfor.contains(varName))||dontDumpfor==null) {

                                  try {

                                        clog.trace("XML:\n\n"+ ((AbstractXmlObject)varValue).toXml()+"\n");

                   } catch (GeneralException e) {

                                        clog.debug("toXml() failed");

                   }  catch (Exception ex) { clog.warn("toXml() failed hard."); }

               }

            }

          }

    }

       clog.debug("Bsh.namespace done");

     if(forceTraceLevel) clog.setLevel(oldlevel);

}

To call java code from an email template, see if you can use a similar approach to what's in here:  

The problem is not the context, but the beanshell namespace. :smileysad:

I see your concern. I was just answering how to call a java method from within the Email Template.

The problem with what you want to do is that there is no beanshell context inside en email template. Email templates use Apache velocity.

Perhaps there is a way in Apache velocity to see all the variables defined in it's context?

Version history
Revision #:
2 of 2
Last update:
‎Jul 13, 2023 05:39 PM
Updated by:
 
Contributors