Thursday, November 18, 2010

BI Publisher: Passing Runtime Parameters into RTF Template and If conditions

When creating reports using BI Publisher, we could define parameters to dynamically get the proper data set as business needs.

The parameters we created are like the "binding variables" put into the where condition of the SQL (Data Source). Please note the name of the parameter has to be the same.

If the parameters are also the columns in our data source, it will be displayed in the template as a data attribute, for example,

But in certain scenario, you want to display the input parameters as independent on the report. The reasons are:

1) If the user input for the parameters doesn't match in our database and there will no rows fetched. In this way, format will give you empty value. But at this moment, you still want to see the user input values from the report even there is no data rows.

2) If the user input parameter is not a binding variable in the where clause. For example, there is a user input parameter called "description" and user could input comments and want to print out their inputs with the report. Since the "description" is not database and   will not work.

So how to pass runtime parameters into template?

Step 1: Assuming the parameter is already created in the BI Publisher Server UI. From the RTF template, declare the parameter as:

parameter_name is the parameter name
parameter_value is the default value
Step 2: Refer to the parameter in the template by prefixing the name with a "$" character

To use if conditions in RTF template:

If we are passing a empty value to the parameters and we need to display some texts if the parameter is empty.

The syntax could be like:
For Example:
Please refer the BI Pub document for more details.

Monday, November 8, 2010

Refresh ADF table programmatically

This is the same post to this post.

It achieve the same result of PPR. This is used when somehow PPR in the table isn't working properly. For instance, you have a transaction process on the selected row in a table. You select the row in the table, and click the button which will perform the transaction process, but somehow the table isn't refreshed to the updated state of the row (even though you setup the PPR declaratively).

But you alway could solve this programmatically.

Here I posted the snapshot of the coding snippet.

You can call setSelectedRow(getSelectedRowStr()) inside the actionListener of the button which will perform the custom transaction.

Another scenario: if you have a called task flow to process some transaction on the table and upon return to the calling task flow, the user wants to see the transaction changes which were performed during the called task flow. The solution is you can add a method action in the calling task flow to refresh the binding iterator of the table before returning to the page having the table.

Please note the refresh method is put in the backing bean and by default has no binding at all. Since we can calling the iteratorBinding, it's required to add the proper iterator in the binding. So Create page definition for the method action and add the proper iterator.

Take a look at the icon of the method action in the calling task flow, if it already has a page definition, it will have a little icon at the right bottom.

Friday, November 5, 2010

Programmatically Call Iterator and Refresh Iterator from UI (Managed Bean)

The code snippet is as follows:

 DCBindingContainer bindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding iter = bindings.findIteratorBinding("ReceiptsIterator");

Get the iterator through DCIteratorBinding 

Thursday, November 4, 2010

How to access Application Module from UI Layer

Application module is in the business service layer and is separated from user interface layer. The first thing to do is to get the bridge to business service from user interface - BindingContext.

BindingContext bctx = BindingContext.getCurrentInstance();

And then;

BindingContainer bc = bctx.getCurrentBindingEntry();

The method is get ApplicationModule is through "DCDataControl" by method: getApplicationModule (for any non-bc4j application, this method returns null).

To get DCDataControl, you could use DBBindingContainer by "getDataControl". But look at the API instructions, "*** For internal framework use only *** Returns the DCApplciation object to which this form binding belongs." So this method is for Oracle internal developers only.

The workaround on this is to use EL to reference the ApplicationModule bound to the UI page and use EL resolving to cast to application module type.

To find the Data Control Name:

    public static DCDataControl findDataControl(String dataCtlName)
       return BindingContext.getCurrent().findDataControl(dataCtlName);

To get the application Module data control by name:

  public static ApplicationModule getApplicationModuleForDataControl(String name)
    return (ApplicationModule)JSFUtils.resolveExpression("#{data." +
                                                          name +

JSFUtils.resolveExpression method can be found from Frank and Steve's ADF JSFUtils class.

Tuesday, November 2, 2010

Programmatically Access Page Bindings

Using EL references bindings declaratively in ADF should always be followed, but there always is room for you to argument your application behavior in your own code.

Here I am summarizing to access page bindings programmatically.

How to access Page Definitions/Binding Context/Binding Container?

BindingContainer bc = BindingContext.getCurrent().getCurrentBindingsEntry();

How to access page bindings in the page definition?

There are different types of bindings: attributeBinding, treeBinding, listBinding, actionBinding, methodBinding, etc
The corresponding types of codings have only two types: controlBinding and operationBinding. It's easy to recognize here. ActionBinding and methodBinding reference some actions and custom methods which are supposed to be executed somehow, therefore goes into the type of OperationBinding because it has execute() function. Other bindings are belonging to the valueBinding type so controlBinding is used.

The codings are:

OperationBinding oper = bc.getOperationBinding("actionMethodName");

We can also use JUCtrlActionBinding for actionBinding

ControlBinding cb = bc.getControlBinding("valueBindingName");

When using getControlBinding() method, we probably already know what type of valueBinding to access. So it usually is cast to the type of binding. For example,

1. attribute binding
AttributeBinding attr = (AttributeBinding)bc.getControlBinding("attrBindingName");

2. tree binding
JUCtrlHierBinding hierBinding = (JUCtrlHierBinding)bc.getControlBinding("treeBindingName");

Check here for the controlBinding implementing class.

Expression Language Conversion in ADF

Expression Language (EL) is widely used in ADF Binding to reference items in the Binding Context. In some scenario, direct use of EL reference isn't enough and manipulation of several EL references needed to accomplish the task. While you can always manipulate the logics in a manged bean, if you want to go with "declarative", here is why I am saying about.

Varchar2 type in SQL format (database) is converted to String automatically, but Number type in SQL is converted to oracle.jbo.domain.Number format. EL inherit generic Java API and can only recognize java.lang.Number type.

Therefore, if you have two EL binding references to two database Number attributes: #{bindings.NumberAtt1.inputValue} and {bindings.NumberAtt2.inputValue}. If you want to evaluate if the first number greater than the second number, you cannot use compareTo() method which is belongs to oracle.jbo.domain.Number and you cannot use #{A > B} because A or B is not java.lang.Number

A simple conversion is to attach ".value" in the end of EL binding reference and it will convert it to a java.lang.Double format type.

Create a SQL query at runtime in Application Module

We should use view object and related view criteria or bind variable to get any values from the database. Even though it is not recommended in many reasons, you still could try this way if the query is simple and trying to get a single value from the query.

In your application module implementation file, you could use getDBTransaction().createStatement() method to execute a sql query at run time.

Note there are three SQL statement types available in the DBTransaction interface: statement, callableStatement and preparedStatement.

Here is the snippet of coding in your application module file: