Using ADF SDO Find Criteria

The less talked about and the most confusing subject when it comes to service based model is Find Criteria. You may not need to add explicit view criteria to filter records, if you use the SDOs (Service Data Objects). Here, I will show how you can use a simple Find Criteria.

Creating Proxy from the Deployed FASDOAppModuleService:
Say, you have deployed an application module service interface called FASDOAppModuleService and the URL is http://soabpm-vm:7001/FASDOModel/FASDOAppModuleService?wsdl. First, let’s create a proxy project using this info.
FASDOModel wsdl

In JDeveloper, create a generic project called FASDOModelProxy. Follow the steps with figures below to create the proxy project now.
Create New Project
Choose Generic Project

Once the project is created, let’s generate the Web Service Proxy. In JDeveloper, click File –> New –> navigate to Business Tier –> select Web Service Proxy –> click OK. Then just follow the Web Service Proxy Creation Wizard as shown below.
Create Proxy From WSDL
Screenshot-CreateWebServiceProxy-Step1of7
Screenshot-CreateWebServiceProxy-Step2of7
Screenshot-CreateWebServiceProxy-Step3of7
Screenshot-CreateWebServiceProxy-Step4of7
Screenshot-CreateWebServiceProxy-Step5of8
Screenshot-CreateWebServiceProxy-Step6of8
Screenshot-CreateWebServiceProxy-Step7of9
Screenshot-CreateWebServiceProxy-Step8of9
Screenshot-CreateWebServiceProxy-Step9of9

You will see something like below once the wizard is completed.
FASDOModelProxy

Using Find Criteria
Now, let’s use the Find Criteria to filter the records as per our need. Say, you are interested in retrieving records of all active employees (ACTIVE=’Y’) and potentially apply more filters to it. If you simply invoke the operation findEmpView() from FASDOAppModuleService without criteria, it will retrieve all the records from the EMP table which is not the result we want. Therefore, let’s create a simple method that takes an attribute (Column name) and its value to construct the Find Criteria. Something to keep in mind, make sure all the object types used here are from the Web Services Proxy project, like the one created above, e.g. fasdomodel.types.ObjectFactory under FASDOModelProxy project.

//a simple method which takes attribute and value to filter
private static FindCriteria setFindCriteriaFilter(final String attribute,
                                                  final String operator,
                                                  final Object value){
  ObjectFactory obj = new ObjectFactory();
  ViewCriteriaRow vcr = obj.createViewCriteriaRow();
  ViewCriteria vc = obj.createViewCriteria();
  //setting view item
  ViewCriteriaItem vci  = obj.createViewCriteriaItem();
  vci.setAttribute(attribute);
  vci.getValue().add(value);
  vci.setOperator(operator);
  vci.setConjunction(Conjunction.AND);
  vcr.getItem().add(vci);
  vc.setConjunction(Conjunction.AND);
  vc.getGroup().add(vcr);
  FindCriteria fc = obj.createFindCriteria();
  fc.setFetchSize(-1);
  fc.setFetchStart(0);
  fc.setFilter(vc);
  return fc;
}

Testing above utility is simple, use the following test client code:

  ...
  FindCriteria fc = setFindCriteriaFilter("Active", "=", "Y");
  try {
      fASDOAppModuleService.findEmpView(fc, null);
  } catch (ServiceException e) {
    //throw exception here
  }
  ...

But, there will be instances where multiple filters might be needed to get the right result set. We can further refine the utility that will take any numbers of filters and apply that to the Find Criteria to bring back the desired result set. As part of employing multiple filters, let’s retrieve the records of active employees who also get commissions using the refined Find Criteria utility and the test client below.

/*
* append any numbers of filters that you might have and create a view criteria out of it, main filtering logic is here
/*
private static ViewCriteria _setViewCriteria(final Map<Map<String, String>,
                                             List<Object>> criteriaMap){
  //object factory from proxy project as mentioned above
  ObjectFactory obj = new ObjectFactory();
  // getting view criteria and view criteria row from proxy object factory
  ViewCriteriaRow vcr = obj.createViewCriteriaRow();
  ViewCriteria vc = obj.createViewCriteria();

  //looping thru attributes maps for filtering
  for(Map<String, String> attribMap : criteriaMap.keySet()){
    List<Object> values = criteriaMap.get(attribMap);
    //setting view item
    ViewCriteriaItem vci  = obj.createViewCriteriaItem();
    for(String attrib : attribMap.keySet()){
      vci.setAttribute(attrib);

      //incase you have multiple values you want to test against, this loop will handle it
      //e.g. column_name in (val1, val2, val3)
      for(Object value : values){
        vci.getValue().add(value);
      }

      //operators are self explanatory, could be =, !=, >, <, in, like etc
      vci.setOperator(attribMap.get(attrib));

      //this is what appends multiple attributes to filter on
      vci.setConjunction(Conjunction.AND);
    }
  vcr.getItem().add(vci);
  }
  vc.setConjunction(Conjunction.AND);
  vc.getGroup().add(vcr);
  return vc;
}

/*
* initial settings of Find Criteria
*/
private static FindCriteria _getFindCriteria(){
  ObjectFactory obj = new ObjectFactory();
  FindCriteria fc = obj.createFindCriteria();
  //2 attributes defined below could be used for pagination to retrieve set of record at a time
  fc.setFetchSize(-1);
  fc.setFetchStart(0);
  return fc;
}

/**
* used if multiple filters are needed in find criteria
* @param Map criteriaMap
*      Criteria Map consists of
*      <ul>
*          <li>Map of attribute and operator e.g "Active" and "=" or  "Commission" and "!="</li>
*          <li>List of values to filter on e.g. "Y", "null"</li>
*          <li>e.g. Active = "Y" AND Comm != null</li>
*      </ul>
* @return FindCriteria fc
*/
public static FindCriteria setFindCriteriaFilter(final Map<Map<String, String>,
                                                 List<Object>> criteriaMap){
  //setting view criteria
  ViewCriteria vc = _setViewCriteria(criteriaMap);
  //setting Find criteria filter
  FindCriteria fc = _getFindCriteria();
  fc.setFilter(vc);
  return fc;
}

/**
* used if only one filter is needed in find criteria
* e.g. Active = true
* @param attribute Column to filter on
* @param operator Operator for condition
* @param value Matching filter value
* @return FindCriteria fc
*/
public static FindCriteria setFindCriteriaFilter(final String attribute,
                                                 final String operator,
                                                 final Object value){

  Map<String, String> attribMap = new Hashtable<String, String>(1);
  attribMap.put(attribute, operator);
  List<Object> values = new ArrayList<Object>(1);
  values.add(value);
  Map<Map<String, String>, List<Object>> criteriaMap = new Hashtable<Map<String, String>, List<Object>>(1);
  criteriaMap.put(attribMap, values);
  return setFindCriteriaFilter(criteriaMap);
}

/**
* frequently used utility, retrives only active records, i.e. Active = "Y"
* @return FindCriteria fc
*/
public static FindCriteria setFindCriteriaForActiveRefData(){
  return setFindCriteriaFilter(STR_ACTIVE, EQUAL, STR_Y);
}

Now test it with a client and see the result yourself.

public class FASDOAppModuleServiceSoapHttpPortClient
{
  @WebServiceRef
  private static FASDOAppModuleService_Service fASDOAppModuleService_Service;

  public static void main(String [] args)
  {
    //create criteria map with multiple filters
    Map<String, String> attribMap = new Hashtable<String, String>();
    attribMap.put("Comm", "!=");
    List<Object> values = new ArrayList<Object>();
    values.add(null);
    Map<Map<String, String>, List<Object>> criteriaMap =
         new Hashtable<Map<String, String>, List<Object>>();
    criteriaMap.put(attribMap, values);
    attribMap = new Hashtable<String, String>();
    attribMap.put("Active", "=");
    values = new ArrayList<Object>();
    values.add("Y");
    criteriaMap.put(attribMap, values);

    /*
    * you can apply filter criteria in multiple ways
    */
    // (1) filter by only one attribute, this is the most commonly used method
    // FindCriteria fc = setFindCriteriaFilter("Active", "=", "Y");

    // (2) for frequently used query you can create a utility like this
    // FindCriteria fc = setFindCriteriaForActiveRefData();

    //(3) apply multiple filter with criteria map created above
    FindCriteria fc = setFindCriteriaFilter(criteriaMap);

    //display the result of the applied find criteria
        try {
            List sdoList = fASDOAppModuleService.findEmpView(fc, null);
            for(EmpViewSDO sdo : sdoList){
                System.out.println("Emp Name: "+sdo.getEname().getValue());
                System.out.println("Commission: "+sdo.getComm().getValue());
                System.out.println("Active: "+sdo.getActive());
                System.out.println();
            }
        } catch (ServiceException e) {
          //throw exception
        }
  }
}

Testing FASDOAppModuleService service from web
You can also test the deployed FASDOAppModuleService directly from web, if you would like:

Result from the deployed FASDOAppModuleService using findEmpView() operation.

Sanjib