Friday, January 21, 2011

OAF:R12:JRAD Missing TroubleShooting

Check JRAD File Missing In MDS Repository for R12 OAF framework.

1)-From SQLPPLUS exec jdr_utils.listdocuments('/oracle/apps/ap/oie/webui');

2)-See what all files are missing in this output and what extra files are there in $AP_TOP/mds/oie/webui.


3)-You can copy those extra files from $AP_TOP/mds/oie/webui to $JAVA_TOP and use the XMLImporter command.

adjava -mx128m -nojit oracle.jrad.tools.xml.importer.XMLImporter
$JAVA_TOP/oracle/apps/ap/oie/webui/MonitorNtfResponseDetailPG.xml
-username apps -password apps
-dbconnection "(description=(address_list=(ADDRESS=(PROTOCOL=TCP)(HOST=myHost)(PORT=1521)))(CONNECT_DATA=(SID=mysid)))"
-rootdir $JAVA_TOP


replace the $JAVA_TOP with physical path of JAVA_TOP directory and change the
database info in the command.

4)-Bounce Apache and thats all..


For a single file you can use

exec jdr_utils.printDocument("oracle/apps/ap/oie/webui/MonitorNtfResponseDetailPG.xml");

This situation arises when driver is not applied properly..

If huge no of JRAD files are missing, then you can think of applying the driver once more by using the following command(in today's new unified driver)

adpatch options=nocopyportion,nocheckfile,nogenerateportion

or

If the file difference between the output of the SQL proc and the $AP_TOP/mds/oie/webui is merely 1 or 2 then you can manually import through XMLImporter.

Wednesday, January 19, 2011

Opening a Remote HTTP URL inan ADF Dialog using Bounded Taskflow

Requirement
We want to open an HTTP remote URL(say http://www.google.com) in an ADF Dialog Framework window while user clicks a commandLink in the base jspx/jsff page.

Implementation
1.Create a wrapper TF called MyFlowTF in adfc-config.xml.

<?xml version="1.0" encoding="UTF-8" ?>
<adfc-config xmlns=" http://xmlns.oracle.com/adf/controller" version="1.2" id="__8">
<task-flow-definition id="MyFlowTF">
<default-activity id="__1">MyPage</default-activity>
<transaction id="__6">
<new-transaction/>
</transaction>
<data-control-scope id="__7">
<isolated/>
</data-control-scope>
<managed-bean id="__4">
<managed-bean-name id="__2">popupBean</managed-bean-name>
<managed-bean-class id="__3">oracle.ui.bean.popupBean</managed-bean-class>
<managed-bean-scope id="__5">backingBean</managed-bean-scope>
</managed-bean>
<view id="NotificationPage">
<page id="__9">/oracle/ui/page/MyPage.jsff</page>
</view>
<task-flow-call id="PopupNotifWrapperTF">
<task-flow-reference>
<document>/WEB-INF/oracle/ui/flow/PopupWrapperTF.xml</document>
<id>PopupWrapperTF</id>
</task-flow-reference>
<input-parameter id="__11">
<name>mesgUrl</name>
<value>#{backingBeanScope.popupBean.remoteAppUrl}</value>
</input-parameter>
<input-parameter id="__12">
<name>taskDefId</name>
<value>#{backingBeanScope.popupBean.taskDefId}</value>
</input-parameter>
<input-parameter id="__13">
<name>remoteAppUrl</name>
<value>#{backingBeanScope.popupBean.remoteAppUrl}</value>
</input-parameter>
<input-parameter id="__14">
<name>dynamicTaskDefId</name>
<value>#{backingBeanScope.popupBean.taskDefId}</value>
</input-parameter>
<run-as-dialog id="__10"/>
</task-flow-call>
<control-flow-rule id="__20">
<from-activity-id id="__21">MyPage</from-activity-id>
<control-flow-case id="__22">
<from-outcome id="__24">taskDetails</from-outcome>
<to-activity-id id="__23">PopupWrapperTF</to-activity-id>
</control-flow-case>
</control-flow-rule>
<use-page-fragments/>
</task-flow-definition>
</adfc-config>



2.Wrapper TF code:

<?xml version="1.0" encoding="UTF-8" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
<task-flow-definition id="PopupWrapperTF">
<default-activity id="__3">remoteTaskFlowCall</default-activity>
<input-parameter-definition id="__1">
<name id="__2">remoteAppUrl</name>
<value>#{requestScope.remoteAppUrl}</value>
<class>java.lang.String</class>
<required/>
</input-parameter-definition>
<input-parameter-definition id="__6">
<name id="__5">dynamicTaskDefId</name>
<value>#{requestScope.dynamicTaskDefId}</value>
<class>oracle.adf.controller.TaskFlowId</class>
<required/>
</input-parameter-definition>
<managed-bean id="__10">
<managed-bean-name id="__8">opupBean</managed-bean-name>
<managed-bean-class id="__9">oracle.ui.bean.PopupBean</managed-bean-class>
<managed-bean-scope id="__7">backingBean</managed-bean-scope>
</managed-bean>
<task-flow-call id="remoteTaskFlowCall">
<dynamic-task-flow-reference>#{requestScope.dynamicTaskDefId}</dynamic-task-flow-reference>
<remote-app-url>#{requestScope.remoteAppUrl}</remote-app-url>
</task-flow-call>
</task-flow-definition>
</adfc-config>



Add the permission for this TF in jazn-data.xml, if your WebApp is secured.

UI Change: 

<af:commandImageLink text="#{'MyMessage'}" id="cil2"
inlineStyle="white-space:normal;"
clientComponent="true"
shortDesc="#{'shortDesc'}"
action="taskDetails"
useWindow="true"
windowHeight="600"
windowWidth="750"
actionListener="#{backingBeanScope.popupBean.onClick}">
<af:setActionListener from="#{'http://www.google.com'}"
to="#{pageFlowScope.detailsUrl}"/>
</af:commandImageLink>

3.Add required code in the bean method..

public String remoteAppUrl = null;
public TaskFlowId taskflowDefId = null;

public void setTaskDefId(TaskFlowId taskflowDefId) {
this.taskflowDefId = taskflowDefId;
}

public TaskFlowId getTaskflowDefId() {
return taskflowDefId;
}

public void setRemoteAppUrl(String remoteAppUrl) {
this.remoteAppUrl = remoteAppUrl;
}

public String getRemoteAppUrl() {
return remoteAppUrl;
}


public void onClick(ActionEvent actionEvent) {
// Add event code here...
//gets the taskflow details url.
String taskflowUrl = (String)ADFUtil.evaluateEL("#{pageFlowScope.detailsUrl}");
//sets the taskflow Id and remote url to be passed to the remote task flow call activity.
this.setTaskDefId(this.getTaskFlowDefinitionId(taskflowUrl));
this.setRemoteAppUrl(this.getRemoteAppURL(taskflowUrl));
}

/**@
* This method gets the task flow Id from the complete url.
* @param taskDetailsURL
* @return
*/
public TaskFlowId getTaskFlowDefinitionId(String detailsURL) {
//Checks if the url is null.
if (detailsURL == null)
return null;
//gets the parameter list from the url.
String parameterList =
detailsURL.substring(detailsURL.indexOf("?") + 1,
detailsURL.length());
//tokenizes the url.
StringTokenizer stok = new StringTokenizer(parameterList, "&");
String taskFlowId = null;
String documentName = null;
//gets the taskflowId from the url.
while (stok.hasMoreTokens()) {
String parameter = stok.nextToken();
String[] parts = parameter.split("=", 2);
if (parts[0].equals("_id"))
taskFlowId = parts[1];
if (parts[0].equals("_document"))
documentName = parts[1];
}

//decodes the encoded url.
try {

documentName = URLDecoder.decode(documentName, "UTF-8");
taskFlowId = URLDecoder.decode(taskFlowId, "UTF-8");

} catch (Exception ex) {
ex.printStackTrace();
}

return new TaskFlowId(documentName, taskFlowId);
}


/**@
* This method extracts the remoteAppUrl.
* @param detailsURL
* @return
*/
public String getRemoteAppURL(String detailsURL) {
if (detailsURL == null)
return null;
int index = detailsURL.indexOf("&_id");

String url = "";
//extracts the remote app url part.
if(index > 0)
url = detailsURL.substring(0,taskDetailsURL.indexOf("&_id"));

return url;

}


Register the notification bean in WrapperTF as backing bean scope to read the input parameters.

ADF declarative component

A Sample ADF Declarative component that supports attributes, facets,Even Listener is here

         <?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<af:componentDef var="attrs" componentVar="component">
<af:xmlContent>
<component xmlns="http://xmlns.oracle.com/adf/faces/rich/component">
<display-name>MyComp</display-name>
<facet>
<facet-name>additionalInfo1</facet-name>
</facet>
<facet>
<facet-name>additionalInfo2</facet-name>
</facet>
<attribute>
<attribute-name>
MyValue
</attribute-name>
<attribute-class>
java.lang.String
</attribute-class>
<required>
true
</required>
</attribute>
<component-extension>
<component-tag-namespace>oracle.myComponent.Ui.component</component-tag-namespace>
<component-taglib-uri>http://xmlns.oracle.com/myComponent/MyComp</component-taglib-uri>
<method-attribute>
<attribute-name>
actionListener
</attribute-name>
<method-signature>
void method(javax.faces.event.ActionEvent)
</method-signature>
</method-attribute>
</component-extension>
</component>
</af:xmlContent>

Webcenter Discussion Forum Programmatic APIs

        import oracle.webcenter.collab.announcement.AnnouncementFilter;
import oracle.webcenter.collab.announcement.AnnouncementService;
import oracle.webcenter.collab.announcement.AnnouncementSession;
import oracle.webcenter.collab.forum.Category;
import oracle.webcenter.collab.forum.CategoryService;
import oracle.webcenter.collab.forum.Forum;
import oracle.webcenter.collab.forum.ForumService;
import oracle.webcenter.collab.forum.ForumSession;
import oracle.webcenter.collab.forum.MyDiscussionsService;
import org.apache.myfaces.trinidad.util.Service;
import oracle.webcenter.collab.forum.Topic;
import oracle.apps.atk.helpPortal.model.HelpPortalDiscussionForumAM;
import oracle.webcenter.collab.share.LoginFailedException;

import oracle.webcenter.collab.share.Session;
import oracle.webcenter.collab.share.LoginFailedException;


public ForumSession session = null;
public CategoryService catService = null;
public ForumService forumService = null;


Category
catService = (CategoryService)session.getService(CategoryService.class);  
Category newCreatedCategory = catService.createCategory(null, new Long(parentCategoryId).toString(),categoryName, categoryName, categoryName);
categoryId = Long.parseLong(newCreatedCategory.getId());

catService = (CategoryService)session.getService(CategoryService.class);
long rootCategoryId = Long.parseLong(catService.getRootCategoryId());


Forum
List<Forum> forums = catService.getForums(new Long(categoryId).toString(), null,true);
forumService = (ForumService)session.getService(ForumService.class);
Forum newCreatedForum = forumService.createForum(null,new Long(RootCategoryId).toString(),TopicName, TopicName, TopicName);
forumId = Long.parseLong(newCreatedForum.getId());
Forum forum = forumService.getForum(new Long(forumId).toString());
long topicCount = forum.getTopicCount();



Announcement
AnnouncementSession annSession = this.isLoggedInUserJiveAdminUser() ? AnnouncementSession.getSession(AnnouncementSession.SYSTEM_USER) :
AnnouncementSession.getSession();
AnnouncementService annService = annSession.createAnnouncementService();

public boolean isLoggedInUserJiveAdminUser(){
boolean isAuthenticated = ADFContext.getCurrent().getSecurityContext().isAuthenticated();
if(!isAuthenticated)
return false;
try{
{
session = ForumSession.getSession(ForumSession.SYSTEM_USER);
String forumAdminUserName = session.getUser().getUsername();
String adfLoggedInUserName =
ADFContext.getCurrent().getSecurityContext().getUserName();
if (adfLoggedInUserName != null &&
adfLoggedInUserName.equalsIgnoreCase(forumAdminUserName))
return true;
}
}catch(Exception e){
e.printStackTrace();
}
return false;

af:poll interval manipulation

Introduction
af:poll is an ADF Faces Component that periodically polls the Middle Tier webserver and does a post back.

UseCase
Say, we have an ADF page with an af:poll that queries some data from the underlying DB table.We want the poll to happen in 5 seconds as soon as page loads and brings the data to the UI.After that we want the poll to happen after 3 minutes(Say).

Code
<af:poll id="p2"
interval="#{adfFacesContext.postback == false ? 5000 : 180000}"
immediate="true"
clientComponent="true"
</af:poll>

ViewObject getRow() v/s findByKey()

ViewObject getRows(key) returns the rows from the ViewStorage by default which looks through the cached rows, doesnt really query from DB.
As a performance standard, if you have set the MaxFetchSize value of the VO as something say "N"(Say 2000), then a row we query for which resides in a slot > N(say 2010),the getRow() wont fetch the data.That means,we cannt get the desired value.

However,we need a composite solution where we want to lookup the cache in Middle Tier and if its there, then the row should be returned from the Mid-Tier cache, if not in cache, it should return from the DB using an efficient Query with findByKey()

Code
public String getCurrentEmpName(String currentEmpId) {
String empName = "";
if (currentEmpId != null && currentEmpId.length() > 0) {
ViewObjectImpl empVO =
this.getEmpVO();
if (empVO != null) {
Key key = new Key(new Object[] { currentEmpId });
//Searching for the row with key
//getRow(key) will search in the cache which contain atmost
//2000 records Becoz the MaxFetchSize of EmpVO is 2000
EmpVORow empRow =
(EmpVORow)EmpVO.getRow(key);
//if the record with key is not present in the cache
if (empRow == null) {
//Searching for the row with key in the DataBase
//findByKey() searches in DB
Row[] empRows = empVO.findByKey(key, 1);
if (empRows != null && empRows.length != 0) {
empRow = (EmpVORow)empRows[0];
}
}
if (empRow != null) {
empName = empRow.getName();
}
}
}
return empName;
}

SharedAM Unfold Again

Shared Application Modules are mostly used to cache static data.
If a SharedAM has a ViewObject instance in it, we really cannt apply Dynamic ViewCriteria nor setWhereClause().This causes Multi User threading issues from SharedAM and unexpected errors prop up.

UseCase
Query from SharedAM VO based on Dynamic VOAttrName and Value.

Solution
         /**
* @author AMulya Mishra
* This method iterates the SharedAM Vo rowset and matches the VOAttrname and Value.
* Then returns a collection of the matched rows.
* Note, since these Vos are from SharedAM, hence they are already executed in the
* PrepareSesion of the SharedAMImpl.
* So, in this method, there is no DB queries fired for these VOs.
*
* @param vo
* @param sharedAMName
* @param keyVals
* @return
*/
public static List<Row> getRowsFromSharedAMVOs(ViewObject vo, String amName,
String[][] keyVals) {
//Initialiaze the Row List
List<Row> returnedRows = new ArrayList<Row>();
{
//Get the Original RnageSize of the VO so that we can reset back
int rsize = vo.getRangeSize();
//to ensure we get a complete esimated row count
vo.setRangeSize(-1);
//gets all the VO rows.
Row[] rowsArray = vo.getAllRowsInRange();
//Loop through the row set
for(Row row : rowsArray){
//Initialize the rowmatch boolean variable
boolean matchedRowFound = true;
if (keyVals != null && keyVals.length > 0) {
//Iterates through the key value pairs.
for (String[] keyValArray : keyVals) {
//get the voAttrName
String voAttrName = keyValArray[0];
//get the voAttrValue
String voAttrVal = keyValArray[1];

{
//If value matches then make the variable true
if(voAttrVal != null && voAttrVal.equals((String)row.getAttribute(voAttrName))){
matchedRowFound = matchedRowFound && true;
}
else{
matchedRowFound = false;
}
}
}
}
//If a row match found, then add the row to the list
if(matchedRowFound == true){
returnedRows.add(row);
}
}
//Reset the VO
vo.reset();
//Reset the RangeSize of the VO
vo.setRangeSize(rsize);
}
//return the Found Rows
return returnedRows;

}

Tuesday, January 04, 2011

Duplicating a Row in the VO

UseCase
We have an EmpVO.We want to create a duplicate Row in the EmpVO given an existing EmpRow.The new Duplicated row would have all Data Same except the EmpName,PK and the WHO columns

          public void doDuplicateEmpVORow(EmpVOImpl empVO, EmpVORowImpl origEmpRow, String newEmpName) {
EmpVORowImpl newEmpRow = null;
AttributeListImpl attrList = new AttributeListImpl();
//gets the AttributeNames
String[] attrNames = origEmpRow.getAttributeNames();
attrList.setAttribute("EmpName", newEmpName);
for (String attrName : attrNames) {
//Gets the AttributeDef
AttributeDef attrDef =
origEmpRow.findAttributeDef(attrName);
//Gets the sqlType of the Attribute
int sqlType = attrDef.getSQLType();
//Checks if the Attribute is a PK or not.
boolean isPK = attrDef.isPrimaryKey();
//Set Attribute value if the attribute is not PK nor EmpName nor RowSetIterator nor ViewAccessor
if (!isPK && !"EmpName".equals(attrName)&& sqlType > 0 &&
!isHistoryAttribute(attrName) &&
isPersistantAttribute(attrDef)) {
//Sets the attribute value.
attrList.setAttribute(attrName,
origEmpRow.getAttribute(attrName));
}
} //End of duplicate EMP OBject
//Creates a new Emp Row
newEmpRow =
(EmpVORowImpl)empVO.createAndInitRow(attrList);
}

/**
* This method checks if an attribute is a history attribute or not.
*
* @param attributeName
* @return
*/
private boolean isHistoryAttribute(String attributeName) {
//for HistoryAttribute and ObjectVersionNumber, return TRue.
return ("CreatedBy".equals(attributeName) ||
"CreationDate".equals(attributeName) ||
"LastUpdateDate".equals(attributeName) ||
"LastUpdatedBy".equals(attributeName) ||
"LastUpdateLogin".equals(attributeName) ||
"ObjectVersionNumber".equals(attributeName)) ?

true : false;
}

/**
* This method checks if an attribute is a Persistant attribute or not.
*
* @param attributeDef
* @return
*/
private boolean isPersistantAttribute(AttributeDef attributeDef) {
return (attributeDef.getAttributeKind() ==
AttributeDef.ATTR_PERSISTENT);
}

Monday, January 03, 2011

ViewObject Attribute Information

    public void printVOAttributeDetails(){
ViewObjectImpl vo = getPopupItemsVO1();
ViewAttributeDefImpl[] attrDefs = vo.getViewAttributeDefImpls();
for(ViewAttributeDefImpl attrDef : attrDefs){
String name = attrDef.getName();
String dbColumnName = attrDef.getColumnName();
String aliasName = attrDef.getAliasName();
}

}

Replace all existing rows in an EO Based VO

UseCase
We have an EO based VO and want to always delete the rows from DB, EO Cache and ViewStorage.Then repopulate the same rows back to the VO again.

Here is the exact code

Solution#1

    public void doReplaceExistingRowsInEOBasedVO1(){
ViewObjectImpl vo = getPopupItemsVO1();
int origRSize = vo.getRangeSize();
vo.setRangeSize(-1);
Row[] allRows = vo.getAllRowsInRange();
vo.getQueryCollection().clear();
System.out.println("Size="+vo.getQueryCollection().size());
List<AttributeListImpl> attrListColl = new ArrayList<AttributeListImpl>();
for(Row row : allRows){
vo.getQueryCollection().add(row);
}
System.out.println("Size="+vo.getQueryCollection().size());
System.out.println(vo.getQueryCollection());
vo.setRangeSize(origRSize);

}


Solution # 2

    public void doReplaceExistingRowsInEOBasedVO(){
ViewObjectImpl vo = getPopupItemsVO1();
int origRSize = vo.getRangeSize();
vo.setRangeSize(-1);
Row[] allRows = vo.getAllRowsInRange();

List<AttributeListImpl> attrListColl = new ArrayList<AttributeListImpl>();
for(Row row : allRows){
AttributeListImpl attrList = new AttributeListImpl();
String[] attrNames = row.getAttributeNames();
for(String attrName : attrNames){
Object val = row.getAttribute(attrName);
System.out.println(attrName+"--->"+val);
attrList.setAttribute(attrName, val);
}
attrListColl.add(attrList);
row.remove();
}

for(AttributeListImpl attrList : attrListColl){
Row newRow = vo.createAndInitRow(attrList);
vo.insertRow(newRow);
}

allRows = vo.getAllRowsInRange();
System.out.println(vo.getQueryCollection());
vo.setRangeSize(origRSize);

}