Monday, May 31, 2010

ADF:Sorting a Programmatic/Transient ViewObject

Often we use Transient ViewObject to store In-Memory data to represent in UI or manipulate business logic.
We may need to sort these Transient ViewObjects based on certain attribute.

MyTransVO.setSortBy("AttributeName");
MyTransVO.setQueryMode(ViewObject.QUERY_MODE_SCAN_VIEW_ROWS);
MyTransVO.executeQuery();

Monday, May 24, 2010

ViewCriteria in Shared AM-Reuse BindVariable and QueryCollection from Cache

A VO on a sharedAM caches multiple rowsets by the bind variables. So if you query a VO 5 times with 5 different bind variables, it does cache 5 rowsets. And if you go back and requery by those same bind variables you dont not see any database I/O

Here is a sample code

    public void applyVC() {
EmpVOImpl vo = this.getEmpVO1();

ViewCriteria vc = vo.getViewCriteria("findByEmpId");
vo.setNamedWhereClauseParam("pEmpId", "931");
vo.applyViewCriteria(vc);
vo.refreshCollection(null, true, true);
vo.reset();

int rowcount = 0;
while (vo.hasNext()) {
Row row = vo.next();
rowcount++;
}
System.out.println("Total # of rows = " + rowcount);

}


Execute this multiple times from AM tester or from ADF UI and you will see the difference.

Important note is,instead of executeQuery() you should use refreshFromCollection() so that the Rowset is resued from QueryCollection cache.

Technical Analysis
For SharedAM,Once the RowSet is closed, the QueryCollection will be released to the QueryCollection cache and potentially reused upon the next request.

ADFbc:Common Util class for testing CRUD operation of an EO based VO

A simple common util class that your Junit class can extend for verifying standard CRUD operation for a a single EO based VO.

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.server.AttributeListImpl;
import oracle.jbo.server.ViewObjectImpl;


public class AtkCommonVOActionsTest {
public AtkCommonVOActionsTest() {
super();
}

public Row testCreateRow(ViewObjectImpl viewObject, Map<String,Object> attributeList){
AttributeListImpl initVals = createAttributeList(attributeList);
Row row = viewObject.createAndInitRow(initVals);
return row;
}

public Row testUpdateRow(ViewObjectImpl viewObject, Map<String,Object> attributeList, Key pkObject){
if(pkObject != null){
Row[] rows = viewObject.findByKey(pkObject, 1);
if(rows != null && rows.length > 0){
Row row = rows[0];
List<String> keyList = getKeyList(attributeList);
List<Object> valueList = getValueList(attributeList);
row.setAttributeValues(keyList, valueList);
return row;
}

}
return null;
}


public Row testDeleteRow(ViewObjectImpl viewObject, Key pkObject){
if(pkObject != null){
Row[] rows = viewObject.findByKey(pkObject, 1);
if(rows != null && rows.length > 0){
Row row = rows[0];
row.remove();
return row;
}
}
return null;
}



private AttributeListImpl createAttributeList(Map<String,Object> attributeList){
AttributeListImpl attrList = new AttributeListImpl();
Iterator<String> keys = attributeList.keySet().iterator();
while(keys.hasNext()){
String key = keys.next();
Object value = attributeList.get(key);
attrList.setAttribute(key, value);
}
return attrList;
}

private List<String> getKeyList(Map<String,Object> attributeList){
List<String> keyList = new ArrayList<String>();
Iterator<String> keys = attributeList.keySet().iterator();
while(keys.hasNext()){
String key = keys.next();
keyList.add(key);
}
return keyList;
}

private List getValueList(Map<String,Object> attributeList){
List valueList = new ArrayList();
Iterator<String> keys = attributeList.keySet().iterator();
while(keys.hasNext()){
String key = keys.next();
Object value = attributeList.get(key);
valueList.add(value);
}
return valueList;
}



}

Monday, May 17, 2010

ADF input forms generator (from XSD to a web page)

Requirement
There is one XSD file which has is "Define Conuntry application input data definition".
So it defines all the data you have to fill in to create a Country info. XSD defines which fileds are mandatory and which are optional.
We would like to create an internet service to allow creating/displaying a Country.

Example
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.oracle.com/pcbpel/CountryInfo"
elementFormDefault="qualified">
<element name="CountryInfo">
<complexType>
<sequence>
<element name="Country" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="Name" type="string"/>
<element name="Capital" type="string"/>
<element name="Area" type="decimal"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>


Solution
1)-In JDev, Select the XSD in the Applications Navigator.
2)- Right Click the xsd file and select "Generate JAXB2.0 contet Model".
3)-It generates the required java files.
4)-Right click the relevant Java file(e.g in this case , CountryInfo.java)
5)-Select "Create Data Control" and generate the .dcx file.

Now you can use this Data Control to drag and drop to build any ADF component such as a Form Layout or a Table etc etc.

Bottom Line is somehow you need to create a DataControl out of the XSD file to use that declaratively to build an ADF UI.

Note
You can also generate the Webservice out of these XSD through JAXB and expose that to build UI, either using ADF datacontrol or any standard J2EE solution.

Saturday, May 15, 2010

ADF:Bring a specific row in a VO to the top slot

Requirement
You have a view object populated with some rows.You want to put a specific row(identified by a PK attribute) at the top of the VO query collection.

Example
if(pEmpno != null){
Row foundEmpRow = empVO.getRow(new Key(new Object[]{pEmpno}));
if(foundEmpRow != null){
ViewObjectImpl empVOImpl = (ViewObjectImpl)empVO;
empVOImpl.getQueryCollection().remove(foundEmpRow);
empVOImpl.getQueryCollection().add(0, foundEmpRow);
}
}

Tuesday, May 11, 2010

EntityObject:Creating your own History Attributes

ADF Entity Objects allows a functionality to define History Attributes for the Entity Objects.Such as "CreatedOn","ModfiedOn","CreatedBy","ModifiedBy" etc etc.

For your application, if you want you can introduce/extend these History Attributes from the JDev preference.

Steps To create a custom history type:

From the Tools menu, choose Preferences.
In the Preferences dialog, expand Business Components, and click History Types.
On the History Types page, click New.
In the Create History Type dialog, enter a string value for the name (spaces are allowed) and a numerical Id.
Open the EntityImpl.java file and add a definition for the numerical id such as
private static final byte MYCUSTOM_HISTORY_TYPE = 20;

Override the getHistoryContextForAttribute(AttributeDefImpl attr) method in the EntityImpl base class

@Override
protected Object getHistoryContextForAttribute(AttributeDefImpl attr) {
if (attr.getHistoryKind() == MYCUSTOM_HISTORY_TYPE) {
// Custom History type logic goes here
}
else {
return super.getHistoryContextForAttribute(attr);
}
}

Monday, May 03, 2010

Mapping ADF(Faces + ADFbc) to J2EE MVC

An interesting mail I found today.Simple and explanatory.

How to map the ADF application projects to J2EE MVC Architecture.

To be simple..
MODEL (M in MVC):
what ever you see in Model.jpr(which contains ADF BC componenets like EO,VO,AM ) . Interestingly they call this as Business Services in ADF and call "Data Bindings" and "Data Controls" as ADF Model. Data Controls(Application Modules) will be part of your Model.jpr and Data Bindings will be part of your UI.jpr.
So, Simply MODEL means combination of Data Bindings and Data Controls in ADF
It can be ADFbc,TopLink,EJB, even POJOs.

View (V in MVC):
View is simply what ever user see and interact with application. So, what ever u see under UI.Jpr like .jsff, .jspx, Flow.xml etc.. all these comes under View Componenets. You can see lot many XML files under UI.jpr, like PageDef.xml(this is where you will have your page level Data Bindings) and other configuration files(like web.xml, adfc-config.xml etc..)

Controller (C in MVC):
Unfortunately you can't map declaratively as we do for M and V. But, in ADF controller is "FacesServlet" which is the first controller java servlet which will listen to user request and initiate the faces life cycle process. In most of the Web frameworks(like , Struts, JSF) a servlet acts as a controller. So, here in ADF it is "FacesServlet"(you can search for this entry in web.xml). "FacesServlet" job is to listen to user request and decide which View to be shown to the user by interacting with which Model Components.
(Note: In Jdev, Controller basically resides in UI project itself, thats why they name UI project as ViewControler (where as Model project name is Model))

ADF:Check if there are pending changes in UI

Situations arise when we may need to check if there is any pending transactions in the ADF UI.
You can do it easily from ADFbc.

Use DBTransactionImpl.isDirty()

Or From ADF Faces side

BindingContext bctx = oracle.adf.controller.binding.BindingUtils.getBindingContext();
bctx.findDataControlFrame(bctx.getCurrentDataControlFrame()).isTransactionDirty();