Generate Unique Value Activity
Clone this wiki locally
The Generate Unique Value activity is used to generate a string value based on the specified recipe for generation of the value and a uniqueness criteria to check that the generated value is unique in the FIMService database and optionally unique in the LDAP stores (e.g. Active Directory) as well.
Activity Display Name
Optional. Name of the activity to be displayed on the MIM / FIM workflow designer.
Activity Execution Condition
Optional. The condition which must be satisfied for execution of this activity's core task (i.e. generate a unique value). This can be any WAL function expression resolving to a boolean value. See Activity Execution Condition wiki for more information.
Target for Generated Value
Required. The attribute name or workflow data dictionary key to which the generated value is published. This is specified as a lookup expression. e.g.
Required. The XPath Search Filter which identifies conflicts for the generated value. The
[//Value] lookup is used in the filter to represent the value being evaluated for uniqueness and is a simple token replacement in the specified filter before filter resolution occurs. e.g.
/Person[AccountName = '[//Value]'].
In addition to the equality check, the use of starts-with() in the XPath filter is also supported. This will cause the
[//UniquenessKey] (explained later in the section) to jump to the next available incremented value. e.g.
/Person[starts-with(AccountName,'[//Value]')]. In this case, if the base
[//Value] to be tested is "johndoe" and the account names from "johndoe2" to "johndoe49", "johndoe51" to "johndoe75", "johndoe77",.... have already been taken in the FIMService database, the
[//UniquenessKey] will be positioned at 50 causing "johndoe50" to be tested directly for uniqueness. If "johndoe50" is not unique because user with that name is present in LDAP (see below), "johndoe76" will be tested next for uniqueness and so on.
Query LDAP for Conflicts
Optional. The activity can be configured to query one or more LDAP directories to identify conflicts for the generated value.
Required when "Query LDAP for Conflicts" is selected. Specifies one or more LDAP queries which should be run by the activity to identify conflicts. The
[//Value] lookup should be used in each LDAP filter to represent the value being evaluated for uniqueness. All queries are executed under the context of the FIMService account.
Directory Entry Path
The path at which to bind to the LDAP directory. This can be an unquoted string, a lookup or a function expression. e.g.
"LDAP://" + [//Target/ADOU]
The search filter string in LDAP format. This can be an unquoted string, a lookup or a function expression. The
[//Value] lookup is used in the filter to represent the value being evaluated for uniqueness and is a simple token replacement in the specified filter before filter resolution occurs e.g.
Uniqueness Key Seed
Required. Specifies the first number which should be included in the value when the evaluation of all previous value expressions results in a value that is not unique. If all previous value expressions evaluated return a conflict, this number is incremented until a unique value is found. This current value of this number is accessible as the
Required. Specifies a successive list of expressions to be evaluated to generate a unique value. The first expression which results in a unique value will be used. The last expression in the list must contain the
[//UniquenessKey] lookup to ensure a unique value can be generated. As a last resort, the
[//UniquenessKey] lookup will be incremented until a unique value is identified. The activity will abort execution after the last expression is evaluated 512 times and still failed to generate a unique value.
While the value generated by the Generate Unique Value activity is unique at the time it is generated, there is no guarantee that the value generated will be unique at the time it is committed. This is due to the MIM / FIM product architecture where workflows run in parallel and asynchronously to each other. So if two workflows running concurrently generate the same "unique" value, the first workflow to commit the value to the database will succeed invaliding the uniqueness of the value generated by the second workflow. The longer the activity runs, the lesser the guarantee of it succeeding in generating a unique value, so you should design your activity such that a unique value is generated in a very few iterations of the defined list of value expressions. The activity will log a warning in the event log for every 20th increment of the uniqueness key.
Workflows in MIM, in general, are not meant to be run on batch / bulk updates. This is particularly true for Generate Unique Value activity as it typically does read and write to the same attribute. If the activity is executed as a result of batch updates, the activity may fail to generate the unique value as described earlier or simply abort altogether due to database locks or read/write timeout limits defined in the FIMService config file.
The following Generate Unique Value activity generates an account name that is unique in the FIMService database as well as Active Directory. The account name is generated using user's first name and last name, optionally middle name and suffixed with a number, if required, to make it unique.
|Activity Display Name||Generate Unique AccountName|
|Target for Generated Value||[//Target/AccountName]|
|Conflict Filter||/Person[AccountName = '[//Value]']|
|Directory Entry Path||LDAP Filter|
|Uniqueness Key Seed||2|
|NormalizeString([//Target/FirstName] + [//Target/LastName])|
|NormalizeString([//Target/FirstName] + Left([//Target/MiddleName], 1) + [//Target/LastName])|
|NormalizeString([//Target/FirstName] + [//Target/LastName]) + [//UniquenessKey]|
To exclude a user itself from query results and be able to use the same workflow for new users as well as updated users replace Conflict Filter with
/Person[AccountName = '[//Value]' and not(ObjectID='[//Target/ObjectID]')], also replace LDAP Filter with
(&(objectClass=user)(objectCategory=person)(sAMAccountName=[//Value])(!(employeeID=[//Target/EmployeeID])))- assuming employeeID gets populated in AD.