SAP UI5 Presentation for SUP Hybrid Application – Part 3 – JSON Data

Continuing the series (previous article link) of using SAP UI5 with SUP 2.x (Sybase/SAP Unwired Platform), this covers transforming the SUP native data stream from iMO to JSON expected by the SAPUI5 controls.
This shows the clear and straightforward – but not efficient approach.  Needless to say the production system does it in one step, but it is complicated.

The code for the override to hwc.processDataMessage(), with all the extra bits removed.

hwc.processDataMessage = function processDataMessage(
     incomingDataMessage     // incoming XML data message
){
[1]  workflowMessage = new WorkflowMessage(incomingDataMessage);
[2]
[3]  var jsonObject = hwc.createJsonFromDataMessage(
               workflowMessage.getValues() );
[4]  oModel.setData(jsonObject);
};

Line [1] creates the global variable workflowMessage which is a binary representation of the incoming XML data message.  This is the legacy SUP central data store for the HWC application.
The function in line [3] goes through the values in the workflowMessage and builds a JSON string, here called jsonObject – but it’s really just the string representing the incoming data in a JSON friendly format as one long string.  The routine ‘createJsonFromWorkflowMessage()’ is simple and boring, and simpler than most data marshaling functions I’ve written.

Finally, on line [4], using the built-in support from SAPUI5, we assign this JSON representation of an artificial JSON source into a global variable named oModel.
The global variable oModel was previously created with:

oModel = new sap.ui.model.json.JSONModel();
sap.ui.getCore().setModel(oModel);

A couple things to note on this implementation:

  • Remember I said it was inefficient – so don’t use for production.
  • The workflowMessage variable has a lifetime outside this function.  That is because we need the original data-set in any outbound (reply) messages.
  • I am assigning the oModel into the global default model out of convenience (and some would say laziness).  This model is used to create a binding context which is then assigned to the screen when we navigate to it.

Classically – the return path, to send data back to the server is in our override to the SUP standard hwc.getMessageValueCollectionForOnlineRequest(screenKey, requestAction, keys, …) .

This uses the two global variables – workflowMessage and oModel.  What we need to do is take the updated values form the oModel (which is tied to the binding context of the SAPUI5 controls), merge the data back into the binarySUP workflowMessage then send that back to the SUP server.  This shows the basics of the process, with error handling and extra trappings removed.

hwc.getMessageValueCollectionForOnlineRequest = 
function getMessageValueCollectionForOnlineRequest(
    screenKey, requestAction, 
    keys, keyTypes, context) {

 var dataMessageToSend = new WorkflowMessage("");

 var mvc = workflowMessage.getValues();
 dataMessageToSend.setHeader(workflowMessage.getHeader());
 dataMessageToSend.getValues().setKey(mvc.getKey());
 dataMessageToSend.getValues().setState(mvc.getState());

 var i;
 var value;
 var jsonValues = oModel.getData();    // **** BOUND DATA ****

 for (i = 0; i < keys.length; i++) {
     var keyValue = keys[i];
     var boundValue = jsonValues[keyValue];
     value = mvc.getData(keys[i]);
     dataMessageToSend.getValues().add(keys[i], value);
 }
 dataMessageToSend.setWorkflowScreen(screenKey);
 dataMessageToSend.setRequestAction(requestAction);

 return dataMessageToSend;
};

Note:
As a cheat – I often short-circuit things and just roll my update payload by hand and call the generated JavaScript API directly.  This is simple because the SAPUI5 data-bound controls are all available as simple controls.  These controls are available in my context when the user presses ‘submit’, so it’s pretty simple.
This ends up not using the real SAPUI5 databinding for the outgoing payloads though.

SAP UI5 Presentation for SUP Hybrid Application – Part 2

Continuing the series (previous article link) of using SAP UI5 with SUP 2.x (Sybase/SAP Unwired Platform), this covers creating a JSON access layer into the MBO (Mobile Business Object) running on the SUP server.

A few points to remember about this environment:

  1. The application is still running in the SUP Hybrid Web Container (HWC).  In addition to a PhoneGap (Cordova) based runtime environment, this container provides the data transport and security to the SUP server.
  2. The SUP 2.x data transport protocol is still Sybase/SAP ‘iMO’ (iAnywhere Mobile Office – a secure proprietary protocol from the Sybase iAnywhere team).
  3. The JSON data layer presented here is purely internal to the application itself.  This serves two purposes:
    1. SAP UI5 has extensive data binding which can take advantage of standard data sources.
    2. There is the possibility that the future SAP servers will be using OData rather than iMO (unofficial speculation).  Using JSON in the rest of the application helps our application prepare for the possible future.
      This sample uses translates iMO into JSON, which is functionally equivalent to using OData in the application layer (since SAPUI5 simply views this as ‘data’).

Like before, the MBO being used in the example is Employee in the package BasicDataTests.  This MBO is simply a view onto the Employee table in the sampledb database supplied with all SUP installations.
This MBO contains the typical features along with all the capabilities of the SUP server.
After this simple MBO was created in the SUP designer, it was deployed to the server in the standard manner.

Create the Javascript Data API

Using a new feature in the 2.2 SUP design environment, we will generate a JavaScript API that can be used from any application executing within the Hybrid Web Container. This JavaScript API (described below) handles the data access from the application to the SUP server freeing the rest of the application for any 3rd party tool.

To create this JavaScript API:

  1. Open the SUP 2.2 design tool environment (the Eclipse based design tooling),
    (maybe original recipe, maybe SP02 – I’m not clear when this became public)…
  2. In the project explorer, select the top-level project – in my sample it is the BasicDataTests project within the Eclipse workspace.
    None of the editors need to be opened, just the project explorer which contains some MBOs deployed to your SUP server.
  3. Right-Mouse the project and select Generate Hybrid App API… in the context menu.
  4. Select the MBO of interest, here ‘Employee’.
  5. Press the Finish button.
  6. Examine the files generated, in this version they are in the folder:
    …/Generated Hybrid App/APIs.
    The JavaScript are in the js sub-folder.
    The WorkflowClient.xml configuration file in the APIs folder.

These screen shots should help:

Selecting the new
‘Generate Hybrid App’ feature in the SUP Workspace Explorer.
 WorkspaceNavigator_GenerateHybridAPI
The only page of the
‘Generate Hybrid App’ wizard we are concerned with.Note: We do not need to fill in the next screen of the wizard, ‘Server-Initiated Notification Configuration’, as we are not using that feature in these samples.
UI5_EmpGenHybridApp1
The files generated for the
JavaScript API which we will use in our application.
UI5_EmpNewFilesAfterGenerateHybridApp

Generated JavasSript Data API Details

After generating the JavaScript API for this MBO, the generated functions for the MBO object queries of interest are all in the file HybridApp.js.
The JavaScript APIs of interest are:

function employee_findAll(employeeObj, credInfo, errorCallback)
Return a list of all employee records.
Action: Employee_findAll
Object query: ‘findAll’ within MBO ‘Employee’
function employee_findByPrimaryKey(employeeObj, credInfo, errorCallback)
Return a single employee record after doing a lookup based on the primary key, the employee ID field.
Action: Employee_findByPrimaryKey
Object query: ‘findByPrimaryKey’ within MBO ‘Employee’
function employee_delete_onlineRequest(employeeObj, oldEmployeeObj, credInfo, errorCallback)
Delete the specified (single) employee record.
Action: Employee_delete
Object operation: ‘delete’ within MBO ‘Employee’
function employee_update_onlineRequest(employeeObj, oldEmployeeObj, credInfo, errorCallback)
Update the specified employee record.
Action: Employee_update
Object operation: ‘update’ within MBO ‘Employee’
function employee_create_onlineRequest(employeeObj, credInfo, errorCallback)
Create an employee record based on the object pased in.
Action: Employee_create
Object operation: ‘create’ within MBO ‘Employee’
function employee_findByLastName(employeeObj, credInfo, errorCallback)
Return a list of employee records by searching for a string fragment in the last name field.
This object query is not used in this sample.
Action: Employee_findByLastName
Object query: ‘findByLastName’ within MBO ‘Employee’

Note: In a typical Hybrid Application generated through the designer; this file, HybridApp.js, also provides the interface from application menu items (and actions) to the specific MBO online requests.

Note: The phrase ‘Action’ here relates to the naming in WorkflowClient.xml which is the string used when the call is made to the online request in the JavaScript APIs in HybridApp.js.

One important point to remember here is that the data we are retrieving and sending to the server is still the SUP ‘iMO’ format.  On top of that, the functions in the API described above are purely JavaScript APIs, not OData or JSON sources.

The next article will show an early hack to translate the data payload from the API call here into an in-memory JSON data source.  This in-memory source will be used for data binding for both incoming and outgoing communications with the SUP server.