Tuesday, September 21, 2010

ADF function call from EL statement in jspx page


Hi

I created three new helper classes with wide usage potential. In specific cases they can significantly simplify the code and make it re-factoring friendly and even faster because there is no need to reference a view object to get an attribute value. I already use them on my daily ADF tasks.

-----------------------
In short (and exciting)
-----------------------

(1)
Class DynMap
This is helper class to mimic function call from an EL statement, with one passing parameter.

(2)
Class DynMap2
This is a variant of the upper class allowing you to pass two parameters to a function from an EL statement.
Following the same rules you can create corresponding classes to serve 3 and more parameters, too.

(3)
Class DynMapIn
Cool small class to test if some (binding) value is included in a final set of values.

----------------------
In detail (and boring)
----------------------

Currently, EL (Expression language) on ADF platform doesn’t support calling functions with parameters. For example you might want to write a (very logical) function call like this:

< af:inputText  value="#{mybean.func(bindings.var.inputValue, "V")}" />



...but you can’t do it in ADF. The standard approach is to create a getter on your managed bean, and there to read the attribute from the bindings and do the logic.

public String getFunc(){
DCIteratorBinding iterator = ADFUtils.findIterator("MyIterator");
String myVar1 =iterator.getCurrentRow().getAttribute("MyVar");
String myVar2 =’V’;

//some logic here
return myVar1+”,”+myVar2;

}

And that’s what we usually do, and in most cases it is the only way. A negative consequence of doing it this way is that it that the code cannot be re-factored, because of strings used to reference objects.

I got an idea from how ADF page is using bundles for labels, as it passes a parameter of a key to return associated value. So I used the same idea and constructed a kind of dynamic maps, where the key returned is not a fixed value, but is calculated at the moment of the call. Then I wrapped it all in an easy to use classes.

On the page:

< af:inputText  value="#{mybean.func[bindings.var.inputValue]["V"]}" />

In the bean, the getter:

public DynMap getFunc(Object myvar1, Object myvar2){
return new DynMap2() {    
@Override
       public Object ret(Object var1, Object var2) {

//put some logic here
              return var1+","+var2;

       }};
}


This is when we have two parameters to pass. And here is a simpler example, when only one parameter has to be passed:


The getter:

public DynMap getFunc(Object myvar) {
        return new DynMap() {
            @Override
            public Object ret(Object var) {
//put some logic here
                return var1+"!";
            }
        };
}

The last example is for testing if a value is included in some set of values:

So instead of:

       disabled="#{!(bindings.CriterionTypeId.inputValue=='01'
              || bindings.CriterionTypeId.inputValue=='02'
              || bindings.CriterionTypeId.inputValue=='03'
              || bindings.CriterionTypeId.inputValue=='04'
              || bindings.CriterionTypeId.inputValue=='05'
              || bindings.CriterionTypeId.inputValue=='06'
              || bindings.CriterionTypeId.inputValue=='08'
              || bindings.CriterionTypeId.inputValue=='09'
              || bindings.CriterionTypeId.inputValue=='10'
              || bindings.CriterionTypeId.inputValue=='11'
              || bindings.CriterionTypeId.inputValue=='12'
              || bindings.CriterionTypeId.inputValue=='13'
              || bindings.CriterionTypeId.inputValue=='14'
              || bindings.CriterionTypeId.inputValue=='15'
              || bindings.CriterionTypeId.inputValue=='16'
              || bindings.CriterionTypeId.inputValue=='17'
       )}"


...I have to write only:

disabled="#{my_Backing.isDisabled[bindings.ValueTypeId.inputValue]}"

and the getter:

public DynMap getIsDisabled() {
return new DynMapIn("01|02|03|04|05|06|08|09|10|11|12|13|14|15|16|17");
}



Implementations:

public class DynMap extends HashMap {
    @Override
    public Object get(Object ob) {
        return ret(ob);
    }

    Object ret(Object ob) {
        return null;
    }
}

public class DynMap2 extends HashMap> {
    @Override
    public Map get(final Object test1) {
        return new HashMap() {
            @Override
            public Object get(Object test2) {
                return ret(test1, test2);
            }
        };
    }

    public Object ret(Object test1, Object test2) {
        return null;
    }
}

public class DynMapIn extends DynMap {
    String sInput;
    String sDelimiter;

    public DynMapIn(String p_sInput) {
        super();
        sInput = p_sInput;
        sDelimiter = ",";
    }

    @Override
    Object ret(Object ob) {
        return Arrays.asList(sInput.split(sDelimiter)).contains(ob);
    }
}


Regards,
Sasha


Friday, May 28, 2010

JDeveloper 11.1.1.3 panelCollection Columns Hidden

Hi!

After updating to JDeveloper 11.1.1.3 on our project, we were surprised to see a new status line below Table in ADF panelCollection component, showing how many columns are hidden. It could be quite useful, but, when there are several tables on the page, this new box takes significant space, and, at least at the moment, I don't see some property to control its appearance.

One simple solution to make it hidden on global level is to add the following code in your CSS definition file:

af|panelCollection::statusbar{
  display: none;
}

Cheers!
S_

Friday, March 19, 2010

Taming loooong combo boxes in ADF page Query block

During designing ADF fusion form layout in JDeveloper, sometimes there is a problem with combo boxes in query block:
·          They become too long, as they always try to fit the longest string
·          They change the width randomly as we select other autosubmit elements on which combo boxes are dependent.
 
It can be tamed a bit if you attach specific css class directly on the query, as it is shown here in the following example:

STEP 1:
On your application CSS definition file, add the following class def: 

af|query.queryComboBox af|selectOneChoice::content{
    width: 50px;
}


STEP 2:
On the (jspx) page, attach style class directly to the query element:

styleClass="queryComboBox" …


However, be aware that all combos take the same width in the query, as I still don't know if there is a way to control individual combo boxes in queries.



Thursday, March 11, 2010

ADF - PL/SQL Procedure or Function Call - Simple and Effective Tool

Even ADF Fusion has been brilliantly designed to rescue developers from coding direct calls to PL/SQL procedures and functions, sometime it still has to be done "by hand". After some time of using different techniques, from basic commands to using full frameworks, I finally wrote a helper class named DbCall, which significantly reduces the strain of creating complicated statements. Still, it is very light on code, and easy to expand for any customization you might need.

A few advantages are here:
  • DbCall can be used equally simple for function and procedure calls.
  • No need to take care about types of IN parameters.
  • There is convenient and simple way of handling OUT params.
  • No need to build complex BEGIN/END PL/SQL string with question-marks.
  • It greatly simplifies the code you write
  • There is internal exception handling, but also can be moved externally.

And few examples of "DbCall" in action:

Very simple procedure call with two IN parameters:

DbCall dc = new DbCall("MYPACKAGE.MYPROC", this.getDBTransaction());

//add some carefully created string
dc.addIn("ABC");

//add some integers too, as they are great partners to strings
dc.addIn(123);

//Call it here... Done!!!
dc.execute();


Example of Procedure Call with various IN/OUT parameters:

DbCall dc = new DbCall("MYPACKAGE.MYPROC", this.getDBTransaction());

//add the current user
dc.addIn(this.getUserPrincipalName());

//give a bit of mmh to you...
dc.addIn(this.getMMH());

//everybody needs some time
dc.addIn(new Timestamp(new java.util.Date().getTime()));

//here you cannot go wrong!
dc.addIn(null);

//register this as OUT param as I need it later. dc.addOut("IS_SUMMER",Types.CHAR);

//I need this info too.
dc.addOut("HOW_HOT", Types.FLOAT);

//call it here!!!
dc.execute();

//and here is the summer!
Object Summer = dc.getObj("IS_SUMMER");

//here is how hot it is!
Object Hot = dc.getObj("HOW_HOT");


Example of Function Call with various IN/OUT parameters:

DbCall dc = new DbCall("?:=MYPACKAGE.MYFUNC", this.getDBTransaction());

//the function will return us something, here it goes
dc.addRet("ret", Types.VARCHAR);

//simple simple string as IN param
dc.addIn("ABC");

//some OUT param, as I need to know this.
dc.addOut("RET", Types.FLOAT);

//here is very cool IN/OUT param
dc.addInOut(123,"WHAT",Types.NUMERIC);

dc.execute();
Object ret = dc.getObj("RET");
Object what = dc.getObj("WHAT");



Give it a try!
It is already in use on a big ADF-Fusion project!

DbCall ADF to PL/SQL wrapper is released under the GNU GPL licence and was published on the 12 March 2010.

Download DbCall source code here!

and please leave any comment if you find this code useful ... or whatever...

Welcome

Hello! My name is Sasha Stojanovic. I am involved professionally in programming from 1990. I've been using many mainstream and even some exotic technologies and frameworks in developing real world applications. I am specialized in creating working bridges in situations when there is no out of the box solution, from audio real-time data processing to enterprise data intensive client and server applications.

I will present here some interesting and (hopefully) reusable programming solutions I have created during my work on real world ADF - Fusion applications.

Sasha Stojanovic





Copyright © 2010 Sasha Stojanovic.