« ADF: Getting the iterator binding from an attribute binding in ADF | Main | ADF Faces: diabling user input for af:selectInputDate »
ADF Faces RC – Implementation strategies for global buttons in page templates
By frank.nimphius | November 23, 2007
One of the new features added to ADF Faces in JDeveloper 11 is templating. Its so cool that you might wonder how we could have been so long without. New features however lead to new usecases to document, which is good as it keeps me in the job.
A usecase that has been posted recently on the OTN forum [JDeveloper 11 / JDeveloper 10.13 and earlier]was about implementing global buttons for navigating iterators in a template. The idea is to create a template that has "next" and "previous" buttons, which then would work on any JSf page that implement the template.
There are two strategies to implement this, that came to my mind:
- Using the ADF binding layer
- Using a managed bean
1. Using the ADF binding layer
========================
Because the ADF bindings object is always present in ADF applications, you can reference the "next" and "previous" operations added to the pageDef files of the pages that use the template.
- Insert "next" and "previous" navigation as action binding to the pagedef bindings file. You do this by opening the pageDef file in the JDeveloper structure window, selecting the bindings entry and choosing "Insert Inside binding" --> "Generic Bindings" from the context menu
- Select the ViewObject (if using ADF BC) and select the "next" or "previous" operation from the drop down list to create the binding
- Repeat these steps for all pages (pageDef files) that use the template
![]() |
To ensure the data gets refreshed when pressing the buttons (note that partial submit is set to true, which means that the page doesn't get reloaded when pressing the buttons), set the ID property of the buttons to a unique value like "nextBut" or "prevBut". These values can now be assigned to e.g. the af:paneForm PartialTrigger property.
The benefit of this ADF binding only strategy is that there is no coding involved. However, the disadvantage is that there is no way of telling developers that they have to create a "next" and "previous" navigation binding in their pagedef file when re-using the template. In addition, the buttons always require the "next" and "previous" binding to exist, making it appear less flexible.
2. Using a managed bean
========================
The managed bean strategy is more flexible but requires more coding. The idea of this strategy is to have the template buttons calling a managed bean functionality, which then itself propagates the request to a managed bean of the page implementing the template. This way you can create any kind of global template buttons. To explain the idea:
![]() |
The template has two buttons (which of course could be many more) in this example. The two buttons are supposed to scroll within a collection on the page that implements the template. The buttons are bound to two methods next() and previous() in a managed bean used with the template. using a managed bean ensures that JSF takes care of all instantiations.
The contract for this strategy is that all pages that use the template must have a managed bean created (which must not be a backing bean) which has the pages viewId, which usually is the page name plus the extension (.jspx), in its name plus e.g. the word ManagedBean (to indicate that this is a managed bean class). Following this contract, the managed bean for the Departments.jspx page would be "DepartmentsManagedBean". Similar, the Employees page would have a bean "EmployeesManagedBean". All managed beans must implement a custom Java interface that you write for the global methods that the global button bar should perform on the pages that inherit the template.
-
public interface NavigationBarControlInterface {
-
public void next();
-
public void previous();
-
}
The interface serves two purposes: i) it makes it possible to type cast all managed beans to the same Java class ii) it ensures all managed beans incorporate the same methods. Alternatively to an interface, you can also use an abstract class that then is extended from the managed beans (as you know, managed beans can be extended from a base class and JDeveloper 11 encourages this by supporting the superclassing of managed bean upon creation).
The DepartmentsManagedBean would look similar to the following
-
public class DepartmentsManagedBean implements NavigationBarControlInterface{
-
public DepartmentsManagedBean() {
-
}
-
-
public void next() {
-
DCBindingContainer bindings = (DCBindingContainer) valueExpression;
-
bindings.findIteratorBinding("DepartmentsView1Iterator").getViewObject().next();
-
}
-
-
public void previous() {
-
DCBindingContainer bindings = (DCBindingContainer) valueExpression;
-
bindings.findIteratorBinding("DepartmentsView1Iterator").getViewObject().previous();
-
}
-
-
/**
-
* Create value binding for EL exression
-
* @param expression
-
* @return Object
-
*/
-
FacesContext fc = FacesContext.getCurrentInstance();
-
ELContext elctx = fc.getELContext();
-
ExpressionFactory elFactory = fc.getApplication().getExpressionFactory();
-
}
-
}
This example, which is written for ADF BC, acesses the "bindings" object in code to then obtain a handle to the ViewObject,on which we want to execute an operation: "next" or "previous". The two methods next() and previous() are defined by the interface, which is implemented by this managed bean. This way the page developer is in control of what exactly is executed when the global button in the template is pressed.
Now comes the interesting part, which is to access a managed bean from the managed bean created fro the template. Remember that the template buttons are bound to a managed bean method. When the button is pressed, the managed bean method is caled to delegate execution to the managed bean associated with the current page (the page using the template)
-
public class TemplateBeanClazz {
-
public TemplateBeanClazz() {
-
}
-
-
-
NavigationBarControlInterface nbc = (NavigationBarControlInterface) valueExpression;
-
nbc.previous();
-
-
return null;
-
}
-
-
-
NavigationBarControlInterface nbc = (NavigationBarControlInterface) valueExpression;
-
nbc.next();
-
-
return null;
-
}
-
-
FacesContext fctx = FacesContext.getCurrentInstance();
-
return managedBeanName;
-
}
-
-
/**
-
* Create value binding for EL exression
-
* @param expression
-
* @return Object
-
*/
-
FacesContext fc = FacesContext.getCurrentInstance();
-
ELContext elctx = fc.getELContext();
-
ExpressionFactory elFactory = fc.getApplication().getExpressionFactory();
-
}
-
}
The method "next_action" for example is supposed to cal the next() method on the page's managed bean. For this it needs to
- Determine the managed bean name
- Get a hold of the bean
- Call the next() method
By contract, the managed bean is the combination of "page name without file extension", plus the word "ManagedBean". Because this name needs to be created for the previous_action as well, I created a separate method for it. Once we have the bean name, we can use a ValueExpression to get a reference to it. The Java interface now becomes handy because we can cast the bean reference to the interface class. This is a much better approach than fiddling with introspection to get the bean's class type. Once casted to the interface type, we can call next() or previous()
Summary
========================
This blog entry introduces two strategies for implementing a global buttons in templates. Most likely I lost many of you in explaining the second approach. The first approach is easier to use as it requires less coding. This seems to be ok for whenever the functionality you want to execute is bound through ADF binding. The managed bean approach however appears to be more flexible, as it could be used for functionality that is not exposed through ADF binding: for example sendMessage, checkCard, notifyOwner ... . In addition, using a Java interface ensures that all developers understand the methods that need to be implemented for a consistent approach.
Topics: ADF Faces RC | No Comments »
Comments are closed.


