Friday, September 12, 2014

Oracle MAF : Creating Select One Choice from a webservice (REST with JSON output)

This post is to show how we can create a select one choice from a REST service with JSON output.
This example is using RESTServicesAdapter. Using that programmatically you can call a REST service and you can manipulate response as per need.

STEP 1: Create a REST Connection
---------------------------------------------
Right Click Connections, select New and then Select REST Connection


My REST Service Details:
URL:  https://host.com/WS/WSTest.asmx/GetNationalities
JSON Output :
[{"LOOKUP_CODE":"Afghanistan","DESCRIPTION":"Afghanistan"},{"LOOKUP_CODE":"Albania","DESCRIPTION":"Albania"},{"LOOKUP_CODE":"Algeria","DESCRIPTION":"Algeria"},
{"LOOKUP_CODE":"American Samoa","DESCRIPTION":"American Samoa"},{"LOOKUP_CODE":"Andorra","DESCRIPTION":"Andorra"}]

Now in the New REST Connection we have to provide Name and URL End Point.

The END Point which we have given contains the basic url and doesn`t contain the REST operation name, so that all the REST operations under it can be used with the same REST Connection.



STEP 2: Create a Lookup class
---------------------------------------
Create a java bean for Lookup which denotes each value in a select one choice, generate setters/getters for code and description. It is created in View Controller Project -> Application Sources.
public class Lookup {
    private String code;
    private String description;
    public Lookup() {
        super();
    }
}


STEP 3:
-------------
Create one more Java Bean which represents your form. For an example I am developing a Create Employee Page, so I will create an Employee Class which contains Nationality attribute as well as other important attributes of Employee. Generate setters and getters of attributes. It is created in View Controller Project -> Application Sources.
public class Employee{
    private String name;
    private String nationality;
    public Employee() {
        super();
    }
}

STEP 4: Creating a Java Bean Data Control
-------------------------------------------------------
Create a Java Class say EmployeeService.

Add an Employee reference and create an Employee object in default constructor.

Add a list in which we will be adding nationality one by one as a Lookup. Create an ArrayList for it in the constructor.

Create a method getNationalities which returns Lookup[]. This will be used to populate select one choice

Now create another method(setNationalitiesFromWS) which will get data by calling REST service and add the data in the list. We need to call this method in the constructor so that it is called only once.

public class EmployeeService{
    private Employee emp;
   private static List s_nationalities = null;

   public EmployeeService() {
      if(emp == null)
         emp = new Employee();
        if (s_nationalities == null) {
            s_nationalities = new ArrayList();
   }

    public Lookup[] getNationalities() {
        Lookup e[] = null;
        e = (Lookup[]) s_nationalities.toArray(new Lookup[s_nationalities.size()]);
        return e;
    }

    private void retrieveLookupValuesFromWS() {
        s_nationalities.clear();
     
   }

    private void setNationalitiesFromWS() {

        RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

        // Clear any previously set request properties, if any
        restServiceAdapter.clearRequestProperties();

        // Set the connection name
        restServiceAdapter.setConnectionName("ePass");

        // Specify the type of request
        restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);

        // Specify the number of retries
        restServiceAdapter.setRetryLimit(0);

        // Set the URI which is defined after the endpoint in the connections.xml.
        // The request is the endpoint + the URI being set
        restServiceAdapter.setRequestURI("/GetNationalities");

// This is if your webservice has BASIC authentication
        String theUsername = "username";
        String thePassword = "password";
        String userPassword = theUsername + ":" + thePassword;
        String encoding = new sun.misc.BASE64Encoder().encode(userPassword.getBytes());
        restServiceAdapter.addRequestProperty("Authorization", "Basic " + encoding);

        // Execute SEND and RECEIVE operation
        try {
            // For GET request, there is no payload
            String response = restServiceAdapter.send("");
            JSONArray res = null;
                res = new JSONArray(response);

   //This method will parse json array and create a list containing lookup objects
            s_nationalities = transformObject(res);
        } catch (Exception e) {
            e.printStackTrace();
            //handle exception
        }
    }

     //This method will parse json array and create a list containing lookup objects
     public static ArrayList transformObject(JSONArray resultList) {
        ArrayList response = new ArrayList();
       int size = resultList.length();
        for (int i = 0; i < size; i++) {
            try {
                Lookup lookup = new Lookup();
                JSONObject result = resultList.getJSONObject(i);

                String lookupCode = (String) result.get("LOOKUP_CODE");
                String description = (String) result.get("DESCRIPTION");
                lookup.setCode(lookupCode);
                lookup.setValue(description);

                response.add(lookup);
            } catch (JSONException e) {
                e.printStackTrace();
// handle exception
            }
        }

        return response;
    }
}


Right click your EmployeeService java class and Create Data Control.


STEP 5: Using Data Control in amx page
-----------------------------------------------------
Go to page definition of your amx.
In executables add an accessor iterator, select nationalities from your DC
Now one by one drag and drop name and nationality from "emp" of your DC from your Data Controls on to the page to create a form.
Use select one choice when dropping nationality.
In the wizard set the following parameters:
List Data Source: nationalities
List Attribute in DataMapping: code(this value will be saved in your emp object`s nationality attribute)
Display Attribute: description(this will be displayed in select one choice)

Run the page and you can test your select one choice.

MAF BUG : There is an existing issue in select one choice where a blank value is not shown. And when the value is blank then by default the first value in select one choice is shown in the field. But the underlying attribute still contains null and you need to click on select one choice and select a value to set the value in underlying attribute(ie emp`s nationality attribute)

Hope this is helpful.


Regards,
Deepak

9 comments:

  1. Dear, could this be done by SOAP web service? , actully I'm searching how to write a SOAP web service that's return an array of objects, and how can I deal with it in MAF, your help is highly appreciated :)

    ReplyDelete
  2. Yeah you can do it by creating a webservice data control.

    ReplyDelete
  3. Dear
    I tried your approach and the application didn't leave oracle logo at start up although I developed another application and they was running fine, so it's not an environment issue, do you have any Idea ??
    Thanks in advance

    ReplyDelete
  4. Check if the below helps:
    Open http://deepak-adf.blogspot.ae/2014/08/adf-mobile-issues-tips-and-tricks.html
    and then check
    3. ( MAF Application Hangs / Stuck at Splash screen showing Oracle logo )

    Regards,
    Deepak

    ReplyDelete
  5. It`s better if you start posting your questions at Oracle MAF Forum:
    https://community.oracle.com/community/oracle-mobile/oraclemaf

    ReplyDelete
  6. hello,
    where did you get this method from?

    lookup.setValue(description);

    Would it be lookup.setDescription(description);

    Thanks!

    ReplyDelete
  7. Thanks. Yeah it should be setDescription. In my actual implementation I had value also in lookup class and hence the abkve code had that.

    ReplyDelete
  8. Hi Deepak

    I did the same way as mentioned above but in MAF page, my list is empty. I am not able to understand how the list will be populated as I don't see the method setNationalitiesFromWS() getting called from anywhere withing the data control class. How will this method be called and used to populate the list. Maybe I am missing somehting. Can you please let me know if i am missing somehting.

    Thanks

    ReplyDelete