31 Mar 2014

Groovy Expressions in Custom Attribute Properties

Custom attributes properties is a handy ADF BC feature which is often used in order to add some extra information to the attribute definition. We can use custom attribute properties in our business logic and in the UI as well, referring to the custom properties as to the common attribute hints. These custom properties along with their values can be defined at either View definition level or Entity definition level. So the values of the custom properties are shared across all user sessions, as they are defined at the definition level. But it would be cool, if the values can be evaluated for each usage dynamically at run-time, depending on some context.  Actually, that's possible. We can use Groovy expressions in custom attribute properties.

There is no way to setup a Groovy expression for a custom property at design time, but we can do it easily at run-time.  Let's consider a simple VO for a flight booking form:

The Returndate attribute has a custom property Visible. At this point we don't bother about its value. Just because it can't be empty, its value is "Value".
What we need to do is to override the resolveDefObject() method in our custom ViewDef class and  setup a Groovy expression for the Visible property:

public class VFlightBookingDefImpl extends ViewDefImpl {

  public void resolveDefObject() {
    AttributeDefImpl attrDef =  (AttributeDefImpl) findAttributeDef("Returndate");          
    attrDef.setPropertyExpression("Visible", "Roundtrip == 'Y'");  

The Visible custom property can be used for defining the visible attribute of the inputDate ADF Faces component:
<af:inputDate value="#{bindings.Returndate.inputValue}"

So, the input component for the Returndate attribute is going to be visible only for a round trip flight.

The sample application for this post requires JDeveloper R2.

That's it!

22 Mar 2014

Binding Container Viewable Attribute

In this post I'm going to show how the "viewable" attribute of the binding container can change the ADF controller exception handling behavior.

Let's consider a very simple task flow:

Here we go from the view1 to the view2, calling the badMethod on the way. The badMethod method call, as the name suggests, causes an exception. Always. It invokes a managed bean method:
public String methodCall() {
    BindingContainer bindings = getBindings();
    OperationBinding operationBinding = 
    return "go";

The methodCall uses the binding layer in order to invoke the badServiceMethod business service method:
    public void badServiceMethod() {
      throw new JboException("Help!");

Since the badServiceMethod is invoked via ADF model using methodAction binding definition, the methodCall method is not going to be interrupted.  The exception is going to be caught and processed by the binding layer and registered with the binding container of the task flow activity.  The badMethod method call has its own binding container, containing the methodAction binding.  After invoking the method call, the controller checks whether the activity's binding container has any exceptions, and if it has then the further control will be passed to the exception handler. This is the exception handler's job to take care about errors. For example, like this:
 public void exceptionHandler() {
    ControllerContext context = ControllerContext.getInstance();
    ViewPortContext currentRootViewPort = context.getCurrentViewPort();

    if (currentRootViewPort.isExceptionPresent()) {
        Exception ex = currentRootViewPort.getExceptionData();
        if (ex != null) {
            FacesContext fc = FacesContext.getCurrentInstance();
            FacesMessage facesMessage =
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                 ex.getMessage(), null);
            fc.addMessage(null, facesMessage);

So, this is the default framework behavior. According to that we'll never reach view2. After the exception has been thrown, we go back to the view1 showing the exception message to the user. This message will be kindly added to the FacesContext by the ExceptionHandler.

The binding container has the "viewable" attribute, which is true by default.  It can be changed in the page definition file:
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
        SkipValidation="true" viewable="false"

Note, that "viewable" starts with a lower case letter.

When the ADF binding layer processes an exception it starts with the root binding container and goes down registering the exception for each nested binding container if it is a viewable one.  So switching off the viewable property will prevent the framework from registering an exception for this binding container. That means, that our "Help!" JboException will not be registered for the badMethod's binding container, and the control will not be passed to the ExceptionHandler after invoking the method. The controller will go further to the view2. However, the exception is going to be registered for the parent binding container, containing the task flow. So, the user will see the error message anyway, but at the view2 view activity. Note, that the ExceptionHandler is not going to be invoked  in this case at all.
This behavior is demonstrated across all ADF 11g versions (both R1 and R2) except 11gR1 PS6. In the the exception handler is going to be invoked anyway, without bothering whether the binding container causing the exception is viewable or not.  In this case the control flow will not go forward, it's going to stop, and the user will see the error message at the view1 view activity.
That's it!