الأربعاء، 6 مايو 2020

ADF: Programmatic View Object Using Ref Cursor.

ADF: Programmatic View Object Using Ref Cursor.

Sometimes user needs to create View Object based on procedure or function which returns Ref cursor. For this type of requirement ADF framework provides programmatic VO option.  In this tutorial I’ll explain you how we can create View Object using Cursor.

 

To create programmatic View Object you have to override following methods of View Object Impl Class.

1. create()

2. executeQueryForCollection()

3. hasNextForCollection()

4. createRowFromResultSet()

5. getQueryHitCount()

6. protected void releaseUserDataForCollection()

Here I’m using a function which returns Ref Cursor

CREATE OR REPLACE FUNCTION HR.FUNC_returncursor
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;

To create the read-only programmatic view object:

1. In the Application Navigator, right-click the project in which you want to create the view object and choose New.

2. In the New Gallery, expand Business Tier, select ADF Business Components and then View Object, and click OK.

3. In the Create View Object wizard, in the Name page, provide a name and package for the view object. For the data source, select Rows populated programmatically, not based on a query.

1

 

4. In the Attributes page, click New one or more times to define the view object attributes your programmatic view object requires.

2

 

5. In the Attribute Settings page, adjust any setting you may need to for the attributes you defined.

6. In the Java page, select Generate View Object Class to enable a custom view object class (ViewObjImpl) to contain your code.

7. Click Finish to create the view object.

3

Code of ViewObject Impl class which override above define method.

package com.in.adftutorials.model;

import java.math.BigDecimal;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import oracle.jbo.JboException;
import oracle.jbo.server.DBTransaction;
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.
// --- Sat Apr 20 11:40:36 IST 2013
// --- Custom code may be added to this class.
// --- Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class EmpVoImpl extends ViewObjectImpl {
/**
* This is the default constructor (do not remove).
*/
public EmpVoImpl() {
}
protected void create() {
getViewDef().setQuery(null);
getViewDef().setSelectClause(null);
setQuery(null);
}
/**
* executeQueryForCollection - overridden for custom java data source support.
*/
protected void executeQueryForCollection(Object qc, Object[] params,
int noUserParams) {
storeNewResultSet(qc, retrieveParamsResultSet(qc, params));
super.executeQueryForCollection(qc, params, noUserParams);
}

private ResultSet retrieveParamsResultSet(Object qc, Object[] params) {
ResultSet rs =getStoredProcParams();
return rs;
}

public ResultSet getStoredProcParams() {
Connection conn = null;
ResultSet rs = null;
try {

String sp = "{? = call func_returncursor()}";
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 storeNewResultSet(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) {
/* Object[] params = viewRowSet.getParameters(true);
BigDecimal id = (BigDecimal)params[0];
CallableStatement st = null;
try {
st = getDBTransaction().createCallableStatement(COUNTSQL,
DBTransaction.DEFAULT);

st.registerOutParameter(1,Types.NUMERIC);

if (id == null) st.setNull(2,Types.NUMERIC);
else st.setBigDecimal(2,id);
st.execute();
return st.getLong(1);
}
catch (SQLException s) {
throw new JboException(s);
}
finally {try {st.close();} catch (SQLException s) {}} */

// long value = super.getQueryHitCount(viewRowSet);
//return value;
return 108;
}
}

Result

4

 

Sample Code

الأربعاء، 29 أبريل 2020

How to display a please wait message when the server is processing using addBusyStateListener in ADF ?


Clients often require their ADF applications to process a lot of data or upload big files when their users click on a specific button.
Those treatments can often take a couple of minutes to run and your user may lose patience or wonder why the application isn’t responding.
As a best practice, you should always aim to provide a fast responding application and run the big treatment in an asynchronous way behind the scene to avoid blocking the user interface.
But if you still have to process the long action synchronously, for example, to upload a big file, you need to display a message for the user to know his request is getting processed.
You’ll also need to prevent user interaction with the screen that could stop this treatment being processed. (navigation for example)
To implement it in ADF, you’ll need :
  • A modal ADF popup or another element to display the “processing in progress” message :
Tip 1: Be sure that this group is set on all the page where you need to warn the user. (If you need it more than once set it in a template)
Tip 2: Be sure that the popup is set as clientComponent=”true”. (if not it’ll fail to display most of the time and you’ll have a hard time understanding why)
Tip 3 (optional) : set a pure HTML div <div id=”loaderId”></div> before the popup to simplify getting it’s absolute id. (It’s hard to retrieve the absolute ADF element id in javascript)
<af:group id="pt_g3">
<div id="loaderId"></div>
<af:popup id="processingP" contentDelivery="immediate" clientComponent="true">
<af:dialog id="d2" title="Processing..." type="none" closeIconVisible="false" inlineStyle="text-align:center;" clientComponent="true"
modal="true">
<f:facet name="buttonBar"/>
<af:panelGroupLayout id="pgl2" layout="vertical" halign="center">
<af:spacer width="10" height="10" id="s11"/>
<af:outputText value="Please wait..." id="ot2669"/>
</af:panelGroupLayout>
</af:dialog>
</af:popup>
</af:group>
  • client listener to trigger the busy listener only on the buttons where you require the user to be warned :
<af:commandButton text="Do Something" immediate="true" partialSubmit="true" actionListener="DoSomething" >
<af:clientListener method="warnAndPreventUserInput" type="action"/>
</af:commandButton>
  • Define this javascript resource for your page :
Tip 1: Also ensure this javascript is set on the page where you need to warn the user.
(I usually recommend to set it in the header template so it’s available on all page using it)
Tip 2: If your popup often open itself again after being closed the first time be sure to set the listener on the clicked element (clickedElem = evt.getSource();)
Most issues are due to the removeBusyStateListener arguments being different from the previous addBusyStateListener
Tip 3: Refer to the comments describing how we use the ADF public javascript API to get notified when the server is busy and done.
(for more information: https://docs.oracle.com/html/E12046_04/oracle/adf/view/js/base/AdfPage.html#addBusyStateListener_Object__Function_)
var popup = null;
var clickedElem = null;
function triggerOnLoad(event) {
//You can either set the popup using the pure html div id (recommended)
popup = AdfPage.PAGE.findComponentByAbsoluteId(document.getElementById('loaderId').nextSibling.id);
//or set the popup knowing the full id of your popup for example :
//popup = AdfPage.PAGE.findComponentByAbsoluteId('p1:processingP');
//popup = AdfPage.PAGE.findComponent('processingP');
return true;
}
function warnAndPreventUserInput(evt) {
//To avoid most mistake where addBusyStateListener and removeBusyStateListener don't have the same arguments
//You can set the element to listen for the application busy state to be the one the user just clicked :
clickedElem = evt.getSource();
if (popup != null) {
//Adds a listener to call the handleBusyState function whenever there is a busy state event.
AdfPage.PAGE.addBusyStateListener(clickedElem, handleBusyState);
//Don't authorize the user to interact with ADF while it's busy
evt.preventUserInput();
} else {
console.error('The processing pop up isnt defined on this page ');
}
}
//JavaScript call back handler
function handleBusyState(evt) {
if (popup != null) {
if (evt.isBusy()) {
//Processing in progress so we display the popup
popup.show();
} else {
//Processing is done so we can close the popup
popup.hide();
//Important : We remove the listener from the clicked object so it will
//stop looking for a busy event to display the popup
AdfPage.PAGE.removeBusyStateListener(clickedElem, handleBusyState);
}
} else {
console.error('The processing pop up isnt defined on this page ');
}
}

ADF: Programmatic View Object Using Ref Cursor.

ADF: Programmatic View Object Using Ref Cursor. Posted by:  Manish Pandey   April 25, 2013   in  ADF   Leave a comment   3758 Views Sometime...