ADF Application Exposed as REST Web Service and Consumed in MAF Application

Version 10

    Namit Kakkar examines how Oracle Mobile Application Framework interacts with a database through JSON REST services based on Application Development Framework-Business Components, then shows how to create an ADF application that interacts with a database and exposes itself as a REST web service.


     

    By Namit Kakkar

     

    Follow the steps below to create an ADF-based JSON Rest Service and then to consume the service through a MAF application.

     

    ADF Web Service


    • Create an ADF Fusion web application

    001FusionApp.jpg002FusionApp.jpg

    • Choose the default for all other steps in the wizard above, and finish the wizard.
    • Create an ADF-BC model layer and create EmployeeEO and EmployeeVO. Put EmployeeVO in AM.

    003FusionApp.jpg

    • Create a Java class and name it Employee.java. Generate setters and getters for the attributes below:
    @XmlRootElement
    public class Employee {
     @XmlElement
        private Integer employeeId;
        @XmlElement
        private String firstName;
        @XmlElement
        private String lastName;
        @XmlElement
        private String email;
        @XmlElement
        private String phoneNumber;
        @XmlElement
        private Date hireDate;
        @XmlElement
        private String jobId;
     @XmlElement
        private BigDecimal salary;
     @XmlElement
        private BigDecimal commissionPct;
     @XmlElement    
    private Integer managerId;
    
    
    
    
    
    
    
    
    
    
    • Create a Java class, Employees.java, with this code:
              @XmlRootElement
    public class Employees {
     @XmlElement(name = "employee")
        private List<Employee> employees;
        
        public Employees() {
            super();
        }
        public void setEmployees(List<Employee> employees) {
     this.employees = employees;
        }
        public List<Employee> getEmployees() {
            return employees;
        }
            public void addEmployees(Employee employee) {
            if (employees == null) {
     employees = new ArrayList<Employee>();
            }
     employees.add(employee);
        }
    }
    
    
    
    
    
    
    
    
    
    
    • Create EmployeeResource.java and use the code below for searchmethod:

     

     

     private static final String amDef = "br.com.poc.model.AppModule";
        private static final String config = "AppModuleLocal";
    
        @GET
     @Path("search/{id}")
        public Employees getById(@PathParam("id") Integer id) {
     ApplicationModule am = Configuration.createRootApplicationModule(amDef, config);
     ViewObject vo = am.findViewObject("EmployeesView1");
            Employee employee = null;
     Employees employees = new Employees();
            Key key = new Key(new Object[] { id });
            Row[] rowsFound = vo.findByKey(key, 1);
            if (rowsFound != null && rowsFound.length > 0) {
                Row row = rowsFound[0];
     employee = new Employee();
     employee.setEmployeeId((Integer) row.getAttribute("EmployeeId"));
                employee.setEmail((String) row.getAttribute("Email"));
     employee.setHireDate((Timestamp) row.getAttribute("HireDate"));
     employee.setJobId((String) row.getAttribute("JobId"));
     employee.setLastName((String) row.getAttribute("LastName"));
     employee.setFirstName((String) row.getAttribute("FirstName"));
                
     employee.setPhoneNumber((String) row.getAttribute("PhoneNumber"));
     employee.setSalary((BigDecimal) row.getAttribute("Salary"));
     employee.setCommissionPct((BigDecimal) row.getAttribute("CommissionPct"));
     employee.setManagerId((Integer) row.getAttribute("ManagerId"));
     employee.setDepartmentId((Integer) row.getAttribute("DepartmentId"));
            }
     employees.addEmployees(employee);
    
     Configuration.releaseRootApplicationModule(am, true);
            return employees;
        }
    
    
    
    
    
    
    
    
    
    

     

    • Right click the EmployeeResource class and create REST web service:

    004FusionApp.jpg

    005FusionApp.jpg006FusionApp.jpg

    • Test the web service

    007FusionApp.jpg008FusionApp.jpg


    MAF APPLICATION


    • Create a MAF application and name it MAFRESTJSONApp
    • Create a MAF feature and name it employee.
    • Click the Content tab and press the green symbol at the end of the File text box, to create EmployeesTF.

    0024FusionApp.jpg

     

    • Create the REST Connection.

    0010FusionApp.jpg


    Important Note: Use 10.0.2.2 IP because Android uses this host to access your local host.


    • Create Employee class. Under Optional Attributes, click the green "plus" symbol and select Cloneable.

     

    0011FusionApp.jpg

     

    • Copy the code below and generate Accessors.

     

    public class Employee implements Cloneable {
        private Integer employeeId;
        private String firstName;
        private String lastName;
        private String email;
        private String phoneNumber;
        private Date hireDate;
        private String jobId;
        private BigDecimal salary;
        private BigDecimal commissionPct;
        private Integer managerId;
        private Integer departmentId;
        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
            public Employee() {
            super();
        }
    
    
    
    
    
    
    
    
    
    

     

    • Create Employees class and copy the code below:

     

        public class Employees {
     public Employees() {
     super();
     }
     rivate Employee [] employee;
    
     public void setEmployee(Employee[] employee) {
     this.employee = employee;
     }
        public Employee[] getEmployee() {
     return employee;
     }
     public List getEmployeesAsList() {
     return Arrays.asList(this.employee);
     }
    }
    
    
    
    
    
    
    
    
    
    

     

    • Create RestServiceUtil class and copy the code below:

     

    public class RestServiceUtil {
            private String connectionName;
            public RestServiceUtil(String connectionName) {
            super();
     this.connectionName = connectionName;
        }
            public String invokeCreate(String requestURI, Object postData) {
            return invokeRestService(RestServiceAdapter.REQUEST_TYPE_PUT, requestURI, postData);
        }
            public String invokeUpdate(String requestURI, Object postData) {
            return invokeRestService(RestServiceAdapter.REQUEST_TYPE_POST, requestURI, postData);
        }
        
        public String invokeDelete(String requestURI) {
            return invokeRestService(RestServiceAdapter.REQUEST_TYPE_DELETE, requestURI, null);
        } 
        public String invokeFind(String requestURI, Object postData) {
            return invokeRestService(RestServiceAdapter.REQUEST_TYPE_GET, requestURI, postData);
        }    
        private String invokeRestService(String requestType, String requestURI, Object postData) {      
     RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();
     restServiceAdapter.clearRequestProperties();
     restServiceAdapter.setConnectionName(connectionName);
     restServiceAdapter.setRequestType(requestType);
     restServiceAdapter.setRetryLimit(0);
     restServiceAdapter.setRequestURI(requestURI);
            restServiceAdapter.addRequestProperty("Content-Type", "application/json");
     restServiceAdapter.addRequestProperty("Accept", "application/json; charset=UTF-8");
            
            String response = "";
            String postDataStr = "";
                try {
                if (postData != null) {
     JSONObject jsonObj = (JSONObject) JSONBeanSerializationHelper.toJSON(postData);
     removeNullsAndTypeFromJSON(jsonObj);
     postDataStr = jsonObj.toString();
     }            
     response = restServiceAdapter.send(postDataStr);
                } catch (AdfInvocationException ex) {
                if (AdfInvocationException.CATEGORY_WEBSERVICE.compareTo(ex.getErrorCategory()) == 0) {
     throw new RuntimeException("Error with the server. Please try later.");
                }
            } catch (Exception e) {
     throw new AdfException(e.getLocalizedMessage(), AdfException.ERROR);
            }
            return response;
        }
        private void removeNullsAndTypeFromJSON(JSONObject jsonObj) throws JSONException {
     jsonObj.remove(".type");
            for (int i = 0; i < jsonObj.length(); i++) {
     String key = jsonObj.names().getString(i);
                if (JSONBeanSerializationHelper.isObjectNull(jsonObj.get(key))) {
     jsonObj.remove(key);
     i--;
                }
            }
        }
    }
    
    
    
    
    
    
    
    
    
    

     

    • Create EmployeesPojoDC

     

    private final String connectionName = "RESTWebServiceConn";
        private static final String requestURI = "/employees";
        private RestServiceUtil restServiceUtil = new RestServiceUtil(connectionName);
        private Employee employee;
        private List employees = new ArrayList();
        public EmployeesPojoDC() {
            super();
        }
        public static String GetSearchByIdURI(Integer sid){ 
            return requestURI+"/search/"+sid;}
            public void setEmployee(Employee employee) {
     this.employee = employee;
        }
        public Employee getEmployee() {
            return employee;
        }
        public Employee[] getEmployees() {
            return (Employee[]) employees.toArray(new Employee[employees.size()]);
        }
        public void initEmployeeToAdd() {
            employee = new Employee();
        }
        
        public void initEmployeeToEdit(Employee employee) throws CloneNotSupportedException {
     this.employee = (Employee) employee.clone();
        }
      public void getById(Integer id) {
            String uri = null;
            String response = null;
     Employees employees = null;
            int i=0;
     this.employees.clear()    
            try {
     uri=GetSearchByIdURI(id);
     response = restServiceUtil.invokeFind(uri,null);
     employees = (Employees) JSONBeanSerializationHelper.fromJSON(Employees.class, response);
     this.employees.addAll(employees.getEmployeesAsList());
                i=1;        
            } catch (Exception e) {
     e.printStackTrace();
     throw new AdfException(e.getLocalizedMessage()+uri+"||"+response+"--"+employees+"i="+i+"EMP LIST=="+this.employees, AdfException.ERROR);          
            }
        }    
        public void findAll() {
     this.employees.clear(); 
            try {
     String response = restServiceUtil.invokeFind(requestURI, null);
     Employees employees = (Employees) JSONBeanSerializationHelper.fromJSON(Employees.class, response); this.employees.addAll(employees.getEmployeesAsList());
    
            } catch (Exception e) {
     throw new AdfException(e.getLocalizedMessage()+"employees=="+employees, AdfException.ERROR);
            }
        }    
        public void update(Employee employee) {
     restServiceUtil.invokeUpdate(requestURI, employee);
        }
        
        public void create(Employee employee) {
     restServiceUtil.invokeCreate(requestURI, employee);
        }
        public void delete(Employee employee) {
     restServiceUtil.invokeDelete(requestURI + "/" + employee.getEmployeeId());
        }
    
    
    
    
    
    
    
    
    
    

     

    • Create Data Control from the EmployeesPojoDC.java  class

    0012FusionApp.jpg

     

    • Open the EmployeesTF.xml file. Go to the Data Controls panel and expand EmployeesPojoDC. Drag the findAll, initEmployeeToAdd and initEmployeeToEdit operations and drop inside the EmployeesTF. In the Edit Action Binding dialog, set the value of employee to #{pageFlowScope.employeeSelected}.
    • Drag four Views , method calls and  Router  inside EmployeesTF as shown in figure below . Connect them using the Control Flow Case component.

     

    0025FusionApp.jpg


    • Double-click all View components and click OK to create the AMX Pages.

    • Click in the Router component and configure it as shown in the image below:

    0014FusionApp.jpg


    • Open the empList page. Go to the Data Control panel, drag the employees collection and drop inside page as MAF List View.

    • Go to Bindings and edit the employees binding.  Add lastName and firstName as Display Attributes.

    0015FusionApp.jpg


    • Open the empDetail page. Go to the Data Control panel, drag the employees collection and drop inside page as MAF Read-only Form.

    • Go to the Data Control panel, drag the Delete operation and drop inside the secondary facet as MAF Button. In the Edit Action Binding, set the value of employee to #{bindings.employeesIterator.currentRow.dataProvider}.


    0016FusionApp.jpg

    • Open the empEdit page. Go to the Data Control panel, drag the employee Structured Attribute and drop inside page as MAF Form.
    • Go to the Data Control panel, drag the create and update operations and drop as MAF Button. In the Edit Action Binding, set the value of employee to #{bindings.employeeIterator.currentRow.dataProvider}.

    • Open search.amx page, drag getById(Integer) as form, and add a search button to pass the enter value.

    0017FusionApp.jpg0018FusionApp.jpg


    • Deploy the application and test.


    List of employees


    0019FusionApp.jpg

     

    Employee Detail Page with Delete and Edit  and Edit Screen


      0020FusionApp.jpg      0021FusionApp.jpg

     

    Search Screen  and Search result screen


    0022FusionApp.jpg0023FusionApp.jpg




    About the Author

     

    Namit Kakkar is a Principal Consultant in Oracle Consulting Services-Global Service Delivery, where his focus is on ADF, Webcenter, and Oracle mobility solution.