Wednesday, April 28, 2010

ADF:usage of RowQualifier

A useful note , for those who are not aware of this cool feature of ADFbc..
Like we apply ViewCriteria on the ViewObject, we can apply similar SQL structured WHERE clause predicate on the ViewObject ResultCache in middle tier..(not in the DB)...using RowQualifier(oracle.job.server.RowQualifier)

            //Create a new RowQualifier object with the filtering condition.
RowQualifier qualf = new RowQualifier("ApplicationId = "+applicationId+" AND ContextName ='"+contextName+"'");

//Filtered the rowset based on Attribute applicationId and the value user passes.
Row[] rows = getContextVO().getFilteredRows(qualf);


The above Rowqualifier constructs a middle tier WHERE clause predicate and apply on the ViewObject resultset.

The major advantage of RowQualifier on VC is, like VC we dont need a design time artifact on VO, nor do we need to write complicated code for programmatic implementation..This is quick and instantaneous..

ADF:getBindingContainer in JDev 11g

No need of evaluating :#{bindings} EL expression..
Simply use the direct API call

  /* Get the current binding container */
BindingContainer bc = BindingContext.getCurrent().getCurrentBindingsEntry();
/* Lookup and invoke the action binding named "yourMethodName" */
Object retVal = bc.getOperationBinding("yourMethodName").execute();

PLSQL:handy script to truncate tables of your choice

declare
cursor cur_tables IS
select table_name from user_tables where table_name like 'EMP%';
begin
for c_rec in cur_tables LOOP
execute immediate 'truncate table '||c_rec.table_name;
end loop;
end;

Me and Mama

ADF af:carousel implementation

af:carousel implementation is really easy.Dont get afraid.

You have a ViewObject say DepartmnentsVO exposed in a DataControl(i.e AM).
From DataControl pallete, drag and drop the VO as af:carousel onto your page.
It creates a Tree binding in the pagedef automnatically and an af:carousel UI component.
Interesting thing in the Jspx/Jsff page for af:carousel is the var property usage.
See the sample code below.

Jspx code

              <af:carousel currentItemKey="#{bindings.DepartmentsView1.treeModel.rootCurrencyRowKey}"
value="#{bindings.DepartmentsView1.treeModel}"
var="item" id="c1"
carouselSpinListener="#{SpinHelper.onSpin}">
<f:facet name="nodeStamp">
<af:carouselItem id="ci1">
<af:panelFormLayout id="pfl1">
<f:facet name="footer"/>
<af:panelLabelAndMessage label="#{item.bindings.DepartmentId.hints.label}" id="plam1">
<af:outputText value="#{item.bindings.DepartmentId.inputValue}" id="ot1"/>
</af:panelLabelAndMessage>
<af:panelLabelAndMessage label="#{item.bindings.DepartmentId.hints.label}"
id="panelLabelAndMessage1">
<af:outputText value="#{item.bindings.DepartmentName.inputValue}"
id="outputText1"/>
</af:panelLabelAndMessage>
<af:panelLabelAndMessage label="#{item.bindings.ManagerId.hints.label}"
id="panelLabelAndMessage3">
<af:outputText value="#{item.bindings.ManagerId.inputValue}"
id="outputText3"/>
</af:panelLabelAndMessage>
<af:panelLabelAndMessage label="#{item.bindings.LocationId.hints.label}"
id="panelLabelAndMessage2">
<af:outputText value="#{item.bindings.LocationId.inputValue}"
id="outputText2"/>
</af:panelLabelAndMessage>
</af:panelFormLayout>
</af:carouselItem>
</f:facet>
</af:carousel>


PageDef code
    <tree IterBinding="DepartmentsView1Iterator" id="DepartmentsView1">
<nodeDefinition DefName="adf.sample.model.DepartmentsView"
Name="DepartmentsView10">
<AttrNames>
<Item Value="DepartmentId"/>
<Item Value="DepartmentName"/>
<Item Value="ManagerId"/>
<Item Value="LocationId"/>
</AttrNames>
</nodeDefinition>
</tree>

ADF security-programming artifacts

All should be self explanatory.

#{securityContext.authenticated}
#{securityContext.userName}
#{securityContext.taskflowViewable['/WEB-INF/TaskFlowColor.xml#TaskFlowColor']}
#{securityContext.regionViewable['mypackage.page1']}
#{securityContext.userInRole['role1,role2,roleN']}
#{securityContext.userInAllRoles['role1,role2,roleN']}

Adding templates to your DefaultDomain JDev Integrated WLS Server

shutdown integrated WLS from JDev.
Close Jdev
run $mw_home/jdeveloper/oracle_common/common/bin/wlst.sh

Then execute the following codes in the wlst>

readDomain('....full path to jdev default domain...')
addTemplate('$MW_HOME/jdeveloper/common/templates/applications/TheTemplateYouWant.jar')
updateDomain()
exit()

* Start JDev.
* Start JDev integarted Default server.
* Go to localhost:7101/console
* Deployments

SortCriteria in pageDef iterators-Override ViewObject OrderBy

We have Order By clause for ADFbc view object so that the Data renders in specific order.
Likewise, we can override the default ViewObject OrderBy in PageDef iterator using sortCriteria to render a different orders set of data in the Jspx/Jsff page.

<iterator Binds="Emp" DataControl=MyAMDataControl"
id="EmpVOIter" RangeSize="25">
<sortCriteria>
<sort attribute="Ename" ascending="true"/>
</sortCriteria>
</iterator>


Caution
It tries to sort the iterator every time it executes.Hence a little bit additional work.

ADF/JSF way of finding all UIComponents in a DOM Recusrively

CAUTION:This is expensive and must be done only when the UIComponents are static, i.e rendered property is not EL expressed.

public static HashMap<String, UIComponent> viewCompMap =  new HashMap<String, UIComponent>();


public static HashMap<String, UIComponent> populateViewComponentsMap(HashMap<String, UIComponent> compMap) {
FacesContext fc = FacesContext.getCurrentInstance();
//Gets the ui view root component.
UIComponent uiComp = (UIComponent)fc.getViewRoot();
//Puts the ui view root component into static map.
compMap.put(uiComp.getId(), uiComp);
//Calls the recursive method which walks down the view tree and populates them in the static map.
populateChildrenInMap(uiComp, compMap);
return compMap;
}

public static void populateChildrenInMap(UIComponent uiComp,
HashMap<String, UIComponent> compMap) {
//Checks if the compMap is not null.
if (uiComp != null) {
//Gets all the children of the ui component as an iterator.
Iterator<UIComponent> uiCompChildren =
uiComp.getFacetsAndChildren();
if (uiCompChildren != null) {
//Iterates through the children.
while (uiCompChildren.hasNext()) {
UIComponent child = uiCompChildren.next();
if (child != null) {
//puts the child component in the map.
compMap.put(child.getId(), child);
}
//Calls the recursive method for each of the child component.
populateChildrenInMap(child, compMap);

}
}

}
}

ADFway of rendering a BLOB from a Servlet

Say, you have a BLOB in one of your DB table column.
You want to stream the BLOB onto your ADF page.How to do it?

The ViewOBject contains 4 columns.
PrimaryKey,FileName,MimeType and Blob

Here is the servlet code involving ADFbc.

public ApplicationModule getHPApplicationModuleFromPool(){
try{
//Get the ApplicationModule Client Interface and get the MyVO
String amDef = "mypackage.applicationModule.MyAM";
String amConfig = "MyAMLocal";
ApplicationModule am =
Configuration.createRootApplicationModule(amDef, amConfig);

return am;

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

return null;

}


public void blobProcessing(String primaryKey) {
ApplicationModule am = null;
try{
{
//Get the Row for the Passed TopicId
Key key = new Key(new Object[]{primaryKey});
am = getHPApplicationModuleFromPool();
ViewObject vo = am.findViewObject("MyVo");

Row row = vo.getRow(key);
if(topicRow != null){
String fileName = (String)row.getAttribute("FileName");
mimeType = (String)row.getAttribute("MimeType");
//Sets the MimeType
response.setContentType(mimeType != null ? mimeType : "application/octet-stream");
//Sets the content disposition style
response.addHeader("Content-Disposition", "inline; filename="+ fileName);
//Read the row.getBlob() and redirect to an outPutStream
BlobDomain blobContent = (BlobDomain)row.getAttribute("Blob");
//gets the ByteArray from BlobDomain
byte[] bytearray = topicContent.toByteArray();
//gets the Binary InputStream from BlobDomain
InputStream reader = blobContent.getBinaryStream();;
int size = 0;
//Read the InputStream and write to Servlet's output Stream.
while ((size = reader.read(bytearray)) != -1)
response.getOutputStream().write(bytearray,0,size);
//Close the reader stream
reader.close();
}
Configuration.releaseRootApplicationModule(am, false);
}//End Blob processing

}catch(Exception e){
try{
if(am != null)
Configuration.releaseRootApplicationModule(am, false);
e.printStackTrace();
}catch(Exception e1){
e1.printStackTrace();
}
}
}


JSF/ADF way of getting Browser Name and Version

Here is how you can identify the browser version and Name in your JSF or ADF application.

#{requestContext.agent.agentName}
#{adfFacesContext.agent.agentVersion}

Common Utility Methods for ADF Faces

There are common utility and very frequently used Helper methods to work with ADFm.

ADFUtil.java

import java.util.HashMap;
import java.util.Locale;

import java.util.Map;

import java.util.ResourceBundle;

import javax.el.ELContext;

import javax.el.ExpressionFactory;

import javax.el.MethodExpression;
import javax.el.ValueExpression;

import javax.faces.context.FacesContext;

import oracle.adf.model.BindingContext;
import oracle.adf.model.DataControlFrame;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCIteratorBinding;

import oracle.javatools.resourcebundle.BundleFactory;
import oracle.javatools.resourcebundle.NamedMessageFormat;


/**
* Provides various utility methods that are handy to
* have around when working with ADF.
*/
public class ADFUtil {

/**
* When a bounded task flow manages a transaction (marked as requires-transaction,.
* requires-new-transaction, or requires-existing-transaction), then the
* task flow must issue any commits or rollbacks that are needed. This is
* essentially to keep the state of the transaction that the task flow understands
* in synch with the state of the transaction in the ADFbc layer.
*
* Use this method to issue a commit in the middle of a task flow while staying
* in the task flow.
*/
public static void saveAndContinue() {
Map sessionMap =
FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
BindingContext context =
(BindingContext)sessionMap.get(BindingContext.CONTEXT_ID);
String currentFrameName = context.getCurrentDataControlFrame();
DataControlFrame dcFrame =
context.findDataControlFrame(currentFrameName);

dcFrame.commit();
dcFrame.beginTransaction(null);
}

/**
* Programmatic evaluation of EL.
*
* @param el EL to evaluate
* @return Result of the evaluation
*/
public static Object evaluateEL(String el) {

FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
ExpressionFactory expressionFactory =
facesContext.getApplication().getExpressionFactory();
ValueExpression exp =
expressionFactory.createValueExpression(elContext, el,
Object.class);

return exp.getValue(elContext);
}

/**
* Programmatic invocation of a method that an EL evaluates to.
* The method must not take any parameters.
*
* @param el EL of the method to invoke
* @return Object that the method returns
*/
public static Object invokeEL(String el) {

return invokeEL(el, new Class[0], new Object[0]);
}

/**
* Programmatic invocation of a method that an EL evaluates to.
*
* @param el EL of the method to invoke
* @param paramTypes Array of Class defining the types of the parameters
* @param params Array of Object defining the values of the parametrs
* @return Object that the method returns
*/
public static Object invokeEL(String el, Class[] paramTypes,
Object[] params) {

FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
ExpressionFactory expressionFactory =
facesContext.getApplication().getExpressionFactory();
MethodExpression exp =
expressionFactory.createMethodExpression(elContext, el,
Object.class, paramTypes);

return exp.invoke(elContext, params);
}

/**
* Sets a value into an EL object. Provides similar functionality to
* the &lt;af:setActionListener&gt; tag, except the <code>from</code> is
* not an EL. You can get similar behavior by using the following...<br>
* <code>setEL(<b>to</b>, evaluateEL(<b>from</b>))</code>
*
* @param el EL object to assign a value
* @param val Value to assign
*/
public static void setEL(String el, Object val) {

FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext elContext = facesContext.getELContext();
ExpressionFactory expressionFactory =
facesContext.getApplication().getExpressionFactory();
ValueExpression exp =
expressionFactory.createValueExpression(elContext, el,
Object.class);

exp.setValue(elContext, val);
}

/**
* Get the BindingCOntainer reference.
* Then based on the IteratorName, return the DCIteratorBinding.
*
* @param String iteratorName
* @return DCIteratorBinding
*/
public static DCIteratorBinding getDCIteratorBinding(String iteratorName) {

FacesContext fctx = FacesContext.getCurrentInstance();
ExpressionFactory exp = fctx.getApplication().getExpressionFactory();

DCBindingContainer bc;
bc =
(DCBindingContainer)exp.createValueExpression(fctx.getELContext(), "#{bindings}",
DCBindingContainer.class).getValue(fctx.getELContext());

DCIteratorBinding iter = bc.findIteratorBinding(iteratorName);
return iter;
}


}

Debgging Javascript issues in ADF app

To help make debugging easier add the below context params to your ADF web application's web.xml

<context-param>
<param-name>org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>oracle.adf.view.rich.LOGGER_LEVEL</param-name>
<param-value>WARNING</param-value>
</context-param>


Then restart the server.

ADF:Programatically adding Bookmark in FF3

FireFox has a limitation of creating Bookmarks using Javascript.Till FF2.X version, it used to open in Browser Side Bar.

Here is a piece of code in ADF you can use.

JSFF/JSPX code
<af:commandbutton text="BookMark Me" id="cb1" actionlistener="#{DemoBean.invokeBookMark}" partialsubmit="true">
</af:commandbutton>


Managed Bean code
 private String FIREFOX_BOOKMARK_SCRIPT = " alert('in FF');     netscape.security.PrivilegeManager.enablePrivilege(\"UniversalXPConnect\"); \n" +
" var bmsvc = Components.classes[\"@mozilla.org/browser/nav-bookmarks-service;1\"].getService(Components.interfaces.nsINavBookmarksService); \n" +
" var ios = Components.classes[\"@mozilla.org/network/io-service;1\"].getService(Components.interfaces.nsIIOService); \n" +
" var uri = ios.newURI(url, null, null); \n" +
" var hpBookMarkId = bmsvc.insertBookmark(bmsvc.bookmarksMenuFolder, uri, bmsvc.DEFAULT_INDEX, title); \n" +
" alert('hpBookMarkId='+hpBookMarkId);";


public void invokeBookMark(ActionEvent actionEvent) {
// Add event code here...

String title = "XXXX";
String url = "http://127.0.0.1:7104/contextRoot/faces/MyPage";
String script = "var title='" + title + "'; " + "var url='" + url + "'; " + BOOKMARK_JAVASCRIPT;

ExtendedRenderKitService service =
Service.getRenderKitService(FacesContext.getCurrentInstance(),
ExtendedRenderKitService.class);

service.addScript(FacesContext.getCurrentInstance(), script);

}



Note:

However, for browser scripting security in FF 3,0, user have to do the following.I have updated the same in the bug.
This is a normal web world practice, nothing specific to JSF or ADF.

1)-In Firefox browser,in address location type "about:config" and reload the tab.
2)-It will prompt for a message.Say Yes.
3)-Out of the list of properties, search for "signed.applets.codebase_principal_support".
4)-Double click on the value "false" and it becomes true.

Close the browser and try clicking Bookmark Icon for the HelpPortal Topic.
Make sure you check the checkbox "Remember this decision", when FireFox will display this message.

Thursday, April 22, 2010

Java:Wrap a HTML word with some HTML tags

Input : A Given HTML String
Output : A formatted HTML string with a word wrapped up with some HTML tags.

String startTag = "";
String endTag = "
";
String title = "Hi My Name is AMulya Mishra";
String keyWord = "AMulya";

title = title.replaceAll("(?i)\\b\\p{Alpha}*" + keyWord + "\\p{Alpha}*\\b",startTag + "$0" + endTag);


output = "Hi My Name is AMulya Mishra"

Refreshing SharedAM viewobjects periodically

SharedAM viewobjects get instantiated once per JVM life cycle.In the mean time , if we have a requirement to have the ViewObjects of the SharedAM reflect the latest changes of Data from underlying Database Tables, we have a programmatic way to do so.

public long lastRefreshedTime;

private void setLastRefreshedTime(long lastRefreshedTime) {
this.lastRefreshedTime = lastRefreshedTime;
}

private long getLastRefreshedTime() {
return lastRefreshedTime;
}


private void refreshSharedAMVOs() {
String[] voNames = this.getViewObjectNames();
for (String voName : voNames) {
ViewObjectImpl vo = (ViewObjectImpl)this.findViewObject(voName);
processDatabaseChangeNotification(vo);
}
}


public void refreshSharedAM() {

long currentTime = System.currentTimeMillis();
long lastRefreshedTime = getLastRefreshedTime();

//hardcoded to 1 day
if ((currentTime - lastRefreshedTime) > 12 * 60 * 60 * 1000) {
synchronized (this) {
refreshSharedAMVOs();
}
setLastRefreshedTime(currentTime);
}
}

private void processDatabaseChangeNotification(ViewObjectImpl vo) {
try {
Row currentRow = vo.getCurrentRow();

if (currentRow == null) {
int rangeStartBeforeQuery = vo.getRangeStart();
vo.executeQuery();
vo.setRangeStart(rangeStartBeforeQuery);
} else {
Key currentRowKey = currentRow.getKey();
int rangePosOfCurrentRow = vo.getRangeIndexOf(currentRow);
int rangeStartBeforeQuery = vo.getRangeStart();
vo.executeQuery();
vo.setRangeStart(rangeStartBeforeQuery);
vo.findAndSetCurrentRowByKey(currentRowKey,
rangePosOfCurrentRow);
}

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


ADF 11g JavaScript Doc

ADF exposes a whole lot of JavaScript APIs.
http://download.oracle.com/docs/cd/E12839_01/apirefs.1111/e12046/overview-summary.html

Back to Blogging

After quite sometime(May be after 2 years) , am back to my blogging.