Go with the flow
Build Web applications with Webflow components
Webflow is the core of the BEA WebLogic Portal framework. BEA WebLogic Portal encompasses many components including user management, commerce, entitlements, and campaigns. Web applications built with BEA WebLogic Portal can leverage the Webflow system to help separate the presentation logic and the underlying business processes.
The Model-View-Controller 2 (MVC2) pattern is the foundation of Webflow’s architecture. Webflow functions mostly as a controller, but it also provides basic model support and includes tag libraries for the view. Unlike most other controller systems, Webflow is more like a workflow system. It provides the ability to chain multiple business logic classes together and supports branching. It builds on the event and handler concept of other controller systems, like Struts, but provides more functionality through chaining and branching based on events.
Web applications can leverage Webflow’s functionality to set up event, logic, and site flows. Webflow’s “flow” begins at a presentation node (JavaServer Pages (JSP)) and continues through zero or more classes (event handlers called InputProcessor
s) until another presentation node is encountered. This design makes Webflow a powerful tool for building Web applications.
Webflow’s key features include:
- Component-based structure encourages code reuse; frontend, middle-tier, and backend components are all addressed
- Java 2 Platform, Enterprise Edition (J2EE) compliance
- Built-in form validation
- Inherent separation between responsibilities of frontend and backend developers
Let’s examine each component and then discuss some best practices for Webflow development.
Note: You can download this article’s source code from Resources.
Webflow components
A Webflow is composed entirely of nodes. A node is an abstract component that represents an object in a Web application. Nodes are interconnected by transitions (events). A simple Webflow can illustrate this:
Origin JSP -> Input processor -> Destination JSP
Each arrow in the illustration is an event processed by the Webflow system. Therefore, a Webflow is a string of connected nodes that outlines a logical flow of a part of a Web application. This section briefly describes the types of nodes and other concepts that compose the Webflow framework. We will not rehash existing BEA documentation here. In-depth information about these components can be found on BEA Systems’ Website (see Resources).
Presentation nodes
Presentation nodes represent components that allow users to interact with a Web application. Some examples include JSP, HTML, Wireless Markup Language (WML), or servlets.
InputProcessor nodes
These nodes are Java classes that implement the InputProcessor
interface. As a result, InputProcessor
s must implement the following method:
public Object process(HttpSerlvetRequest request, Object requestContext) throws ProcessingException
The HttpServletRequest
object is the request submitted to the WebLogic application server from a client. This request derives from the presentation node that preceded the InputProcessor
. In the simple Webflow example above, a form or anchor tag in the Origin JSP creates the request that passes to the InputProcessor
. The requestContext
is a unique identifier for the request.
Pipelines and PipelineComponent nodes
PipelineComponent
s execute specific tasks related to business processes and can be transactional or nontransactional. Multiple PipelineComponent
s can connect into a single pipeline. Pipeline execution is linear because it does not support branching. Transactional pipelines ensure that all the components complete successfully or the transaction will roll back. PipelineComponent
s contain business logic that may apply to multiple Web applications within a larger enterprise application and are therefore loaded into BEA WebLogic’s Enterprise JavaBeans (EJB) container. PipelineComponent
s implement the PipelineComponent
interface. As a result, PipelineComponent
s must implement the following method:
public Object process(PipelineSession pipelineSession, Object requestContext) throws PipelineException, RemoteException
The PipelineSession
mechanism allows communication between InputProcessor
s within the Web application and PipelineComponent
s within the enterprise application. The requestContext
is the same unique identifier passed to the InputProcessor
s.
Namespaces
Namespaces allow developers to divide a Web application into multiple Webflows. Each Webflow has its own namespace, and it is not embeddable. Usually, namespaces are created along logical lines. For example, in a typical e-commerce Website, a developer could create separate namespaces for an online catalog, profile management, check-out, and order lookup.
Events
Events are the transitions from one node to another and the transitions between Webflows and pipelines. When a node completes its task, it returns an event used by the Webflow system to determine the next node in the Webflow to call. Presentation nodes can generate events from form submissions, hyperlinks, or any other method of generating a request to the server. InputProcessor
nodes generate events by the return value from the process method. They can also generate exception events by throwing exceptions. Both event types from InputProcessor
s tell the Webflow system which node is next.
The E-Business Control Center
The E-Business Control Center (EBCC) is the main graphical user interface (GUI) application used to create Webflows and manage the BEA WebLogic Portal application. Within EBCC, developers can associate nodes with JSP pages, PipelineComponent
s, and InputProcessor
classes. They can also perform other tasks related to BEA WebLogic Portal such as user management tasks and campaign tasks. For this article, we just focus on EBCC aspects related to Webflow creation and management.
Under EBCC’s hood, several XML files store the information about a Webflow. While a developer usually doesn’t edit these files directly, it is important to know about the following Webflow files:
- The project file,
<project name>.eaprj
, is the main project file for a Webflow application - The
.wf
file,<namespace>.wf
, contains the primary information for a Webflow namespace, including transitions/events between nodes - The
.wf.ui
and.ui
files contain information used to display Webflow components in the way they were last organized in the EBCC - The
.wfx
file allows extensions to Webflow and is outside this article’s scope
Sample Webflow application
In this section, we create a sample application using Webflow to simulate a shipment tracking process. This sample application includes the concept of emailing tracking information to the user. However, the actual work of retrieving the tracking information and emailing it has been removed to keep the application simple.
Remember: Pipelines are linear, so branching based on a pipeline’s result is difficult, and looping is even more difficult; therefore, pipelines should be placed in a location where the flow is linear and no branching or looping occurs. Unless you need transactions, pipelines are usually too restricting.
Webflow in EBCC
The first step in building a Webflow-based application is to conceptually break down the pieces. A few best practices apply here. For example, it is a good idea to separate form validation from the rest of the logic. In the Webflow world, this means putting the validation logic into its own InputProcessor
.
Another best practice involves deciding whether to use pipelines and PipelineComponent
s. Pipelines are ideal when business logic is grouped together and no branching or looping conditions exist, as mentioned above. If the execution flow will reach a certain point after which one of many different flows are taken next, then you should use InputProcessor
s. Likewise, if you have a condition where you need to repeat the same flow again, you should use InputProcessor
s. However, if neither of these cases applies to you, pipelines may suit your needs.
Lastly, consider whether the flow needs to be transactional. For example, if a flow contains two steps and both must complete successfully and commit or unsuccessfully and roll back, you may want to leverage PipelineComponent
s as EJB components, as this allows support for transactions.
In our application, we have a branching case, regardless of whether the user selects to receive email about the tracking information. Therefore, we put all our logic into InputProcessor
s. We’ll have three InputProcessor
s for our application’s three logical steps. These steps are:
- Retrieve input from the user and validate it
- Retrieve tracking information from the backend system
- Optionally email tracking information to the user
An implied fourth step is displaying the tracking information to the user. That logic is not part of our business logic, but rather the view logic, and therefore belongs in a JSP page.
The Webflow, following the addition of InputProcessor
s and the setup of JSP pages, is depicted in Figure 1:
You can see the starting node is the index presentation node. This node contains a single event named submit (shown in Figure 2) that directs the flow to the ExampleValidationIP
.
For this node, there are two events. The first one, shown in Figure 3, is an exception event for the com.bea.p13n.appflow.Webflow.forms.InvalidFormDataException
exception. If the ExampleValidationIP
class throws an instance of this exception, then the Webflow will follow this event back to the index presentation node.
Details for Figures 2 and 3 are shown in Figures 4 and 5, respectively:
The JSP page
We now need to write the code that performs validation and throws the exception. Before we tackle this piece, we first need to construct our JSP page or at least have in mind what the JSP page will contain. We will have a single form for the user to supply tracking information, such as a tracking number. The user will have a selection for email and a place to insert his email address.
As part of Webflow, BEA provides a tag library that supplies tags that facilitate form value validation. These tags and the associated API are called the validated form. The validated form is an under-documented feature of Webflow. Roughly speaking, a validated form allows developers to easily validate form fields by name (the HttpServletRequest
parameter’s name) and populate very simple JavaBean properties. This API does not support complex JavaBean operations.
First we include the tag library on the JSP page like this:
<%@ taglib uri="WebFlow.tld" prefix="wf" %>
Our validated form within the JSP looks like this:
<wf:validatedForm event="submit" namespace="Example" applyStyle="field" invalidStyle="color: red;">
Tracking number <wf:text name="trackingNumber"/><br>
Email? <wf:checkbox name="email" value="true"/><br>
Email address <wf:text name="emailAddress"/><br>
<input type="submit" value="Submit" name="submit"/>
</wf:validatedForm>
The validation code
Now that we have set up our JSP page, we can start on the validation code. We will use a few classes from the ValidatedForm
API: the ValidatedFormFactory
creates the ValidatedForm
class, and the ValidatedValuesFactory
creates the ValidatedValues
class. The ValidatedForm
class and the ValidatedValues
class together track the values the user supplies on each form field and determine whether the particular form field is valid. So, when validation errors are encountered, and our Webflow redirects the user back to the input page, the ValidatedForm
API repopulates the form fields with the previous values, and any error messages will display.
The code to validate a form field looks like this:
// Create the request JavaBean and store it in the request
TrackingRequest trackingRequest = new TrackingRequest();
request.setAttribute("trackingRequest", trackingRequest);
ValidatedForm vForm = ValidatedFormFactory.getValidatedForm();
ValidatedValues vValues = ValidatedValuesFactory.getValidatedValues(request);
// Set the JavaBean values, except the Boolean for the check box, which
// we will have to set automatically, because the ValidatedForm API from
// BEA doesn't handle it
vForm.validate(vValues, trackingRequest);
...
// Validate the tracking number
vForm.validate(vValues, STRING_VALIDATOR, "trackingNumber", new MinMaxExpression(10, 15),"The tracking number must be between 10 and 15 characters");
// If the user selected email, validate the email address
if (trackingRequest.isEmail()) {
vForm.validate(vValues, STRING_VALIDATOR, "emailAddress",
new MinMaxExpression(10, 100),
"The email address must be between 10 and 100 characters");
}
if (vValues.getInvalidFieldCount() > 0) {
throw new InvalidFormDataException("Please correct the invalid fields");
}
This code snippet uses the validate()
method. This method takes the name of the request parameter to validate, the name of the validator to use (here we use the STRING_VALIDATOR
, which is a validator provided by BEA), and an expression to assist the validator during validation.
Another important feature of the validated form is the JavaBean population. We use the validate()
method in our code, which takes the ValidatedValues
class and the JavaBean
class. Based on the values, the JavaBean properties are set accordingly.
If any validation errors occur, we throw an InvalidFormDataException
, which, as we mentioned above, redirects the user back to the index JSP page. If the user does not supply a proper tracking number, he receives the error message, “The tracking number must be between 10 and 15 characters.”
If the validation succeeds, then the ExampleValidationIP
returns the string "success,"
which signals to the Webflow to direct the flow to the ExampleBackendIP
(see Figures 1, 2, and 4).
InputProcessor branching
The ExampleBackendIP
InputProcessor
‘s code is left out intentionally. It is more important to see how Webflow acts as a flow system rather than delve into complex business logic. The Webflow diagram in Figure 1 shows that this InputProcessor
has two events diverging from it: one to the result presentation node and the other to the ExampleEmailIP
. Here is the code that chooses which event to return from the ExampleBackendIP
:
// Retrieve the TrackingRequest out of the request
TrackingRequest trackingRequest = (TrackingRequest) request.getAttribute("trackingRequest");
...
// Check what to forward to
return trackingRequest.isEmail() ? "email" : "complete";
This returns the correct value to the Webflow system, which in turn determines which path continues execution. For our example, if the user selects to receive email, then the string "email"
returns. Otherwise, the string "complete"
returns. Although Figure 1 doesn’t show you exactly which event points to which part of the Webflow, it is easy enough to assume that the event leading from the ExampleBackendIP
to the ExampleEmailIP
is "email,"
and the event leading from the ExampleBackendIP
to the result.jsp
is "complete."
In general, the events within the Webflow system are just simple strings. If you recall from above, the return value from the InputProcessor
‘s process()
method is type object. The Webflow system will execute a toString()
on this object to determine how to continue executing.
In Figure 1, the ExampleEmailIP
also has a link to result.jsp
. This link is also called “complete” (not shown), but could be named whatever we wished. This is the string the ExampleEmailIP process()
method returns. This flow is not the only Webflow possibility. The system is flexible enough to allow branching to other InputProcessor
s as well as other presentation nodes. You can branch or link to any type of node that Webflow allows, including custom nodes.
We have left out the code for the ExampleEmailIP
. We also left out the business logic so the code is not cluttered and you can more easily learn the Webflow techniques. You can view this and the rest of our application by downloading the complete source.
Results
In our example, the final JSP page contains some very simple logic to display the tracking information we gathered in the ExampleBackendIP
and stored in the HttpServletRequest
:
<jsp:useBean id="trackingData" scope="request" type="com.inversoft.javaworld.TrackingData"/>
<jsp:useBean id="trackingRequest" scope="request" type="com.inversoft.javaworld.TrackingRequest"/>
The value of your shipment:
<jsp:getProperty name="trackingData" property="value"/>
The description of your shipment:
<jsp:getProperty name="trackingData" property="description"/>
<%
if (trackingRequest.isEmail()) {
%>
Your shipment information has been emailed to:
<jsp:getProperty name="trackingRequest" property="emailAddress"/>
<%
}
%>
The results are retrieved from the HttpServletRequest
because either the ExampleBackendIP
or the ExampleEmailIP
forwards the request to this node. This common mechanism communicates data from the InputProcessor
s to JSP pages. Developers can also store data in the user’s session or the application context if they wish, but must weigh the value and consequences along with each possibility’s business requirements before deciding.
Branch out
Webflow is a very useful framework for developing Web-based applications using BEA WebLogic and BEA WebLogic Portal. Concepts such as inter-input processor communication, pipelines, and event branching make Webflow unique. We hope the ideas we presented here give you a better idea of what Webflow is and what it can do. You can find more information about Webflow, including other framework components such as wildcard nodes or exception events, at BEA’s Website.