by: Daniel Ovalle
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.
Promotion | User attributes criteria |
---|---|
A | user age between 18 and 24 years and member_code equals to ‘O’ or ‘P’ or ‘Q’ |
B | 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 --> <rde-dm:rdb alias="repoX" mode="query" rde-id="1" item-tag="row" sql="SELECT ATTRIBUTE_X, ATTRIBUTE_Y FROM TABLE WHERE USER_ID = [#request:userid#]" /> <!-- Get output into request attributes - XPATH --> <rde-dm:attribute mode="write" attribute="request:user_attributeX" op="set" value="[#xpath:rde-node('1')/row/ATTRIBUTEX/text()#]" /> … 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.
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:
he specific tasks into the WebService are:
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 --> <rde-dm:include content="dynaments/sample/mvel.xml"/> <!-- DEBUG --> <rde-dm:attribute attribute="request:mvelout" mode="read"/>
In the sample dynament content, we can identify the following:
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:
Promotion | User attributes criteria |
---|---|
A | fn.age(BIRTHDATE) <= 18 && fn.age(BIRTHDATE) >= && MEMBERCODE ~= ‘[OPQ]’ |
B | 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.
Source: Using MVEL Expression Language with OpenText Technology
© copyright 2011 by oshyn