Tuesday, December 22, 2015

Oracle MAF: Programmatically call REST service ( REST with JSON output)

This example is using RESTServicesAdapter. Using that programmatically you can call a REST service and you can manipulate response as per need.

My REST service details are as follows:

URL: localhost:1111/HrServiceFirst-ViewController-context-root/resources/view/emp

{"lstEmp":[{"address":"ss","empId":22222,"empName":"sss"},{"address":"SKING","empId":100,"empName":"Steven"},{"address":"NKOCHHAR","empId":101,"empName":"Neena"},{"address":"LDEHAAN","empId":102,"empName":"Lex"},{"address":"AHUNOLD","empId":103,"empName":"Alexander"}]}

Step 1: Create new Mobile Application Framework (MAF) Application:



Step 2 :Right click on Connenction create new REST Connection

Give the name of rest Connection and URL End point click ok as follow:

Step 3: Create Employee Class and add following variable and generate accessors

    public Integer empId;
    public String empName;
    public String address;


Step 4: create  CallService class and add follwing code in it

package mobile;

import java.util.ArrayList;
import java.util.List;

import oracle.adfmf.dc.ws.rest.RestServiceAdapter;
import oracle.adfmf.framework.api.Model;
import oracle.adfmf.json.JSONArray;
import oracle.adfmf.json.JSONException;
import oracle.adfmf.json.JSONObject;

public class CallService {
    public CallService() {
        super();
    }
    List<Employee> lstEmp=new ArrayList<Employee>();
    private Employee emp;
    public void setLstEmp(List<Employee> lstEmp) {
        this.lstEmp = lstEmp;
    }

    public List<Employee> getLstEmp() {
        return lstEmp;
    }
    public void getEmployees() {
           RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter(); 
           restServiceAdapter.clearRequestProperties();  
           restServiceAdapter.setConnectionName("restConn");  
           restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);    
           restServiceAdapter.setRetryLimit(0);
           restServiceAdapter.setRequestURI("/emp");
           try {
               String response = restServiceAdapter.send(""); 
               JSONObject res = null;  
               res = new JSONObject(response);     
               JSONArray lstOfEmp=res.getJSONArray("lstEmp");
               
               for(int i=0;i<lstOfEmp.length();i++){
                  JSONObject obj=lstOfEmp.getJSONObject(i);
                  System.out.println("Emp name "+obj.getString("empName"));
                   Employee e=new Employee();
                   e.setEmpName(obj.getString("empName"));
                   lstEmp.add(e);
               }
           } catch (JSONException jsone) {
               // TODO: Add catch code
               jsone.printStackTrace();
           } catch (Exception e) {
               // TODO: Add catch code
               e.printStackTrace();
           }
       }
}

Step 5:create Data Control of CallService Class;


 Step 6: create feature in maf-feature.xml with type MAF Task Flow and create Task Flow.
create ViewActivity call named RestServiceCall and Create .amx Page

Then select getEmployees() method from data control drop in task flow:


           

In PageDef of method View add accessor iterator in executables

Step 6: drag and drop DC in Page with empName view Attribute in List View


Step 7: Deploy project on emulator

Output:


Monday, December 21, 2015

ADF : Exposing BC Component using REST Service

In this blog, we are Exposing BC Component using Rest Service.

For example write service to get 5 Employees name from Employees table.
Use following steps:

Step 1: create ADF Application 
Step 2: Create EO and VO for Employee

Step 3:Create java class name Employee and 3 variable as :
    private Integer empId;
    private String empName;
    private String address;

and generate accessors for this

Step 4: Create java class for EmpWrapper ,In this class create  private List<Emplyee> lstEmp; variable to store Objects of Employee.

write @XmlRootElement above EmpWapper Class

Step 5: create java class EmpService
write  public EmpWapper getEmp() {}
In this method write bc4j  press Ctrl+Enter you will get follwing suggestion

Press Enter, code is generated to access AM instances

        ADFContext oldContext = ADFContext.initADFContext(null, null, null, null);
        try {
            String amDef = "test.TestModule"; 
            String config = "TestModuleLocal";
            ApplicationModule am = Configuration.createRootApplicationModule(amDef, config);
            ViewObject vo = am.findViewObject("TestView"); // VO to Access
            // Work with your appmodule and view object here
            Configuration.releaseRootApplicationModule(am, true);
        } finally {
            ADFContext.resetADFContext(oldContext);
        }

Add your logic to get 5 Employes name:

Copy and Paste following method code in Class


public EmpWapper getEmp() {
        EmpWapper objEmp=new EmpWapper();
       
        ADFContext oldContext = ADFContext.initADFContext(null, null, null, null);
        try {
            String amDef = "model.AppModule";
            String config = "AppModuleLocal";
            ApplicationModule am = Configuration.createRootApplicationModule(amDef, config);
            ViewObject vo = am.findViewObject("EmployeesView");
            int i=0;
            List<Emplyee> lstEmp=new ArrayList<Emplyee>();
            while(vo.hasNext()){
                
              Row row= vo.next();
               
              Emplyee emp=new Emplyee();
              emp.setAddress(row.getAttribute("Email").toString());
              emp.setEmpId(new Integer(row.getAttribute("EmployeeId").toString()));
              emp.setEmpName(row.getAttribute("FirstName").toString()); 
              lstEmp.add(emp);
              
               
             i++;
             if(i==5)
               break;
            }
            objEmp.setLstEmp(lstEmp);   
            // Work with your appmodule and view object here
            Configuration.releaseRootApplicationModule(am, true);
           
        } finally {
            ADFContext.resetADFContext(oldContext);
        }
        return objEmp;

    }

Step 6: right click on EmpService class and click on Create Restful Service

you will window like as follws:
Click on Produce and select application/xml media Type

Step 7: No win Configure HTTP method set

Type = Get
Produce = application/json
path =emp

and last finish.

then WebService is created . EmpService class looks like as follws:


Step 8:Now Deploye project and Test service

Output:

Note : suppose you will select in Step 7 :
Produce = application/xml

then output will be like this;

Hope this will help you

Thursday, August 20, 2015

ADF : Refresh the parent view when a taskflow displayed in a popup returns


- Refreshing the parent view when an in-line popup taskflow returns.

This scenario usually arises when the second task flow updates tables used by the first one from a different transaction context. 

There are two taskflows, both work with separate transaction contexts(Transaction attribute is set as new-transaction). Second taskflow is invoked from the first one as a dialog. The requirement here is to refresh the 'executables' of calling page(from first taskflow) when the second taskflow returns. 



createWO view from first task flow.

truckCompTF is the second taskflow.


- Define a returnListener for secondary window on the command button (which invokes second taskflow as dialog)

- Create method as dialogReturnListener in returnListner and copy below code

    public void dialogReturnListener(ReturnEvent returnEvent) {
        BindingContext bc = BindingContext.getCurrent();
          DCBindingContainer dcb =
            (DCBindingContainer)bc.getCurrentBindingsEntry();
          DCIteratorBinding iter =
            dcb.findIteratorBinding("TransportUnitVOIterator");   //your VOIterator 
          iter.executeQuery();         // It refresh the underlying IteratorBindings used by the parent page. 
       RequestContext.getCurrentInstance().addPartialTarget(returnEvent.getComponent().getParent().getParent());

    }


Tuesday, August 4, 2015

ADF - How-to show a glasspane and splash screen for long running queries


A Glass Pane is a pop-up that prevents user-input while a large database job or query is running in the background. It uses a splash screen with an animated image giving the impression of activity while the job completes.

The Glass Pane will consist of a pop-up that is activated by a javascript function included in the page-template.

Add Javascript File and Popup to Page Template:

Add the Popup in the Template as follows:

 <af:popup id="Busypopup"  contentDelivery="immediate">
                <af:dialog id="d2" type="none" closeIconVisible="false" title="File uploading...">
                    <af:panelGroupLayout id="pgl5" layout="vertical">
                        <af:image source="/resources/images/1processing.gif" id="i1"/> 
                    </af:panelGroupLayout>
                </af:dialog>
            </af:popup>

Include below Javascript code in the Template by using a Resource component.



function enforcePreventUserInput(evt) {
              var popup = AdfPage.PAGE.findComponentByAbsoluteId('pt1:Busypopup');
              if (popup != null) {
                  AdfPage.PAGE.addBusyStateListener(popup, handleBusyState);
                  evt.preventUserInput();
              }
          }
              function handleBusyState(evt) {
                  var popup = AdfPage.PAGE.findComponentByAbsoluteId('pt1:Busypopup');
                  if (popup != null) {
                      if (evt.isBusy()) {
                          popup.show();
                      }
                      else if (popup.isPopupVisible()) {
                          popup.hide();
                          AdfPage.PAGE.removeBusyStateListener(popup, handleBusyState);
                      }
                  }

              }

In above Code , pt1 is the page template id and Busypopup is the popup id.
pt1:Busypopup by this we get the address of popup.



Client Listener

On the button that calls the query or database job add a clientListener.
Ensure the PartialSubmit of the button is set to true (the default)


Add enforcePreventUserInput as the method (the javascript function we created earlier)


For  <af:inputFile> component use Type -> click in Client Listener
For  <af:button>     component use Type -> action in Client Listener


Output:



Monday, August 3, 2015

ADF- Checkbox selection will be calculated using Groovy, based on additional helper attribute.

In this blog we will see how to select or deselect checkbox value:

Steps:

Create your EO and VO of Table.
In this Example , i have TransportUnitVO. Here,I want to set a check box value (true or false) to attribute Discard.


create one new transient attribute of type Boolean named as CheckedDis and write groovy as follow in expression field of that attribute.

 Now in a page create one column, drag and drop this attribute in it.
On value changed write below Code in managed bean:

public void discardCheck(ValueChangeEvent valueChangeEvent) {
       Row  row = ADFUtils.getSelectedCurrentRow("TransportUnitVOIterator");
        if(valueChangeEvent.getNewValue().toString().equalsIgnoreCase("true")){
            row.setAttribute("Discard", "true");
        }else{
            row.setAttribute("Discard", "false"); 
        }
    }

After drag and drop, in a page source should be:

<af:selectBooleanCheckbox value="#{row.bindings.CheckedDis.inputValue}"
                                               label="#{row.bindings.CheckedDis.label}"
                                       shortDesc="#{bindings.TransportUnitVO.hints.CheckedDis.tooltip}"
                                     autoSubmit="true" immediate="true" id="sbc1" 
                      valueChangeListener="#{workOrderBean.discardCheck}"/>



Save all changes and run Page:

Output:
After saving details of TransportUnitVO value inserted of attribute Discard is true or false:

                   



Wednesday, July 29, 2015

JDeveloper Memory And Performance

As a general rule, Java is optimized for throughput, not latency. Once the garbage collector kicks in, performance drops like a rock. A 2 second pause every once in a while is OK for a server, but for an IDE it's misery. So here's the fix:


  1. Go to your JDeveloper root directory, is should be something like C:\Oracle\jdev\Middleware\jdeveloper
  2. Open the file ide\bin\ide.conf, scroll down to the default memory settings:
  3.         AddVMOption  -Xms128M
            AddVMOption  -Xmx768M
    
  4. Boost the memory to something larger, like so:
  5.         AddVMOption  -Xms1024M
            AddVMOption  -Xmx1024M
    
  6. Open the file jdev\bin\jdev.conf
  7. Add the following config settings:
  8.         # optimize the JVM for strings / text editing
            AddVMOption -XX:+UseStringCache
            AddVMOption -XX:+OptimizeStringConcat
            AddVMOption -XX:+UseCompressedStrings
    
            # if on a 64-bit system, but using less than 32 GB RAM, this reduces object pointer memory size
            AddVMOption -XX:+UseCompressedOops
    
            # use an aggressive garbage collector (constant small collections)
            AddVMOption -XX:+AggressiveOpts
    
            # for multi-core machines, use multiple threads to create objects and reduce pause times
            AddVMOption -XX:+UseConcMarkSweepGC
    
  9. Then restart JDeveloper... If it doesn't start, you'll need to reduce the amount of memory allocate in the ide.conf file from step 3.

ADF : Insert Row at the Top and Bottom of table

To insert row at the bottom of table follow followings steps:

Step 1 -  Generate VOimpl class of your  View Object.

Step 2 - Go to VOimpl class and add below code

         /**
     * Insert new Rows at the end of RowSet.
     * @param row
     */
    @Override
    public void insertRow(Row row) {
        //go to the end of Rowset if it has rows
        Row lastRow = this.last();
        if (lastRow !=null){
             //insert new row at the end and make it current
            int indx = this.getRangeIndexOf(lastRow)+1;
            this.insertRowAtRangeIndex(indx,row);
            this.setCurrentRow(row);
        }else { // empty Rowset
        super.insertRow(row);
        }
        }

In this way row always insert at bottom of table.


To insert row at the top of table follow following steps:

Step 1 - Generate VOimppl class of your View Object.

Step 2 -Go to VOimpl class and add below code,

         /**
     * Insert new Rows at the top of RowSet.
     * @param row
     */
    @Override
    public void insertRow(Row row) {
        //go to the First of Rowset if it has rows
        Row firstRow = this.first();
        if (firstRow !=null){
             //insert new row at the top and make it current
            int indx = this.getRangeIndexOf(firstRow);
            this.insertRowAtRangeIndex(indx,row);
            this.setCurrentRow(row);
        }else { // empty Rowset
        super.insertRow(row);
        }
        }

In this way row always insert at top of the table.


Tuesday, July 21, 2015

ADF-How To call and Execute sql function Programatically (using operationBinding.getParamsMap() )

Most of the scenarios , we need to call sql function pragmatically.

Here, is the one approch by using Map we can put input parameter to function and get result as Object.

1- Suppose we have Login Table as follows:

2-we want to fetch name of particular user id. So, for that we will create function is database as follows.

3-Now create Application Test ,create Login EO, LoginVO,
4-In AppModuleImpl.class write following method to get result from database.



5-From  Managed Bean call above method as follows:

    OperationBinding operationBinding =
                 (OperationBinding) bindings.getOperationBinding("getName");//AppModuleImpl.class method Name
operationBinding.getParamsMap().put("id", <Pass ID here>);
Object result = operationBinding.execute();//we can get Name of that user Id in result Object


ADF- How to Apply and Create View Criteria Programatically


   

 1.   I have already created a view criteria in EmployeeVO, and I want to call it programmatically.

                public void searchEmployee(Number employeeId) {
                            ViewObjectImpl vo = getEmployeesView1();    
                            ViewCriteria vc = vo.getViewCriteria("findEmployeeVC");   
                            vo.applyViewCriteria(vc);               
                            vo.setNamedWhereClauseParam("pEmployeeId", employeeId);    
                            vo.executeQuery();            
                 }


    2.    I want to create a view criteria dynamically and execute it programmatically.

                   public void searchByEmployeeIdEmail(Number employeeId, String email) {
                                   ViewObjectImpl vo = getEmployeesView2();
                                   ViewCriteria vc = vo.createViewCriteria();
                                   ViewCriteriaRow vcRow = vc.createViewCriteriaRow();
     
                                    vcRow.setAttribute("EmployeeId", employeeId);
                                    vc.addRow(vcRow);
                                    vcRow.setAttribute("Email", email);
                                    vc.addRow(vcRow);
     
                                    vo.applyViewCriteria(vc);
                                    vo.executeQuery();
                    }

Monday, June 22, 2015

ADF -Total Sum of a Column in a Table using Groovy:

In this blog we will see how to get a sum of column in table.

For Example:Sum of salary in employee table:

So,we will use Groovy for this task:

Model Project:

-create EmployeeVO based on Employee EO Table.

-go to EmployeeVO, create one transient attribute say TotalSalSum




-go to accessors,create view accessor of EmployeeVO
Shuffle EmployeeVO,following screen will appear:


-Then give the Groovy for TotalSalSum as follows:
EmployeeVO1.sum(“Salary”)




-Create a new page. Drag and Drop EmployeesVO from data control and create a new read only table "without" TotalSalSum Attribute.
-Now go to the Salary Column, add Facet-column ->footer



-Now from data control drag and drop TotalSalSum attribute in Salary attribute footer


-Go to the source of TotalSalSum ->  change output text value Attribute
From : <af:outputText value="#{row.TotalSalSum}"
To:  <af:outputText value="#{bindings.TotalSalSum.inputValue}"


-Now go to bindings and create a new binding for this attribute.



Save all and run Page:Result:





Wednesday, June 17, 2015

Programmetic View Object in ADF

Sometime we need to call Stored Procedure or Stored function in ADF application. Programmetic View objects are used for this. In this blog I will explain how to use Programmetic VO to call the Strored procedure and function.

We need to override following methods of the ViewImpl class
1.executeQueryForCollection()
2.hasNextForCollection()
3.createRowFromResultSet()
4.releaseUserDataForCollection()
Below are the detailed steps
    1.create VO as below


   2. add the needed atributes
   3. Override the above mentioned methods in VOImpl Class
   4. Make sure all the attributes in VO are updatable
   5. Atleast one attribute should be key attribute
   6. I have created Employee VO as below
   




Define the Stored Function in DB,

CREATE OR REPLACE FUNCTION HR.FUNC_returnEmployee
RETURN SYS_REFCURSOR
AS
REF_TEST   SYS_REFCURSOR;
BEGIN
OPEN REF_TEST FOR
SELECT   employee_id,first_name,phone_number,salary
FROM   employees;
RETURN REF_TEST;
END;


Code of ViewObject Impl class which override above define method.


package model.views;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jbo.JboException;
import oracle.jbo.server.ViewObjectImpl;
import oracle.jbo.server.ViewRowImpl;
import oracle.jbo.server.ViewRowSetImpl;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Mon May 05 14:59:26 IST 2014
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class EmployeeProgramaticVoImpl extends ViewObjectImpl {
    /**
     * This is the default constructor (do not remove).
     */
    public EmployeeProgramaticVoImpl() {
    }
    /**
     * executeQueryForCollection - overridden for custom java data source support.
     */
    protected void executeQueryForCollection(Object qc, Object[] params,
                                             int noUserParams) {
        addEmployeeRecords(qc, callToStroredFunc(qc, params));
        super.executeQueryForCollection(qc, params, noUserParams);
    }
   
    private ResultSet callToStroredFunc(Object qc, Object[] params) {
    ResultSet rs =getStoredProcParams();
    return rs;
    }
   
    public ResultSet getStoredProcParams() {
    ResultSet rs = null;
    try {
    String sp = "{? = call func_returnEmployee()}";
    CallableStatement proc = null;
    proc = this.getDBTransaction().createCallableStatement(sp,0);
    proc.registerOutParameter(1, OracleTypes.CURSOR);
    proc.executeQuery();
    rs= ((OracleCallableStatement)proc).getCursor(1);
    } catch (SQLException sqlerr) {
    throw new JboException(sqlerr);
    }
    return rs;
    }
    private void addEmployeeRecords(Object qc, ResultSet rs) {
    ResultSet existingRs = (ResultSet)getUserDataForCollection(qc);
    // If this query collection is getting reused, close out any previous rowset
    if (existingRs != null) {
    try {
    existingRs.close();
    } catch (SQLException e) {
    throw new JboException(e);
    }
    }
    setUserDataForCollection(qc, rs);
    hasNextForCollection(qc); // Prime the pump with the first row.
    }

     /**
     * hasNextForCollection - overridden for custom java data source support.
     */
     protected boolean hasNextForCollection(Object qc) {
     ResultSet rs = (ResultSet)getUserDataForCollection(qc);
     boolean nextOne = false;
     if (rs != null) {
     try {
     nextOne = rs.next();
     /*
     * When were at the end of the result set, mark the query collection
     * as "FetchComplete".
     */
     if (!nextOne) {
     setFetchCompleteForCollection(qc, true);
     /*
     * Close the result set, we're done with it
     */
     rs.close();
     }
     } catch (SQLException s) {
     throw new JboException(s);
     }
     }
     return nextOne;
     }
     /**
     * createRowFromResultSet - overridden for custom java data source support.
     */
     protected ViewRowImpl createRowFromResultSet(Object qc,
     ResultSet resultSet) {
     resultSet = (ResultSet)getUserDataForCollection(qc);
     /*
     * Create a new row to populate
     */
     ViewRowImpl r = createNewRowForCollection(qc);
     if (resultSet != null) {
     try {
     /*
     * Populate new row by attribute slot number for current row in Result Set
     */
     populateAttributeForRow(r, 0,
     resultSet.getString(1));
     populateAttributeForRow(r, 1,
     resultSet.getString(2));
     populateAttributeForRow(r, 2,
     resultSet.getString(3));
     populateAttributeForRow(r, 3,
     resultSet.getString(4));
     } catch (SQLException s) {
     throw new JboException(s);
     }
     }
     return r;
     }
     protected void releaseUserDataForCollection(Object qc, Object rs) {
     ResultSet userDataRS = (ResultSet)getUserDataForCollection(qc);
     if (userDataRS != null) {
     try {
     userDataRS.close();
     } catch (SQLException s) {
     /* Ignore */
     }
     }
     super.releaseUserDataForCollection(qc, rs);
     }
     /**
     * getQueryHitCount - overridden for custom java data source support.
     */
     public long getQueryHitCount(ViewRowSetImpl viewRowSet) {
   
     return 100;
     }
   
}

Run the AM and see the result.