30 Sep 2017

Right getters for "Boolean" and "boolean" values

In this post I would like to highlight a small pitfall that sometimes spoils ADF/JSF developers lives.  It happens when an EL expression on a page is referring to a boolean property of a managed bean or an object and a getter for this property is declared in a wrong way. This leads to either PropertyNotFound or  PropertyNotReadable exceptions.

Let's consider a simple example. There is a managed bean with the following methods:

  public boolean isPrimitiveValue()
  {
    return true;
  }


  public Boolean isObjectValue()
  {
    return Boolean.TRUE;
  }


There is a page with a couple of buttons referring to the he managed bean:

 <af:button text="button 1" id="b1" rendered="#{theBean.primitiveValue}"/>
 <af:button text="button 2" id="b2" rendered="#{theBean.objectValue}"/>

It works well for the first button, but it doesn't for the second one raising a PropertyNotFound exception like "...The class 'com.cs.adfpractice.view.TheBean' does not have the property 'objectValue'...".

The thing is that the EL engine can't resolve a getter starting with "is" for the Boolean type returning an object. It works only for the primitive boolean type.

If we change the second getter like this:

  public Boolean getObjectValue()
  {
    return Boolean.TRUE;
  }

It will work perfect.

That's it!


10 Sep 2017

Using Custom View Objects with Entity Associations

While implementing business logic at ADF BC layer we leverage entity associations in our code as a convenient approach to manipulate entities that are related to each other by design. For example, there is DepartmentEmployeesEL association linking Department and Employee entities. In Department entity implementation class there is an association accessor returning a row iterator with employees working for this department:
  public RowIterator getEmployees()
  {
    return (RowIterator) getAttributeInternal(EMPLOYEES);
  }

This accessor can be used in a method iterating over all associated employees and performing some actions with each of them:
  private void processEmployees()
  {
    RowIterator employees = getEmployees();
    while (employees.hasNext())
    {
      EmployeeImpl employee = (EmployeeImpl) employees.next();
      // do something with employee
    }
  }
In order to retrieve the list of employees the framework builds an internal view object according to the association definition. However, there is a way to control how this view object is going to be created, for example we want to specify a desired sorting order or add an extra where clause to the VO query. We can tell the framework to use our custom view object definition instead of using a default one:






Having done that we have a full control on how the rows returning by the association accessor are going to be retrieved from the database.

That's it!

20 Aug 2017

An easy way to clean ADF BC entity cache

It's time to get back to posting. In this short post, the first one after a long break,  I am going to show an easy way to clean up entity cache of a specific entity definition and to force dependent view objects to get re-executed.

Let's say there is a dashboard page containing lots of various charts, diagrams, lists and tables. All that fancy stuff is based on a number of view objects. Let's assume these view objects represent data in different ways from a database table containing some billing information BillingLog. So, there is an entity BillingLogEO and all dashboard VOs are based on this entity. When it comes to dashboards, a common use-case is to get the dashboard refreshed either manually or automatically. We could implement that just by running over all dashboard view objects and re-executing them one-by-one explicitly, or we can just tell the framework to clean up entity cache of BillingLogEO in our application module implementation class:
getDBTransaction().clearEntityCache("model.entities.BillingLogEO");
This will clean the specified entity cache in the current transaction and clean VO caches of all dependent view objects which will force them to get re-executed.

That's it!



30 Apr 2017

Shared View Object with Range Paging access mode

Recently I came across an interesting issue related to shared view object instances with range paging access mode.  So, there is a VO instance defined in a shared application module with the pagination feature on:



This shared VO instance is used in a view accessor



Well... It doesn't work.  The LOV's search dialog always shows only first (~50) records. It is impossible to scroll down and see the rest of records.

I am not sure if it is documented somewhere, but it makes sense. A shared view object is supposed to share its row sets with many clients. Obviously, with range paging access mode this concept just can't work as each client could have its own active range.

Actually, this is not a common use-case to switch on Range Paging access mode for shared VOs. Usually, range paging is used for VOs returning a great number of records, and this is not common for shared VOs providing some common reference data.  But, anyway,  just be aware of this behavior.

That's it!


25 Mar 2017

Passing Values to JavaScript from Managed Bean

In this simple post I am going to consider a common use case when we need to invoke a JS function from a managed bean method and this function consumes some value provided by a managed bean. Let's have a look at what options we have to pass this value from a Java bean to a JS function.

The easiest and the most obvious option is to pass the value as a parameter of the JS function:

JavaScript function:
        function alertParamValue(paramValue)
        {
          alert(paramValue);
        }

Managed bean method:
  private void renderScript(String script)  {
    FacesContext fctx = FacesContext.getCurrentInstance();
    ExtendedRenderKitService erks = null;
    erks = Service.getRenderKitService(fctx, ExtendedRenderKitService.class);
    erks.addScript(fctx, script);
  }

  public void paramButtonListener(ActionEvent actionEvent) {
    StringBuilder script = new StringBuilder();
    script.append("alertParamValue('came from managed bean');");
    renderScript(script.toString());   
  }

However, sometimes it might happen that passing a parameter to a JS function is not the best option due to complicated implementation of the function and it would require much effort to pass parameter's value to the exact place in the code where this value is used. In this case the JS function may refer to a "helper" JS function returning parameter's value. And this JS function is going to be rendered dynamically in a managed bean:

Java Script function:
        function alertFunctionValue()
        {
          alert(renderedFunction());
        }

Managed bean method:
public void functionButtonListener(ActionEvent actionEvent) {
 StringBuilder script = new StringBuilder();    
 script.append("function renderedFunction() {return 'came from managed bean'}");
 script.append("alertFunctionValue();");
 renderScript(script.toString());
}

Another solution for this case could be implemented by means of JavaScript variables:

Java Script function:
        var varValue;

        function alertVarValue()
        {
          alert(varValue);
        }

Managed bean method:
  public void varButtonListener(ActionEvent actionEvent)  {
    StringBuilder script = new StringBuilder();
    script.append("varValue = 'came from managed bean';");
    script.append("alertVarValue();");
    renderScript(script.toString());
  }

The sample application for this post is available here. It requires JDeveloper 12.1.3.

That's it!