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


No comments:

Post a Comment






Copyright © 2010 Sasha Stojanovic.