Part 2: Building the MAF REST infrastructure

Like all endeavors, it's important to work with a good infrastructure. A good first step with MAF applications, is to develop the client infrastructure that access remote services.

With the REST services used in this tutorial, you need to think about data objects (entities) that are required to hold the data information queried from the service, and any helper classes that make your life easier. In order to create these classes, a bit of insight is required into how MAF works and how REST-JSON services are integrated. Before you create these Java helper classes, lets look at what they are and do.

The next section of this tutorial will guide you through building an easy to use infrastructure for interacting with the HR Rest Service.

    Java helper classes
    For this tutorial you will first create five categories of Java classes listed below

    Helper class Purpose
    Data control class A JavaBean that exposes methods to query and update the remote REST service
    Data objects Java objects for the Departments and Employees resource
    JSON helper classes Java classes that represent the JSON structure (a collection of departments or employees with a single property name), as well as a class representing JSON objects for update and create operations.
    In addition you need classes that help parsing payload and responses from Java to JSON and from JSON to Java
    URI helper REST works with Uniform Resource Identifiers (URIs) to address the resources. To simplify maintenance it’s a good idea to save these URIs in a central place and reference then with meaningful names. For example, the URI to request all departments in this sample is <host>:port/jee_path/resources/hrappsrvc/departments. Though this is easy to remember, parameterized URIs may be more complex in their structure, requiring you to know about the REST service. So in this tutorial you will create a method that returns this URI via a simpler synonym.

    public static String getAllDepartmentsURI( ){};
    Utility class To simplify the calls to the MAF REST adapter, a utility class is created that wraps the so called “boilerplate code”, containing the reoccurring setup code you need to build into all calls to the REST-JSON services
Step 1: Create Java Helper Classes

In this step, create all five categories of Java helper classes. In this step, you'll mainly create the classes and in step 2 you'll add the code to implement them.

  1. To create the Departments and Employees data objects (entity).
    Select the ViewController project with the right mouse button and then select New > Java Class from the menu.

  2. Create the Departments entity and provide the following information to the dialog fields.
    Leave the remaining values at their default and click OK.

    Name DepartmentsEntity
    Package maf.code.corner.hr.mobile.entities
    Extends java.lang.Object
    alt text

  3. Create the Employees entity and provide the following information to the dialog fields.
    Leave the remaining values at their default and click OK.

    Name EmployeesEntity
    Package maf.code.corner.hr.mobile.entities
    Extends java.lang.Object
    alt text

  4. Open the DepartmentsEntity class with a double click onto the Java file.
    Add the following properties on top of the Java class right after the Java class declaration.

    private Integer departmentId = null;
    private String departmentName = null;
    private Integer locationId = null;
    private Integer managerId = null;

    Note: To save you from typing, the tutorial DOC/CODE_TXT directory has various code snippets for you to copy and paste.
    In this case, you can copy the properties above from DepartmentsEntity.txt

  5. Use the right mouse button and click into the Java class but below the class constructor and select Generate Accessors.

    alt text
  6. In the opened dialog, ensure you generate accessors for all properties in the class. Also make sure that the Scope property is set to public and that you select the Notify listeners when property changes checkbox. This latter setting ensures that your MAF is notified of any entity value changes and will therefore be able to tell the UI to refresh and show the changed value.

    alt text
  7. At the end of the file, add a clone method to easily create a physical copy of the object. We could put the method in the data control class, but putting it here is a bettter practice.
    Copy the code from the cloneDepartment.txt in to the end of the DepartmentEntity.java class.

    alt text
  8. Repeat the previous three steps (create a class, add properties, generate accessors-notify listeners) but for the EmployeesEntity class using the following properties (use the properties from the EmployeesEntity.txt in the tutorial DOC/CODE_TXT folder).
    An import statement for the java.util.Date class should automatically be added. If not, then select the Date type and press alt-key+enter –key (on Windows).

    private Double commissionPct = null;
    private String email = null;
    private Integer employeeId = null;
    private String firstName = null;
    private Date hireDate = null;
    private String jobId = null;
    private String lastName = null;
    private Integer managerId = null;
    private String phoneNumber = null;
    private Integer salary = null;

    Then, generate the accessors and save all your work.

    alt text

    Like with Departments, at the end of the file, add a clone method to easily create a physical copy of the employee object. Copy the code from the cloneEmployee.txt in to the end of the EmployeeEntity.java class.

    alt text

  9. In this tutorial, the URI helper class is specific for the shape of the REST services it uses. In the following steps, create the class and then copy and paste the content from the DeptEmpURIs.txt file in the tutorial DOC / CODE_TXT folder.

    As before, select the ViewController project with the right mouse button and select New > Java Class from the menu and in the Java class creation dialog provide the following values.

    Name DeptEmpURIs
    Package maf.code.corner.hr.mobile.uri
    Extends java.lang.Object
    alt text
  10. Replace the Java class content with the content you find in the DeptEmpURIs.txt file in the tutorial DOC/CODE_TXT folder using use your package declaration.

    Take some time and familiarize yourself with the URIs defined in the class. Notice how every method also indicates the HTTP verb it uses. Again, this helper class is a suggestion for the tutorial but may be a helpful template or valuable as a developer's guideline.

    alt text

  11. There are a number of classes found in the JSON helper category. Again, the code is provided in the tutorial DOC/CODE_TXT folder. However, it's recommended that you read and understand the provided source code rather than simply copying it. this way you'll know what you need to do when applying the same principles to your own REST-JSON projects.

    In the ViewController project, create the following Java class file following the step explained earlier and then add the code from the corresponding file in the DOC / CODE_TXT folder.

    Create a class that converts a Departments entity to a JSON string

    Name DepartmentEntityToJson
    Package maf.code.corner.hr.mobile.json.helper
    Extends java.lang.Object


    alt text
  12. Create a class that converts an Employees entity to a JSON string.

    Name EmployeesEntityToJson
    Package maf.code.corner.hr.mobile.json.helper
    Extends java.lang.Object

  13. Create a class that converts a JSON array to DepartmentsArray

    Name JsonArrayToDepartmentsArray
    Package maf.code.corner.hr.mobile.json.helper
    Extends java.lang.Object

  14. Create a class that converts a a JSON array to EmployeesArray.

    Name JsonArrayToEmployeesArray
    Package maf.code.corner.hr.mobile.json.helper
    Extends java.lang.Object

  15. Create a class that represents a JSON Departments array structure.

    Name DepartmentsResultArray
    Package maf.code.corner.hr.mobile.json.dao
    Extends java.lang.Object

  16. Create a class that represents a JSON Employees array structure.

    Name EmployeesResultArray
    Package maf.code.corner.hr.mobile.json.dao
    Extends java.lang.Object

  17. Save your work. The image below shows the classes and package structure you created.

    alt text
  18. To call REST services that have no XML payload, MAF's infrastructure provides a RestServiceAdapter class.

    Think of the RestServiceAdapter class as a Java command line browser for REST services, similar to the HTTP analyzer that you earlier used for testing the REST service. In Java you basically tell the RestServiceAdapter class which URI to call, the accepted media type (JSON in this tutorial), the http method (or verb) and the content type (the payload format in case the REST request contains arguments).

    Create a class with the following values.

    Name RestCallerUtil
    Package maf.code.corner.hr.mobile.util
    Extends java.lang.Object

  19. There is one final class you need to create to complete the client infrastructure preparation. This Java class will be exposed on the data control panel.

    Create a class with the following values.

    The class name extension "DC" doesn’t automatically turn this class into a data control, an extra step is required to do this later later. The “DC” suffix is a naming convention that helps to quickly identify those classes in a Java project hierarchy that represent data controls.

    Name DeptEmpDC
    Package maf.code.corner.hr.mobile.datacontrol
    Extends java.lang.Object

    Summary

    If you are new to MAF and have worked through the tutorial steps up to this point, you may have the impression that MAF applications need a lot of Java code.

    In MAFs defense, it is worth noting that REST-JSON services are a special case and do require more code to be written. If you were using REST-XML or SOAP most all the development is declarative. This is simply because of the (relatively) unstructured nature of JSON as a protocol

    What you have defined so far is a clean client model that you later use to declaratively build the rest of the mobile application on. Starting off with a solid foundation like this is a much better approach than building a single monolithic Java file to access the REST-JSON services. You now have a well-organized Java object structure that should look like in the image below

    alt text

Step 2: Implement the Client Infrastructure

In this next section you'll implement the Java helper classes you just created.

    Create the RestCallerUtil class

    The RestCallerUtil class wraps the MAF RestServiceAdapter adapter class to provide a simplified URL to the service requests

  1. Open the RestCallerUtil class with a double click on the file name in the JDeveloper application navigator.

  2. Open and copy the code from the RestCallerUtil.txt file. from the tutorial DOC/CODE_TXT folder, into the RestCallerUtil file. Replace all the existing code in the file except, the package declaration which needs to remain as maf.code.corner.hr.mobile.util.

    Lets look at the implementation code and how it operates.

  3. RestCallerUtil

    alt text

    The invokeRestRequest method wraps the MAF RestServiceAdapter adapter and provides a simplified API for calling the remote REST service. The arguments that you pass to the method include the
    httpMethod, (GET, POST, PUT or DELETE,) the requestURI that identifies the REST resource that the operation is performed on, and – optionally – a payload, as required for PUT and POST updates.

    First, the method attempts to obtain an instance of the MAF RestServiceAdapter and then to read the REST service connection details.


    alt text

    With the connection set, the next step is to specify the request parameters. Some of the parameters are hard coded as they are not expected to change in this sample application. For example, the REST response format is JSON and will not change.

    The settings that change their value are those passed to the method as input arguments.


    alt text

    With this, the REST service call is all set and can be executed, which is done in the code line below.

    alt text

    JSON payloads are in string format and thus the response that is returned from the REST call (if any) is of type java.lang.String.

    Note that REST-JSON is pretty flexible and many developers use the response to also send error codes instead of using HTTP error codes. If this is the case then the response structure will reflect this, which is something to keep in mind when parsing the response into data objects.

    Here's the JSON payload for the REST service used in the tutorial.


    alt text


    A similar payload is returned for employees.

    alt text

    One of the public methods, invokeRead(…) is defined in the utility class and is the API that works with your MAF application. This method further simplifies the REST access in that it makes assumptions based of the request type. For example, GET requests in REST don’t have a payload and therefore the method doesn’t expose this on the public facing API.

    Internally, before calling the private invokeRestRequest method, it sets all the required argument values such as GET for a get request and the payload to null.

    In our case, there are three other public APIs – one for each HTTP method.


    alt text

    Note: The custom REST caller utility class simplifies later application development in that it wraps the complex call to the REST service with a simplistic API. An abstraction like this will pay back very quickly, when working in teams.

    Implement the DeptEmpURI class

    The DeptEmpURI class is a helper class that wraps all REST URI for this tutorial, exposing them as descriptive methods. The benefits of a class like this include:
    • All the URIs are registered in a central place
    • Development teams building MAF applications based on your REST access don’t need to understand the actual composition of your REST URIs
    • You have a place to document your REST Service APIs


  4. In an earlier step, you copied the code from the text file. Now lets look at the implementation code and how it operates.

  5. DeptEmpURI

    The REST-JSON service in this tutorial has a single root resource “hrappsrvc” from where it diverts into two sub-resources for departments and employees. These two URIs are registered as


    alt text

    The methods in this class use the information above to compose parts of the REST URI. Note that the complete REST URL requires the hostname, port, Java EE path and name of the root resource. This information however is registered as the REST connection so that it can be accessed when you actually do the REST call. We won't discuss all of the exposed methods in this class but want to give an example for why such a class makes sense.

    alt text

    Remember that REST is about dynamic URLs, which means that the resource and the action a client invokes on the service are encoded in the URL.
    For the service in this tutorial this means that when you queries all departments, you may want to drill down into seeing the employees in a specific department. The URI for this has the form of

    host:port(javaEE_path/htappsrvc/departments/<deptId>/employees

    You can see how wrapping this URL into a public method allows you to create a generic function that you can provide department ID as the parameter to.



    Implement the JSON data access objects

    For a MAF application to be able to parse JSON string responses into Java objects, JavaBean classes that “mimic” the structure of the JSON response string in their bean properties are required.

  6. In JDeveloper, open the DepartmentsResultArray.java file and place the cursor in a row below the class declaration (but before the constructor) and type

  7. private DepartmentsEntity[] departments = null;

  8. Press alt + enter-key (on Windows) or alt + alt text + i (on OS/X) to import the DepartmentsEntity class.

  9. Place the cursor in a row below the public constructor and press the right mouse button. Then, select Generate Accessors from the menu.

  10. Select the departments property checkbox (after which the set/get methods checkboxes are automatically selected). Ensure the Notify listeners when property changes option is deselected as show in the image below.

    alt text

    The EmployeesResultArray.java class has the same functionality, except using employees.

  11. Open and look at how the DepartmentsResultArray implementation code operates.

  12. DepartmentsResultArray

    For MAF to parse JSON strings into Java objects, you need to have Java classes available that have the JSON response structure built into their properties along with the required setter/getter methods. For the departments collection in this tutorial, the JSON response looks as shown below:

    alt text

    To parse the JSON returned list of department into a Java object, the DepartmentsResult class has a property departments of type DepartmentEntity[] defined. The DepartmentEntity object represents a single department object and has pair of getter and setter methods defined for each attribute.

    Note: If the JSON response contained additional information beyond the pure data result structure, for example error codes or URL references to other REST resources, then this information also needs to be modeled in the DepartmentsResult structure as well if the information should become available in MAF.

    alt text

    For this tutorial, the response string is “flat” meaning that only a single collection with data objects is returned. Therefore a single property of type DepartmentEntity[] is sufficient.

    Note: If at this time you are a little lost, don’t worry. Things will become clearer when you start putting these classes into context. Creating infrastructure classes is like creating hand-woven carpets. It takes some time before individual stitches show as a beautiful pattern.

  13. Repeat the previous steps for the EmployeesResultArray.java class. This time in the code, type:

  14. private EmployeeEntity[] employees = null;


    Make sure to generate the employee accessors and save all your work

    Implement JSON helper classes

    There are two specific types of helper classes required:
    1: A class that translates objects into JSON strings for POST and PUT method calls to create or insert data
    2: A class that translates the JSON array response into a entity array that MAF can work with

    1: Translating objects into JSON strings

    JSON is a string notation, which means that any object that you want to encode in JSON needs to be “translated” into a string representation. This tutorial has departments and employees, as well as their collections represented as Java objects.

    The server side object-“translation” to JSON is handled with JAX-B, which is not available on the MAF client. Here we need to find a custom solution, which for the purposes of this tutorial is deliberately simple and uses the helper classes you are now going to implement.

  15. In JDeveloper, open the DepartmentEntityToJson.java file

  16. On the file system, find and open the DepartmentEntityToJson.txt file in the tutorial’s DOC / CODE_TXT directory.

  17. Copy the content of the text file into your Java class, replacing the existing content except the package declaration.

    DepartmentEntityToJson

    The DepartmentEntityToJson class translates department objects into JSON strings. The department JSON string, which you can analyze using the HTTP analyzer in Oracle JDeveloper, has the following format


    alt text

    Taking the department object as an input argument, the getJson method in this class produces a JSON string translation as shown below

    alt text

    Note: You don’t necessarily need to save this code in a separate helper class. A separate helper class is chosen in this tutorial to make the individual steps more obvious.

  18. Repeat the previous steps for the EmployeesEntityToJson.java class, which has its implementation code in EmployeesEntityToJson.txt within the tutorial DOC / CODE_TXT folder.

    Note: JDeveloper flags code lines that need additional imports with a red underline. To import the classes, press alt + enter-key (or equivalent). When in doubt about which class to import from a list of classes with the same name, choose the class that is in the “oracle.adfmf” package.

    2: Translating JSON string arrays to entity arrays
    Earlier you created the DepartmentsResultArray and EmployeesResultArray classes to hold the JSON result objects returned from a REST query. Now its time to provide the implementation code to the two classes.

  19. In JDeveloper, open the JsonArrayToDepartmentsArray.java file

  20. On the file system, find and open the JsonArrayToDepartmentsArray.txt file in the tutorial’s DOC / CODE_TXT directory.

  21. Copy the content of the text file into your Java class, replacing the existing content except the package declaration

  22. Repeat the process using the JsonArrayToEmployeesArray.java and text file.

  23. Examine the JsonArray files.

  24. With all the copy & paste happening don’t forget to look at the code you've been reusing and think about how you might apply something similar in your own custom project. Here is a method from the JsonArrayToEmployeeArray class which accepts a JSON string argument to return an array of employees.

    The EmployeesResultArray class you created earlier receives the REST-JSON response from the web service.

    alt text

    The JSONBeanSerializationHelper object is a MAF framework class that serializes JSON structures into Java objects, the EmployeesResultArray and DepartmentsResultArray classes in this tutorial. As a reminder, the two classes “mimic” the JSON object and collection structure of the REST response.

    alt text

    The next lines then serializes the JSON string into the EmployeesResultArray object.

    alt text

    The remaining code lines catch any exceptions to report into the log files. If things go well then the employees array is returned to the caller.

    alt text

    Summary

    So far you've invested a fair bit of time preparing the client model. As we mentioned before, getting this right will save you time and effort later.

    You focused on creating helper classes that wrap the processes involved in querying a REST-JSON web service from MAF. The classes are individual for the REST-JSON service provided with the tutorial but the concepts are transferable to your own projects.

    For many custom mobile application projects, the person building the client model also is the developer building the mobile UI for it. However, from a code organization point of view there is an interesting alternative provided in MAF. MAF allows developers to build new mobile applications based on application archive files, the Mobile Application Archive (MAA) files.

    MAA files allow developers to create a common model for the services they need to access and then deploy these in a MAA archives for other developers to extend to build mobile applications from. A limitation to be aware of here is that an application can be only extended from a single MAA file and that the Java resources inside of the archive are of course compiled so they cannot be edited at design time, although, they can of course be extended in standard Java fashion.

    As an additional exercise, step back from the infrastructure work that you have carried out so far and think about how you would propose development guidelines for building reusable mobile client models. Take a piece of paper and draw out a picture for how you think the code should be arranged and what you think could be in a reusable MAA file. Imagine that is a proposal for the organization of a large mobile application project.

Step 3: Implement DeptEmpDC DataControl class

There is only one class that you haven't touched yet, the DeptEmpDC.java class. This is the JavaBean that you'll expose as the data control. Data controls in MAF expose the service data model to the mobile client developer. The functionalities that the data control needs to expose for this tutorial are:

- Query all departments
- Query employees for a department
- Create a new employee for a department
- Update an employee
- Remove an employee

Note: This tutorial does implement any data caching and instead directs all UI-data queries to the remote REST service. Caching is recommended for all real-world mobile application projects and can be implemented on the data control level using Java objects for temporary in-memory caching or SQLite for offline-caching.

    Implement the data control class
  1. In JDeveloper, open DeptEmpDC.java in the source code editor.

  2. On the file system, open DeptEmpDC.txt located in the tutorial’s DOC/CODE_TEXT folder and copy the content into the DeptEmpDC.java file replacing the existing content except for the package name.

  3. Wait for any file imports to complete.

  4. Find the public DepartmentsEntity[] getAllDepartments() method, which is the only method that is not yet implemented in this class. We'll use the implementation of this method to show the benefit of all of your careful preparation. The txt file contains this code, so read along to understand how the code work.

  5. In a line above the return statement there is a if condition that checks for (allDepartments == null){ … }. Though in this tutorial we don’t cover caching strategies, the DeptEmpDC uses in memory caching for departments data queried from the REST service. The department data is read-only in this tutorial.

  6. In this if-condition you are going to query the REST service for all departments data. The first line of code you need is to obtain the REST URI for the departments query.

    THis line of code performs this function:

  7. String restURI = DeptEmpURIs.GetAllDepartmentsURI();

    Note: the helper class returns “/departments” as a string, which is simple and you could have typed it directly in. However, have a look at some of the more complex methods (for example createEmployee(…) )and you will see why it is a good idea to create these wrapper classes as helpers.

  8. The next thing to do is to query the REST service, again there is a helper to assist you.
    These two lines of code invoke the remote REST service and return a list of departments as a JSON array string.

    The next two lines of code accomplish this..

  9. RestCallerUtil rcu = new RestCallerUtil();
    String jsonArrayAsString = rcu.invokeREAD(restURI);

  10. The last step to complete the method is to convert the JSON string into an array of employee entities.

  11. DepartmentsEntity[] departments = JsonArrayToDepartmentsArray.getDepartmentsArray(jsonArrayAsString);
    allDepartments = departments;

  12. Compare your allDepartments() method with the one shown below. It should look identical

    alt text

  13. Spend some time studying the implementations of the createEmployee, updateEmployee and removeEmployee methods that also use these infrastructure classes to keep the actual lines of code in the data control methods to a minimum.

  14. The DeptEmpDC class is the POJO object that exposes the REST service functionality to MAF as a data control. The class contains the following methods

    alt text

    To display the the allDepartments query as a collection in the MAF data control, a setter and getter method is needed for the allDepartments property, which is of type DepartmentsEntity[]. The setter is required and therefore left empty, all we need is the get-method to read data from the REST service.

    alt text

    Just like the allDepartments attribute, the allEmployees attribute is exposed by a setter and getter pair so it shows as a collection in the MAF data control. In the implementation, the getAllEmployees method always returns a list of employees for the current selected department. This information has to be supplied by the mobile application, invoking the prepareEmployeesForDepartment method.

    The reason why the allEmployees information is exposed as a collection instead of a result set returned by a method invocation is to enable provider change events to be fired to instantly refresh employee data displayed on a page (which makes sense if the departments data and the employee data are displayed on the same page – for example in a tablet design).

    alt text

    This method queries employees for a specific department from the remote REST service and saves the result set in the allEmployees property. You can refer to this kind of master-detail as “deferred master-detail” as the detail rows are not queried embedded in the parent data object but on demand when the parent object is selected.

    alt text

    Both methods pass a JSON object to the remote service to either create a new employee or update an existing. The HTTP methods associated with these calls are PUT and POST

    alt text

    Calls a REST service URI to remove a resource. The HTTP method associated with this call is DELETE

    alt text

    The setEditableEmployees method creates a copy of the object passed for edit. Without copying the employee data we would work on a object reference of the existing object, which makes it difficult to undo the user edits.

    These two methods are helper methods that implement a MAF pattern to support form-cancel. In mobile applications, any change added in an input text field is immediately saved in the underlying data object. To cancel a data change actually requires resetting the data object using a copy of the original data. Alternatively the edit could be performed on a separate collection so that only when the user presses submit at the end, the data changes are persisted in the collection.

    The latter approach is what these two methods support. When navigating to the edit form, then instead of editing the allEmployees collection, users edit the editableEmployee collection. To cancel the edit, all that a user needs to do is to navigate away from the edit form page.

  15. Save all your work.

  16. Create Data Controls
  17. Remember, a particular class is not automatically a data control, it has to be configured to be so. This process of configuration is referred to as the “create data control” process. For this tutorial you will configure the DeptEmpDC class as a POJO data control.

    In the Applications window, select the DeptEmpDC file and press the right mouse button.

  18. From the menu, select Create Data Control to generate a MAF data control.

    alt text
  19. Click Next to accept the default name and bean class name, then Finish to complete the data control creation process.

  20. In JDeveloper, open the Data Controls panel. You may see nothing, depending what you've been doing previously in the IDE. To update the panel and view the data control that you have just created click the refresh button (the icon with the two blue arrows).

    Expand the DeptEmpDC node and the panel should now look like this. Here are the APIs that will be available to the UI developer.

    alt text
  21. Save all your work.

 


Bookmark Print Expand all | Hide all
Back to top
Copyright © 2014, Oracle and/or its affiliates. All rights reserved.