Thursday Oct 17, 2013

Simple GET operation with JSON data in ADF Mobile

Usecase:

This sample uses a RESTful service which contains a GET method that fetches employee details for an employee with given employee ID along with other methods. The data is fetched in JSON format.

This RESTful service is then invoked via ADF Mobile and the JSON data thus obtained is parsed and rendered in mobile in a table.

Prerequisite:

Download JDev build JDEVADF_11.1.2.4.0_GENERIC_130421.1600.6436.1 or higher with mobile support. 

Steps:

Run EmployeeService.java in JSONService.zip. This is a simple service with a method, getEmpById(id) that takes employee ID as parameter and produces employee details in JSON format. 

Copy the target URL generated on running this service. The target URL will be as shown below:

http://127.0.0.1:7101/JSONService-Project1-context-root/jersey/project1

Now, let us invoke this service in our mobile application. For this, create an ADF Mobile application. 

Gallery

Name the application JSON_SearchByEmpID and finish the wizard.

appName

Now, let us create a connection to our service. To do this, we create a URL Connection. Invoke new gallery wizard on ApplicationController project. 

newGallery

Select URL Connection option.

urlConn

In the Create URL Connection window, enter connection name as ‘conn’. For URL endpoint, supply the URL you copied earlier on running the service. Remember to use your system IP instead of localhost. Test the connection and click OK.

conn

At this point, a connection to the REST service has been created.

Since JSON data is not supported directly in WSDC wizard, we need to invoke the operation through Java code using RestServiceAdapter. For this, in the ApplicationController project, create a Java class called ‘EmployeeDC’. We will be creating DC from this class.

javaclass

Add the following code to the newly created class to invoke the getEmpById method.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public Employee fetchEmpDetails(){

RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

restServiceAdapter.clearRequestProperties();

restServiceAdapter.setConnectionName("conn"); //URL connection created with this name

restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);

restServiceAdapter.addRequestProperty("Content-Type", "application/json");

restServiceAdapter.addRequestProperty("Accept", "application/json; charset=UTF-8");

restServiceAdapter.setRetryLimit(0);

restServiceAdapter.setRequestURI("/getById/"+inputEmpID);

String response = "";

JSONBeanSerializationHelper jsonHelper = new JSONBeanSerializationHelper();

try {

response = restServiceAdapter.send(""); //Invoke the GET operation

System.out.println("Response received!");

Employee responseObject = (Employee) jsonHelper.fromJSON(Employee.class, response);

return responseObject;

} catch (Exception e) {

}

return null;

}

Here, in lines 2 to 9, we create the RestServiceAdapter and set various properties required to invoke the web service. At line 4, we are pointing to the connection ‘conn’ created previously.

Since we want to invoke getEmpById method of the service, which is defined by the URL

http://IP:7101/REST_Sanity_JSON-Project1-context-root/resources/project1/getById/{id}

we are updating the request URI to point to this URI at line 9. inputEmpID is a variable that will hold the value input by the user for employee ID. This we will be creating in a while.

As the method we are invoking is a GET operation and consumes json data, these properties are being set in lines 5 through 7. Finally, we are sending the request in line 13.

In line 15, we use jsonHelper.fromJSON to convert received JSON data to a Java object. The required Java objects' structure is defined in class Employee.java whose structure is provided later. Since the response from our service is a simple response consisting of attributes like employee Id, name, design etc, we will just return this parsed response (line 16) and use it to create DC.

As mentioned previously, we would like the user to input the employee ID for which he/she wants to perform search. So, in the same class, define a variable inputEmpID which will hold the value input by the user. Generate accessors for this variable.

accessor

Lastly, we need to create Employee class. Employee class will define how we want to structure the JSON object received from the service. To design the Employee class, run the services’ method in the browser or via analyzer using path parameter as 1. This will give you the output JSON structure.

jsonOutput

Ours is a simple service that returns a JSONObject with a set of data. Hence, Employee class will just contain this set of data defined with the proper data types.

Create Employee.java in the same project as EmployeeDC.java and write the below code:

package application;

import oracle.adfmf.java.beans.PropertyChangeListener;

import oracle.adfmf.java.beans.PropertyChangeSupport;

public class Employee {

private String dept;

private String desig;

private int id;

private String name;

private int salary;

private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

public void setDept(String dept) {

        String oldDept = this.dept;

this.dept = dept;

propertyChangeSupport.firePropertyChange("dept", oldDept, dept);

}

public String getDept() {

return dept;

}

public void setDesig(String desig) {

String oldDesig = this.desig;

this.desig = desig;

propertyChangeSupport.firePropertyChange("desig", oldDesig, desig);

}

public String getDesig() {

return desig;

}

public void setId(int id) {

int oldId = this.id;

this.id = id;

propertyChangeSupport.firePropertyChange("id", oldId, id);

}

public int getId() {

return id;

}

public void setName(String name) {

String oldName = this.name;

this.name = name;

propertyChangeSupport.firePropertyChange("name", oldName, name);

}

public String getName() {

return name;

}

public void setSalary(int salary) {

int oldSalary = this.salary;

this.salary = salary;

propertyChangeSupport.firePropertyChange("salary", oldSalary, salary);

}

public int getSalary() {

return salary;

}

public void addPropertyChangeListener(PropertyChangeListener l) {

propertyChangeSupport.addPropertyChangeListener(l);

}

public void removePropertyChangeListener(PropertyChangeListener l) {

propertyChangeSupport.removePropertyChangeListener(l);

    }

}

Now, let us create a DC out of EmployeeDC.java.

createDC

 DC as shown below is created.

DC

Now, you can design the mobile page as usual and invoke the operation of the service. To design the page, go to ViewController project and locate adfmf-feature.xml. Create a new feature called ‘SearchFeature’ by clicking the plus icon.

feature

Go the content tab and add an amx page. Call it SearchPage.amx.

createPage

Call it SearchPage.amx. Remove primary and secondary buttons as we don’t need them and rename the header.

preview

Drag and drop inputEmpID from the DC palette onto Panel Page in the structure pane as input text with label.

inputText

Next, drop fetchEmpDetails method as an ADF button.

fetchButton

For a change, let us display the output in a table component instead of the usual form. However, you will notice that if you drag and drop Employee onto the structure pane, there is no option for ADF Mobile Table. Hence, we will need to create the table on our own.

To do this, let us first drop Employee as an ADF Read -Only form. This step is needed to get the required bindings. We will be deleting this form in a while.

form

finalPage

Now, from the Component palette, search for ‘Table Layout’. Drag and drop this below the command button. 

table tableStructure

Within the tablelayout, insert ‘Row Layout’ and ‘Cell Format’ components. Final table structure should be as shown below. Here, we have also defined some inline styling to render the UI in a nice manner.

<amx:tableLayout id="tl1" borderWidth="2" halign="center" inlineStyle="vertical-align:middle;"

width="100%" cellPadding="10">

<amx:rowLayout id="rl1" >

<amx:cellFormat id="cf1" width="30%">

<amx:outputText value="#{bindings.dept.hints.label}" id="ot7" inlineStyle="color:rgb(0,148,231);"/>

</amx:cellFormat>

<amx:cellFormat id="cf2">

<amx:outputText value="#{bindings.dept.inputValue}" id="ot8" />

</amx:cellFormat>

</amx:rowLayout>

<amx:rowLayout id="rl2">

<amx:cellFormat id="cf3" width="30%">

<amx:outputText value="#{bindings.desig.hints.label}" id="ot9" inlineStyle="color:rgb(0,148,231);"/>

</amx:cellFormat>

<amx:cellFormat id="cf4" >

<amx:outputText value="#{bindings.desig.inputValue}" id="ot10"/>

</amx:cellFormat>

</amx:rowLayout>

<amx:rowLayout id="rl3">

<amx:cellFormat id="cf5" width="30%">

<amx:outputText value="#{bindings.id.hints.label}" id="ot11" inlineStyle="color:rgb(0,148,231);"/>

</amx:cellFormat>

<amx:cellFormat id="cf6" >

<amx:outputText value="#{bindings.id.inputValue}" id="ot12"/>

</amx:cellFormat>

</amx:rowLayout>

<amx:rowLayout id="rl4">

<amx:cellFormat id="cf7" width="30%">

<amx:outputText value="#{bindings.name.hints.label}" id="ot13" inlineStyle="color:rgb(0,148,231);"/>

</amx:cellFormat>

<amx:cellFormat id="cf8">

<amx:outputText value="#{bindings.name.inputValue}" id="ot14"/>

</amx:cellFormat>

</amx:rowLayout>

<amx:rowLayout id="rl5">

<amx:cellFormat id="cf9" width="30%">

<amx:outputText value="#{bindings.salary.hints.label}" id="ot15" inlineStyle="color:rgb(0,148,231);"/>

</amx:cellFormat>

<amx:cellFormat id="cf10">

<amx:outputText value="#{bindings.salary.inputValue}" id="ot16"/>

</amx:cellFormat>

</amx:rowLayout>

    </amx:tableLayout>

The values used in the output text of the table come from the bindings obtained from the ADF Form created earlier. As we have used the bindings and don’t need the form anymore, let us delete the form. 

tableImg

One last thing before we deploy. When user changes employee ID, we want to clear the table contents. For this we associate a value change listener with the input text box.

valChange

Click New in the resulting dialog to create a managed bean.

valChangeDialog managedBean

Next, we create a method within the managed bean. For this, click on the New button associated with method. Call the method ‘empIDChange’.

newMethod empIDChange

Open myClass.java and write the below code in empIDChange().

public void empIDChange(ValueChangeEvent valueChangeEvent) {

// Add event code here...

//Resetting the values to blank values when employee id changes

AdfELContext adfELContext = AdfmfJavaUtilities.getAdfELContext();

ValueExpression ve = AdfmfJavaUtilities.getValueExpression("#{bindings.dept.inputValue}", String.class);

ve.setValue(adfELContext, "");

ve = AdfmfJavaUtilities.getValueExpression("#{bindings.desig.inputValue}", String.class);

ve.setValue(adfELContext, "");

ve = AdfmfJavaUtilities.getValueExpression("#{bindings.id.inputValue}", int.class);

ve.setValue(adfELContext, "");

ve = AdfmfJavaUtilities.getValueExpression("#{bindings.name.inputValue}", String.class);

ve.setValue(adfELContext, "");

ve = AdfmfJavaUtilities.getValueExpression("#{bindings.salary.inputValue}", int.class);

ve.setValue(adfELContext, "");

}

That’s it. Deploy the application to android emulator or device. Some snippets from the app.

Snapshot1 Snapshot2

About

Tips and Tricks from Oracle's JDeveloper & ADF QA

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today