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.
Name the application JSON_SearchByEmpID
and finish the wizard.
Now, let us create a connection to our service. To do this,
we create a URL Connection. Invoke new gallery wizard on ApplicationController
project.
Select URL Connection option.
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.
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.
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.
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.
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.
DC as shown below is created.
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.
Go the content tab and add an amx page. Call it SearchPage.amx.
Call it SearchPage.amx. Remove primary and secondary buttons as we don’t need them and rename the header.
Drag and drop inputEmpID from the DC palette onto Panel Page in the structure pane as
input text with label.
Next, drop
fetchEmpDetails method as an ADF button.
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.
Now, from
the Component palette, search for ‘Table Layout’. Drag and drop this below the
command button.
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.
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.
Click New in the resulting dialog to create a managed bean.
Next, we create a method within the managed bean. For this, click on the New button
associated with method. Call the method ‘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.