While recently working on an OpenText Web Solutions (formally RedDot) project for a client, I came across the common issue of retrieving user attributes that are stored on several different data repositories. Many organizations face this issue due to the fact that their user repository configurations are usually a product of several years of different technology implementations. To address this issue requires the implementation of complex criteria logic to evaluate user attributes and segment users into groups to grant access to specific CMS content.
To address the need of complex criteria logic, it is common practice to use a synchronization process to link all of the user’s information for different situations (i.e. login, update user information forms, business logic events, etc.).
In order to achieve this, we need to provide a solution that applies different criteria logic that evaluates the eligibility of a user for different contents of the CMS. For example:
Say the CMS content is a list of product promotions targeted to different groups of users. Each promotion has eligibility criteria logic match with the user attributes to decide if the promotion should be displayed or not.
User attributes criteria
user age between 18 and 24 years and member_code equals to ‘O’ or ‘P’ or ‘Q’
user birthday was no more than 10 days before today and
no more than 15 days after today and
member_code could be ‘H’, or ‘J’ or ‘K’
All the user attributes are stored on different data repositories (databases) and are accessed using standard database connections. So if we want to use standard dynaments to accomplish the criteria expressions, a lot of XML content is needed.
Here is a sample of a dynament used to get user attributes from a data repository and into a dynament to build a criteria logic evaluation:
<!-- Get User attribute - SQL -->
sql="SELECT ATTRIBUTE_X, ATTRIBUTE_Y FROM TABLE
WHERE USER_ID = [#request:userid#]" />
<!-- Get output into request attributes - XPATH -->
… a XPATH should follow for each user attribute.
This is common on dynaments; the maintenance of the XML content becomes a cumbersome task. Looking at the amount of criteria logic implemented on different dynaments (XML content) for the project, we can see that a lot of similar logic will be created for the XLM content.
Using MVEL Expressions Language
With so much criteria logic needing to be created for this project, it is easy to see the advantage of using a service like MVEL that can make building criteria logic (expressions) easier.
The objective of this sample is to offer a Boolean expression evaluator for users attributes based expressions using MVEL language.
First, we selected to build a web service to implement the MVEL expressions evaluator logic and the code to access all of the user attributes data sources.
Here is the architecture diagram for the implementation:
The specific tasks into the WebService are:
- Get the user’s attributes from all the existent repositories. This is done using a SQL sentence query for each of the data repositories. This query should return only one record for a specific user.
- Replace the user attributes field names on the provided Boolean MVEL expression using the user attributes fields values extracted from the data repositories. In this step, the WebService verifies the embedded cache for specific user attributes values, if possible, it uses cache values, and otherwise it retrieves values from the data repositories and stores those values into the cache.
- Evaluates the MVEL expression and returns the Boolean result.
Now we can see one example of the dynaments that can be used into the project to run criteria logic expression over user attributes:
<!-- MVEL expression to evaluate the user birthday attribute. -->
<rde-dm:attribute attribute="request:expression" mode="write"
value="BIRTHDATE != null || BIRTHDATE <= fn.date('2999-12-31')"/>
<!-- Includes the MVEL dynament -->
<!-- DEBUG -->
<rde-dm:attribute attribute="request:mvelout" mode="read"/>
In the sample dynament content, we can identify the following:
- We build a request attribute “expression” to store the string value with the MVEL language expression.
- This expression uses the user “BIRTHDATE” parameter and verifies the value of the parameter to be different than NULL.
- Then compares the value of the “BIRTHDATE” parameter against the result of a function “fn.date(String date)” that returns a Date value from the String representation on a date using the “YYYY-MM-DD” format.
- Finally evaluates the result of the two previous results using the logic operator “||” OR.
- Includes the dynament that execute the request to the MVEL WebService using the “request:expression” and the current session user data.
- The result of the WebService is stored into a request attribute “request:mvelout”, so this attribute can be used on the dynaments project logic.
Implementing the Criteria Logic
Once the WebService is implemented and the connectors and prepared envelopes configured, we can start using the MVEL to build our criteria expressions.
First we build the MVEL expression for each promotion:
User attributes criteria
fn.age(BIRTHDATE) <= 18 && fn.age(BIRTHDATE) >= && MEMBERCODE ~= ‘[OPQ]’
fn.birthday(BIRTHDATE) < fn.date(fn.today(),10) && fn.birthday(BIRTHDATE) > fn.date(fn.today(), -15) && MEMBERCODE ~= ‘[HJK]’
It’s important to note that on MVEL we can add custom functions implementing a simple approach described on the MVEL documentation page (http://mvel.codehaus.org/), this is the case for our fn.age(), fn.date() and fn.birthday() functions.
Now to accomplish the objective to build as many criteria expressions as needed, we can use a database table or a configuration file to store the MVEL expressions and assign an ID so we can retrieve the expression content using a dynament.
Our implementation uses the following relational design to bind the promotions and the specific MVEL criteria expressions to be evaluated:
On the previous design the MVEL expressions are stored into the PROMOTION_GROUP.CRITERIA_EXPRE field.
The PROMOTION_GROUP.GROUPID binds a specific promotion to a specific criteria expression.
When you need to implement criteria logic using XML based content (dynaments) or something different than a programming language the use of MVEL expression language is a great tool.
Externalizing business logic into web services has been proven as a good practice for RedDot Live Server implementations, and enables the organizations to reuse this logic outside the LiveServer domain.