IBM BPM How to get user email addresses directly from LDAP

Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInShare on RedditShare on Tumblr

Trying to retrieve user and email via BPM JS API

Let’s say you have the requirement to send an email to the current user of a task. Right… easy as pie. We just need to find our user object (of TWUser type), using the JS API and then retrieve the email:

function retrieveUserEmailByLoginName( /* String */ userLoginName ){
	var userEmail = "";

	if (!userLoginName) return "";
	
	// use BPM API to access user information by login name
	var userObj = tw.system.org.findUserByName( userLoginName );
        
   // if user found, look for his email in the attributes record
	if ( userObj && userObj.attributes){
		userEmail = userObj.attributes["Task Email Address"];
	}

	return userEmail;
}

// use the helper function above to get current user's email 
//   and store it in a service variable for future use
tw.local.currentUserEmail = retrieveUserEmailByLoginName( tw.system.user_loginName );

Basically, it means we are trying to retrieve the email straight from the BPM Database (BPM DB). And sometimes the email attribute is set, yet in most cases it is not. To understand this better we have to take a quick look into how BPM does its user management.

Short introduction in IBPM BPM user management

The platform behind the scenes goes in its BPM DB and looks at its referenced users. Then it tries to retrieve a custom attribute called “Task Email Address” which by default does not exist, because custom attributes are not synchronized from external sources.

“Even though IBM Business Process Manager security is based on WebSphere Application Server security and any user attribute that you mark as supported for a security provider (LDAP or otherwise) is technically available through the Virtual Member Manager API, a Business Process Manager user does not know anything about these attributes. The only attributes that are available for a Business Process Manager user, that actually come from the underlying security provider, are the user name and display name.

– Source Link: http://www-01.ibm.com/support/docview.wss?uid=swg21609893

Users usually come from external sources via Federated Repositories ( you can have various LDAPs and FileRegistries mashed together), and BPM only saves the user name and display name of those accounts in its BPM DB when it synchronizes with them.

Bellow is an image to visualize this:
ibm_bpm_user_management

If you have users coming from an LDAP repository (like most organizations do, see User1,2,3,4 in the example above) you will have information about internal structure and internal group memberships at the BPM level, yet you will not have synchronization with custom LDAP attributes for those users.

So you will not be able to obtain Email address via the OOTB Javascript API. In order to access the supported attributes form LDAP you will need to use a custom integration with the Virtual Member Manager API. Happily there is already a java implementation which can be easily plugged in!

If you want to read more information on user management and synchronization, you can look at the following Knowledge Center links:

 

Integration with the Virtual Member Manager API via VMMUtil.jar

We will be doing a Java Integration service and use VMMUtil.jar to connect to VMM Api and retrieve supported attributes like mail.
ibm_bpm_get_user_email_from_ldap

Step 1. Download LDAP Integratation Project

Access https://hub.jazz.net/git/ryancox/BPM.VMM_LDAP_Toolkit
and download the project files. (If the links ever stops working you can google BPM VMM_LDAP_Toolkit)
ibm_bpm_vmm_ldap_toolkit_project_download

Step 2. Import the VMMUtil.jar as Server File in Process Designer

In Process Designer, create a new Server File, and browser in the downloaded project above, in the source folder for VMMUtil.jar.
ibm_bpm_upload_server_file_vmm_util_jar
Once the file is added, it should appear under Files > Server File, like below:
ibm_bpm_server_file_vmm_util_jar

Step 3. Create new Integration Service “RETRIEVE LDAP Attributes for users” and do JAVA Integration with VMM

From Implementation > Integration Service, create a new “RETRIEVE LDAP attributes for users”
ibm_bpm_create_new_integration_service
Once created you will need to add the Input / Output variables:

  • userNames (String) – comma separted login names ex: “admin,bdaniel,diatan”
  • userAttributeNames (String) – comma separated LDAP attributes ex: “mail,uid,sn,cn” or any supported attribute available in the LDAP
  • usersAttributesMap (Map) – results of the VMM integration jar will be saved in a Map file with informations for each user saved under user’s name key

ibm_bpm_new_integration_service_retrieve_ldap_attributes_for_users
Once variables are created, you can drag the Java Integration block from the right.
ibm_bpm_add_java_integration_and_map_to_vmm_util_jar
And then, from select the block and in the Properties > Definition tab you will map the VMMClient Class from the VMMUtil.jar. Use the HasMap getUsers(String,String) for Method.
ibm_bpm_select_vmm_client
Last step is to map the service variables created earlier to the expected variables of the Java Integration block:
ibm_bpm_add_java_integration_data_mapping
That’s it, now we have a nice black box, where we pass in a list of user names and a list of attributes and expect a Map object with the attributes for each user.

If you want to read more on the VMM integration they have a toolkit and a pdf documentation file in the project. Yet mainly what it does is to get “supported” (need to be specifically marked as supported in LDAP) attributes for a user or list of comma separted user names.

Step 4. Create a new General System Service to wrap around the Integration Service and to use for retrieving users’ emails

Now that we have a service block that can get user attributes directly from LDAP let’s use it to get email addresses for a list of users.
Will need to create a Implementation > General System Service. We can call it “RETRIEVE LDAP Emails for users”.
And let’s do the input / output variables:

  • userLoginNames(String)(List) – List of String names as input
  • userEmails(String)(List) – List of emails as output
  • userLoginNamesCommaSeparated(String) – Will need a private String variable to concatenate all userLoginNames items in order to pass them to the Integration Service that does the work
  • usersAttributesMap(Map) – Will also need a private variable Map to keep the results of the Integration Service, and which we will parse to retrieve our output list of emails

ibm_bpm_new_general_system_service_variables
After that we will add a Server Script (Init), a nested service (RETRIEVE LDAP Attributes for user), and finally another Server Script (Perpare Emails Output). Should have 3 boxes like in the image below:
ibm_bpm_new_general_system_service_nested_service

  • Init – this is where we prepare the inputs for our nested Integration Service. Basically we need transform our list of String to a single comma separated one.
    So if for example we had [“admin”,”diatan”,”bdaniel”] we want “admin,diatan,bdaniel”

    // MAIN function
    // --------------------
    function main(){
        tw.local.userLoginNamesCommaSeparated = tw.local.userLoginNames.listToNativeArray().join(",");
    }
    
    main();
    
  • RETRIEVE LDAP Attributes for user – this is where we map our previously constructed Integration Service. And we map the variables accordingly. See the Data Mappings in the image above. Note that for “userAttributesNames” we map directly “mail”
  • Preapre Emails Output – here we’ll take the tw.local.usersAttributesMap and parse it to retrieve the email addresses for each user:
    function retrieveEmailsFromMap(map, userNamesList){
        var userEmails = new tw.object.listOf.String();
    
        for (var i = 0; i<userNamesList.listLength; i++){
            var userName = userNamesList[i];
            var userData = map.get( userName );
            var userEmail = userData.get("mail");
            
            userEmails[i] = userEmail;
        }
        return userEmails;
    }
    
    // MAIN function
    // --------------------
    function main(){
        tw.local.userEmails = retrieveEmailsFromMap( tw.local.usersAttributesMap, tw.local.userLoginNames);
    
    }
    
    main();
    
Step 5. Celebrate!

Done!

If you have any issues / questions / remarks please don’t hesitate to let us know via the comments section.

Thank you.