bea.com | products | dev2dev | support | askBEA |
![]() |
![]() |
|
![]() |
e-docs > WebLogic Platform > WebLogic Portal > Development Guide > Using the Expression Package |
Development Guide
|
Using the Expression Package
This topic illustrates how to use the services of the Expression package. The Expression package is part of the Personalization and Interaction Management features in WebLogic Portal. The Expression package allows you to externalize calculations, business policies, decision trees, and other operations from your Java code.
This section includes information on the following subjects:
What Is the Expression Package?
As previously mentioned, the Expression package allows you to externalize business logic or formulas from your Java code. Using the Expression package, any arithmetic, boolean, relational or conditional statement can be represented. You can use the Expression package to dynamically assemble and evaluate your own business logic.
An example of Expression package use is a rental car agency using it for calculating rental costs, which may change frequently. Rather than expressing the calculation using Java statements, the calculation can be externalized from the Java code into an XML document and interpreted at run time.
WebLogic Portal provides an Expression example. To see this example, take the following steps:
Figure 16-2 Execute Expression Example
Figure 16-3 JSP Source
This page shows the JSP source (exec_expression.jsp) for the Expression Example. After the expression is executed (and a parameter is changed), the results are contained in the exec_expression_results.jsp. Both JSP files are located in the <BEA_HOME>\weblogic700\samples\portal\p13nDomain\beaApps\p13nApp\p13n directory.
The next step provides information about how the expression works.
Figure 16-4 How Does It Work? Execute Expression
Figure 16-5 Preview Expression as XML
The next section discusses the differences between the Expressions package and the Rules Framework.
Using Rules or Expressions
One of the applications of the Rules Manager is to use business rules to match users and groups with appropriate content. The Rules Manager, like the Expressions package, is part of WebLogic Portal Personalization and Interaction Management.
The most important difference between the Expression package and the Rules Engine is that the Expression package uses named variables, while the Rules Engine does not. Additionally, the Rules Manager uses rule sets, where one rule can trigger another, that is, the rules can cascade.
In general, you use expressions when you want to bind variables to values (usually only one) and rules where you need pattern detection and want to evaluate all possible bindings to variables.
The Rule Engine has extremely powerful pattern matching and inferencing capabilities. However, these capabilities may come with a performance penalty. If you find yourself repeatedly executing a named rule, consider converting the rule to an expression. If you do not leverage the inferencing capabilities of the Rule Engine or rarely have more than one potential variable-value binding, then use expressions.
You should carefully evaluate the performance differences between using expressions, supplying an explicit binding between variables and values through a UnificationList or custom Unifier, and using the Rule Engine to explore all potential bindings.
Table 16-1 shows some examples of when to use rules and expressions.
To see an example of rules, take the following steps:
Figure 16-6 Rules Manager Example
Figure 16-7 How Does It Work? Rules Manager
Expression Package Classes
The Expression package allows users to dynamically assemble and execute XML-based expressions. The package defines a set of Java classes that represent various types of expression operators, and contains services for evaluating expressions consisting of instances of these operators.
The Expression package includes a base Expression class, a Variable class, and the following operator classes for operating on Expressions and Variables:
The Expression package also includes the following services for operating on expressions:
Unlike an expression written directly in Java and executed from within a Java program, the Expression package allows you to dynamically assemble and modify expressions from within your Java programs. An expression may be modified any number of times both before and after evaluation. When you assemble expressions using the Expression package you can also take advantage the advanced features of the Expression package, such as expression caching, validation, and optimization.
The Expression package serves as the foundation of the BEA Rules Engine. The Rules Engine leverages the package in order to represent and evaluate rule condition and action expressions. Likewise, you can use the Expression package to dynamically assemble and evaluate your own business logic.
The Package Structure for the Expression Package
The Expression package interfaces and abstract classes can be found in the following package: com.bea.p13n.expression
The Expression package operators are organized in the following packages:
Basic language operators—com.bea.p13n.expression.operators
Logical operators—com.bea.p13n.expression.operators.logical
String operators—com.bea.p13n.expression.operators.string
Mathematical operators—com.bea.p13n.expression.operators.math
Comparative operators—com.bea.p13n.expression.operators.comparative
Collection operators—com.bea.p13n.expression.operators.collection
The Expression package related classes are packaged in the p13n_util.jar archive.
Assembling and Managing Expressions
Before you can begin using expressions, you must first learn how to programmatically assemble them using the various operator classes provided in the Expression package.
An expression is represented as a tree, where each node is another expression itself or a plain Java object. Expression trees are assembled in a bottom-up manner; a child expression or Java object is first created, and then added to a parent expression.
Figure 16-8 illustrates the steps required to build an expression tree.
Figure 16-8 Building an Expression Tree
Maintaining Parent-child Relationships
Each of the operator classes defined in the Expression package extends a common base class that contains the necessary logic for maintaining parent-child relationships; therefore, you do not have to worry about maintaining these relationships while assembling expressions. However, it is possible to modify the structure of an expression after it has been created.
Table 16-2 shows the operators provided in the Expression interface for adding, modifying, or removing subexpressions in an expression.
For more information about the Expression interface, see the Javadoc. Managing the Expression Cache The expression interface also includes methods to manage the caching of results. The result of evaluating an expression may be cached in each expression object. When the cache is enabled for an expression, trying to evaluate the same expression a second time will return the cached value. Note: By default, caching is turned off. You may want to keep the cache turned off for some operators, such as MethodCall. Table 16-3 shows the methods provided in the Expression interface to manage the caching of results.
For more information about the Expression interface, see the Javadoc.
Working with Expressions
After you have assembled an expression, you are ready to work with it using the various Expression package services. These services allow you to prepare an assembled expression for evaluation, validate that the expression is well-formed, optimize its structure, and finally, evaluate the expression.
The following information is presented in this section:
The Expression Factory
The ExpressionFactory provides methods to create the various Expression package services and data structures used by these services.
For example, the following method will create an instance of the Validator service:
ExpressionFactory.createValidator(null);
For more detail on how to construct the various Expression package services, see the Javadoc.
Expression Package Services
The Expression package offers services which can be used on any expression that is built using the operators in the Expression package.
Unification Service
The Unifier is used to unify variables (assign values to variables) present in an expression. The Unifier uses a data structure known as a UnificationList that stores the variable name and the corresponding value of the variable. Like the Unifier, the UnificationList instances are created via the ExpressionFactory. The Unifier gets the value from the list for a particular variable using the variable name as a key to search the UnificationList, and binds the retrieved value to the variable.
For more information about the Unifier interface and the ExpressionFactory class, see the Javadoc.
Optimization Service
The Optimizer is used to optimize an expression. The default optimization algorithm used by the Optimizer is shown below.
For more information about the Optimizer interface and the ExpressionFactory class, see the Javadoc.
Validation Service
The Validator is used to validate an expression. The default validation algorithm used by the Validator is as follows:
For each operand of an operator:
The Validator can be used in a stateless or stateful mode. In stateless mode, any expression evaluations necessary to perform validation will be executed in stateless mode.
For more information about stateless and stateful evaluation modes, see the Evaluation Service section below.
For more information about the Validator interface and the ExpressionFactory class, see the Javadoc.
Evaluation Service
The Evaluator is used to evaluate an expression. An expression can be evaluated in stateful or stateless mode:
Stateful mode
In this mode, the value of each variable that appears in the expression is determined by retrieving the value set within the variable.
In other words, stateful mode relies upon the expression having been previously unified by a Unifier.
When an expression is evaluated in stateful mode and results caching is turned on, the results of evaluation will be cached within the expression.
Stateless mode
In this mode, the value of each variable that appears in the expression is determined by looking up a value that is bound to the name of the variable in an external data structure.
In other words, the evaluation process does not rely upon state associated with the expression, and as such, does not require the expression to be unified before evaluation.
The data structure that contains the name-value mappings for variables is known as a UnificationList and is associated with the Evaluator. Like the Evaluator, the UnificationList instances can be created using the ExpressionFactory.
A side effect of stateless mode is that expression evaluation cannot take advantage of results caching.
You can use of stateful mode in a situation where an expression need only be evaluated within a single thread of execution. In the case of multithreaded evaluation of a single expression, you must use stateless mode.
Note: If an expression does not contain variables, then there is no difference between the two evaluation modes.
For more information about the Evaluator interface and the ExpressionFactory class, see the Javadoc.
Execution Service
The Executor aggregates the Unification Service, Validation Service and Evaluation Service. The execute method on an Executor takes a Unifier, a Validator and an Evaluator to execute a cycle of unification-validation-evaluation operations.
The algorithm used by the Executor is shown below:
Unification
Note: The Unifier should be null in the case where the expression passed to the Executor is already unified, or the expression is to be evaluated in stateless mode.
Validation
Evaluation
Note: If the Evaluator passed is stateless, then the Unifier should be null.
For more information about the Executor interface and the ExpressionFactory class, see the Javadoc.
Code Examples
This section contains examples that illustrate how to construct expressions programmatically and use the Expression package services.
This section contains the following four code examples:
Stateful Evaluation of a Simple Expression
A logical expression is constructed and executed in stateful mode. The expression does not contain any variables.
Listing 16-1 Example
The source code for creating and executing the expression is shown below:
Expression expression = new LogicalAnd(Boolean.TRUE, Boolean.FALSE);
// Prepare for creating an executor by creating a stateful
// evaluator. Since the expression does not contain variables,
// we are not using a validator or a unifier in this example,
// so we will not create them.
// null is passed for the environment Map.
Evaluator evaluator = ExpressionFactory.createEvaluator(null);
// null is passed for the environment Map.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing null for both the unifier
// and validator parameters.
Object result = executor.execute(expression, null, null, evaluator);
// The result should be Boolean.FALSE.
Stateful Evaluation of an Expression Containing Variables
An expression containing variables is constructed and evaluated in stateful mode.
Listing 16-2 Example
The source code for creating and executing the expression in stateful mode is shown below.
// Create a variable that can store an object of type Boolean
// and whose name is "?booleanVariable".
Variable booleanVariable = new Variable("?booleanVariable", Boolean.class);
// Now, we will use the variable that we created in the above step.
Expression expression = new LogicalAnd(Boolean.TRUE, booleanVariable);
// Next, we'll unify the expression by binding any variables
// present in the expression. In the above case, there is one
// variable in the expression so the variable needs to be assigned a
// value. This is shown below.
// Create a UnificationList to store the variable name and value as
// key-value pairs.
UnificationList unificationList = ExpressionFactory.createUnificationList(null);
UnificationList.addObject("?booleanVariable", Boolean.FALSE);
// Create a unifier.
Unifier unifier = ExpressionFactory.createUnifier(null, unificationList);
// Prepare for creating an executor by creating a stateful
// evaluator. We are not using a validator in this example,
// so we will not create one.
// null is passed for the environment Map.
Evaluator evaluator = ExpressionFactory.createEvaluator(null);
// null is passed for environment Map.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing a unifier and a null
// validator.
Object result = executor.execute(expression, unifier, null, evaluator);
// The result should be Boolean.FALSE.
Note: The expression can be unified before calling the execute method by calling the unify method on the Unifier. Once the expression is unified there is no need to pass a unifier to the execute method of the executor.
Stateless Validation and Evaluation of an Expression
Containing Variables
An expression containing variables is constructed and evaluated in stateless mode. The Validator service is also used to validate the expression.
Listing 16-3 Example
The source code for creating and executing the expression in stateless mode is shown below.
// Create a variable that can store an object of type Boolean
// and whose name is "?booleanVariable".
Variable booleanVariable = new Variable("?booleanVariable", Boolean.class);
// Now we will use the variable that we created in the above step.
Expression expression = new LogicalAnd(Boolean.TRUE, booleanVariable);
// Next, we'll unify the expression by binding any variables
// present in the expression. In the above case there is one
// variable in the expression, so the variable needs to be assigned
// a value. This is shown below.
// Create a UnificationList to store the variable name and value as
// key-value pairs.
UnificationList unificationList = ExpressionFactory.createUnificationList(null);
UnificationList.addObject("?booleanVariable", Boolean.FALSE);
// Prepare for creating an executor by creating a stateless
// evaluator. We are not using a unifier in this example,
// so we will not create one.
// Creating a stateless evaluator by passing null for the
// environment Map and the UnificationList.
Evaluator evaluator = ExpressionFactory.createEvaluator(null, unificationList);
// Creating a stateless validator.
Validator validator = ExpressionFactory.createValidator(null, evaluator);
// Creating an executor.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing null for the unifier and
// a non-null validator.
Object result = executor.execute(expression, null, validator, evaluator)
// The result should be Boolean.FALSE.
// After calling execute method, the given expression will not be
// modified by any services that were used above.
// The stateless execution mode is useful if an expression is shared
// between multiple threads.
Stateful Validation and Evaluation of an Expression
Containing Variables
An expression containing variables is constructed and evaluated in stateful mode. The Validator service is also used to validate the expression.
Listing 16-4 Example
The source code for creating and executing the expression in a stateful mode is shown below.
// Create a variable that can store an object of type Boolean
// and whose name is "?booleanVariable".
Variable booleanVariable = new Variable("?booleanVariable", Boolean.class);
// Now we will use the variable that we created in the above step.
Expression expression = new LogicalAnd(Boolean.TRUE, booleanVariable);
// Next, we'll unify the expression by binding any variables
// present in the expression. In the above case, there is one
// variable in the expression, so the variable needs to be assigned
// a value. This is shown below.
// Create a UnificationList to store the variable name and value
// as key-value pairs.
UnificationList unificationList = ExpressionFactory.createUnificationList(null);
UnificationList.addObject("?booleanVariable", Boolean.FALSE);
// Create a unifier.
Unifier unifier = ExpressionFactory.createUnifier(null, unificationList);
// Prepare for creating an executor by creating a stateful
// evaluator and validator.
// null is passed for the environment Map.
Evaluator evaluator = ExpressionFactory.createEvaluator(null);
// null is passed for the environment Map.
// Creating a validator.
Validator validator = ExpressionFactory.createValidator(null);
// Creating an executor.
Executor executor = ExpressionFactory.createExecutor(null);
// Execute the above expression by passing a unifier and a non-null
// validator.
Object result = executor.execute(expression, unifier, validator, evaluator);
// The result should be Boolean.FALSE.
Note: The expression can be unified before calling the execute method by calling the unify method on the Unifier. Once the expression is unified there is no need to pass a unifier to the execute method of the Executor. The validation service can be used directly by calling the validate method. The validate method throws an InvalidExpressionException if the given expression is invalid.
Configuring the Expression Package
The expression.properties file contains configuration settings for the Expression package and should be modified with care.
This file is archived in p13n_util.jar under the package com.bea.p13n.expression.
##
# Expression Comparator null handling
#
# If the following property is set to true the Expression
# Comparator will return false as the result of comparing
# any non-null value to a null, regardless of the
# comparison being performed.
#
# Defaults to true.
##
expression.comparator.nullcheck=true
##
# Expression Comparator equality epsilon.
#
# The following property determines the epsilon value for
# numeric equality comparisons.
#
# Defaults to 0.
##
expression.comparator.epsilon=0.00001
##
# Expression Introspector Method Array Caching
#
# If the following property is set to true the Expression
# Introspector will cache the array of Methods implemented by a
# Java Class.
#
# Defaults to true.
##
expression.introspector.method.array.cache=true
##
# Expression Introspector Method Caching
#
# If the following property is set to true the Expression
# Introspector will cache Methods by signature.
#
# Defaults to true.
##
expression.introspector.method.cache=true
##
# Expression Parser Node Support Classes
#
# This property supports a comma-delimited list of classes
# extending the base AST NodeSupport class. Such classes
# provide node creation support for expression-schema namespaces
# required for constructing the intermediate AST representing a
# given Expression instance.
#
# All NodeSupport subclasses must co-exist peacefully with the
# required CoreNodeSupport instance.
##
parser.node.support.list=\
com.bea.p13n.expression.internal.parser.expression.ExpressionNodeSupport
##
# Expression Parser Transform Visitor Class
#
# This property specifies the ExpressionTranformVisitor or
# subclass to be used for intermediate AST-to-Expression
# transformations.
#
##
parser.transform=\
com.bea.p13n.expression.internal.parser.expression.ExpressionTransformVisitor
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |