Tuesday, June 25, 2013

Exposing ADF BC as Service Interface

Here I have provided detailed steps to expose ADF Business Components as a Web service interface using sample application.

Steps:
  • Create an ADF application
  • Go to Model project and right click New

  • Select Business Components from Tables
  • Select Database connection and click OK
  • Select required tables as entity objects
  • Select required View Objects
  • Choose Application Module
  • Click Finish to create Business Components in Model project
  • Click on Application Module and go to Service Interface section. Click on Green plus icon.
  • Check ‘Generate Asynchronous Web Service Methods’
  • Select required component instances and respective operations
  • Click Finish to create Service Interface
  • Right click on Model project --> select New --> Go to Deployment Profiles section. Select Business Components Service Interface
  • Provide Deployment profile name and click OK
  • Go to Application Properties --> Deployment --> New
  • Select Archive Type as EAR file and provide name
  • In the EAR Deployment Profile editor, select the node Application Assembly and select only MiddleTier and click OK.
  • Back in the Deployment page for the Application Properties; uncheck the checkbox “Auto Generate and Synchronize weblogic-jdbc.xml Descriptors During Deployment”
  • Go to ApplicationModule --> Configuration. Set AM Service configuration as Default Configuration
  • Go to Model Project Properties --> Java EE Application --> Change Web application name and Web Context root as needed
  • Create required Data Source in Weblogic Console
  • Deploy to Weblogic Server



  • After successful deployment, Login to WLS console and go to deployments. Click on deployed application --> go to Testing tab. Check the Test URL. Alternatively, you can login to EM console to get WSDL details
  • Open browser and access deployed application WSDL
  • Copy the service location URL from WSDL and access the URL from browser. Check the list of operations available
  • Select any one operation and test it


Tuesday, June 18, 2013

Integrating Google Maps with ADF - Search using Address

The blog post written by James Taylor has sample code to search Google maps based on Longitude & Latitude. Here I am going to share code snippet to search Google maps API service based on Address/City/Zip code.

Add following changes to existing application discussed in blog post:

Note: Following changes tested with ADF v11.1.2.3.0 and Google Maps API V3.

1. Update existing Java Script section as follows:

    <f:facet name="metaContainer">
           <af:resource type="javascript" source="https://www.google.com/jsapi?key=[API Access Key]"/>
           <af:resource type="javascript">
                    google.load("maps", "3",  {other_params:"sensor=false"});
                    var map;
                    var geocoder;
                    function initialize()
                    {
                     geocoder = new google.maps.Geocoder();
                     var myLatlng = new google.maps.LatLng(-34.397, 150.644);
                     var myOptions = {
                                      zoom: 8,
                                      center: myLatlng,
                                      mapTypeId: google.maps.MapTypeId.ROADMAP
                                     }
                     map = new google.maps.Map(document.getElementById("map"), myOptions);
                    }
                    google.setOnLoadCallback(initialize);                  
            </af:resource>
            <af:resource type="javascript">
                        function codeAddress(evt)
                           {
                            var str = [];
                            str[0] = evt.getSource().getProperty("str");
                            str[1] = evt.getSource().getProperty("city");
                            str[2] = evt.getSource().getProperty("zip");
                            var address = str.join(',');
                            geocoder.geocode( { 'address': address}, function(results, status) {
                            if (status == google.maps.GeocoderStatus.OK)
                            {
                                map.setCenter(results[0].geometry.location);
                                var marker = new google.maps.Marker(
                                    {
                                    map: map,
                                    position: results[0].geometry.location
                                    }
                                );
                            } else {
                                alert('Geocode was not successful for the following reason: ' + status);
                            }
                            });
                        }
            </af:resource>
      </f:facet>


2. Implement Client Listeners for user interaction as mentioned below.

Find the code:
                                <af:outputText value="#{row.Zip}" id="ot2">
                                    <af:convertNumber groupingUsed="false"
                                                      pattern="#{bindings.HousesUVO1.hints.Zip.format}"/>
                                </af:outputText>

And replace it to look like this.
                                <af:outputText value="#{row.Zip}" id="ot2">
                                    <af:convertNumber groupingUsed="false"
                                                      pattern="#{bindings.HousesUVO1.hints.Zip.format}"/>
                                    <af:clientAttribute name="str" value="#{row.Street}"/>
                                    <af:clientAttribute name="city" value="#{row.City}"/>
                                    <af:clientAttribute name="zip" value="#{row.Zip}"/>
                                    <af:clientListener method="codeAddress" type="click"/>                                                      
                                </af:outputText>


Finally run the page and click on any Zip code in Zip column to see the respective address on the Map region.





Thursday, June 13, 2013

af:table - pagination

Another new feature of ADF release 11.1.1.7.0: paging af:table component

To enable pagination functionality, following af:table attributes needs to be modified.

  • scrollPolicy="page"
  • autoHeightRows="0"
  • the table should be put inside a flowing container like panelGroupLayout with layout attribute as "scroll"


af:inputText - placeholder property

As a part of ADF 11.1.1.7.0 release, a new property introduced w.r.t af:inputText component.

placeholder --> Text to be displayed in the input component when a value is not present.


Wednesday, June 12, 2013

BPM Notification Error 500 -- Internal Server Error

When we install SOA and WebCenter into same middleware home, we will get 500 internal server error in BPM worklist notification email. This happens when we select WebCenter and SOA in domain configuration wizard. While doing this domain configuration, permissions to bpm-services.jar referenced by oracle.soa.workflow.wc application are not correctly setup.

To resolve this issue, we need to manually grant permissions to bpm-services.jar referenced by oracle.soa.workflow.wc application.

Steps to grant permissions:

1. Go to WebLogic Server console and click on deployment. Click on oracle.soa.workflow.wc and locate path directory

2. Open DOMAIN_HOME/config/fmwconfig/system-jazn-data.xml.

3. Make sure that the bpm-services.jar path directory is same as above. If not, copy the entire <grant> block for the bpm-services.jar and paste the entire grant block again in the file. Change the directory location of the new copy of the bpm-services.jar <grant> block to match the oracle.soa.workflow.wc path that was located in step 1. (or) just replace the ${soa.oracle.home} with ${ucm.oracle.home} in the new copy of bpm.services.jar <grant> block.

4. Try once. If it's not working, restart server.

Retrieving Managed Beans Programmatically

Incase of ADF applications, sometimes we need to access one managed bean properties from another managed bean. Following code provides details on how to access managed beans programmatically specified in different scopes.

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

ExternalContext exctx = FacesContext.getCurrentInstance().getExternalContext();

AppBean appBean = (AppBean) exctx.getApplicationMap().get("appBeanName");
SessionBean sessionBean = (SessionBean) exctx.getSessionMap().get("sessionBeanName");
RequestBean sessionBean = (RequestBean) exctx.getRequestMap().get("requestBeanName");

AdfFacesContext adfctx = AdfFacesContext.getCurrentInstance();

ViewBean viewBean = (ViewBean)adfctx.getViewScope().get("viewBeanName");
PageFlowBean pageFlowBean = (PageFlowBean)adfctx.getPageFlowScope().get("pageFlowBeanName");

Using Trinidad ComponentReference in ADF

We should use ComponentReference if we need to have a reference to an instance of the UIComponent class in managed bean that are longer than requested scoped.

Example:
Following code will be generated by default in managed bean when we create binding for UIComponent.

import oracle.adf.view.rich.component.rich.output.RichOutputText;

private RichOutputText acctId;

public void setAcctId(RichOutputText acctId) {
        this.acctId = acctId;
    }

public RichOutputText getAcctId() {
        return acctId;
    }

And this can be rewritten using ComponentReference as shown below.

import oracle.adf.view.rich.component.rich.output.RichOutputText;
import org.apache.myfaces.trinidad.util.ComponentReference;

private ComponentReference acctId;

public void setAcctId(RichOutputText acctId) {
      this.acctId =
                ComponentReference.newUIComponentReference(acctId);
    }

public RichOutputText getAcctId() {
        if (acctId != null) {
            return (RichOutputText)acctId.getComponent();
        }
        return null;
    }

Detailed explanation about ComponentReference can be found in following links.
http://myfaces.apache.org/trinidad/trinidad-api/apidocs/org/apache/myfaces/trinidad/util/ComponentReference.html

http://docs.oracle.com/cd/E16162_01/web.1112/e16181/gs_jdev.htm

WebCenter 11g Architecture

WebCenter 11g architecture diagram with the different core constituents with their components that can be used with WebCenter.