Using Data Binding in Page Flows

Data binding is the process that ties data to presentation tags in JSPs, thereby creating dynamic web applications that are easy to build and maintain. Various JSP tags can tie data from various databinding contexts. The topic Using Form Beans to Encapsulate Data showed an example of a databinding context, called actionForm, which ties form fields to variables of a form bean. The current topic discusses the various databinding contexts, how to add data to a context, and how to retrieve data from a context.

Data Binding Contexts

To tie data to a JSP using a JSP tag, you refer to a data binding context name, as in the following example:

<netui:form action="ChangeZipCode">
     <netui:textBox dataSource="{actionForm.postalCode}"/>
     <netui:button>Submit</netui:button>
<netui:form>

In this example, the dataSource attribute on the netui:textBox tag references the variable postalCode in a form bean. Form beans are associated using the keyword actionForm. All data binding context elements can be accessed using the 'dot' notation, and the entire expression must always be enclosed in braces. For more information on accessing these elements, see Accessing Data Binding Context Properties below.

Most NetUI tags can reference a data binding context. These include all NetUI Data Binding tags and most tags in the NetUI library, in particular form field tags and other tags with a value or defaultValue attribute. For more information on the NetUI library, see Designing User Interfaces in JSPs. For more information on NetUI Data Binding tags, see Presenting Complex Data Sets in JSPs. For a detailed description of a tag and its attributes, see JSP Tags Reference, or in Source View, place your cursor inside the tag and press F1.

An overview of the various data binding contexts is given in the following table. The databinding contexts are discussed in more detail below, with the exception of application. For information on this context, consult your favorite JSP documentation. A summary of the lifetime and scalability of these contexts is described in separate section called Lifetime and Scalability of Data Binding Contexts:

Context Name
Object the Context References
Comments
pageFlow The current page flow. Properties that are defined in the current page flow controller class can be referenced. Values are read-write.
globalApp The Global App object for the web application.

Properties that are defined in Global.app, located in the web project's WEB-INF/src/global folder, can be referenced anywhere in the web application. Values are read-write.

actionForm The form bean used in an action referenced by a netui:form tag in a JSP. Properties that are defined in the form bean can be referenced. Values are read-write.
request The request that triggered the loading of the JSP. Attributes that are defined as part of a request inside an action method can be referenced in the JSP called by the action method. Values are read only.
url Query parameters on the current JSP's URL. Query parameters that are part of the URL can be referenced. Values are read only.
session Attributes in the JSP's session context. The session refers to the JSP user session object (javax.servlet.http.HttpSession) representing an individual's user session. Values are read only.
container An item in a complex data set. Refers to data referenced by many complex data binding tags, such as repeater tags. Values are read only.
pageContext The JSP's PageContext object.

The pageContext references the PageContext's page-scope attribute map of a JSP. Values are read only. In WebLogic Workshop the pageContext is also used to access actionForm, container, globalApp and pageFlow data in scriptlet when it is placed there using the netui-data:getData tag.

bundle Properties that are defined in a message resources file.

The bundle context references properties that you define in a message resources file, which allows you to implement internationalized web applications by not hard-coding text labels in your JSP pages. Values are read only.

pageInput Member variables defined in the page flow controller class.

When you have declared page inputs by using a <netui-data:declarePageInput> tag in your JSP, you can use the pageInput context to display the value of member variables that were defined in the page flow controller class. Values are read only.

application The JSP's application context. The application refers to the JSP application object (javax.servlet.ServletContext) representing the application to which the JSP belongs. Values are read only.

pageFlow

When you define a variable in your controller class, you can access this variable from any JSP page that is part of that page flow. For example, if the JPF file contains this code:

public class SimpleflowController extends PageFlowController
{
    public String labelName = "This is a label"
    ...

You can access this variable on a JSP, for instance by using a netui:label:

<netui:label value="{pageFlow.labelName}" />

The variable is read-write and can be changed, for instance in the controller's action method as is shown in the next example:

/**
 * @jpf:action
 * @jpf:forward name="success" path="nextPage.jsp"
*/
public Forward labelAction(NameActionForm form)
{
    ...
    labelName = "Default Label";
    return new Forward( "success");
}

It can also be changed in a JSP by using a form, as is shown next:

  <netui:form action="submitAction">
      <netui:textBox dataSource="{pageFlow.labelName}"/>
      ...
      <netui:button value="submit"/>
  </netui:form>

In this example, the text box will display the current value of the pageFlow's labelName variable when the form is first loaded, and upon submit the variable will hold the new value the user entered.

Accessing Page Flow Properties

In the example used above, the page flow property was defined as a public member variable in the page flow controller class. Alternatively you can define a private variable and provide access with a getter and setter method, as is shown in the following example:

  private String firstName;
    
  public String getFirstName() { 
      return firstName;
  }

  public void setFirstName(String aStr) { 
      firstName = aStr; 
  }

You can access this variable on a JSP exactly like before. For instance, you can bind the value to a netui:label as is shown next:

<netui:label value="{pageFlow.firstName}" />

In the example the method getFirstName is used to provide read access to the variable. For more information on getter and setter methods, see Naming Conventions for Form Beans below.

You can also define and access variables that are part of an object created in the controller class. You can provide access by using getter and setter methods, or by referencing the object and property name. The latter option is shown next. For instance, if the JPF file contains the code:

public class dataFlowController extends PageFlowController
{
    ...
    public Names myNames = new Names();
    ...
    public class Names implements Serializable {
        public String firstName;
        public String lastName;
    }
    ...

You can access the firstName property in a JSP like this:

<netui:label value="{pageFlow.myNames.firstName}" />

The comments in this section regarding access of page flow properties also apply to properties defined in globalApp, which is discussed next. For more information on accessing properties, see Accessing Data Binding Context Properties.

globalApp

If you need an attribute to be available across all the page flows in a web application's user (browser) session, such as a user's unique session key, you can use the Global class defined in the file Global.app. This file is located in WEB-INF/src/global. In addition to session-wide attributes, you can also use the Global class to define fallback action methods and exception handlers. An instance of this class is included by default in the JPF file, but the reference is commented out; you must uncomment the following line of code in your controller class if you want to use the Global.app instance from within a page flow:

protected global.Global globalApp

For instance, if you define a variable in the Global class:

public class Global extends GlobalApp
{

    public String defaultText = "Please Define";

And your controller file references the Global class as described above, you can use it in a JSP file:

<netui:textBox dataSource="{actionForm.firstName}" defaultValue="{globalApp.defaultText}"/>

Notice that the netui:textBox tag in the example binds to a form bean to post data and binds to globalApp's defaultText to receive its default value.

You can also write to globalApp from a JPF:

/**
 * @jpf:action
 * @jpf:forward name="success" path="nextPage.jsp"
*/
public Forward writeAction(Form form)
{
    ...
    globalApp.setDefaultText("Altered");
    return new Forward( "success");
}

actionForm

To bind to data in a form bean, you use the actionForm context in the JSP's form fields to bind to the form bean properties. You can present a new form to a user and bind to empty variables in a form bean (for an example, see Using Form Beans to Encapsulate Data), or you can prepopulate the form fields, for instance, if you want to update a record stored in a database, as is shown in the next example:

/**
* @jpf:action
* @jpf:forward name="update" path="updateItems.jsp"
* @jpf:catch method="sqlExceptionHandler" type="SQLException"
*/
public Forward updateItems(DatabaseForm form) throws Exception
{
    ...
    form.applyValuesToForm(getCurrentRow());
    return new Forward("update");
}

This action method reads a record from a database using a built-in DataBase control (this code is omitted in the example), and updates the fields in the form bean with the record before calling the JSP updateItems.jsp. This JSP will display a form field containing the values read from the record:

<netui:form action="submitUpdate">
    <netui:content value="{actionForm.itemnumber}"/>
    <netui:textBox dataSource="{actionForm.itemname}"/>
    ...
</netui:form>

In the action method called by the form, you can then write these values back to the database:

/**
 * @jpf:action
 * @jpf:forward name="updated" path="getItems.do"
 * @jpf:catch method="sqlExceptionHandler" type="SQLException"
*/
public Forward submitUpdate(DatabaseForm aDatabaseForm) throws Exception
{
    getSortFilterService().reset();
    RowSet currentRow = getCurrentRow();
    aDatabaseForm.applyUpdateValuesToRowSet(currentRow);
    javax.sql.RowSet var = myControl.updateItems(currentRow) ;
    return new Forward("updated");
}

The action attribute on the netui:form tag determines which action method is called when the user submits the form. The action method in turn determines which form bean is used to store the form fields' values upon form submission. In other words, the action method called by the form determines which form bean is used in the actionForm context. In the example, the action method submitUpdate is called in the action attribute of the netui:form tag. This action method has the form bean DatabaseForm as its argument, so it is this form bean that is used to store the values that the users entered.

When you have a form with prepopulated fields, as is the case in this example, you need to ensure that both the action method loading the JSP and the action method called upon form submission use the same form bean. The actionForm is first used to bind data to the form fields before loading the JSP, and the actionForm is subsequently used to post the user data to a new instance of the form bean. If you want to use one form bean to prepopulate form fields and use another form bean to store the data when the user submits the form, you must use a combination of the actionForm and request data binding contexts. For more information, see request below.

In the above example, the updateItems action method was passed an instance of the form bean DatabaseForm in its argument, presumably filled with data the user entered in a form that called the action method (this JSP code is not actually shown above). The action method updated this instance with a record from a database before passing the form bean object to the JSP updateItems.jsp. Alternatively, it is possible to create a new form bean inside the action method, assign values to its variables, and associate these variables with form fields on the next JSP. This is shown in the next example, which builds on the above example:

/**
 * @jpf:action
 * @jpf:forward name="update" path="updateItems.jsp"
 * @jpf:catch method="sqlExceptionHandler" type="SQLException"
 */
public Forward updateItems() throws Exception
{
    DatabaseForm form = new DatabaseForm();
    ...
    form.applyValuesToForm(getCurrentRow());
    return new Forward("update", form);
}

Notice that in this case, you need to supply the form as the second argument on the Forward object. The form fields in the JSP that is subsequently loaded bind to the form bean properties in the same manner as shown above through actionForm. If you only want to display the values in the next JSP, that is, you don't need the user to change the property values of the form bean, use request instead (see below).

In the above example, the form that is passed as the argument on the Forward object will be used to prefill the form fields. Similarly, you can have an action method that is passed one form bean in its argument, but loads data in a new form bean instance which is used in the next JSP, as is shown in the following example:

/**
 * @jpf:action
 * @jpf:forward name="update" path="updateItems.jsp"
 * @jpf:catch method="sqlExceptionHandler" type="SQLException"
 */
public Forward updateItems(SomeOtherForm oldForm) throws Exception
{
    DatabaseForm form = new DatabaseForm();
    form.selectiveCopy(oldForm);
    return new Forward("update", form);
}

In the example, only the instance of the form bean DatabaseForm is passed to the next JSP. If you want to know how to create a JSP that uses multiple forms and form beans, see How Do I: Use Multiple Forms in a JSP?

Working with Complex Form Beans

In most cases you will likely use form beans with properties that are Strings, primitive data types (such as int, long, boolean, or char), primitive data type wrappers, or arrays of any of these data types. However, in some cases your design might require a form bean that holds an instance of a complex class. When your form bean contains a complex data type, you must add a reset method to your form bean definition to ensure that an instance of the complex class is available to hold the values that the user entered in a form and subsequently submitted (posted).

Note: The reset method is called by the underlying Struts framework used by WebLogic Workshop. You do not need to call this method directly anywhere in the code.

The following example uses a form bean with a Customer property, holding customer data returned by a Java control. The source code for the form bean is shown first. Please note that you must add the reset method to the source code, using the exact signature as shown below:

public static class CustomerForm extends FormData
{
    private Customer customer;
    private String couponNumber;

    public void setCustomer(Customer customer) 
    { 
        this.customer = customer; 
    }

    public Customer getCustomer() 
    {
        return this.customer;
    }

    public void setCouponNumber(java.lang.String couponNumber)
    {
        this.couponNumber = couponNumber;
    }
   
    public java.lang.String getCouponNumber()
    {
        return this.couponNumber;
    }

    public void reset(org.apache.struts.action.ActionMapping mapping, javax.servlet.http.HttpServletRequest request)
    {
        this.customer = new Customer(); 
    }
}

Notice that the reset method creates a new instance of the Customer class. The couponNumber property is a String and therefore does not have to be mentioned in this method.

Apart from the definition of the reset method, the form bean is used in exactly the same way as a form bean with simple data types only. In the JSP you reference the various properties through the actionForm context as before:

<netui:form action="submitAction" focus="">
    ...
    Customer LastName: <netui:textBox dataSource="{actionForm.customer.lastName}"></netui:textBox>
    ...
    Customer FirstName: <netui:textBox dataSource="{actionForm.customer.firstName}"></netui:textBox>
    ...
    Coupon Number: <netui:textBox dataSource="{actionForm.couponNumber}"></netui:textBox>
    ...
    <netui:button value="Submit"></netui:button>
</netui:form>
  

And in the action method called by the form upon submit, you handle the data in the form bean as before:

/**
 * @jpf:action
 * @jpf:forward name="success" path="showDiscount.jsp"
*/
protected Forward submitAction(CustomerForm form)
{
    customerControl.updateCustomer(form.getCustomer());
    ...
    return new Forward("success");
}
Naming Conventions for Form Beans

When you create a form bean, it is recommended that you follow standard naming conventions by defining lowercase form bean properties (such as item) and the corresponding getter and setters methods (getItem and setItem). When you use the form bean editor in the controller's Flow View or Action View, the proper getter and setter methods will be automatically created for you, following the rules given in the below table. Notice that the first row in the table shows the recommended approach to naming form bean properties:

property name
(form bean variable name)

getter name
example expression
item getItem {actionForm.item}
ITem getITem {actionForm.ITem}
_Item get_Item {actionForm._Item}
iTem getiTem {actionForm.iTem}
itEm getItEm {actionForm.itEm}
_ItEm get_ItEm {actionForm._ItEm}
iTEm getiTEm {actionForm.iTEm}

Note that you cannot create a variable name that starts with an uppercase letter and is followed by a lowercase letter.

If you create the form bean in Source View, you must add the proper getter and setter methods for the various form bean properties to enable read and write access to these properties through the actionForm context, following the rules given in the above table. For getter methods, you must also make sure that:

For setter methods, you must also make sure that:

The follow example shows a form bean property and its getter and setter method:

private java.lang.String item;

public void setItem(java.lang.String item)
{
    this.item = item;
}

public java.lang.String getItem()
{
    return this.item;
}

request

If you want to call a JSP and bind it to data that you initialized in the calling action method, you can use the request data binding context. This data can either be contained in a form bean or in the request's attribute map.

Using Form Beans in the Request Context

If you want to display (read-only) the values of a form bean that the user entered in the preceding page, you can add the form bean as the second parameter to the Forward method:

/**
 * @jpf:action
 * @jpf:forward name="success" path="displayOnly.jsp"
*/
public Forward lastNameAction(NameActionForm form)
{
    // process the form...
    ...
    return new Forward( "success", form );
}

In the JSP, you reference the form bean's properties by referring to the class name, with the class name's uppercase first letter changed to lowercase (assuming you are following standard class naming conventions):

<netui:label value="{request.nameActionForm.firstname}" />

Note that the netui:label tag is not used as a form field, that is, it is not part of a form. Also notice again that you are not referring to the form bean's instance name but to the class name, with the first letter in lowercase.

You can also create a new form bean instance in the action method and add it to the request context:

/**
 * @jpf:action
 * @jpf:forward name="confirm" path="done.jsp"
*/
public Forward confirm()
{
    NameActionForm myForm = new NameActionForm();
    myForm.firstname = "John";
    return new Forward("confirm", myForm);
}

And then call the properties of this form in the same manner (the example would display "John"):

<netui:content value="{request.nameActionForm.firstname}" />

If you want to load a JSP with a form whose fields are prefilled with data from one form bean, and submit the form to another form bean, you need to use a combination of the request and actionForm binding contexts. The following example illustrates how to do this.

This is the code of the action method that adds the form bean to the request context (by passing it to the Forward constructor) and calls the JSP :

  /**
   * @jpf:action
   * @jpf:forward name="success" path="lastNameFilledViaRequest.jsp"
   */
  protected Forward prefillWithRequest()
  {
      ParentNameActionForm form1 = new ParentNameActionForm();
      // read parent's last name from database
      ...
      return new Forward("success", form1);
  }

In the JSP, the form field binds to the form bean in the request context through its defaultValue attribute and, upon form submission, posts the data the user entered to another form bean in the actionForm context via the dataSource attribute:

  <netui:form action="lastNameAction">
      ...
      <netui:textBox dataSource="{actionForm.lastname}" defaultValue="{request.parentNameActionForm.lastname}"/>
      ...
  </netui:form>

Note that the actionForm context binds to the form bean of the action method lastNameAction. For more information, see actionForm above.

Using the Attribute Map of the Request Context

Instead of using form beans to store data, you can also create an object of any other class and add it to the request context's attribute map. You do this by using the getRequest and setAttribute methods in your action method, as is shown in the following example:

/**
 * @jpf:action
 * @jpf:forward name="confirm" path="done.jsp"
*/
public Forward confirm()
{
    getRequest().setAttribute("firstname", new String("John"));
    return new Forward("confirm");
}

And you would bind to this attribute in the JSP by entering:

<netui:content value="{request.firstname}" />

Notice that in the action method, you set an attribute with a name (firstname) and a value (John) in the request object, which you accessed with the getRequest method. In the JSP, you bind to the data by simply referring to the name of the attribute.

The above example used a simple Java type, but you could define an attribute to refer to an instance of any (serializable) class:

getRequest().setAttribute("someAttribute", new MyClass(...));

And bind to it from the JSP like this:

<netui:label value="{request.someAttribute.someMyClassVariable}"/>

url

You can bind to query parameters on a URL using the url data binding context. For instance, a JSP might contain the following code snippet:

<netui:anchor action="deleteUser">Delete User
    <netui:parameter name="User_Index" value="1"></netui:parameter>
</netui:anchor>

When a user clicks the Delete User link, the deleteUser action method is invoked, loading a new JSP page and adding the User_Index attribute with value 1 to its URL, which will look something like this: http://localhost:7001/MyProjectWeb/myPageFlow/deleteUser.do?User_Index=1. On the loaded page, you can bind to this data as follows:

<netui:content value="{url.User_Index}"></netui:content>

Note: The url data binding context only binds to the first value of a query parameter. If there are multiple values for a query parameter (www.mycompany.com?User_Index=1,45,643), it will only read the first one. If you want to forward multiple-valued attributes to a JSP, use request attributes instead.

session

If you want to work with sessions (instead of with pageFlow or globalApp), you can define attributes in an action method and refer to these attributes in the JSP in very much the same way as discussed above for request. For instance, if an action method contains:

getSession().setAttribute("myAttributeKey", myObject);

Then, an expression in the JSP might be:

<netui:content value="{session.myAttributeKey.someProperty}"></netui:content>

You can use the <session-timeout> element of the /WEB-INF/web.xml file to set the session timeout value. The <session-timeout> element is part of the <session-config> element, and sets the number of idle minutes after which sessions in this Web application expire. The value set in this element can override the value set in the TimeoutSecs attribute of the <session-descriptor> element in the WebLogic-specific deployment descriptor weblogic.xml. For details, see the <session-config> section of the web.xml Deployment Descriptor Elements topic on the BEA E-docs web site.

container

The container data binding context is used to refer to the current item in complex data binding expression such as an repeater tag. Complex data binding expressions are discussed in detail in Presenting Complex Data Sets in JSPs. In short, a complex data binding expression ties to a complex data set such as a String array:

<netui-data:repeater dataSource="{actionForm.stringArray}">
    ...
    <netui:label value="{container.item}"/>
    ...
</netui-data:repeater>

For each item in the referenced String array, the item is displayed on its own line using a netui:label tag. In order to bind to the repeater's current item, the container binding context is used within the body of the repeater. The container binding context has the following properties:
Property Name
Description
item The current item in the data set. This is used in the example.
index The integer index of the current item in the data set.
container A reference to the container holding the current item.
dataSource A reference to the data set that the current container uses.
metadata A keyword reserved for implementation in a future release.

In most cases you will probably only use the container's item or index.

pageContext

The pageContext data binding context references the PageContext's page-scope attribute map of a JSP. This map contains name/value pairs which can be accessed using the pageContext.getAttribute(String) and pageContext.setAttribute(String, Object) methods. Within WebLogic Workshop the pageContext can also be used to access actionForm properties, container data, pageFlow variables and globalApp variables in scriptlet. This is accomplished with the NetUI data binding tag netui-data:getData, which places databound values in the pageContext. The following example demonstrates its use with form bean properties:

<netui:form action="lastNameAction" focus="lastname">
    ...
    <netui-data:getData resultId="first" value="{actionForm.firstname}"/>
    ...
    <%
        String firstName = (String) pageContext.getAttribute("first");
        System.out.println("First Name = " + firstName);
        ...
    %>
    ...
</netui:form>

In the example, the netui-data:getData tag is used to add an attribute to the pageContext object. The name of the attribute is defined in the tag's resultID attribute and its value is defined in its value attribute. You can subsequently access the attribute through the pageContext's getAttribute method.

The following example shows how to use netui-data:getData and pageContext with containers:

<netui-data:repeater dataSource="{pageFlow.strArr}">
    ...
    <netui-data:repeaterItem>
        <netui:label value="{container.item}" />
        <netui-data:getData resultId="item" value="{container.item}"/>
        <%
            String currentItem = (String) pageContext.getAttribute("item");
            System.out.println(currentItem);
            ...
        %>
    </netui-data:repeaterItem>
    ...
</netui-data:repeater>

The netui-data:getData tag does not only bind data from the actionForm, container, pageFlow, and globalApp contexts to the pageContext object, but can also be used to bind data from the other data binding contexts. However, the other data binding contexts can be accessed in other ways in scriptlet and therefore generally do not have to be added to the pageContext. For more information, see How Do I: Access Data Binding Contexts in Scriptlet and JavaScript?

bundle

The bundle data binding context references properties that you define in a message resources file, which allows you to implement internationalized web applications by not hard-coding text labels in your JSP pages.

For example, in your page flow controller class, you can add an annotation such as the following:

/**
 * @jpf:controller 
 * @jpf:message-resources resources="labels.Messages"
 */
 public class Controller extends PageFlowController
 { ...

In this example, the naming convention is that the message resources file must be located in the project's /WEB-INF/classes/labels directory, and the file must be named Messages.properties.

In the Messages.properties file, you might have a property such as:

nameLabel=Name 

Then in your JSP page, you can use a data binding expression such as the following:

<netui:label value="{bundle.default.nameLabel}"/> 

Alternately, you can use the key attribute on the @jpf:message-resources annotation:

In your page flow controller class annotation:

/**
 * @jpf:controller 
 * @jpf:message-resources key="foo" resources="labels.Messages"
 */
 public class Controller extends PageFlowController
 { ...

Assume that the Messages.properties file in the /WEB-INF/classes/labels directory is the same as shown in the previous example. In the JSP page, you could use a tag such as the following:

<netui:label value="{bundle['foo/jpfDirectory'].nameLabel}"/>    

In this case, your page flow controller class file is /jpfDirectory/Controller.jpf.

Another option is to use the <netui-data:declareBundle> tag. For example, in your JSP page:

<netui-data:declareBundle name="someMessages" bundlePath="com/foobar/resources/WebAppMessages"/>

This tag declares a bundle that can be referenced in a data binding expression, such as in the following example:

<netui:label value="{bundle.someMessages}"/> 

For more information, see the topics about the @jpf:message-resources Annotation and the <netui-data:declareBundle> Tag.

pageInput

When you have used one or more <netui-data:declarePageInput> tag(s) in your JSP, you can use the pageInput context to display the value of member variables defined in the page flow controller class. The values are read only. For example, a page flow named PageInputController.jpf contains an action method such as the following:

  /**
   * @jpf:action
   * @jpf:forward name="simple" path="simple.jsp"
   */
   public Forward simple()
   {
       Forward f = new Forward("simple");
       f.addPageInput("fooBean", new FooBean());
       return f;
   }

In the same page flow, a JavaBean named fooBean is defined as follows:

    public static class FooBean
{
private String foo = "This is a Foo String";
        public String getFoo()
        {
            return foo;
        }
        public void setFoo(String foo)
        {
            this.foo = foo;
        }
    }

A JSP page in this page flow might contain the following tags, which identify the type of data that will be used in the JSP, and displays the read-only value:

<netui-data:declarePageInput name="fooBean" type="pageInput.PageInputController.FooBean"/>
...
<netui:label value="{pageInput.fooBean.foo}"></netui:label>

At runtime in the rendered JSP, the label's value will be: This is a Foo String

For more information and a more interesting example, see Declaring Page Inputs.

Lifetime and Scalability of Data Binding Contexts

The data binding contexts available in WebLogic Workshop differ considerably in scope. The data of some contexts remains available globally for extended periods of time, while other data is short-lived and available locally. Design decisions to store large amounts of data in a context with too wide a scope can greatly impact scalability, and should generally be avoided. The following table summarizes lifetime and scalability considerations for the various data binding contexts, ordered from high impact to relatively low impact:

Context Name
Lifetime and Scalability
globalApp

Data in the globalApp context is available from the first request to a page flow until the end of the user session. In other words, the data in this context is maintained for each user currently using the web application. Try to limit the data that you store in this context, and consider using database storage instead for continued data persistence. In clustered (distributed) sessions, non-transient globalApp data is serialized across the cluster.

session The lifetime and scalability of session data is comparable to data in the globalApp context object. In other words, for this context you should similarly try to limit the data that you store in this context, and consider using database storage instead for continued data persistence.
pageFlow

Data in the pageFlow context is available throughout the span of the user's interactions with a page flow, including all JSP pages. When exiting a page flow, data that is contained in variables defined in the JPF is no longer available (and the associated memory becomes available for renewed use).

Although the scope of pageFlow data is more limited than that of globalApp and session data, storing large amounts of data should be done with care. All pageFlow data is stored indirectly in the session object, so any non-transient data will be serialized across the cluster, and (transient and non-transient) data is maintained separately for each user for the duration of the page flow.

request

The request object stores all the data pertaining to the request made by a user - for instance, by submitting a form or clicking a link - and the handling of the request via the JPF's action method (and possibly intermediary actions) before rendering the next JSP back to the browser. Within the action method, attributes can be added to the request and, depending on some decision logic, one of various JSPs can subsequently be called to bind to the data. Once the page is loaded on the browser, the data is no longer available.

actionForm

The actionForm object makes form bean properties available to form fields in a JSP. When this JSP calls a action method upon form submission, that in turn loads a JSP with a form, the actionForm object binds to the same form bean properties on the next JSP (unless you explicitly override this by calling a different form bean).

The amount of data available in an actionForm is determined by the form bean. A properly designed form bean, as a specific instance of good class design, should contain all and only related properties.

pageContext Data stored in the pageContext are only available for the duration of a single JSP page.
url The url context binds data to the parameters in the URL in a read-only fashion. It is not possible to bind multiple values to a single parameter.
container The container context only stores the current item (record) of a larger data set. Its lifetime is bound by the lifetime of the complex databinding tag using the container, such as a netui-data:Repeater tag.

Good state management is only one aspect of scalability for J2EE-based web applications. The design and use of EJBs, communication with databases, and the handling of query results are just a few other factors that need to be carefully considered when considering scalability.

Accessing Data Binding Context Properties

Data binding context elements referenced in a JSP are accessed using the 'dot' notation, and the entire expression must always be enclosed in braces:

<netui:textBox dataSource="{actionForm.postalCode}"/>

In the example, the netui:textBox binds to a form bean's postalCode property, which is a simple Java type. In general, you will want to bind to simple types such as a String, int, float, or Boolean. To include braces as part of the expression itself, you should offset a brace character with a backslash, "\". The property can also be a variable of an object that is for instance defined in the JPF file, or is part of a request. For more information, see pageFlow and request above.

You can also bind to a data element that is part of a Java array, List, or Map. References to elements in an array or List are made through standard Java array indexing syntax. For example:

{actionForm.purchaseOrder.lineItem[4].unitPrice}

The data binding expression references the unit price of the fifth line item in a customer's purchase order.

To bind to a value contained in a Java Map class, such as a HashMap, you can reference its key:

{pageFlow.inhabitantsMap['San_Francisco']}

In the example, the value associated with the key San_Francisco which is contained in inhabitantsMap is accessed.

If you want to bind to multiple elements in a complex data set, you should use a Netui Data Binding tag such as a repeater. For more information, see Presenting Complex Data Sets in JSPs.

In addition to binding to variables that are part of a form bean or a Java object, you can also bind to an XML document's elements and attributes using the same 'dot' notation and array indexing. A perhaps easier and more powerful way to access and manipulate XML data is through XML beans. You can then bind to XML elements through the XML bean in the exact same way as you would reference a form bean or Java object. For more information, see Getting Started with XMLBeans. You can also display the XML elements by using NetUI Data Binding tags in the same manner as you would with any complex data set. For more information on complex data sets, see Presenting Complex Data Sets in JSPs.

Binding to Properties with Periods in Their Names

If the name of the property being accessed contains a period (.), enclose the property name in square brackets. For example, assume that a property is added to the Session object where the property has periods in its name.

getSession().setAttribute("property.with.periods.in.its.name", "StringValue");

To bind to this property, enclose the property name in square brackets.

<netui:label value="{session['property.with.periods.in.name']}"/>

Related Topics

Using Form Beans to Encapsulate Data

Designing User Interfaces in JSPs

How Do I: Customize Message Formats in Page Flows?

How Do I: Use Multiple Forms in a JSP?

JSP Tags Reference

Samples

Data Binding Contexts Sample

Using a Wizard to Collect User Infomation Sample

<netui-data:repeater> and related Tags Sample

Multiple Forms on a Page Sample