ads

X

Tuesday, April 29, 2014

BarCode Reader - SBA | Oracle ADF

Integration of BarCode Readers with Oracle ADF Applications Specially our Charity SBA Package (Smart Business Applications) and how to make Oracle ADF Easy & Flexible for one purpose which is "Enable End user from Controlling & Coding Stock Element Fast" !
Demo Link here !




BarCode From Basic Definition is just Fast Keyboard to read Unique keys, and it is common used in Operational Systems like Point of Sale & Inventory Applications !.

for this reason, i will show complete solution from our SBA Charity Package just to use barcode to scan & Define Element Description before using in Stock Level.

Solution is a complete Back Bean Methods, Art of Controlling of Interface in ADF is the best way to cover, Control the Barcode Solution into your Application, so before going to implement, you have to understand well below Back Bean Scripts.
 Result 

 

Source Code

 



References



Back Bean Switching For Dynamic Region | Oracle ADF

How to control your ADF Application using One Dynamic Region & Use it to switch among multiple task Flows in smart way using Back Beans without using Switcher UI Component using default Task Flow Bean created while creating Task Flow as Dynamic Region.

Solution point, is how to modify .xml url using dynamic Task Flows Names.

private String taskFlowId = "/WEB-INF/DefaultTask.xml#DefaultTask";
setDynamicTaskFlowId("/WEB-INF/" + getMySwitchingVal() + ".xml#" + getMySwitchingVal());

- before implementing this solution, you have to define multiple Task Flows with cleared names and binding it to Back Bean.



- I Have Menu items to control My Dynamic Switcher to Execute Back Bean Method passing Task Flow Name before using set property listener.


 - Now, we can build our Back Bean Method as below to control it (getMySwitchingVal is getting the task flow name based on set property listener from your Action UI Component).


Notes

1- For Business Needs, we made Auto Roll Back before Switching.
2- PrepareBeforeBavigate Method is just s simple Method to cover business before switching.

References




Thursday, April 17, 2014

Update Model Values while Validation (Exception) occurs on page on Value Change event- Oracle ADF (processUpdates)

In ADF when we have some validation on page and we try to submit any value, but normally after validation (Exception) values are not updated in Model until exception is handled.
This tutorial is about how to update values in Model while exception on page.
For a scenario, i have used department (default HR Schema) table and form in a JSP XML fragment inside bounded taskflow.
In form Department Id and Department Name is mandatory field, ManagerId and Location Id has auto submit true.

  • I have dropped createInsert,Execute,Commit and Rollback as buttons on page
  • Click on create button and first enter manager id, as this field has autosubmit true so on submission of value page is validated and then Required Fields throw exception, and after exception you can see that manager id & location id is not updated in Model, and not reflected in af:table also.


  •  Normally what we do, set immediate true to skip validations, but in this case i have witten ValueChangeListener on manager Id and Location Id to process values in Model.- see code

  •     public void mangrIdVCE(ValueChangeEvent vce) {
            vce.getComponent().processUpdates(FacesContext.getCurrentInstance());
        }
    

  • processUpdates() method of UIComponent class perform the coponent tree processing for all facet of this component by Update Model Values phase of request processing, and pushes data to Model

  • Now after calling this method, run application- Now values are populated in af:table and validation is still there on page


  • this approach can be used while using validators on page and want to process some values after validation (as conditional validation of some fields etc)

Get updated model values in value change listener instantly, ProcessUpdates in ADF (a beauty)

Get updated model values in value change listener instantly, ProcessUpdates in ADF (a beauty)

hello all,
this posts talks about updating model instantly when a attribute is changed on page level.
In ValueChangeListener of component if we try to get new value from Model layer, it always returns old value, then we have only one option to get new value, use event object (evt.getNewValue();)
but sometimes we need to update model same time
So how to do this-

  • Created a Fusion Web Application using Departments table of HR Schema (Oracle)


  • dropped Departments Vo on page as a form, and created ValueChangeListener on DepartmnetName field to get new value 


  • now i have written a code to get DepartmentName from current row of Departments VO (ViewObject) and to get from ValueChangeEvent

  • Method in AMImpl- Called in ValueChangeListener through binding Layer

    /**Method to print Department Name */
        public void getDeptNameAction() {
            ViewObject depart = this.getDepartments1();
            Row curRow = depart.getCurrentRow();
            if (curRow != null) {
                System.out.println("Current Department from model is-" + curRow.getAttribute("DepartmentName"));
            }
        }
    


    Code in ValueChangeListener - AM Method Called and Code to get new value from event itself

        /**Value change listener for Department Name
         * @param vce
         */
        public void deptNmVCE(ValueChangeEvent vce) {
            if (vce.getNewValue() != null) {
                System.out.println("New Value in VCE-" + vce.getNewValue());
                BindingContainer bc = BindingContext.getCurrent().getCurrentBindingsEntry();
                OperationBinding ob = bc.getOperationBinding("getDeptNameAction");
                ob.execute();
            }
        }
    

  • In this case when i have changed value on page 



  • see the result -output from valuechangelistener- Model layer returns old value :-(


  • Now to update value in Model layer , i have just called processUpdates in ValueChangeListener- See the code

  •     /**Value change listener for Department Name
         * @param vce
         */
        public void deptNmVCE(ValueChangeEvent vce) {
            if (vce.getNewValue() != null) {
                //Method to update Model in VCE
                vce.getComponent().processUpdates(FacesContext.getCurrentInstance());
                System.out.println("New Value in VCE-" + vce.getNewValue());
                BindingContainer bc = BindingContext.getCurrent().getCurrentBindingsEntry();
                OperationBinding ob = bc.getOperationBinding("getDeptNameAction");
                ob.execute();
            }
        }
    

  • see the result -Value is updated in model instantly (in VCE)
so this is how processUpdates works

ViewObject Validation rules for transient attributes (Model level validation in ADF)

this post is about model level validation for transient attributes, often we need to apply some common types of validation on transient attributes (as for negative value, for email, for phone number)
in ADF ViewObject there is a editor for validation rules for transient attributes, so now see how to use that editor and rules



  • create a fusion web application and prepare model layer using Departments table of HR schema


  • then create a transient attribute in viewObject and you can see that Validation Rules tab appears only in case of transient attribute


  • now click on add icon to add new validation rule for attribute, you can see there are multiple types for that validation rule 




  • in this post i have used Compare and Regular Expression rules, suppose i have to check that value of transient attribute must not be 100 , so for that rule will be like this, and write a proper message for failure handling 



  • now run your BC4J tester and check , a window with error message appears there in case of failure

  • you can also check this validation on your page, some more- i have added one more transient field for Email Address and applied a regular expression to validate this field (ADF by default provides regular expression for Email and Phone Number pattern for others you can use your own pattern)


  • after model level configurations , i have dropped Departments ViewObject on page as ADF form, here you can see both validation are working 




  • Thanks & Cheers :-) happy learning

Thursday, April 10, 2014

Bindings

Binding provides objects to link components, it is the most innovative part of ADF after Task Flows and provides direct interaction with Appication Module. We can work with bindings in ManagedBean and also in Expression Builder. Bindings are basically used for the interaction on the model and the viewController in an ADF Application.

When we drag any DataControl on page then a binding entry is made in the pageDef of the page for that particular field. Suppose we want to Use CreateInsert operation on a button clik in the page, then we have to create the binding of CreateInsert action in the pageDef on that page and then we can use this action in our ManagedBean to perform the desired operation.

Oracle ADF provides following types of bindings:


  1. Action Binding

    Action Binding is specifically defined for a button component. Provides access to operations defined by the business object. Such as CreateInsert , Delete.
    //The code below gets the Bindings entry of the binding container and fetches the current bindings entry
     BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
     //Gets the opertaion bindings for the method "CreateInsert"
     OperationBinding operationBinding = bindings.getOperationBinding("CreateInsert");
     //Then execute executes the method of the binding
     operationBinding.execute(); 
     
    Likewise you can use the above code to call bindings in ManagedBean.
  2. Iterator Binding
  3. When we drag tables on the page in ADF then ADF creates a IteratorBinding in the pageDef of the page. The iterator binding can be used to get the iterator of the table in the ManagedBean.
  4. Given below is the code that can be used to get the IteratorBinding in the ManagedBean.
        BindingContext btx = BindingContext.getCurrent();
        DCBindingContainer dcbct = (DCBindingContainer)btx.getCurrentBindingsEntry();
        DCIteratorBinding binding = dcbct.findIteratorBinding("StudentIterator");
        Row currentRow = binding.getCurrentRow();
  5. Here in the last line I have get the current Row from th iterator. 
    LikeWise you can use it to perform desired action. 
  6. 
    
  7. ValueBindings
    Value Bindings are created in the pageDef for all the attributes that are added on the page from the dataControl.

Optimising the Validator Logic, Using af:attribute to make validation easy

This post I will try to focus on how we can make validations in an editable table more effectively.

So what would we do if we have two attributes in a row in a table and we need to validate one on the basis of the other?

The answer is simple.


  • We will get the instance of the viewObject 
  • Then get the current row 
  • Then we will get the attribute with which we need to compare and then we will compare and check the validation.
This process is fine, but i have a more easy and effective way to do so.
I have created a Transient attribute in EmployeeVO where the newSalary of the Employee is to be entered. We have to make sure that the new Salary is greater than old salary.
Drag the EmployeeVO into the page. Then add an af:attribute component in the inputText of newSalaryTrans . Give attribute name and a value here i have used 'oldSal' and assigned with value of old Salary i.e. #{row.Salary}.
Now we need to implement the validation and for that I created a Validator on the NewSalaryTrans field.

In the bean I have used the code given below :

    public void newSalaryVAL(FacesContext facesContext, UIComponent uIComponent, Object object) {
        Object val = uIComponent.getAttributes().get("oldSal");
        System.out.println("New Sal is  : "+object+" Old Sal is  : "+val);
        if(val != null){
            BigDecimal oldVal = (BigDecimal)val;
            BigDecimal newVal = (BigDecimal)object;
             if(oldVal.compareTo(newVal) >=0 ){
                throw new ValidatorException(new FacesMessage("New Salary Cannnot be less than Old Salary!"));
            }
        }
    }
On putting less value in newSalaryTrans

Pagination in ADF table with Jdeveloper 12.1.2 (ADF 12C) - returned back

pagination in ADF table was very requested feature after Jdev & ADF 10g.
now in 12C again it is here and quite simple


  •  Created a fusion web application using Departments table of HR Schema and dropped it on page as ADF table


  • now suppose i want to show pagination after 5 rows so to achieve this follow these steps
  • Select table in structure window and go to property inspector change it's scrollPolicy to page ,scrollPolicy is mechanism to scroll data inside table


  • Now select table on page and go to binding tab and select IteratorBinding of Departments table and change rangeSize to 5, by default it is 25 (means fetched 25 rows at a time)


  •  set autoheightRows to 0 and styleClass to AFStretchWidth and you are done now run your page


  • It works good in mozilla ,chrome and IE, but sometimes you can face a problem of finding current row as it may be in second page :-(

Programmatic ViewObjects in ADF, Populating programmatic viewObject with an ArrayList

Today I am going to demonstrate about how to make programmatic viewObject in ADF.
There are basically 4 types of viewObjects.

1. ViewObjects based on Entity.
2. ViewObjects based on SqlQuery (also called Readonly viewObject)
3. Static viewObjects (contains fix now of rows)
4. Programmatic viewObjects (Programmatic viewObjects are viewObjects that are not populated from an sql query).

For understanding  the working of programmatic viewObjects, you must first understand the lifecycle of a viewObject. You need to know what methods are called when a viewObject is executed. Here is the sequence of methods that are called when a viewObject is executed.

LIFECYCLE

When a viewObject is called the following methods are executed in the given sequence. 
  • At first when the viewObject is first executed the method first called in the ViewObjectImpl is
    executeQueryForCollection(Object qc, Object[] params, int noUserParams)
    This method executes the Database Query in the viewObject and then calls the next method.

  • After executeQueryForCollection is executed then method hasNextForCollection(Object qc) is called. This method checks if the collection returned have a row or not. If hasNextForCollection(Object qc) returns True then the next method of the lifeCycle is called which converts the row to ADF understandable form i.e. into ViewObjectRowImpl from.

  • So when method hasNextForCollection retuns true then method createRowFromResultSet(Object qc, ResultSet resultSet) is called and this method converts the row into ADF understandable form.

  • This goes on until all the rows are covered and there is no rows left in collection. When there are no rows in the collection then the method hasNextForCollection returns false .

  • Then method setFetchCompleteForCollection(java.lang.Object qc,boolean val) is called and it sets the flag for fetch completion. This indicates that the rows from the collection are fetched.
- See more at: http://adfjavacodes.blogspot.in/2013/12/how-viewobjects-get-executed.html#sthash.whg7AwM9.dpuf

Now create an ADF Application and create a programmatic viewobject



Then press next and define attributes for the viewObject




Generate the following java classes




Click Finish.


Now we have made the viewObject. We will have to override the lifeCycle methods. Here is the code that I have used for this viewObject.


package programmaticvotestapp.model.views;

import java.sql.ResultSet;

import java.util.ArrayList;

import oracle.jbo.Row;
import oracle.jbo.server.ViewObjectImpl;
import oracle.jbo.server.ViewRowImpl;
import oracle.jbo.server.ViewRowSetImpl;

import programmaticvotestapp.model.EmpDC;
// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Wed Apr 09 14:28:40 IST 2014
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class ProgrammaticVOImpl extends ViewObjectImpl {
    private ArrayList<EmpDC> empList = new ArrayList<EmpDC>(); 
    /**
     * This is the default constructor (do not remove).
     */
    public ProgrammaticVOImpl() {
    }

    /**
     * executeQueryForCollection - overridden for custom java data source support.
     * This method is executed at first.
     * So in this method we need to load our data source . 
     * In simple words initialize the list
     */
    protected void executeQueryForCollection(Object qc, Object[] params, int noUserParams) {
        // Populate the list for the firstTime
        populateArrayList();
        //To set the initial position for fetch to start
        setFetchPosition(qc,0);
        super.executeQueryForCollection(qc, params, noUserParams);
    }

    /**
     * hasNextForCollection - overridden for custom java data source support.
     * This method is called after executeQueryForCollection to check if any row exist in the datasource or not.
     * When returned true, createRowFromResultSet is called and a new row from the rowset is created.
     */
    protected boolean hasNextForCollection(Object qc) {
        return getFetchPosition(qc) < empList.size();
    }

    /**
     * createRowFromResultSet - overridden for custom java data source support.
     * creates a newRow and adds it to viewObject
     */
    protected ViewRowImpl createRowFromResultSet(Object qc, ResultSet resultSet) {
        int fetchPosition = getFetchPosition(qc);
        System.out.println("Fetch Position is : "+fetchPosition);
        ViewRowImpl newRow = (ViewRowImpl)createNewRowForCollection(qc);
        EmpDC c = empList.get(fetchPosition);
        // Setting value in the new row which is created.
        newRow.setAttribute("EmpId", c.getEmpId());
        newRow.setAttribute("EmpName", c.getEmpName());
        newRow.setAttribute("Salary", c.getSalary());
        // Updating the fetch Position
        setFetchPosition(qc, fetchPosition+1);
        
        return newRow;
    }

    /**
     * getQueryHitCount - overridden for custom java data source support.
     */
    public long getQueryHitCount(ViewRowSetImpl viewRowSet) {
        long value = empList.size();
        return value;
    }
    /**
         * Method to set the new fetch position
         * @param rowset
         * @param position
         * To set the position on the nextRecord to fetch i.e. next record of arrayList
         */
        private void setFetchPosition(Object rowset, int position) {
            if (position == empList.size()-1) {
                setFetchCompleteForCollection(rowset, true);
            }
            setUserDataForCollection(rowset, new Integer(position));
        
    }
    /**
         * Method to get the current fetch position
         * @param rowset
         * @return
         * 
         * This method gets the fetchPosition to fetch the row from the arrayList to retrieve the data
         */
        private int getFetchPosition(Object rowset) {
            int value = ((Integer)getUserDataForCollection(rowset)).intValue();
            return value;
        }
    
    public void populateArrayList(){
        empList.clear();
        empList.add(new EmpDC(1,1100,new StringBuffer("First Employee")));
        empList.add(new EmpDC(2,2100,new StringBuffer("Second Employee")));
        empList.add(new EmpDC(3,1300,new StringBuffer("Third Employee")));
        empList.add(new EmpDC(4,1700,new StringBuffer("Fourth Employee")));
        empList.add(new EmpDC(5,1200,new StringBuffer("Fifth Employee")));
        empList.add(new EmpDC(6,5100,new StringBuffer("Sixth Employee")));
        empList.add(new EmpDC(7,1900,new StringBuffer("Seventh Employee")));
        empList.add(new EmpDC(8,1200,new StringBuffer("Eight Employee")));
        empList.add(new EmpDC(9,1200,new StringBuffer("Ninth Employee")));
        empList.add(new EmpDC(10,1100,new StringBuffer("Tenth Employee")));
    }
}

on running the application you can see



You can download the sample application here ProgrammaticVoApp

Likewise you can use other datasources to populate the programmatic viewObject. The above model shows a very simple implementation, use cases can be much complex.