Friday, October 17, 2008

New feature - Scope of Page Bean is Process!!

In the last 2.5 years of experience working in Chordiant projects, i have seen many instances, when a very simple and most common requirement in a JSP when implemented in JSF, turned into nightmare. Whenever we need the same page to be presented to the customer more than once, based on his actions, example when you select a dropdown, screen refreshes to present different details etc., to contain all the values previously captured, either we need to have the page bean scope defined as session or if not have the bean in request scope and place the objects in IOMap or session and access them each time. This would be pretty complex to maintain and have performance impact as the load increases.

Recently, there is an enhancement in Interaction Controller layer of Chordiant 6.3 to handle this. The gist of the same is below.. (Derived from Chordiant Mesh.)

The main idea is to move the request scoped bean into the same scope as the client task and so rather than represent a page, these beans represent the client task itself. The second enhancement is to provide a set of annotations to simplify validation and “next” processing.

Process Scoped client task beans ----> Subclassing ICFacesBackingBean automatically places the bean in process scope which can then be accessed from the page. The subclass needs to defined in faces config as request scope just as before. Or provide the text in @Name annotation that matches what the ic framework is looking for.

The bean is placed in process scope under the name “pageBean”. The backing bean superclass looks after managing this bean in its scope and unlike the default chordiant jsf framework, it instantiates the bean before the page is rendered. This allows a certain amount of preprossing before the page renders which is useful.

You can then access the bean from your page by using #{processScope.pageBean}. As the bean is maintained in processscope for the duration of the client task, validation loops and ppr calls are much easier as temporary state can be stored directly on the bean.

This framework to make things simpler had made use of annotations. They are

@Name(value)This is a type level annotation and is optional. If you give the bean a name that matches the ic name for it, e.g. @Name("ic$idverify_selectCustomer"), then you don't need the faces-config entry

@PreProcess This is marked on a single method and is invoked after the bean is created. The bean is created on the back of a response from start or next. The client task object is available at this point and so bean initialization can occur. Most common uses for this is to take what is on the iomap and turn it into something more useful for the bean. This could be as simple as putting the customer object as an attribute of the bean.

@Pack(choice)This annotation takes an optional choice argument. Without an argument, it will get executed when next is run. If it is supplied with a choice, then it will only get executed for that particular choice. Note the general @Pack always get executed.

@Validate(choice)Similar to the @Pack annotation, this gets executed during the validation phase (chordiant, not JSF). The general, non-choice @Validate is executed and then any specific ones that match the choice. For example, if you had a back button on your page and which was bound to next but you didn’t want to validate on it, you might only annotate a validation method with @Validate(choice=”next”).

The following example shows a client task responsible for selecting a customer.
--------------------
@Name("ic$idverify_selectCustomer")
public class SelectCustomerBean extends ICBackingBaseBean {

private List customers; private CoreTable table;
public List getCustomers() { return customers; }
public void setCustomers(List customers) { this.customers = customers; }
public CoreTable getTable() { return table; }
public void setTable(CoreTable table) { this.table = table; }

@PreProcess public void init() {
setCustomers((List) getClientTask().getIoMap().get("customers"));
}

@Validate(choice = "select")
public void validateSelection() {
if (getTable().getSelectedRowData() == null) {
//Message - saying select a value
}
}

@Pack(choice = "select")
public void packSelectedCustomer() {
Object rowData = getTable().getSelectedRowData();
getClientTask().getIoMap().put("selectCustomerReturn", rowData);
}
}
---------------------------
This definetely is very useful enhancement.

No comments:

Post a Comment