Thursday, August 29, 2013

ADF Mobile - How to get the Preferences value in HTML page

In my previous blog entry I went over "Usage of User Preferences in ADF Mobile", In this entry we'll see how to get the Preferences value in HTML page.

In this type of scenarios we can use Javascript Callback Function "adf.mf.api.invokeMethod" invoke a Java method from any class in a classpath.

Below Code illustrate how to call the Java method from HTML and get Preferences values back into the HTML.
<script type="text/javascript" charset="utf-8">
  /**
   * Document is done loading this is called and we add a listener for the
   * phonegap event 'deviceready'.
   */
  function onBodyLoad() {
	  document.addEventListener("deviceready", onDeviceReady, false);
  };

  /**
   * When this function is called, PhoneGap has been initialized and is ready to roll.
   */
  function onDeviceReady() {
	  adf.mf.api.invokeMethod("mobile.LoginBean", "getPreferencesData", onSuccess, onFail);
  }

  function onSuccess(request, response) {
	  // Process any return values that comes back in the "response" parameter 
          // Overwrite the below html field values
	  document.getElementById("username").value = response[0];
	  document.getElementById("password").value = response[1];
	  document.getElementById("serviceURL").value = response[2];
  }

  function onFail(request, response) {
  }
</script>
You can download the sample workspace from here
[Runs with Oracle JDeveloper 11.1.2.4.0]

Implementation Steps

Create a ADF Mobile application, In ViewController project. Locate and expand the Application Sources folder, then expand the META-INF folder. You will see the adfmf-feature.xml file, click on the adfmf-feature.xml file to launch the Feature editor. Add a new feature by clicking the green plus sign on the Features table near top of the editor this will launch the new Create ADF Mobile Feature dialog, modify the Feature Name as "feature1".

In the Features table, select the newly created feature feature1  Under the Features table, click the Content tab, and locate the Content table. Notice that the content item feature1.1 is created by default and Type as Local HTML. Next add a new file by clicking the green plus sign and create a index.html file.

Open adfmf-feature.xml, add the adfmf:preferences for "feature1" as shown below.
<?xml version="1.0" encoding="UTF-8" ?>
<adfmf:features xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:adfmf="http://xmlns.oracle.com/adf/mf">
    <adfmf:feature id="feature1" name="feature1" credentials="none">
        <adfmf:content id="feature1.1">
            <adfmf:constraints/>
            <adfmf:localHTML url="feature1/index.html"/>
        </adfmf:content>
        <adfmf:preferences>
            <adfmf:preferenceGroup id="security" label="Security">
                <adfmf:preferenceText id="username" label="User Name" default="oracle"/>
                <adfmf:preferenceText id="password" label="Password" secret="true" default="oracle12"/>
                <adfmf:preferenceText id="serviceURL" label="Security URL" default="http://security.foo.com/provider"/>
            </adfmf:preferenceGroup>
        </adfmf:preferences>
    </adfmf:feature>
</adfmf:features>
In ViewController project, locate and expand the Application Sources folder, create a LoginBean.java file and add the below code.
public class LoginBean {
    public LoginBean() {
        super();
    }

    public List getPreferencesData() {
        List preferences = new ArrayList();
        String username =
            (String)AdfmfJavaUtilities.evaluateELExpression("#{preferenceScope.feature.feature1.security.username}");
        String password =
            (String)AdfmfJavaUtilities.evaluateELExpression("#{preferenceScope.feature.feature1.security.password}");
        String serviceURL = (String)AdfmfJavaUtilities.evaluateELExpression("#{preferenceScope.feature.feature1.security.serviceURL}");
        preferences.add(username);
        preferences.add(password);
        preferences.add(serviceURL);
        return preferences;
    }
}
Open the index.html page and add the below code.
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></meta>
        <title>index</title>
        <script type="text/javascript">
          if (!window.adf)
              window.adf = {
              };
          adf.wwwPath = "../../../../www/";
        </script>
        <script type="text/javascript" src="../../../../www/js/base.js"></script>
        <script type="text/javascript" charset="utf-8">
          /**
           * Document is done loading this is called and we add a listener for the
           * phonegap event 'deviceready'.
           */
          function onBodyLoad() {
              document.addEventListener("deviceready", onDeviceReady, false);
          };

          /**
           * When this function is called, PhoneGap has been initialized and is ready to roll.
           */
          function onDeviceReady() {
              adf.mf.api.invokeMethod("mobile.LoginBean", "getPreferencesData", onSuccess, onFail);
          }

          function onSuccess(request, response) {
              // Process any return values that comes back in the "response" parameter 
              document.getElementById("username").value = response[0];
              document.getElementById("password").value = response[1];
              document.getElementById("serviceURL").value = response[2];
          }

          function onFail(request, response) {
          }
        </script>
    </head>
    <body id="mainBody" onload="onBodyLoad()">
        <div id="bodyPage">
            <div class="amx-view-container current">
                <div class="amx-node amx-view">
                    <div class="amx-node amx-panelPage">
                        <div class="amx-panelPage-header">
                            <div class="amx-panelPage-facet-header">
                                <div class="amx-node amx-outputText" id="message">
                                    <br></br>
                                </div>
                            </div>
                        </div>
                        <div class="amx-panelFormLayout amx-label-position-start amx-field-halign-end amx-layout-one-row amx-node">
                            <div class="amx-panelFormLayout_body">
                                <div class="amx-panelFormLayout_sizing">
                                    <div class="field-label"></div>
                                    <div class="field-value"></div>
                                </div>
                                <div class="field amx-node amx-inputText">
                                    <div class="field-label">
                                        <label>Security URL</label>
                                    </div>
                                    <div class="field-value">
                                        <input type="text" name="serviceURL" id="serviceURL" value=""/>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="amx-panelFormLayout amx-label-position-start amx-field-halign-end amx-layout-one-row amx-node">
                            <div class="amx-panelFormLayout_body">
                                <div class="amx-panelFormLayout_sizing">
                                    <div class="field-label"></div>
                                    <div class="field-value"></div>
                                </div>
                                <div class="field amx-node amx-inputText">
                                    <div class="field-label">
                                        <label>User Name</label>
                                    </div>
                                    <div class="field-value">
                                        <input type="text" name="username" id="username" value=""/>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="amx-panelFormLayout amx-label-position-start amx-field-halign-end amx-layout-one-row amx-node">
                            <div class="amx-panelFormLayout_body">
                                <div class="amx-panelFormLayout_sizing">
                                    <div class="field-label"></div>
                                    <div class="field-value"></div>
                                </div>
                                <div class="field amx-node amx-inputText" onclick="adf.mf.login.focusPassword();">
                                    <div class="field-label">
                                        <label>Password</label>
                                    </div>
                                    <div class="field-value">
                                        <input type="password" name="password" id="password" value=""/>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div style="text-align: center;">
                            <div id="loginButton" class="amx-node amx-commandButton">
                                <div class="amx-node amx-commandButton-label">
                                    <p>Login</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div id="amx-loading" class="amx-loading hidden"></div>
        </div>
    </body>
</html>
Application screen looks like below when it deployed and run on Android Device/Emulator. When the application loads, Security values will be fetched from Preferences and displayed on the html file.

Thursday, August 22, 2013

ADF Mobile - Get REST WebService based form values in managed bean

In my previous blog entry I went over "Get ADF Mobile Form values in managed bean using Accessor Iterator", In this entry we'll see how to get Rest WebService based form values in managed bean programmatically.

Below is one of the way to access Rest WebService based form values, here is the code below.
ValueExpression ve =
            AdfmfJavaUtilities.getValueExpression("#{bindings.editEmployeeIterator.currentRow.dataProvider}",
                                                  Object.class);
        Object obj = ve.getValue(AdfmfJavaUtilities.getAdfELContext());
  if (obj instanceof VirtualJavaBeanObject) {
            VirtualJavaBeanObject vjbo = (VirtualJavaBeanObject)obj;
            if (vjbo.getAttributeInfoCount() > 0) {
                int count = vjbo.getAttributeInfoCount();
                for (int i = 0; i > count; i++) {
                    AttributeInfo fieldName = vjbo.getAttributeInfo(i);
                    String fieldValue = vjbo.getAttribute(fieldName.name).toString();
                    System.out.println(fieldName.name + " :" + fieldValue);
                }
            }
        }

Thursday, August 1, 2013

EJB provides Accessor iterators for Parameterized Named Query in JDeveloper 12c

Scenario is to add new row to the ADF Table, here ADF Table is based on Named Query having parameters.

When a user defines a JPA named query with parameters in Employee entity using persistence xml (for ex: "select o from Employees o where o.departmentId = :bind_departmentId"), these queries were exposed through non-getter methods on the EJB Session or Java Service facade classes and will be exposed as method actions. Method Action looks as below.


In JDeveloper 12c same queries will be exposed through getter methods as Accessor iterators. Accessor iterator looks as below.


Note:- Named Query name should be defined in following pattern: "<entity name>.<query name>" and query name should start with "get" + "<first char should be uppercase>"
For ex: Employees.getByDeptId

If the named query name doesn't follow the above pattern, then it will be exposed as Method Action.

You can download the sample workspace from here
[Runs with Oracle JDeveloper 12.1.2.0.0]

Implementation Steps

Create Fusion Web Application with entity based on Employees table, open the employees entity java class and add the below Named Query inside @NamedQueries section.
@NamedQuery(name = "Employees.getByDeptId",
                          query = "select o from Employees o where o.departmentId = :bind_departmentId")
Next create a session bean and expose all methods to local/remote interface and generate data control.

In ViewController project, create and open the index.jspx page and follow the below steps:
  • In the Data Controls accordion, expand the SessionEJBBean node, drop employeesGetByDeptId->Operations->ExecuteWithParams as ADF Parameter Form. Notice in the below image, parameter value binding will be bind_departmentId.


Note:- ExecuteWithParams operation is supported in EJB Datacontrols from Jdeveloper 12c.
  • Drop employeesGetByDeptId->Table/List View as ADF Table. 
  • In the Data Controls accordion, expand the SessionEJBBean node, drop employeesGetByDeptId->Operations->Create as ADF Button
  • Drop the persistEntity(Object) as Method->ADF Button. In Edit Action Binding window select the binding value as "#{bindings.employeesGetByDeptIdIterator.currentRow.dataProvider}"


Run the index.jspx page and enter values in search form with departmentId as 90 and click on ExecuteWithParam button. Named query will filter the data and display employee records which are associated with departmentId.


Next clicking on Create Button will insert new row inside the table, enter the employee information and click on persistEntity button to save the record.