ADF DataBinding: Yet another thing it does for you.

0

Today I encountered something that I have seen frequently. While developing an ADF application developers tend to invoke methods on an application module directly, instead of invoking them via the bindings framework. You might get some unexpected results and some additional work too…

Correcting this behavior afterwards can be very annoying and time-consuming. In this blog, just to let developers know, I describe what you could do to prevent this error.One of the things the ADF Bindingframework does for you is catch exceptions and show them in a message popup. Let’s see what happens when we build an example.

First create default BC for the EMPLOYEE table in the HR schema. The employee table has (at least it should have) a check constraint that makes sure that whatever happens, an employee at least gets one cent every month (salary > 0).

Next create an Application Module Class and in this class create a method to do salary corrections.

    public void salaryCorrection(Number quantity){
        ViewObject _empVO = this.getEmployeesView1();        
        Row _currentRow = _empVO.getCurrentRow();               
        oracle.jbo.domain.Number _salary = (Number)_currentRow.getAttribute("Salary");                 
        _salary = _salary.add(quantity);                 
        _currentRow.setAttribute("Salary", _salary);                
        getDBTransaction().commit();               
        return;            
        }

Now Publish this method to the client interface. Create a new Page called salaryCorrections.jspx. Create an ADF form based on the employeesView1 collection and make sure to include navigation and submit buttons. Make sure the page works as expected. Drop the salaryCorrection Method from the datacontrol on your page as a ParameterForm.

Run the page and see what happens if you make a correction that results in a negative salary…….

You get a popup with a somewhat technical error message that explains what went wrong. You can close the popup, correct the error and you are ok.

Now let’s create a second button that will bypass the bindings framework and invoke the method on the application module directly.

Create another <af:panelFormLayout/>. Drop a button in this panelform. Go to the action property of the button in the property inspector, and let it point ot a new method in a new bean.

Also create an inputtext which holds the value for the correction amount. The value is retrieved from the backingbean. The code in the panelFormLayout should look like this:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;af:panelFormLayout id=&quot;pfl3&quot;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;af:inputText label=&quot;alternative&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value=&quot;#{salaryCorrectionBB.correction}&quot;/&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;af:commandButton text=&quot;Direct Call&quot; id=&quot;cb7&quot;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; action=&quot;#{salaryCorrectionBB.invokeMethod}&quot;/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/af:panelFormLayout&gt;

Here’s the bean code:

public class SalaryCorrectionBB {

public oracle.jbo.domain.Number correction;

&nbsp;&nbsp;&nbsp; public SalaryCorrectionBB() {
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; public String invokeMethod() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Add event code here...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getAm().salaryCorrection(getCorrection());
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; private HrServiceImpl getAm() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FacesContext fc = getFacesContext();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Application app = fc.getApplication();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExpressionFactory elFactory = app.getExpressionFactory();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ELContext elContext = fc.getELContext();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ValueExpression valueExp =
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elFactory.createValueExpression(elContext, &quot;#{data.HrServiceDataControl.dataProvider}&quot;,Object.class);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (HrServiceImpl)valueExp.getValue(elContext);
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; public static FacesContext getFacesContext() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return FacesContext.getCurrentInstance();
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; public void setCorrection(Number correction) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.correction = correction;
&nbsp;&nbsp;&nbsp; }

&nbsp;&nbsp;&nbsp; public Number getCorrection() {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return correction;
&nbsp;&nbsp;&nbsp; }
}

Run the page again, and see what happens if you make a correction that results in a negative salary…….

An internal server error. Even though you invoked the exact same method as before, you now get an internal server error. The direct call does not handle exceptions and therefore results in an internal server error. So here you go: You have to write "a lot" of code to be able to invoke the method directly, and you have to write even more code to get the error handling in place.  If you use the bindingframework, it will catch the exceptions and show them in a popup.

My Advice: Be smart and use the bindingframework whenever possible, and invoke methods on an application module directly only if strictly necessary.

 

Share.

About Author

Luc Bors is Expertise Lead ADF and technical specialist/architect at AMIS, Nieuwegein (The Netherlands). He developed several Workshops and training on ADF and also is an ADF and JHeadstart instructor. Luc is a member of the ADF Methodology group and publishes articles on ADF in oracle technology related magazines, on the AMIS technology blog, (http://technology.amis.nl/blog).

Comments are closed.