Wednesday, October 19, 2011

Some important links @ADF


1) Reusable Components:
http://download.oracle.com/docs/cd/E12839_01/web.1111/b31974/reusing_components.htm
http://xmlandmore.blogspot.com/2011/06/reusable-adf-componentsapplication.html
http://andrejusb.blogspot.com/2007/03/reusability-in-oracle-adf-business.html

2) Best Practices:
http://andrejusb.blogspot.com/2009/10/oow09-video-oracle-adf-oracle-fusion.html
http://www.oracle.com/technetwork/developer-tools/adf/learnmore/bestpractice-092568.html

3) Transaction and Data Control Scope options:
http://one-size-doesnt-fit-all.blogspot.com/2011/05/jdev-11g-task-flows-adf-bc-always-use.html
http://one-size-doesnt-fit-all.blogspot.com/2011/05/jdev-11g-task-flows-adf-bc-one-root.html
https://forums.oracle.com/forums/thread.jspa?messageID=9534487

4) Nested App Module To improve Performance:
http://andrejusb.blogspot.com/2010/06/adf-regions-and-nested-application.html
http://andrejusb.blogspot.com/2010/10/how-to-reduce-database-connections-and.html

5) RESTful Web Services:
http://marianne-horsch-adf.blogspot.com/2011/03/how-to-create-restful-web-service-that.html

6) Application Architectures:
http://www.sagecomputing.com.au/papers_presentations/ADF%20Architectural%20Patterns%20-%20LongBeach%20ODTUG%20minus%20pics.pptx

7) Session Timeout Warning:
http://blogs.oracle.com/jdevotnharvest/entry/how-to_enable_user_session_time_out_warning_jdev_11114
https://forums.oracle.com/forums/thread.jspa?threadID=547724
http://one-size-doesnt-fit-all.blogspot.com/2008/08/jdevadf-how-to-log-user.html

Saturday, October 1, 2011

UCM Accounts tab not visible in User Admin applet

To enable accounts , go to Admin Server using the Admin server link in Administration, then click on General Configuration and check Enable Accounts.

Sunday, September 18, 2011

Exceptions While Using Tagging Service @Webcenter

1) Caused by: java.sql.SQLSyntaxErrorException: ORA-00904: "T1"."ENTERPRISE_ID": invalid identifier
The reason is clear. The webcenter schema don't have Enterprise_Id column in WC_TAGGING_BOOKMARK table.

Solution: Searched over net but did not find any result. Finally added this column in the tables and the problem resolved.  Not sure whats the role of this column and why its was not present by default.

Tuesday, September 13, 2011

Exceptions While Using RIDC API @ Webcenter


1) Unable to locate authentication handler for Content Server response: HTTP/1.1 502 Bad Gateway
Source breakpoint occurred at line 54 of MyManagedBean.java.
oracle.stellent.ridc.protocol.ProtocolException: java.io.IOException: Input terminated before being able to read line.
at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:142)
at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:107)
at MyManagedBean.RIDC_CreateFolder(MyManagedBean.java:54)

The code i was using to initialize the connection was:

IdcClientManager manager = new IdcClientManager();
IdcClient idcClient = manager.createClient("http://localhost:4444/idc/idcplg");

The problem resolved by changing the code to:


IdcClientManager manager = new IdcClientManager();
IdcClient idcClient = manager.createClient("idc://localhost:4444");

2) oracle.stellent.ridc.protocol.ServiceException: No service defined for null.
at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:135)
at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:107)
at MyManagedBean.RIDC_CreateFolder(MyManagedBean.java:54)

Reason: Ohhh....Very silly mistake. Following is the code with error:

dataBinder.putLocal("idcService", "COLLECTION_ADD");

Correct Code:

dataBinder.putLocal("IdcService", "COLLECTION_ADD");


3) oracle.stellent.ridc.protocol.ServiceException: Unable to display virtual folder information. Unable to open folder.
at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:135)
at oracle.stellent.ridc.protocol.ServiceResponse.getResponseAsBinder(ServiceResponse.java:107)
at MyManagedBean.getFolderIDFromPath(MyManagedBean.java:165)

Reason: I was specifying only the folder name instead of complete path :)... Ex: RIDCFolder instead of /Contribution Folder/RIDCFolder.... in binder.putLocal ("dCollectionPath", path);


4) This time i was not getting any exception. But there was something wrong. I was trying to upload document, the code was working fine but the document was not uploading. The point to be noted is that there was error in code but i was not getting any exception. Actually, i was not using following code to get the document id of the document i was uploading:

DataBinder serverBinder = res.getResposeAsBinder();
S.O.P(serverBinder.getLocal("dDID"));

I re ran my code with above lines and i got my exception at res.getResposeAsBinder(); So it is important to use above line to ensure that the operation was successful and to save some time.

5) java.lang.RuntimeException: oracle.security.jps.service.idstore.IdentityStoreException: JPS-01520: Cannot initialize identity store.
This exception is is not related to RIDC but i got it suddenly while working. This cause my navigation model to stop working properly. In the logs of UCM managed server i found below exception:


javax.naming.CommunicationException [Root exception is java.net.ConnectException: t3://[2001:0:4137:9e76:2c71:1810:854e:e6a5]:9001: Destination unreachable; nested exception is: 
java.net.ConnectException: Connection refused: connect; No available router to destination]


Not sure, resolved it self in next run.

6) File size is to large and can't be uploaded: When using RIDC the default size of document that can be uploaded is 2 MB. In order to increase this limit, we need to make an entry in web.xml file. Under the Application option in Overview tab, expand Context Initialization Parameter and add following parameter:

Name : org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE
Value: The maximum file size in bytes

7) Invalid JCR Name or Path: I am still working on this exception.

Saturday, September 10, 2011

Cannot find FacesContext @ Webcenter

I received java.lang.RuntimeException: Cannot find FacesContext exception when i ran my own login page in webcenter portal application. For configuring refer  Practical Guide for Oracle WebCenter PS3 Security Implementation

The error was because of wrong URL of my login page inside web.xml file. The application is configured with 
form authentication by default. I selected my login page using browse option. The entry in web.xml was 

<form-login-page>/oracle/webcenter/portalapp/pages/MyLoginPage.jspx</form-login-page>

but it worked after changing the URL to 

<form-login-page>/faces/oracle/webcenter/portalapp/pages/MyLoginPage.jspx</form-login-page>

Monday, September 5, 2011

Implementing Login form in ADF

If we need to provide our own JSF login page then we can use following JSF code and corresponding managed bean code :

JSF Code:


<af:panelFormLayout id="pfl1">
                    <af:message for="loginname" partialTriggers="cb1" />
                    <af:inputText label="Login Name" id="loginname" />
                    <af:inputText label="Password" id="password" />
</af:panelFormLayout>

<af:panelGroupLayout id="pgl2">
                    <af:commandButton text="Submit" id="cb1" actionListener="#{MyApp_ManagedBean.Login}"/>
                    <af:commandImageLink text="SignUp" id="cil1"/>
</af:panelGroupLayout>



Managed Bean Code:


  public void Login(ActionEvent actionEvent) {
    FacesContext fctx=FacesContext.getCurrentInstance();
    HttpServletRequest request = (HttpServletRequest)fctx.getExternalContext().getRequest();
    HttpServletResponse response = (HttpServletResponse)fctx.getExternalContext().getResponse();
    UIViewRoot viewRoot=fctx.getViewRoot();
    RichInputText userName = (RichInputText)viewRoot.findComponent("pt1:loginname"); 
    //pt1 indicated the page template naming container.
    String userNameStr = (String)userName.getValue();
    RichInputText password = (RichInputText)viewRoot.findComponent("pt1:password");
    String passwordStr = (String)password.getValue();
    try
    {
      int authSuccess=ServletAuthentication.login(userNameStr,passwordStr,request,response);  
      if(authSuccess==ServletAuthentication.AUTHENTICATED)
      {
        try{
          ExternalContext ectx=fctx.getExternalContext();
         //Using Controller Context  is recommended to implement redirect logic instead of directly calling  //External Context redirect method and passingredirect URL in it "faces/RedirectPage".
          ControllerContext controllerCtx = null;
          controllerCtx = ControllerContext.getInstance();
          String activityURL = controllerCtx.getGlobalViewActivityURL("WelcomePage");
          ectx.redirect(activityURL);


        }catch(IOException ioex){ioex.printStackTrace();}
      }
    }
    catch(LoginException loginex)
    {
      String message="Authentication Failed. Please try again";
      fctx.addMessage("pt1:loginname", new FacesMessage(FacesMessage.SEVERITY_ERROR,message,null));
    }
  }
}


Recommended Reading: Oracle Fusion Developer Guide Building Rich Internet Applications with Oracle ADF Business Components and Oracle ADF Faces

Tuesday, August 23, 2011

Display SWF file in Webcenter Space

There may be a requirement to display SWF inside Oracle Webcenter Space. The SWF file can be added to space as content presenter in following way.

All we need to do is to embed our SWF file inside HTML file. Following is the code that can be used:

<html>
<body>
<object width="500" height="500">
    <param name="movie" value="http://localhost:16200/cs/groups/public/documents/document/newswf.swf">
    <embed src="http://localhost:16200/cs/groups/public/documents/document/newswf.swf" width="400" height="400">
    </embed>
</object>
</body>
</html>

The SWF file in above code is coming from UCM. Once done, the HTML file can be easily added to Webcenter Space as content presenter. The same concept can also be used for some video files.

Sunday, August 21, 2011

Store TaskFlow Input Param in Memory Scope or Managed Bean?

If we need to specify some input parameters for our Bounded task flow then, we can specify value (Note: the value field in Input parameter definition indicates the location where the input parameter will be stored. It does not indicate the value of  the parameter we are defining.) either using managed bean or in memory scope. The recommended way is to use managed bean or a simple pojo class configured as manged bean in a memory scope. The reason of using managed bean is that we can use comments in our class file to indicate the purpose for other developers and also make it clear what exactly the input parameters are and where they are stored as they can now be access using managed bean.

Disable text filed in InputDate Component @ADF

If you need to disable the input text filed for adf:inputDate component then we can do that using any of the java scripts below.

1) This script will disable the key events on the text filed. Thus the user will not be able to edit the selected date using Keyboard.

<af:resource>
function disableEntry(evt){
evt.cancel();
}
</af:resource>

<af:inputDate label="Label 1" id="id1" readOnly="false"
contentStyle="background-color:lightgray;">
<af:clientListener method="disableEntry" type="keyDown"/>
</af:inputDate>


2) This script will completely disable the text filed. The only problem with this script is that, if we have many input date components on a page, then we will need to apply this for all component by their IDs.

<af:document id="d1">
<f:facet name="metaContainer">
<f:verbatim>
<script type="text/javascript">
function disable(evt) {
document.getElementById('id1::content').disabled=true;
}

</script>
</f:verbatim>
</f:facet>
<af:clientListener method="disable()" type="load"/>
.....
<af:inputDate label="Date Picker" value="#{pageFlowScope.genPDF.dateEcheance}" binding="#{pageFlowScope.genPDF.id1}" id="id1"/>




Display UCM content in WebCenter based on Locale


Multilingual Page Name in WebCenter


Monday, July 4, 2011

Bounded Task Flow as ADF Library @ADF

To know how to deploy BTF as ADF library, please refer to this tutorial.

I created two different project, one producer that was deployed as ADF library and one consumer for deployed task flow, with all the default settings. Everything was smooth until running the consumer. While running i got following error:


oracle.jbo.JboException: JBO-34010: The "view/DataBindings.cpx" descriptor appears in the application classpath more than once:
 jar:file://.../JDeveloper/system11.1.1.4.37.59.23/DefaultDomain/servers/DefaultServer/tmp/_WL_user/ApplicationPack_V2.0/63ryyw/war/WEB-INF/lib/BTFADFLibrary.jar!/view/DataBindings.cpx


 file://.../JDeveloper/system11.1.1.4.37.59.23/o.j2ee/drs/ApplicationPack/ApplicationPackWebApp.war/WEB-INF/classes/view/DataBindings.cpx

The reason was same name of the packages in both the projects.  The Databinding.cpx file was under view package in both project.  Tried to change the package name from project properties -> project source path  -> Default Package option but still received the same error. I recreated the producer project with new package names and the error was resolved. Other way will be to use refactoring.


Monday, June 20, 2011

Admin Applets not working @Content Server

I installed content server 11.1.1.3 on windows7 32 bit. The admin applets were working fine just after installation. But later i re-installed oracle database, created new schemas with rcu 11.1.1.4, and updated java version to 1.6.0_21 from 1.6.0_18. Now the admin applets are not working. :-\


Now, whats the reason for this????


Here it is: It was as simple as it should have been. The browser (IE) was having java 1.6.0_26 ad-on. But it was not working. So i ran the application on mozilla and installed java 1.6.0_26 plugin and the applets started working. Surprise was, now the applets were working on IE as well :).


So problem was only because of java version used by the browser.

Saturday, June 18, 2011

Unable to retrieve information for document @Content Server

This is the first time i connected my content server with ADF and tried to retrieve a html page. But on running the  application i received following error:

Event generated by user 'anonymous' at host 'CIS'. Unable to retrieve information for 'MyPC16200000040'. Unable to find latest released revision for item 'MyPC16200000040':

An error has occurred. The stack trace below shows more information. !csUserEventMessage,anonymous,CIS!$!csUnableToGetRevInfo2,MyPC16200000040!csGetFileUnableToFindRevision,csGetFileRevMethodLabel_LatestReleased,MyPC16200000040 intradoc.common.ServiceException: !csUnableToGetRevInfo2,MyPC16200000040 at intradoc.server.ServiceRequestImplementor.buildServiceException(ServiceRequestImplementor.java:2071) at intradoc.server.Service.buildServiceException(Service.java:2207) at intradoc.server.Service.createServiceExceptionEx(Service.java:2201) at intradoc.server.Service.createServiceException(Service.java:2196) at intradoc.server.DocCommonHandler.determineID(DocCommonHandler.java:657) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
......
Caused by: intradoc.common.ServiceException: !csGetFileUnableToFindRevision,csGetFileRevMethodLabel_LatestReleased,MyPC16200000040 at intradoc.server.utils.FileRevisionSelectionUtils.computeDocumentRevisionInfo(FileRevisionSelectionUtils.java:487) at intradoc.server.DocCommonHandler.determineID(DocCommonHandler.java:652)
.......


Now whats the reason?????


Finally, i got the solution for this and that was a bit surprising. The content that i was accessing, was uploaded using WebDAV(Desktop integration). The file was not indexed properly and was not even opening from content server. I re-uploaded the file using new item option and got rid of this error.

Friday, June 3, 2011

JBO-25221: Method not supported Exception @ADF


This has been an exception day. I received two new exceptions, one mentioned in previous post and next is below:

oracle.jbo.InvalidOperException: JBO-25221: Method AppModuleDataControl.EmployeeView1.getRowStatus() not supported
at oracle.adf.model.binding.DCInvokeMethod.invokeMethod(DCInvokeMethod.java:491)
at oracle.adf.model.binding.DCDataControl.invokeMethod(DCDataControl.java:2134)
at oracle.adf.model.bc4j.DCJboDataControl.invokeMethod(DCJboDataControl.java:3020)
at oracle.adf.model.binding.DCInvokeMethod.callMethod(DCInvokeMethod.java:257)
at oracle.jbo.uicli.binding.JUCtrlActionBinding.doIt(JUCtrlActionBinding.java:1625)
at oracle.adf.model.binding.DCDataControl.invokeOperation(DCDataControl.java:2141)
at oracle.jbo.uicli.binding.JUCtrlActionBinding.invoke(JUCtrlActionBinding.java:730)
at oracle.adf.controller.v2.lifecycle.PageLifecycleImpl.executeEvent(PageLifecycleImpl.java:394)
at oracle.adfinternal.view.faces.model.binding.FacesCtrlActionBinding._execute(FacesCtrlActionBinding.java:252) at oracle.adfinternal.view.faces.model.binding.FacesCtrlActionBinding.execute(FacesCtrlActionBinding.java:210)
at BackingBeanClass.onCancel_CancelButtonApp3(BackingBeanClass.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.el.parser.AstValue.invoke(AstValue.java:157)

I was getting this error while calling a method defined in viewobjectimpl class from backing bean. When i tried  system.out.print in the viewobjectimpl method, i found that the method is not even called.

So the reason of this exception was that, the view controller project that i was using was not build at the time i created the application. I created a new ADF Viewcontroller Project later. So the problem was, this view controller project was not dependent on model project in the application. That why when the method in viewobjectimpl was never called. To resolve this, open the view controller project properties and add model.jpr Build Output under the Dependencies.

JBO-25004: Definition name of type Form Binding Definition is invalid @ADF

I got following error message when i ran my application first time:

oracle.jbo.InvalidDefNameException: JBO-25004: Definition name sessiondef.3App_CancelButton.CancelButttonPageDef of type Form Binding Definition is invalid.
at oracle.jbo.mom.DefinitionManager.validateSessionDefName(DefinitionManager.java:509)
at oracle.jbo.mom.DefinitionManager.findSessionDefObject(DefinitionManager.java:548)
at oracle.adf.model.binding.DCBindingContainerDef.findSessionDefObject(DCBindingContainerDef.java:328)
at oracle.adf.model.binding.DCBindingContainerDef.findDefObject(DCBindingContainerDef.java:290)
at oracle.adf.model.binding.DCBindingContainerReference.getDef(DCBindingContainerReference.java:107)
at oracle.adf.model.BindingContext.findBindingContainerDefByPath(BindingContext.java:1555)
at oracle.adf.model.BindingRequestHandler.isPageViewable(BindingRequestHandler.java:371)
at oracle.adf.model.BindingRequestHandler.beginRequest(BindingRequestHandler.java:247)
at oracle.adf.model.servlet.ADFBindingFilter.doFilter(ADFBindingFilter.java:189)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)

In my case, the reason of above error was wrong package name ie 3App_CancelButton. I created a page in a folder named 3App_CancelButton under web content and generated its page definition file. The file was generated it self under package named 3App_CancelButton, which is not a valid package name. To remove this, rename the package using Refactor->Rename to a valid name.

Wednesday, June 1, 2011

Insert row at the End of Table @ADF

In order to add a row at the end of the table and make the inserted row to be current row, we can write following code on the action of a button having partial submit property set to true:

public void insertRowAtLast()
{
   CollectionModel cmodel= (CollectionModel)table.getValue();
   JUCtrlHierBinding adfmodelbind= (JUCtrlHierBinding) cmodel.getWrappedData();
   DCIteratorbinding itr=adfmodelbind.getDCIterator();
   
   Row row_last=itr.getNavigatableRowIterator().last();
   Row row_new=itr.getNavigatableRowIterator().createRow();
   row_new.setNewRowState(Row.State_INITIALIZED);
  
   int lastrow_index=itr.getNavigatableRowIterator().getRangeIndexOf(row_last);
   itr.getNavigatbleRowIterator().insertRowAtRangeIndex(lastrow_index+1,row_new);
   itr.setCurrentRowWithKey(row_new.getKey().toStringFormat(true));


  AdfFacesContext.getCurrentInstance().addPartialTarget(table);
}


To make the newly inserted row to be visible after table refreshes, set the DisplayRow attribute of the table to selected.

Dynamic Navigation in Un-Bounded Task Flow

If the outcome in an unbounded task flow is to be decided based on some user input, then we can use below code to decide which control flow case to follow. In this example the navigation to another page is decided by the user action on the popup. If user press OK the control flow case is followed.

First configure the dialog listener of the dialog used in the popup to capture the DialogEvent in a managed bean.

 public void confirmAction(DialogEvent dialogEvent) 
 {  
  DialogEvent.Outcome result = dialogEvent.getOutcome(); 
  if (result == DialogEvent.Outcome.ok) 
  { 
    NavigationHandler navigationHandler = FacesContext.getCurrentInstance().getApplication().getNavigationHandler(); navigationHandler.handleNavigation( FacesContext.getCurrentInstance(), null, "Control_Flow_Case"); 
  } 
}

Here Control_Flow_Case can be based on some user input as well. However NavigationHandler can't be used in case of bounded task flow. In that case, we will need to set the viewId on the ViewPort that can be accessed through ControllerContext.

Monday, May 30, 2011

Working with JavaScript/Popups @Adf

1) To show popup on page load:  To show popup on page load simply assign clientlistener operation to document element. Chose type as 'load' and create a javascript method as follows:


     function ShowPopupOnPageLoad()
    {
      var popup= AdfPage.PAGE.findComponentByAbsoluteId('p1');
      popup.show();
    }


2) Call JavaScript from Java: We can use our backing bean to call java script as follows:


        StringBuilder script=new StringBuilder();
        script.append("var popup = AdfPage.PAGE.findComponentByAbsoluteId('p1');");
        script.append("if(popup != null) {");
        script.append("popup.show();");
        script.append("}");

        FacesContext fctx=FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks= Service.getRenderKitService(fctx, ExtendedRenderKitService.class);
        erks.addScript(fctx, script);

 
3) Show Popup When Application is Busy: To show a popup when application is busy and prevent input from user in that time we can use following java script functions. In this, a callback method is called when application start getting busy. preventUserInput shows a glass pane to prevent user from interacting with UI. It gets removed automatically when application busy state changes. Also change the content Delivery option of the popup to Immediate.


    function ListenEvent(evt)
    {
      var popup= AdfPage.PAGE.findComponentByAbsoluteId('p2');
      if(popup != null)
      { 
        AdfPage.PAGE.addBusyStateListener(popup,handleBusyState);
        evt.preventUserInput();
      }
    }
    function handleBusyState(evt)
    {
      var popup= AdfPage.PAGE.findComponentByAbsoluteId('p2');
      if(popup != null)
      { 
        if(evt.isBusy())
         popup.show();
      }
      else
      {
        popup.hide();
        AdfPage.PAGE.removeBusyStateListener(popup,handleBusyState);
      }
    }

Sunday, May 29, 2011

Call Java script from Java

Following is a sample code for calling javascript from java:


import org.apache.myfaces.trinidad.render.ExtendedRenderKitService; import org.apache.myfaces.trinidad.util.Service; …

private void writeJavaScriptToClient(String script)
{
  FacesContext fctx = FacesContext.getCurrentInstance();
  ExtendedRenderKitService erks = Service.getRenderKitService(fctx, ExtendedRenderKitService.class);  
  erks.addScript(fctx, script);
}

A popular use case for calling JavaScript from a managed bean is to open a client-side ADF Faces popup dialog, as shown here:

StringBuilder script = new StringBuilder();
script.append( "var popup = AdfPage.PAGE.findComponentByAbsoluteId('p1');");
script.append("if(popup != null){"); script.append("popup.show();"); script.append("}"); writeJavaScriptToClient(script.toString());

Tuesday, May 24, 2011

Delete Rows using Managed Bean @ADF

In order to delete rows using managed bean that has component binding set for Table component, we can use a delete button with partial submit set to true and actionlistener property invoking the bean with following code:

public void onDelete(ActionEvent actionEvent) {
//access the RichTable from the JSF component binding
//created for the table component
RichTable _table = this.getTable1();
RowKeySet rks = _table.getSelectedRowKeys();
//iterate over the set of selected row keys and delete
//each of the found rows
Iterator selectedRowIterator = rks.iterator();
while (selectedRowIterator.hasNext()){
//get the first key
Object key = selectedRowIterator.next();
//make the row current
_table.setRowKey(key);
//the row is an instance of the ADF node binding class
JUCtrlHierNodeBinding rowWrapper = null;
rowWrapper = (JUCtrlHierNodeBinding) _table.getRowData();
//get the actual oracle.jbo.Row object
Row row = rowWrapper.getRow();

row.remove();
}
//partially update the ADF Faces Table
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(_table);
}
However this is simple but not recommended always. Another way is to create delete method in View Object Impl taking list of keys as input and use managed bean returning that list as input parameter to that method. This can be done by droping the method in viewobjectimpl as action and then use the expression builder to refer the managed bean as input parameter.

View Object Impl code:

public void processEmployeeBulkDelete(List employees){
if (employees != null){
for (Object employee : employees) {
Key k = (Key)employee;
Row[] rowsFound = this.findByKey(k,1);
//if the key returns more than one row then the provided
//key obviously is not unique. Ignore in this sample
if (rowsFound != null && rowsFound.length == 1) {
//get the first entry in the array of rows found
Row employeeRow = rowsFound[0];
employeeRow.remove();
}
}
}
}

Managed Bean Code:


public List getSelectedAdfRowKeys() {
List<Key> retVal = new ArrayList<Key>();
//get the selected row keys from the table instance
for (Object rowKey : employeesTable.getSelectedRowKeys()) {
//make the row the current row
employeesTable.setRowKey(rowKey);
Object o = employeesTable.getRowData();
//table rows are represented by the JUCtrlHierNodeBinding
//binding class
JUCtrlHierNodeBinding rowData = (JUCtrlHierNodeBinding)o;
//add the row key to the list
retVal.add(rowData.getRow().getKey());
}
return retVal;
}
//JSF component binding of the table
public void setEmployeesTable(RichTable employeesTable) {
this.employeesTable = employeesTable;
}
public RichTable getEmployeesTable() {
return employeesTable;
}

Now drag the processEmployeeBulkDelete method entry from the Data Controls panel to the page and choose a command action component. Now we can refer getSelectedAdfRowKeys as the input component to the method.

Monday, May 23, 2011

Override af:dialog default Buttons @ADF


To allow the dialog’s OK, Yes, or No button to perform an operation such as a commit or rollback, you use a dialog listener. For example, the following pop-up dialog includes a backing bean method for handling when the pop-up is canceled via the Cancel button or close icon (popupCanceledListener) or the dialog is closed via the OK button (dialogListener):


<af:popup contentDelivery="lazyUncached"
popupCanceledListener="#{DialogBean.handlePopupCancel}">
<af:dialog dialogListener="#{DialogBean.handleDialogClose}">
<!-- Input form defined here -->
</af:dialog>
</af:popup>


The backing bean implements the handlePopupCancel and handleDialogClose methods, as shown in the following code sample. Note that to determine which button was clicked, the handleDialogClose method uses the getOutcome method of DialogEvent.

public void handleDialogClose(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
BindingContext bindingctx = BindingContext.getCurrent();
BindingContainer bindings = bindingctx.getCurrentBindingsEntry();
OperationBinding operationBinding =
bindings.getOperationBinding("Commit");
Object result = operationBinding.execute();
}
}
---

public void handlePopupCancel(PopupCanceledEvent popupCanceledEvent) {
BindingContext bindingctx = BindingContext.getCurrent();
BindingContainer bindings = bindingctx.getCurrentBindingsEntry();
OperationBinding operationBinding =
bindings.getOperationBinding("Rollback");
Object result = operationBinding.execute();
}

Tuesday, May 10, 2011

Entity Object Custom Codes @ADF

Key Entity Objects Features and Events for Programmatic Business Logic


As Entity Object are supposed to be reused in many Application Modules, so they should not depend directly on a View Object Instance in any specific app module data control.To avoid this, entity object can use current application module instance's createViewObject() to create an instance of VO it requires.
Following code show how to access View object for validation.


// Sample entity-level validation method
public boolean validateSomethingUsingViewObject() {
Number numVal = getSomeEntityAttr();
String stringVal = getAnotherEntityAttr();
// Get the view object instance for validation
// Create a new name for the VO instance being used for validation
String name = "Validation_" + viewObjectDefName.replace('.', '_');
// Try to see if an instance of this name already exists
ViewObject vo = getDBTransaction().getRootApplicationModule()
.findViewObject(name);
// If it doesn't already exist, create it using the definition name
if (vo == null) {
vo = getDBTransaction().getRootApplicationModule()
.createViewObject(name,viewObjectDefName);
}
// Set it's bind variables (which it will typically have!)
vo.setNamedBindWhereClauseParam("BindVarOne",numVal);
vo.setNamedBindWhereClauseParam("BindVarTwo",stringVal);
vo.executeQuery();
if ( /* some condition */) {
/*
* code here returns true if the validation succeeds
*/
}
return false;
}

..............................
Reference: Developer’s Guide For Forms/4GL Developers

Saturday, May 7, 2011

Adding View Criteria @ADF

Following are the line of codes that can be used to add view criteria programmatically  in an application:


ApplicationModule am = Configuration.createRootApplicationModule(UserAppMod,UserAppModLocal);
ViewObject vo = am.findViewObject("User");
// 1. Create a view criteria rowset for this view object
ViewCriteria vc = vo.createViewCriteria();
// 2. Use the view criteria to create one or more view criteria rows
ViewCriteriaRow vcr1 = vc.createViewCriteriaRow();
ViewCriteriaRow vcr2 = vc.createViewCriteriaRow();
// 3. Set attribute values to filter on in appropriate view criteria rows
vcr1.setAttribute("UserId","> 304");
vcr1.setAttribute("Email","d%");
vcr1.setAttribute("UserRole","technician");
vcr2.setAttribute("UserId","IN (324,326)");
vcr2.setAttribute("LastName","Baer");
// 4. Add the view criteria rows to the view criteria rowset
vc.add(vcr1);
vc.add(vcr2);
// 5. Apply the view criteria to the view object
vo.applyViewCriteria(vc);
// 6. Execute the query
vo.executeQuery();
while (vo.hasNext()) {
Row curUser = vo.next();
System.out.println(curUser.getAttribute("UserId") + " " +
curUser.getAttribute("Email"));
}
Configuration.releaseRootApplicationModule(am, true);

Thursday, May 5, 2011

JSF Page Life Cycle

Following are the steps involved in JSF page life cycle.

The life cycle handles both Initial and Postback event.(For a page having input text field with value coming fron a bean say #{bean.name}, then Initial request is the request that the browser does in order to display the page with the ${bean.name} tag and Postback happens when the browser posts some or all page values and then the same page that was posted in the first place is returned to the client). When the life cycle handles an initial request, it only executes the restore view and render response phases because there is no user input or actions to process. Conversely, when the life cycle handles a postback, it executes all of the phases.

1) Restore View Phase: Begins when a link or button is clicked.the JSF implementation builds the view of the page, wires event handlers and validators to components in the view, and saves the view in the FacesContext instance.
For Initial request JSF creates an empty view and phase changes to Render response phase. The empty view will be used when page is processed during postback request.
For postback request, a view corresponding to page already exists. The JSF implementation restore the view by using state information saved on client or server.

Phase Result: Component Tree created/restored.

2) Apply Request value phase: Each component in the tree extract its value from decode method. The decode method looks like:
public void decode(FacesContext context, UIComponent component) {
       /* Grab the request map from the external context */
     Map requestMap = context.getExternalContext().getRequestParameterMap();
       /* Get client ID, use client ID to grab value from parameters */
     String clientId = component.getClientId(context);
     String value = (String) requestMap.get(clientId);

     FieldComponent fieldComponent = (FieldComponent)component;
       /* Set the submitted value */
     ((UIInput)component).setSubmittedValue(value);

}
The value is then stored locally on the component. If the conversion of the value fails, an error message associated with the component is generated and queued on FacesContext. This message will be displayed during the render response phase, along with any validation errors resulting from the process validations phase.

Phase Result: The components are set to their new values, and messages and events have been queued.

3) Process Validation Phase: All the validators registered on the component are processed in this phase. These rules are implemented on the local values stored. If local value is invalid, then error message is added to facescontext and phase changes to render phase. If events have been queued during this phase, the JavaServer Faces implementation broadcasts them to interested listeners.

Phase Result: Ensure that the data is valid.

4) Update Model Value Phase: This phase set the object properties to local values. JSF implementation updates only the bean properties pointed at by input component value attribute. If local data can't be converted to type specified by bean propeties and error message is added to facescontext and phase chages to render phase.

Phase Result: The properties of the bean are set to the local variable of the UI component.

5) Invoke Application Phase: This phase deals with invoking application level events like submitting forms or redirecting to other page. While processing redirecting event, if any, a default ActionListener implementation retrive the outcome from component action attribute and passed the outcome to default NavigationHandler. The JSF implementation then set view to new page as per the navigation rule.Otherwise, JSF implementation passes control to render phase.

Phase Result: Change of view in case of any navigation or application's invoke.

6) Render Response Phase: The JSP container is now assigned the authority to render the jsp pages.
If the request is Initial request, the components represented on the page will be added to the component tree as the JSP container executes the page.
If the request is a postback and errors were encountered during the apply request values phase, process validations phase, or update model values phase, the original page is rendered during this phase. If the pages contain message or messages tags, any queued error messages are displayed on the page.
After the content of the view is rendered, the state of the response is saved so that subsequent requests can access it and it is available to the restore view phase.

Phase Result: You have what you want to see :).

The Life cycle of a Page Request in an ADF Application Using ADF Faces Components:


Tuesday, May 3, 2011

Contextual Event @ADF

Below article will help to get some concept about how contextual events work.

af:region tag has a property that require pointer to region model which determine the current View to be displayed. The region model is exposed by bounded task flow through a specific task flow binding added to the page definition file of the page that contains the af:region tag.
Contextual event is functionality of binding layer. The communication allows to pass message object from a producing event to a listening method.

The Event Producer can be defined by event binding element that we declaratively create in page definition file of the page that contains the component region event or the event producer can be defined on the attribute binding that either listen for value change or for currency change if user select different row in table. A producer has a name that identify producer when it map to listening part and optionaly it may have a custom payload defined which over write the native event that is passed by default. The producer consis of a Rasie condition that specify when the event should be raised. The DCBindingContainerValueChangeEvent is native event object for all adf boud input field component.

The Event Consumer is a method that we expose in adf binding layer, that means exposes in data control, that means either in VO or AM. This methos may have zero, one or multiple argument. Once we have a method binding defined on a page definition file of the view that is suppose to listen for the produced event then we can use it for the dispatched event.

Now once we have producer event and consumer method, its time to bind them together. We do this using adf binding medium. The task flow binding is a binding container. The page definition file of the view exposing the bounded task flow is also a binding container. The page definition file of the parent page that contains the region also represent a binding container.Now the parent page binding container has a refrence to task flow binding which has a refrence to the container used by the fragment of the page fragment. So we have heirarchy like tree of conncted active container that we can use the binding layer to navigate to or point to. This is what the dispatching does. Dispatchnig has the ability to connect an event producer in an active binding container with an event listner in an active container.

When an event is first raised it is propogated to local container which also has refrence to component rasing the event. On that container it will looke for the event method. If that event method is available then event will be propagted. Else, next it goes to parent container and looks for event method and continues this way till it reaches the top most binding container.On its way up it broadcat the event to all named producer configuration. Then on the way back it broad cast the event to all the other active binding container that are not directly in the parent chain of raising event. 

Hmmm...enough theory its time for some hands on..Good Luck!!!!

*Please don't forget to post any correction, as i am also a newbie :) ....

Display message on Login @ADF

This is a simple way of displaying message when a user login (if validating using backing bean).

1) Drag and drop a Message component on the page.
2) Under the action listener method of the login button add following code
          FacesMessage msg=null;
          FacesContext fc=FacesContext.getCurrentInstance();
    If login successful :
          msg= new FacesMessage("Welcome");
          fc.addMessage(null,msg);
   If login failed:

          msg= new FacesMessage("Invalid Username/Password");
          fc.addMessage(null,msg);
3) Now just run the app and test.


Friday, April 29, 2011

Managed Bean and Backing Bean @ADF

Managed Bean:

1) Represents a Java class which will be created dynamically during runtime of the JSF application. It can be defined for which scope the bean is valid (Session, Request, Application or none).
2) Simple java object which are declared in "faces-config.xml".
3) In JSF you can access the values of a managed bean via value binding.

Backing Bean:  A backing bean defines UI component properties, each of which is bound to either a component's value or a component instance. A backing bean can also define methods that perform functions associated with a component, including validation, event handling, and navigation processing.

If you are configuring a backing bean that is referenced by a component tag's binding attribute, you should define the bean with a request scope. If you placed the bean in session or application scope instead, the bean would need to take precautions to ensure thread safety because UIComponent instances depend on running inside of a single thread.

Binding a component instance to a bean property has these advantages:
           1) The backing bean can programmatically modify component attributes.
           2) The backing bean can instantiate components rather than let the page author do so.

For Ex:  <inputText binding="#{UserNumberBean.userNoComponent}" />

Binding a component's value to a bean property has these advantages:

           1) The page author has more control over the component attributes.
           2) The backing bean has no dependencies on the JavaServer Faces API (such as the UI component classes), allowing for greater separation of the presentation layer from the model layer.
           3) The JavaServer Faces implementation can perform conversions on the data based on the type of the bean property without the developer needing to apply a converter.

For Ex:     <h:inputText id="userNo"   value="#{UserNumberBean.userNumber}"
                 validator="#{UserNumberBean.validate}" />

Monday, April 18, 2011

What Scope to be used @ ADF

Page flow scope: When you need to pass data values between activities within a task flow.

View scope: Recommended for variables that are needed only within the current view activity, not across view activities.

Request scope: Should be used when the scope does not need to persist longer than the current request. It is the only scope that should be used to store UI component information.
Backing bean scope:  Must be used for backing beans in your task flow if there is a possibility that your task flow will appear in two region components or declarative components on the same page and you would like to achieve region instance isolations.

*Because Pageflow, Backing bean and View scope are not standard JSF scope, EL expression must explicitly include the scope to reference bean. For example, to reference the MyBean managed bean from the backing bean scope, your expression would be #{backingBeanScope.MyBean}.

Friday, April 15, 2011

Application Module Custom Methods @ADF

Once we have created the page and bean corresponding to it, its quite easy to Insert Record in the database table referred by EO. Following code can be used to insert the records:

ApplicationModule am = Configuration.createRootApplicationModule(AMName, ConfigName);
ViewObject myVO= am.findViewObject("MyViewObject1");
Row newEmp = myVO.createRow();
myVO.insertRow(newEmp);
newEmp.setAttribute("Ename","Steve");
newEmp.setAttribute("Empno", new Number(1234));
am.getTransaction().commit();

*You can simply write bc4jclient and press ctrl+Enter and Application module code will be generated automatically.

Another important feature is to provide your Application Module as a Webservice. This can easily be done using following line of codes.
Scenario: Suppose you want to provide a service method to find the Employee's year of service.We will create a new method in AM say 'EmpServiceYears'  and will bind the where clause of VO to employees id passed by employee.

public long EmpServiceYears(long empId) {
  ViewObject emps = findViewObject("Employee1");
  emps.setWhereClause("empno = :0");
  emps.setWhereClauseParam(0, new Number(empId));
  emps.executeQuery();
  Row emp = emps.first();
  return emp == null ? 0 : ((Number)emp.getAttribute("YearsOfService")).longValue();
}


After writting code, deploy it as J2EE web service and select the method to include in client interface panel of AM.

Following code can help to find an Entity object based on primary key:


// Custom method in AppModuleImpl.java
public String findServiceRequestStatus(long requestId) {
String entityName = "devguide.model.entities.ServiceRequest";
// 1. Find the entity definition for the ServiceRequest entity
EntityDefImpl svcReqDef = EntityDefImpl.findDefObject(entityName);
// 2. Create the key
Key svcReqKey = new Key(new Object[]{requestId});
// 3. Find the entity object instance using the key
EntityImpl svcReq = svcReqDef.findByPrimaryKey(getDBTransaction(),svcReqKey);
if (svcReq != null) {
// 4. Return the Status attribute of the ServiceRequest
return (String)svcReq.getAttribute("Status");
}
else {
return null;
}
}

To create a new Entity Row:

//Custom method in AppModuleImpl.java
public long createProduct(String name, String description) {
String entityName = "devguide.model.entities.Product";
// 1. Find the entity definition for the Product entity
EntityDefImpl productDef = EntityDefImpl.findDefObject(entityName);
// 2. Create a new instance of a Product entity
EntityImpl newProduct = productDef.createInstance2(getDBTransaction(),null);
// 3. Set attribute values
newProduct.setAttribute("Name",name);
newProduct.setAttribute("Description",description);
try {
// 4. Commit the transaction
getDBTransaction().commit();
}
catch (JboException ex) {
getDBTransaction().rollback();
throw ex;
}
// 5. Access the database trigger assigned ProdId value and return it
DBSequence newIdAssigned = (DBSequence)newProduct.getAttribute("ProdId");
return newIdAssigned.getSequenceNumber().longValue();



To access the Application Module Client Interface in a JSF Backing Bean:


public class YourBackingBean {
public String commandButton_action() {
// 1. Access the FacesContext
FacesContext fc = FacesContext.getCurrentInstance();
// 2. Create value binding for the #{data} EL expression
ValueBinding vb = fc.getApplication().createValueBinding("#{data}");
// 3. Evaluate the value binding, casting the result to BindingContext
BindingContext bc = (BindingContext)vb.getValue(fc);
// 4. Find the data control by name from the binding context
DCDataControl dc = bc.findDataControl("SRServiceDataControl");
// 5. Access the application module data provider
ApplicationModule am = (ApplicationModule)dc.getDataProvider();
// 6. Cast the ApplicationModule to its client interface
SRService service = (SRService)am;
// 7. Call a method on the client interface
service.doSomethingInteresting();
return "SomeNavigationRule";
}
}


To get Application module instance independent of EO or VO::

 /***
     * This method returns the current instance of the session DBTransaction object.
     * The method below is implemented from a Singleton Object for utilitarian purposes.
     */
    public static synchronized DBTransaction getDBTransaction(){
   
       FacesContext ctx = FacesContext.getCurrentInstance();
       ValueBinding vb            = ctx.getApplication().createValueBinding("#{data}");
       BindingContext bc          = (BindingContext)vb.getValue(ctx.getCurrentInstance());
       DataControl dc             = bc.findDataControl("MyApplicationModuleControl");
       ApplicationModuleImpl am   = ((ApplicationModuleImpl)(ApplicationModule)dc.getDataProvider());
      
       return am.getDBTransaction(); 
      
   }


.......................
Reference: ADF Developer’s Guide For Forms/4GL Developers

What Happens in ADF and Database for New, Update and Delete?

Thursday, April 14, 2011

Some Important Property Attribute @ADF

1) Rendered: this looks an important property attribute. we can use it to make components visible/hidden based on EL expression in it.
For Eg.: If our search result have only one result, then we can remove the Next and Previous buttons. We need to add those button inside a panel container and change its renderes property to

#{bindings.MyIterator.estimatedRowCount >1}

2) FacetName: If we have two facets named 'Found' and 'NotFound' inside switcher, then we can set the facetname to following

#{bindings.TechniciansIterator.estimatedRowCount > 0 ? 'Found' : 'NotFound'}

Bindings Creation at Runtime @ADF

As part of configuring your project for working with Oracle ADF data binding, JDeveloper registers an additional handler that is triggered whenever a client requests a JSP page. This handler is listed in the standard J2EE web application configuration file (web.xml) of your ViewController project. It sets up the correct binding container for the current page based on the related ADF Model XML configuration files, and makes it accessible using the EL expression #{bindings}. During the subsequent handling of the web page request, the JSF standard dictates a predictable set of processing steps known as the page "lifecycle". 


At runtime, multiple objects (i.e., binding context, binding containers, and binding objects) are created in memory to hold binding information. The ADF binding context is a runtime map of all data controls and page definitions within the application. The binding context is the one object that lives in the HttpSession for each end user, accessible using the EL expression #{data}.

The group of bindings supporting the UI components on a page are described in a page definition file. The ADF Model layer uses this file at runtime to instantiate the page's bindings. These bindings are held in a request-scoped map called the binding container, accessible during each page request using the EL expression #{bindings}. This expression always evaluates to the binding container for the current page.



  • Binding Context
    • The binding context provides the data environment for your application. It contains all of the data controls and binding containers that your application can access.
    • The ADF lifecycle creates the ADF binding context from the application module,DataBindings.cpx, and page definition files. Binding context contains references that become data control or binding container objects on demand.
    • You can look up ApplicationModule from a managed bean using the BindingContext:
      BindingContext bc = BindingContext.getCurrent();
      DCDataControl dc = bc.findDataControl("AppModuleDataControl");
      ApplicationModule am = (ApplicationModule)dc.getDataProvider();
    • You can retrieve a ControlBinding named "producerMethod" via BindingContext in this way:
      DCBindingContainer bc = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
      JUCtrlActionBinding actionBnd =
      (JUCtrlActionBinding)bc.getControlBinding("producerMethod");
  • Binding Containers
    • A binding container holds value bindings and iterator bindings (or binding objects) for a page. It provides runtime access to all the ADF binding objects for a page.
At runtime, a web request for http://yourserver/yourapp/faces/some.jsp arrives from the client to the application server. The ADFBindingFilter (defined in web.xml) object looks for the ADF binding context in the HTTP session, and if it is not yet present, initializes it for the first time. If the appropriate binding container for the page has never been used before during the user's session, it is created. Also, if it is the first time an application module data control is referenced during the request, it acquires an instance of the application module from the application module pool. Then the control is forwarded to the page to be rendered. The UI components on the page access value bindings and iterator bindings in the page's binding container and render the formatted output to appear in the browser. Finally, the user sees the resulting page in the browser.

These objects in the ADF model layer provide runtime access to business services:
binding context object ( oracle.adf.model.BindingContext)
Defines a common namespace for use by the client application and allows all model objects to be exposed through a convenient root name. Each web page or Java panel registers with the binding context using the definition for the variable name binding.
data control interfaces ( oracle.adf.model.binding.DCDataControl)
Provides the client application with an interface into the model objects. One data control is needed to wrap the model objects of each business service configuration. Also, in the case of a JavaBeans model object, provides developers with direct access to the native object, when programmatic access is desired.
binding container objects ( oracle.adf.model.binding.DCBindingContainer)
Defines a container for data binding objects, including iterator bindings and control bindings. One binding container is created for each web page or Java panel, but may be reused in multiple pages and panels when they share the same data. The binding container object also lets you specify whether the page or panel is to be used in data entry mode or query mode.
iterator binding objects ( oracle.adf.model.binding.DCIteratorBinding)
Handles the events generated from the associated business service row iterator and sends the current row to individual control bindings to display current data. Iterator bindings can specify the number of rows to display in a web page.
control binding objects ( oracle.jbo.uicli.binding.JUControlBinding)
Defines the way a specific UI component interacts with the corresponding business service. For example, depending upon the control binding selection, a text field may be bound to an Oracle ADF Business Components view object attribute and display as an editable field or a static label. Or, if the business service attribute defines an enumerated list of values, the bound UI component might display a static list, a single-selection list, or a multi-selection list. Other, more complex UI components, such as table and graphs, are also supported by their own control bindings.
action binding objects ( oracle.jbo.uicli.binding.JUCtrlActionBinding)
At runtime, when the user initiates the action, using a button control, the action binding accesses the Oracle ADF binding context and initiates the specified action on the data objects of the selected collection. Action bindings can take parameters that will be passed to the controller to handle.