5Performing AIS Form Service Calls
Understanding JD Edwards EnterpriseOne Mobile Framework APIs
The JD Edwards EnterpriseOne Mobile Framework APIs provide Java classes and methods that enable users to call REST services on the AIS Server. There are APIs that handle login authentication and authorization with the AIS Server, APIs for form service requests and media objects, as well as APIs for retrieving processing option values.
The JD Edwards EnterpriseOne Mobile Framework APIs have a dependency on Oracle MAF. They do not function outside of an Oracle MAF environment.
See the Prerequisites section in this guide for information on how to obtain the APIs. A description of the APIs is available in the JD Edwards EnterpriseOne Mobile Framework Java API Reference Javadoc located at:
http://docs.oracle.com/cd/E53430_01/EOTMP/index.html
With EnterpriseOne Tools release 9.2.1.2, the JD Edwards EnterpriseOne Mobile Framework Java API Reference was updated with classes that enable mobile applications to request EnterpriseOne Watchlist data.
Understanding AIS Server Capabilities
The AIS Server exposes various capabilities that client applications may or may not depend on. If your mobile application requires a certain capability, you must include it in the list of required capabilities in the about.properties file.
If you indicated in the about.properties file that you have a required capability, the Login Module verifies that capability is available when the mobile application launches. If the capability is not available, the application returns an error message. If the capability is available, the application continues to the login screen.
You can access the AIS Server capabilities using the following URL:
http://<AIS Server>:<Port>/jderest/defaultconfig
You can also find a complete list of AIS Server capabilities in the "AIS Server Capabilities and Services" section in the JD Edwards EnterpriseOne Application Interface Services Server Reference Guide.
The following example shows the grid and editable capabilities listed in the about.properties:

Understanding Form Service Requests
This section contains the following topics:
Overview
AIS Server calls that retrieve data from forms in the EnterpriseOne web client are referred to as form service requests. Mobile applications use form service requests to interact with EnterpriseOne web client forms. Form service requests, formatted as REST service calls that use POST, contain form service events or commands that invoke actions on an EnterpriseOne form.
A form service request enables you to perform various operations on a single form. By sending an ordered list of commands, a form service request can replicate the actions taken by an EnterpriseOne web client user, including populating fields, pressing buttons, and other actions.
To send a form service request to the AIS Server, send a POST to the following URL and send JSON in the body:
http://<AIS Server>:<Port>/formservice
If testing with a REST testing tool, you can send JSON directly. If using the JDE Mobile Helpers in a mobile application, you need to specify only the URI when calling the jdeRestServiceCall. The URI is "formservice" and you can use the static variable, for example:
JDERestServiceProvider.FORM_SERVICE_URI
Events Used in a Form Service Request
The following table lists the events that you can include in a form service request and describes the action that each event performs.
Event |
Description |
Parameters (and example values) |
---|---|---|
Set Control value |
Sets the value of a control on a form, like filter fields or any other form control. |
controlID ("25") value ("Bob" or "01/01/2015") |
Set QBE Value |
Sets the value of a QBE column. |
controlID ("1[42]" or "1_2[25]") value ("Jill" or "55") |
Set Checkbox Value |
Sets the value of a check box. |
controlID ("77") value ("on" or "off") |
Set Radio Button |
Sets the value of the radio button. |
controllID ("87") value ("87") |
Set Combo Value |
Sets the value of a combo box entry. |
contolID ("125") value (2) - Index of the entry. |
Do Action |
Presses a button or Hyper Item. |
controlID ("156") |
Select Row |
Selects the specified row in a grid. |
controlID ("1.30") - ID of the grid, dot (.), row index (zero based). |
Select All Rows* |
Select all rows in the specified grid (if multiple selection is allowed). |
controlID ("1") - ID of the grid. |
Un Select All Rows* |
Deselects all rows in the specified grid (if multiple selection is allowed). |
controlID ("1") - ID of the grid. |
Un Select Row* |
Deselects the specified row in a grid. |
controlID ("1.30") - ID of the grid, dot (.), row index (zero based). |
Click Grid Cell** |
Clicks the hyperlink in a grid cell if the cell is enabled as a link. |
controlID ("1.5.22") - ID of the grid, dot (.), row index, dot (.), grid column ID. |
*These events are available only with the selectAllGridRows capability. The JDEMobileFramework API requires these events to be in a try block because they throw a Capability Exception.
**This event is available only with the gridCellClick capability.
Using the Form Service Request Event in FDA
The Form Service Request event is available within FDA for each form. This event occurs after the Post Dialog Initialized event, but before any of the form actions requested in the form service call execute. This event enables you to perform some operations, or business logic, when you know the form that is being called from a form service request.
This event also provides access to the requested form service actions, referred to as CRUD (Create, Read, Update, or Delete) actions, by using the "Get Form Service Request Action" system function. This enables you to create additional logic based on the value sent in the form service request.
Using the Form Service Request event in FDA should be secondary to using events (actions) provided in the Form Service Request from the mobile application. Oracle recommends that you only use the FDA event if you cannot accomplish a desired result with the form action events.
Placing Events in the Proper Order
Place the events in the form service request in the order you want them to execute, for example, populate a filter field value and then press the Find button. Remember that the FDA Form Service Request event occurs before the events you add to this list. Do not set the "Find On Entry" option when using the event model; the extra "find" is not necessary because it executes before the events you requested.
Events on Power Forms
The Form Service Request event and other events that perform actions in a form are also available on power forms so that you can populate a subform value or press a button on a subform.
Control ID Notation for Return Control IDs
You can use the Property Browser in FDA to identify control IDs for fields on each EnterpriseOne form. You can also find control IDs using the Item Help option in the form in the EnterpriseOne web client. In the EnterpriseOne web client form, click the Help button (question mark in the upper right corner of a form) and then click the Item Help option to access field-level help. With the field level help activated, you can click in a field or column to access the control ID and business view information, which is displayed under the Advanced Options section.
For fields on the main form, the control ID will be a single value, such as 25.
Grids also have control IDs. For a traditional form, the grid ID is usually 1. For power forms, subforms, and reusable subforms the grid ID is typically a value other than 1.
The columns within a grid also have unique IDs and are often referenced in conjunction with the grid ID. For example column 28 and 29 in grid 1 would be 1[28,29].
Power forms have more complex IDs. The fields on the main power form are represented with single values. The fields on a subform are complex with an underscore separating them. So field 6 on subform 12 is 12_6. The ID of a re-usable subform is available when viewing the power form that the subform is used on. The IDs of individual fields, a grid, or columns on a re-usable subform is shown in FDA when viewing the subform directly; you cannot get these values when viewing the subform alias.
The returnControlIDs string is bar delimited, without a starting or ending bar.
Example - Requesting fields and grid columns on a traditional form.
formRequest.setReturnControlIDs("19|20|60|125|1[45,49,88]");
In this example, 19|20|60|125
represent field control IDs.
1[45,49,88]
represents columns in the grid.
Example - Requesting main form fields, subform fields, main form grid columns, and subform grid columns.
formRequest.setReturnControlIDs("33|34|17[24,26,28]|50_45|50_53|50_9[35,39,41]");
In this example, 33|34
represent fields on the main form.
50_45|50_53
represent fields on the subform.
17[24,26,28]
represent main form grid columns.
50_9[35,39,41]
represent subform grid columns.
Example of JSON Code in a Form Service Request
The sample code in Example - Executing EnterpriseOne Actions - JSON is an example of JSON code in a form service request that executes EnterpriseOne actions in the following order:
Open the Find/Browse form in P01012.
Enter a value in a QBE field.
Enter a value in a field control.
Select two check boxes.
Click the Find button.
Example - Executing EnterpriseOne Actions - JSON
{ "token": "044BlLYkCUcjQGRxvR3r+LH27liC6l6psFHOTp9whmkPxE=MDE4MDA2MTYxMDIwOTQ1MDU2NTc0NDY0U29hcFVJMTM4NDQ0NjU2NTUwNQ==", "version": "ZJDE0001", "formActions": [ { "command": "SetQBEValue", "value": "E", "controlID": "1[50]" }, { "command": "SetControlValue", "value": "Al*", "controlID": "58" }, { "command": "SetCheckboxValue", "value": "on", "controlID": "62" }, { "command": "SetCheckboxValue", "value": "on", "controlID": "63" }, { "command": "DoAction", "controlID": "15" } ], "deviceName": "REST Service Testing Tool", "formName": "P01012_W01012B" }
Example - Executing EnterpriseOne Actions - JSON Response
{ "fs_P01012_W01012B": { "title": "Work With Addresses", "data": { "lblSearchType_53": { "id": 53, "editable": false, "value": "Search Type", "title": "Search Type", "dataType": 2 }, "txtSearchType_54": { "id": 54, "editable": true, "value": "*", "internalValue": "null", "title": "Search Type", "assocDesc": "", "staticText": "Search Type", "dataType": 2 }, "lblAlphaName_57": { "id": 57, "editable": false, "value": "Alpha Name", "title": "Alpha Name", "dataType": 2 }, "txtAlphaName_58": { "id": 58, "editable": true, "value": "Allen*", "internalValue": "Allen*", "title": "Alpha Name", "staticText": "Alpha Name", "dataType": 2 }, "lblDL01_66": { "id": 66, "editable": false, "value": "", "title": "", "dataType": 2 }, "chkDisplayAddress_63": { "id": 63, "editable": true, "value": "on", "internalValue": "1", "title": "Display Address", "dataType": 1 }, "chkDisplayPhone_62": { "id": 62, "editable": true, "value": "on", "internalValue": "1", "title": "Display Phone", "dataType": 1 }, "gridData": { "titles": { "col_19": "Address Number", "col_20": "Alpha Name", "col_40": "Address Line 1", "col_44": "City", "col_81": "Prefix", "col_46": "Phone Number", "col_47": "Phone Type", "col_48": "Long Address", "col_49": "Industry Class", "col_50": "Sch Typ", "col_51": "Tax ID" }, "rowset": [ { "rowIndex": 0, "MOExist": false, "mnAddressNumber_19": { "id": 19, "editable": false, "value": "576", "internalValue": 576, "title": "Address Number", "dataType": 9 }, "sAlphaName_20": { "id": 20, "editable": false, "value": "Allen", "internalValue": "Allen", "title": "Alpha Name", "dataType": 2 }, "sAddressLine1_40": { "id": 40, "editable": false, "value": " ", "internalValue": " ", "title": "Address Line 1", "dataType": 2 }, "sCity_44": { "id": 44, "editable": false, "value": " ", "internalValue": " ", "title": "City", "dataType": 2 }, "sPrefix_81": { "id": 81, "editable": false, "value": "", "internalValue": "", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_46": { "id": 46, "editable": false, "value": "", "internalValue": "", "title": "Phone Number", "dataType": 2 }, "sPhoneType_47": { "id": 47, "editable": false, "value": "", "internalValue": "", "title": "Phone Type", "dataType": 2 }, "sLongAddress_48": { "id": 48, "editable": false, "value": " ", "internalValue": " ", "title": "Long Address", "dataType": 2 }, "sIndustryClass_49": { "id": 49, "editable": false, "value": " ", "internalValue": " ", "title": "Industry Class", "dataType": 2 }, "sSchTyp_50": { "id": 50, "editable": false, "value": "E", "internalValue": "E", "title": "Sch Typ", "dataType": 2 }, "sTaxID_51": { "id": 51, "editable": false, "value": " ", "internalValue": " ", "title": "Tax ID", "dataType": 2 } } ], "summary": { "records": 1, "moreRecords": false } } }, "errors": [], "warnings": [] }, "stackId": 2, "stateId": 1, "rid": "f199d7dd4210b9af", "currentApp": "P01012_W01012B_ZJDE0001", "sysErrors": [] }
Example of API Methods for a Form Service Request
Oracle provides API methods that you can use to set the commands when coding mobile applications.
Example - API Methods for Setting Commands
FormRequest formRequest = new FormRequest(); formRequest.setFormName("P01012_W01012B"); formRequest.setVersion("ZJDE0001"); //create event holder FSREvent myFSREvent = new FSREvent(); //add actions in order myFSREvent.setQBEValue("1[50]", searchType); myFSREvent.setFieldValue("58", name); myFSREvent.checkBoxChecked ("62"); myFSREvent.checkBoxChecked ("63"); myFSREvent.doControlAction("15"); //add event holder to the form request formRequest.addFSREvent(myFSREvent); // Execute SEND and RECEIVE operation try { JSONObject jsonObject = (JSONObject)JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.FORM_SERVICE_URI); P01012_W01012B_FormParent newFormParent = ((P01012_W01012B_FormParent)JSONBeanSerializationHelper.fromJSON(P01012_W01012B_FormParent.class, response)); }
Grid Action Events
In addition to interacting with fields on the form, you can interact with grids using grid action events. If you use a grid action event, you must include "grid" as a required capability in the about.properties. See Understanding AIS Server Capabilities for more information.
The types of grid action events include:
Selecting grid rows
This action enables you to delete records in the grid by sending a row select event, followed by a delete button press event, and then finally an OK button press event. This is the exact sequence that a user would follow to delete a record in an EnterpriseOne application.
Inserting grid rows
This action enables you to insert one or more rows into a grid, setting the column value for each row. This includes text entry columns, drop-down columns, or check box columns. You must include an OK button pressed event to commit the inserts.
Updating grid rows
This action enables you to update one or more existing grid rows by setting the column values for each row. This includes text entry columns, drop-down columns, or check box columns. You must include an OK button pressed event to commit the updates.
The following table describes the commands that you can use in grid column events to set values for a cell in a grid insert or update event:
Grid Column Event |
Description |
Parameters |
---|---|---|
Set Grid Cell Value |
Sets the value of a cell in a grid. |
"value": "720", "command": "SetGridCellValue", "columnID": "28" |
Set Grid Combo Value |
Sets the value of a drop-down column in a grid. The value that you send is in the "Code" for the UDC associated with the column. |
"value": "ABC" "command": "SetGridComboValue", "columnID": "43" |
Example of Grid Action Events
This section provides examples of grid action events in both JSON and Oracle MAF code.
The sample code in Example - Selecting Grid Rows - JSON is an example of JSON that deletes a phone number in the third row of a grid. It is important to note:
The row index is zero based.
You must get the row index based on a previous fetch (since rows may be hidden and the index may not be consecutive).
By sending 3 form actions, first select row 3, then selecting the Delete button, and then selecting the OK button.
The form inputs will get the correct set of phone records for address number 6001, who's who line 0.
The formServiceAction code is a U for update, so the form is in update mode.
Example - Selecting Grid Rows - JSON
{ "token": "0443HC90ZH4pq9CScdvJ+nkecflSJI9q+YGbc7lXrGZ7So=MDE5MDA2ODQ4MjcyMDk2MTUwMjg0NDkyOFNvYXBVSTEzOTIwNzE5NzY4NzE=", "formActions": [ { "command": "SelectRow", "controlID": "1.3" } , { "command": "DoAction", "controlID": "59" }, { "command": "DoAction", "controlID": "4" } ], "formInputs": [ { "value": "6001", "id": "4" }, { "value": "0", "id": "5" } ], "formServiceAction": "U", "deviceName": "RESTclient", "formName": "P0115_W0115A" }
Example - Selecting Grid Rows - JSON Response
{ "fs_P0115_W0115A": { "title": "Phone Numbers", "data": { "lblDL01_71": { "id": 71, "editable": false, "value": "Ray Allen", "title": "Ray Allen", "dataType": 2 }, "lblWhosWhoLine_52": { "id": 52, "editable": false, "value": "Who's Who Line", "title": "Who's Who Line", "dataType": 2 }, "txtAddressNumber_7": { "id": 7, "editable": false, "value": "6001", "internalValue": 6001, "title": "Address Number", "assocDesc": "Allen, Ray", "staticText": "Address Number", "dataType": 9 }, "lblDL01_54": { "id": 54, "editable": false, "value": "Allen, Ray", "title": "Allen, Ray", "dataType": 2 }, "gridData": { "titles": { "col_28": "Prefix", "col_29": "Phone Number", "col_27": "Phone Type", "col_66": "Phone Type Description", "col_26": "Line Number" }, "rowset": [ { "rowIndex": 0, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "334-4000", "internalValue": "334-4000", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "HOM", "internalValue": "HOM", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Home", "internalValue": "Home", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "1", "internalValue": 1, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 1, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "555-1212", "internalValue": "555-1212", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "CAR", "internalValue": "CAR", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Car or Mobile", "internalValue": "Car or Mobile", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "2", "internalValue": 2, "title": "Line Number", "dataType": 9 } } ], "summary": { "records": 2, "moreRecords": false } }, "lblAddressNumber_6": { "id": 6, "editable": false, "value": "Address Number", "title": "Address Number", "dataType": 9 }, "txtWhosWhoLine_32": { "id": 32, "editable": false, "value": "0", "internalValue": 0, "title": "Who's Who Line", "assocDesc": "Ray Allen", "dataType": 9a } }, "errors": [], "warnings": [] }, "stackId": 5, "stateId": 1, "rid": "c2a9c1c93a6874f0", "currentApp": "P0115_W0115A", "sysErrors": [] }
Example - Selecting Grid Rows - MAF Application Code
This sample code performs the same delete operation as the JSON request example in the preceding section; it deletes a single phone number in a grid of phone numbers.
public void deletePhone(int key) { AdfmfJavaUtilities.setELValue("#{pageFlowScope.errors}", "false"); FormRequest formRequest = new FormRequest(); formRequest.setFormName("P0115_W0115A"); formRequest.setFormServiceAction("U"); formRequest.addToFISet("4", addressNumber); formRequest.addToFISet("5", "0"); FSREvent fsrEvent = new FSREvent(); //get currently selected row P0115_W0115A_GridRow selectedRow = getSelectedPhonebyKey(key); fsrEvent.selectRow("1", selectedRow.getRowIndex()); //press Delete button fsrEvent.doControlAction("59"); //press OK button fsrEvent.doControlAction("4"); //add the FSR event to the request formRequest.addFSREvent(fsrEvent); // Execute SEND and RECEIVE operation try { // For POST request, set data payload is header delimited with | and service input class JSONObject jsonObject = (JSONObject)JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.FORM_SERVICE_URI); P0115_W0115A_FormParent tempFormParent = ((P0115_W0115A_FormParent)JSONBeanSerializationHelper.fromJSON(P0115_W0115A_FormParent.class, response)); if(tempFormParent.getFs_P0115_W0115A().getErrors() != null && tempFormParent.getFs_P0115_W0115A().getErrors().length>0){ AdfmfJavaUtilities.setELValue("#{pageFlowScope.errors}", "true"); }else{ p0115_W0115A_FormParent.getFs_P0115_W0115A().getData().getGridData().setRowsetList (tempFormParent.getFs_P0115_W0115A().getData().getGridData().retrieveRowsetList()); p0115_W0115A_FormParent.getFs_P0115_W0115A().getData().getGridData().setSummary (tempFormParent.getFs_P0115_W0115A().getData().getGridData().getSummary()); } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
Example - Insert Rows - JSON
This sample code is an example of adding two phone numbers with two form actions: a grid action that adds two rows followed by an OK button selection. The form inputs will get the correct set of phone records for address number 6001, who's who line 0. Also, it is important to note that the formServiceAction code is a U for update, which indicates that the form is in update mode.
{"token": "044bO2/lCT8FViW5A0Sm5GqcqU3P8BB2kwUv0bZzG84YYU=MDE4MDA2NTIyNTk1NjQyNTc1MjQ2MzM2U29hcFVJMTM5MjE0OTA4MjYyMA==", "formInputs": [ { "value": "6001", "id": "4" }, { "value": "0", "id": "5" } ], "formServiceAction": "U", "formActions": [ { "gridAction": { "gridID": "1", "gridRowInsertEvents": [ { "gridColumnEvents": [ { "value": "720", "command": "SetGridCellValue", "columnID": "28" }, { "value": "331-4014", "command": "SetGridCellValue", "columnID": "29" }, { "value": "CAR", "command": "SetGridCellValue", "columnID": "27" } ] }, { "gridColumnEvents": [ { "value": "303", "command": "SetGridCellValue", "columnID": "28" }, { "value": "421-1010", "command": "SetGridCellValue", "columnID": "29" }, { "value": "HOM", "command": "SetGridCellValue", "columnID": "27" } ] } ] } }, { "command": "DoAction", "controlID": "4" } ], "deviceName": "RESTclient", "formName": "P0115_W0115A" }
Example - Insert Rows - JSON Response
{ "fs_P0115_W0115A": { "title": "Phone Numbers", "data": { "lblDL01_71": { "id": 71, "editable": false, "value": "Ray Allen", "title": "Ray Allen", "dataType": 2 }, "lblWhosWhoLine_52": { "id": 52, "editable": false, "value": "Who's Who Line", "title": "Who's Who Line", "dataType": 2 }, "txtAddressNumber_7": { "id": 7, "editable": false, "value": "6001", "internalValue": 6001, "title": "Address Number", "assocDesc": "Allen, Ray", "staticText": "Address Number", "dataType": 9 }, "lblDL01_54": { "id": 54, "editable": false, "value": "Allen, Ray", "title": "Allen, Ray", "dataType": 2 }, "gridData": { "titles": { "col_28": "Prefix", "col_29": "Phone Number", "col_27": "Phone Type", "col_66": "Phone Type Description", "col_26": "Line Number" }, "rowset": [ { "rowIndex": 0, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "334-4000", "internalValue": "334-4000", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "HOM", "internalValue": "HOM", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Home", "internalValue": "Home", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "1", "internalValue": 1, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 1, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "555-1212", "internalValue": "555-1212", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "CAR", "internalValue": "CAR", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Car or Mobile", "internalValue": "Car or Mobile", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "2", "internalValue": 2, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 2, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "720", "internalValue": "720", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "331-4014", "internalValue": "331-4014", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "CAR", "internalValue": "CAR", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Car or Mobile", "internalValue": "Car or Mobile", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "3", "internalValue": 3, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 3, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "421-1010", "internalValue": "421-1010", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "HOM", "internalValue": "HOM", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Home", "internalValue": "Home", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "4", "internalValue": 4, "title": "Line Number", "dataType": 9 } } ], "summary": { "records": 4, "moreRecords": false } }, "lblAddressNumber_6": { "id": 6, "editable": false, "value": "Address Number", "title": "Address Number", "dataType": 9 }, "txtWhosWhoLine_32": { "id": 32, "editable": false, "value": "0", "internalValue": 0, "title": "Who's Who Line", "assocDesc": "Ray Allen", "dataType": 9 } }, "errors": [], "warnings": [] }, "stackId": 1, "stateId": 1, "rid": "b7ebc0f0832cfbb", "currentApp": "P0115_W0115A", "sysErrors": [] }
Example - Insert Rows - MAF Application Code
This sample code is an example of adding one new phone number using grid actions.
Important: Your mobile application should allow adding records only when the record count is below the maximum. You can determine this by checking the moreRecords field in the grid summary when you fetch existing records. You will not receive an error message if you attempt to add a record beyond the maximum allowed. The record will simply not be added.
public void addPhone() { AdfmfJavaUtilities.setELValue("#{pageFlowScope.errors}", "false"); FormRequest formRequest = new FormRequest(); formRequest.setFormName("P0115_W0115A"); formRequest.setFormServiceAction("U"); formRequest.addToFISet("4", addressNumber); formRequest.addToFISet("5", "0"); FSREvent fsrEvent = new FSREvent(); GridAction gridAction = new GridAction(); GridRowInsertEvent gri = new GridRowInsertEvent(); //set the column values gri.setGridColumnValue("27", addPhoneType); gri.setGridColumnValue("28", addPhonePrefix); gri.setGridColumnValue("29", addPhoneNumber); //add the row gridAction.insertGridRow("1", gri); //add the grid action to the events fsrEvent.addGridAction(gridAction); //press OK button fsrEvent.doControlAction("4"); //add the FSR event to the request formRequest.addFSREvent(fsrEvent); // Execute SEND and RECEIVE operation try { // For POST request, set data payload is header delimited with | and service input class JSONObject jsonObject = (JSONObject)JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.FORM_SERVICE_URI); P0115_W0115A_FormParent tempFormParent = ((P0115_W0115A_FormParent)JSONBeanSerializationHelper.fromJSON(P0115_W0115A_FormParent.class, response)); if(tempFormParent.getFs_P0115_W0115A().getErrors() != null && tempFormParent.getFs_P0115_W0115A().getErrors().length>0){ AdfmfJavaUtilities.setELValue("#{pageFlowScope.errors}", "true"); }else{ p0115_W0115A_FormParent.getFs_P0115_W0115A().getData().getGridData().setRowsetList (tempFormParent.getFs_P0115_W0115A().getData().getGridData().retrieveRowsetList()); p0115_W0115A_FormParent.getFs_P0115_W0115A().getData().getGridData().setSummary (tempFormParent.getFs_P0115_W0115A().getData().getGridData().getSummary()); AdfmfJavaUtilities.setELValue("#{pageFlowScope.addready}", "true"); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
Example - Update Rows - JSON
This sample code is an example of updating two phone numbers. You must specify the index of the row you want to update. The row index is included in the information returned when you query the grid. Therefore, you must perform a query before you update a row. In this example, the JSON code updates rows 2 and 4 and sets values in each of the three columns for these rows.
This sample code also includes syntax that shows a column that contains a drop-down selection. The value should be the 'code' value, not the description.
"gridColumnEvents": [ { "value": "30", "command": "SetGridComboValue", "columnID": "43" } ]
This sample code shows the phones update request:
{"token": "044t+mf8cq2gxqvAlH1SziE9EnBfs5QYNlj3ZQpmFAW9tc=MDE5MDA2ODQ0NjQ4MjI5OTYxODQ5MjQxNlNvYXBVSTEzOTIwNzI3MjAzMTM=", "formInputs": [ { "value": "6001", "id": "4" }, { "value": "0", "id": "5" } ], "formActions": [ { "gridAction": { "gridID": "1", "gridRowUpdateEvents": [ { "rowNumber": 2, "gridColumnEvents": [ { "value": "720", "command": "SetGridCellValue", "columnID": "28" }, { "value": "111-1111", "command": "SetGridCellValue", "columnID": "29" }, { "value": "CAR", "command": "SetGridCellValue", "columnID": "27" } ] }, { "rowNumber": 4, "gridColumnEvents": [ { "value": "303", "command": "SetGridCellValue", "columnID": "28" }, { "value": "22233333", "command": "SetGridCellValue", "columnID": "29" }, { "value": "CAR", "command": "SetGridCellValue", "columnID": "27" } ] } ] } }, { "command": "DoAction", "controlID": "4" } ], "deviceName": "RESTclient", "formName": "P0115_W0115A" }
Example - Update Rows - JSON Response
{ "fs_P0115_W0115A": { "title": "Phone Numbers", "data": { "lblDL01_71": { "id": 71, "editable": false, "value": "Ray Allen", "title": "Ray Allen", "dataType": 2 }, "lblWhosWhoLine_52": { "id": 52, "editable": false, "value": "Who's Who Line", "title": "Who's Who Line", "dataType": 2 }, "txtAddressNumber_7": { "id": 7, "editable": false, "value": "6001", "internalValue": 6001, "title": "Address Number", "assocDesc": "Allen, Ray", "staticText": "Address Number", "dataType": 9 }, "lblDL01_54": { "id": 54, "editable": false, "value": "Allen, Ray", "title": "Allen, Ray", "dataType": 2 }, "gridData": { "titles": { "col_28": "Prefix", "col_29": "Phone Number", "col_27": "Phone Type", "col_66": "Phone Type Description", "col_26": "Line Number" }, "rowset": [ { "rowIndex": 0, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "334-4000", "internalValue": "334-4000", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "HOM", "internalValue": "HOM", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Home", "internalValue": "Home", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "1", "internalValue": 1, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 1, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "555-1212", "internalValue": "555-1212", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "CAR", "internalValue": "CAR", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Car or Mobile", "internalValue": "Car or Mobile", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "2", "internalValue": 2, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 2, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "720", "internalValue": "720", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "111-1111", "internalValue": "111-1111", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "CAR", "internalValue": "CAR", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Car or Mobile", "internalValue": "Car or Mobile", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "3", "internalValue": 3, "title": "Line Number", "dataType": 9 } }, { "rowIndex": 3, "MOExist": false, "sPrefix_28": { "id": 28, "editable": true, "value": "303", "internalValue": "303", "title": "Prefix", "dataType": 2 }, "sPhoneNumber_29": { "id": 29, "editable": true, "value": "22233333", "internalValue": "22233333", "title": "Phone Number", "dataType": 2 }, "sPhoneType_27": { "id": 27, "editable": true, "value": "CAR", "internalValue": "CAR", "title": "Phone Type", "dataType": 2 }, "sPhoneTypeDescription_66": { "id": 66, "editable": false, "value": "Car or Mobile", "internalValue": "Car or Mobile", "title": "Phone Type Description", "dataType": 2 }, "mnLineNumber_26": { "id": 26, "editable": false, "value": "4", "internalValue": 4, "title": "Line Number", "dataType": 9 } } ], "summary": { "records": 4, "moreRecords": false } }, "lblAddressNumber_6": { "id": 6, "editable": false, "value": "Address Number", "title": "Address Number", "dataType": 9 }, "txtWhosWhoLine_32": { "id": 32, "editable": false, "value": "0", "internalValue": 0, "title": "Who's Who Line", "assocDesc": "Ray Allen", "dataType": 9 } }, "errors": [], "warnings": [] }, "stackId": 2, "stateId": 1, "rid": "b7ebc0f0832cfbb", "currentApp": "P0115_W0115A", "sysErrors": [] }
Example - Update Rows - MAF Application Code
This sample code is an example of updating a single phone row from an MAF application.
public void updatePhone(int key) { AdfmfJavaUtilities.setELValue("#{pageFlowScope.errors}", "false"); FormRequest formRequest = new FormRequest(); formRequest.setFormName("P0115_W0115A"); formRequest.setFormServiceAction("U"); formRequest.addToFISet("4", addressNumber); formRequest.addToFISet("5", "0"); FSREvent fsrEvent = new FSREvent(); GridAction gridAction = new GridAction(); GridRowUpdateEvent gru = new GridRowUpdateEvent(); //get currently selected row P0115_W0115A_GridRow selectedRow = getSelectedPhonebyKey(key); //set the column values gru.setGridColumnValue("27", selectedRow.getSPhoneType_27().getValue()); gru.setGridColumnValue("28", selectedRow.getSPrefix_28().getValue()); gru.setGridColumnValue("29", selectedRow.getSPhoneNumber_29().getValue()); //update the row based on it's index - zero based gridAction.updateGridRow("1", selectedRow.getRowIndex(), gru); //add the grid action to the events fsrEvent.addGridAction(gridAction); //press OK button fsrEvent.doControlAction("4"); //add the FSR event to the request formRequest.addFSREvent(fsrEvent); // Execute SEND and RECEIVE operation try { // For POST request, set data payload is header delimited with | and service input class JSONObject jsonObject = (JSONObject)JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.FORM_SERVICE_URI); P0115_W0115A_FormParent tempFormParent = ((P0115_W0115A_FormParent)JSONBeanSerializationHelper.fromJSON(P0115_W0115A_FormParent.class, response)); if(tempFormParent.getFs_P0115_W0115A().getErrors() != null && tempFormParent.getFs_P0115_W0115A().getErrors().length>0){ AdfmfJavaUtilities.setELValue("#{pageFlowScope.errors}", "true"); }else{ p0115_W0115A_FormParent.getFs_P0115_W0115A().getData().getGridData().setRowsetList (tempFormParent.getFs_P0115_W0115A().getData().getGridData().retrieveRowsetList()); p0115_W0115A_FormParent.getFs_P0115_W0115A().getData().getGridData().setSummary (tempFormParent.getFs_P0115_W0115A().getData().getGridData().getSummary()); } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
Query Events
You can configure a form service request to send ad hoc queries to EnterpriseOne web client application forms that support the query control.
To add a query, you include a single query object in the form service request. A query object includes parameters that contain the same query criteria that you would use to set up a query in EnterpriseOne. The parameters determine:
How the query runs. You can configure query option parameters to load grid records in the form or clear all other fields in the form before the query runs. You can also specify whether the results of the query should match all (AND) or any (OR) of the conditions specified in the query.
The conditions of the query. The query object includes condition parameters that specify the control ID of the columns or fields that you want to query and an operator for filtering results that are equal to, greater than, or less than a particular value.
Important: Queries will work only if the field or columns identified in the query are part of the business view.The value used for the search criteria in the query. The query object includes value parameters that specify the value or range of values that you want displayed in the query results.
Before you add a query object to a form service request, access the form in the EnterpriseOne web client and use the query control to gather the criteria for the query object parameters. For more information about setting up a query, see "Understanding the Query Control" in the JD Edwards EnterpriseOne Tools Foundation Guide.
Also, in the EnterpriseOne form, you need to identify the control ID of the field or column that you want to query, and verify that the field or column is part of the business view. To do so, click the Help button (question mark in the upper right corner of a form) and then click the Item Help option to access field-level help. With the field level help activated, you can click in a field or column to access the control ID and business view information, which is displayed under the Advanced Options section as shown in Example - Example of Control ID and Business View Information Displayed under Advanced Options in the EnterpriseOne Web Client Item Help.
Example - Example of Control ID and Business View Information Displayed under Advanced Options in the EnterpriseOne Web Client Item Help

In the Item Help, the syntax of the control ID is 1.20 with 1 representing the grid ID and 20 representing the column ID, which are separated by a dot (.). In the parameter for the query request, the same control ID must be presented with the following syntax: 1[20]. See the Table 2 for more information.
Query Object Parameters
The following tables describe the parameters for a query object.
Table Query Option Parameters
Parameter |
Description |
Values |
---|---|---|
autoFind |
Directs the query to automatically press Find on the form to populate the grid records. You do not need to include events to press the Find button if you use autoFind. |
true, false |
matchType |
Determines if you want the query to search for records that match all (AND) or any (OR) of the specified conditions. |
MATCH_ALL, MATCH_ANY |
autoClear |
Do you want to clear all other fields on the form (for example default filter fields). |
true, false |
Table Query Condition Parameters
Parameter |
Description |
Value |
---|---|---|
controlId |
The control ID that the condition applies to. This is the field that you add to the query from the form when using the web client to create a Query. It is either a filter field or a grid column that is associated with the business view. |
Example of control IDs: "28", "1[34]" |
operator |
The comparison operation to use with the query. |
For all types, valid values are: BETWEEN, LIST, EQUAL, NOT_EQUAL, LESS, LESS_EQUAL, GREATER, GREATER_EQUAL For strings, valid values are: STR_START_WITH, STR_END_WITH, STR_CONTAIN, STR_BLANK, STR_NOT_BLANK |
Table Query Value Parameters
Parameter |
Description |
Value |
---|---|---|
content |
This is either a literal value to be used in the comparison operation, or it relates to a special value ID. |
Examples of values are: "23", "Joe", "2" |
specialValueId |
This is a special value, mostly for dates that may be today, or calculated dates from today. For calculated dates, the content field is used in the calculation. |
Valid values are: LITERAL, TODAY, TODAY_PLUS_DAY, TODAY_MINUS_DAY, TODAY_PLUS_MONTH, TODAY_MINUS_MONTH, TODAY_PLUS_YEAR, TODAY_MINUS_YEAR |
Query Object Examples
This section contains JSON and API code examples of the query object.
Example - Query - JSON
This is an example of JSON code that executes a query on the W42101C form in EnterpriseOne.
{ "token": "044mK8eBlupO2jaE4BAvXzaRXsMAM7edfHybw26zSZga1w=MDE5MDA2MjUyMTQ1MDE0Njg1NzMwODE2MFNvYXBVSTE0MTIzNTc1MDkwMTc=", "maxPageSize":"20", "formServiceAction": "R", "returnControlIDs": "350|360|41[129,130,116,125,132,123]", "query":{ "condition": [ { "value": [ { "content": "2", "specialValueId": "LITERAL" } ], "controlId": "41[129]", "operator": "EQUAL" }, { "value": [ { "content": "2", "specialValueId": "TODAY_MINUS_YEAR" } ], "controlId": "41[116]", "operator": "GREATER" }, { "value": [ { "content": "7000", "specialValueId": "LITERAL" }, { "content": "8000", "specialValueId": "LITERAL" } ], "controlId": "41[125]", "operator": "BETWEEN" }, { "value": [ { "content": "00070", "specialValueId": "LITERAL" }, { "content": "00001", "specialValueId": "LITERAL" }, { "content": "00077", "specialValueId": "LITERAL" } ], "controlId": "360", "operator": "LIST" } ], "autoFind": true, "matchType": "MATCH_ALL", "autoClear": false }, "deviceName": "RESTclient", "formName": "P42101_W42101C" }
Example - Query - Mobile Framework API
This is an example of API code that executes a query on the W42101C form in EnterpriseOne.
public void executeQuery() { FormRequest formRequest = new FormRequest(); formRequest.setReturnControlIDs("350|360|41[129,130,116,125,132,123]"); formRequest.setFormName("P42101_W42101C"); formRequest.setVersion("ZJDE0001"); formRequest.setFormServiceAction("R"); // Execute SEND and RECEIVE operation try { Query query = new Query(); query.setAutoFind(true); //automatically presses find button (don't need to use form action to find) query.setMatchType(Query.MATCH_ALL); //this is an AND operation on all of the conditions query.setAutoClear(false); //clears any existing filter values on the form //find all line numbers matching NumberCondition numCon = query.addNumberCondition("41[129]", NumericOperator.EQUAL()); numCon.setValue(linNo); //and requested date within num years from today DateCondition dateCon = query.addDateCondition("41[116]", DateOperator.GREATER()); dateCon.setSpecialDateValue(DateSpecialValue.TODAY_MINUS_YEAR(), years); //and sold to between BetweenCondition betCon = query.addBetweenCondition("41[125]"); betCon.setValues(soldTo1, soltTo2); //and company in list ListCondition listCon = query.addListCondition("360"); addValuesToList(listCon); //add the query object to the request formRequest.setQuery(query); formRequest.setMaxPageSize("20"); // For POST request, set data payload is header delimited with | and service input class JSONObject jsonObject = (JSONObject) JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); //Call to JDERestServiceProvider with parameters json string, method (POST), URI (formservice) String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.FORM_SERVICE_URI); p41010_W42101C_FormParent= (P42101_W42101C_FormParent) JSONBeanSerializationHelper.fromJSON(P42101_W42101C_FormParent.class, response); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
Understanding Batch Form Service
If you make several sequential calls to forms without any data dependencies between them, consider using the Batch Form Service. The Batch Form Service will improve your mobile application's performance.
Batch Form Service - JSON Input and Output
The Batch Form Service requires JSON input and output.
The request URL is: POST http://aisserver:port/jderest/batchformservice
You can use this URL in a REST testing tool. In the preceding URL, batchformservice
represents the URI, which you define when you perform the jdeRestServiceCall from the API.
The following examples show JSON input and JSON output in a Batch Form Service.
Example - JSON Input in a Batch Form Service
The JSON consists of an array of form requests along with other single form request fields such as token, environment, role, and so forth. You may send as many requests as desired to the same or different form. Each request is executed individually by the EnterpriseOne HTML (JAS) Server and all responses are compiled into a single response.
This example shows a request for two form executions: W54GS220A and W54HS230A. Each have different form interconnect sets, control sets, and so forth. They are completely independent requests.
{ "formRequests": [ { "formInputs": [ { "value": "09/17/2013", "id": "3" }, { "value": "1", "id": "4" } ], "returnControlIDs": "1[19,20,21,27,28,92,174,177,178]|324", "findOnEntry": "TRUE", "formName": "P54HS220_W54HS220A" }, { "formInputs": [ { "value": "09/17/2013", "id": "2" }, { "value": "1", "id": "3" } ], "returnControlIDs": "1[35,36,37,44,102,105,200,201,277]|368", "findOnEntry": "TRUE", "formName": "P54HS230_W54HS230A" }], "token": "jkfdjfkd" }
Example - JSON Output in a Batch Form Service
The JSON output contains one form element for each form that is called. The forms are numbered in the order they were requested. This is not an array of elements; they are individually defined.
The following sample code is an example of JSON output. For fs_0_P54HS220_W54HS220A, the 0 indicates it was the first form requested. For fs_1_P54HS230_W54HS230A, the 1 indicates it was the second form requested.
{ "fs_0_P54HS220_W54HS220A": { "title": "One View Incident Summary Inquiry", "data": { "txtAlertDescription": { "id": 324, "value": "Recent Incidents", "internalValue": "Recent Incidents", "title": "Alert Description", "dataType": 2 }, "gridData": { "titles": { "col_19": "Incident Number", "col_20": "Incident Description", "col_21": "Incident Date", "col_27": "Incident Status", "col_28": "Incident Severity", "col_92": "Incident Handler Address", "col_174": "Incident Handler Name", "col_177": "Incident Status Description", "col_178": "Incident Severity Description" }, "rowset": [ { "mnIncidentNumber": { "id": 19, "value": "113", "internalValue": 113, "title": "Incident Number", "dataType": 9 }, "sIncidentDescription": { "id": 20, "value": "Gallon drums exposed to sea water rusted and leaked motor oil and coolant", "internalValue": "Gallon drums exposed to sea water rusted and leaked motor oil and coolant", "title": "Incident Description", "dataType": 2 }, "dtIncidentDate": { "id": 21, "value": "09/17/2013", "internalValue": 1379397600000, "title": "Incident Date", "dataType": 11 }, "sIncidentStatus": { "id": 27, "value": "01", "internalValue": "01", "title": "Incident Status", "dataType": 2 }, "sIncidentSeverity": { "id": 28, "value": "03", "internalValue": "03", "title": "Incident Severity", "dataType": 2 }, "mnIncidentHandlerAddress": { "id": 92, "value": "6001", "internalValue": 6001, "title": "Incident Handler Address", "dataType": 9 }, "sIncidentHandlerName": { "id": 174, "value": "Allen, Ray ", "internalValue": "Allen, Ray ", "title": "Incident Handler Name", "dataType": 2 }, "sIncidentStatusDescription": { "id": 177, "value": "Active", "internalValue": "Active", "title": "Incident Status Description", "dataType": 2 }, "sIncidentSeverityDescription": { "id": 178, "value": "Medium", "internalValue": "Medium", "title": "Incident Severity Description", "dataType": 2 } }, { "mnIncidentNumber": { "id": 19, "value": "117", "internalValue": 117, "title": "Incident Number", "dataType": 9 }, "sIncidentDescription": { "id": 20, "value": " ", "internalValue": " ", "title": "Incident Description", "dataType": 2 }, "dtIncidentDate": { "id": 21, "value": "10/01/2013", "internalValue": 1380607200000, "title": "Incident Date", "dataType": 11 }, "sIncidentStatus": { "id": 27, "value": " ", "internalValue": " ", "title": "Incident Status", "dataType": 2 }, "sIncidentSeverity": { "id": 28, "value": " ", "internalValue": " ", "title": "Incident Severity", "dataType": 2 }, "mnIncidentHandlerAddress": { "id": 92, "value": "0", "internalValue": 0, "title": "Incident Handler Address", "dataType": 9 }, "sIncidentHandlerName": { "id": 174, "value": "", "internalValue": "null", "title": "Incident Handler Name", "dataType": 2 }, "sIncidentStatusDescription": { "id": 177, "value": "Default", "internalValue": "Default", "title": "Incident Status Description", "dataType": 2 }, "sIncidentSeverityDescription": { "id": 178, "value": "Default", "internalValue": "Default", "title": "Incident Severity Description", "dataType": 2 } } ], "summary": { "records": 2, "moreRecords": false } } }, "errors": [], "warnings": [] }, "fs_1_P54HS230_W54HS230A": { "title": "One View Incident People Inquiry", "data": { "txtAlertDescription": { "id": 368, "value": "Recent Reportable Incidents", "internalValue": "Recent Reportable Incidents", "title": "Alert Description", "dataType": 2 }, "gridData": { "titles": { "col_35": "Incident Number", "col_36": "Incident Description", "col_37": "Incident Date", "col_44": "Incident Status", "col_102": "Incident Handler Address", "col_105": "Incident Severity", "col_200": "Incident Status Description", "col_201": "Incident Severity Description" }, "rowset": [], "summary": { "records": 0, "moreRecords": false } } }, "errors": [], "warnings": [] } }
Implementing the Batch Form Service
This section describes how to implement the Batch Form Service in your mobile application.
Batch Request Parent Class
To consume the JSON response, the mobile application must have a class that matches the response. You must manually code this class because you have to provide the forms in the order in which they are being called.
Example - Batch Request Parent Class
The following sample code is an example of what the new class looks like with one member defined, with the form level type for each of the forms called. Notice that the names of the class members match the names returned by the JSON response. This is the most important aspect of the class, to enable the deserialization from JSON to this object.
The form objects, which are P54HS220_W54HS220A and P54HS230_W54HS230A in the following sample code, are the same ones generated by the AIS Client Class Generator and are used for a single form request.
package com.oracle.e1.formservicetypes public class BatchRequestParent { private P54HS220_W54HS220A fs_0_P54HS220_W54HS220A; private P54HS230_W54HS230A fs_1_P54HS230_W54HS230A; public BatchRequestParent() { super(); } //getters and setters for everything }
Performing a Batch Form Request
In the data control class, create a method for performing the batch form request. An example of a method named batchFormRequest() follows the steps below.
To create this method:
Create a BatchFormRequest object.
Add each form request to the list of requests. Each form request is an object called SingleFormRequest.
Populate these requests in the same manner that you would use for a single form request.
Call the service with uri JDERestServiceProvider.BATCH_FORM_SERVICE_URI and marshal the JSON response to an instance of BatchRequestParent class.
Example - Batch Form Request
You can use each member of the BatchRequestParent class the same way you would use the response from a single form request. In the following sample code, each form in the batch is saved to a member variable of the main data control class.
public void batchFormRequest() { BatchFormRequest batchFormRequest = new BatchFormRequest(); //Date used for all // Format Incident Date to send to E1 SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy"); String sDate = dateFormat.format(getSearchDate()); //recentIncidents SingleFormRequest formRequest = new SingleFormRequest(); formRequest.setFindOnEntry("TRUE"); formRequest.setReturnControlIDs("1[19,20,21,27,28,92,174,177,178]|324"); formRequest.setFormName("P54HS220_W54HS220A"); formRequest.addToFISet("3", sDate); formRequest.addToFISet("4", "1"); batchFormRequest.getFormRequests().add(formRequest); // recentReportableIncidents formRequest = new SingleFormRequest(); formRequest.setFindOnEntry("TRUE"); formRequest.setReturnControlIDs("1[35,36,37,44,102,105,200,201,277]|368"); formRequest.setFormName("P54HS230_W54HS230A"); formRequest.addToFISet("2", sDate); formRequest.addToFISet("3", "1"); batchFormRequest.getFormRequests().add(formRequest); try { // For POST request, set data payload is header delimited with | and service input class JSONObject jsonObject = (JSONObject)JSONBeanSerializationHelper.toJSON(batchFormRequest); String postData = jsonObject.toString(); String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.BATCH_FORM_SERVICE_URI); BatchRequestParent batchParent = (BatchRequestParent)JSONBeanSerializationHelper.fromJSON(BatchRequestParent.class, response); if(batchParent != null){ //recentIncidents this.p54hs220_formIncidents = new P54HS220_W54HS220A_FormParent(); this.p54hs220_formIncidents.setFs_P54HS220_W54HS220A(batchParent.getFs_0_P54HS220_W54HS220A()); IncidentCount ic = new IncidentCount(); ic.setCount(p54hs220_formIncidents.getFs_P54HS220_W54HS220A().getData().getGridData().getSummary().getRecords()); ic.setTitle("Recent"); ic.setScoreboardNumber("1"); incidentCounts.add(ic); // recentReportableIncidents this.p54hs230_formParent = new P54HS230_W54HS230A_FormParent(); this.p54hs230_formParent.setFs_P54HS230_W54HS230A(batchParent.getFs_3_P54HS230_W54HS230A()); ic = new IncidentCount(); ic.setCount(p54hs230_formParent.getFs_P54HS230_W54HS230A().getData().getGridData().getSummary().getRecords()); ic.setTitle("Reportable"); ic.setScoreboardNumber("4"); incidentCounts.add(ic); } } catch (Exception e) { AdfException adfe = new AdfException("Rest Call Failed" + e.getMessage(), AdfException.ERROR); throw adfe; } }
Working with the EnterpriseOne REST Services Interface
You can make REST calls directly to the AIS Server without using APIs from the JDEMobileFramework.jar. To do so, use a REST service testing tool to send JSON text to AIS Server endpoints. Each endpoint provides a particular service that the mobile application can use to interact with EnterpriseOne applications. You can access AIS Server endpoints using this URL format:
http://<server>:<port>/jderest/<URI>
See EnterpriseOne Rest Services Interface for an illustration of JSON input and output communication between a mobile device and the AIS Server and between the AIS Server and the EnterpriseOne HTML Server.
See the "AIS Services (Endpoints)" section in the JD Edwards EnterpriseOne Application Interface Services Server Reference Guide for a description of the available endpoints on the AIS Server along with the HTTP method used to access them. Unless otherwise stated, the request and response are in the form of JSON strings.
Using a REST Services Client to Interact with AIS
In the text area in the bottom left of the form, enter the JSON string that is the input to the tokenrequest service. Entering an environment and role is optional. Include them only if you want to override the default values.
Example - Acceptable Input for the defaultconfig Service on JSON
The defaultconfig service is the only service that uses an HTTP GET operation. It accepts one parameter for the required capabilities in the client application. If any required capabilities listed in that parameter are missing, the response will indicate the missing capabilities in the "requiredCapabilityMissing" field.
{ "jasHost": "jasserver.domainexample.com", "jasPort": "8412", "jasProtocol": "http", "defaultEnvironment": "DV910", "defaultRole": "*ALL", "displayEnvironment": true, "displayRole": true, "displayJasServer": false, "defaultJasServer": "http://jasserver.domainexample.com:port", "ssoAllowed": true, "allowSelfSignedSsl": false, "sessionTimeout": "30", "timeToLive": "720", "aisVersion": "EnterpriseOne 9.1.4.6", "capabilityList": [ { "name": "grid", "shortDescription": "Grid Actions", "longDescription": "Ability to update, insert and delete grid records.", "asOfRelease": "9.1.4.4" }, { "name": "editable", "shortDescription": "Enabled/Disabled", "longDescription": "Ability to indicate if form field or grid cell is editable (enabled) or not (disabled).", "asOfRelease": "9.1.4.4" }, { "name": "log", "shortDescription": "Logging", "longDescription": "Endpoint exposed for logging to AIS server log from client", "asOfRelease": "9.1.4.6" }, { "name": "processingOption", "shortDescription": "Processing Options", "longDescription": "Processing Option Service exposed for fetching PO values from E1", "asOfRelease": "9.1.4.6" }, { "name": "ignoreFDAFindOnEntry", "shortDescription": "Ignore FDA Find On Entry", "longDescription": "Ability to use the IgnoreFDAFindOnEntry flag", "asOfRelease": "9.1.4.6" } ], "requiredCapabilityMissing": false, "keepJasSessionOpen": true, "jasSessionCookieName": "JSESSIONID" }
Example - Acceptable Input for the tokenrequest Service in JSON
{ "username":"jde", "password":"jde", "deviceName":"RESTclient", "environment":"JDV910", "role":"*ALL" }
Example - Acceptable Input for the tokenrequest Service in JSON Response
{ "username": "jde", "environment": "JDV910", "role": "*ALL", "jasserver": "http://jasserver.domainexample.com:port", "userInfo": { "token": "044kbwMICIsL8P4jttMj/VtpnEhrSK17i7fa2q8V+hVDlc=MDE4MDEwNjA1NTMwODkwMzQ1ODY0MTkyUkVTVGNsaWVudDE0MTI2MDg3MDgzODY=", "langPref": " ", "locale": "en", "dateFormat": "MDE", "dateSeperator": "/", "simpleDateFormat": "MM/dd/yyyy", "decimalFormat": ".", "addressNumber": 2111, "alphaName": "Ingram, Paul" }, "userAuthorized": false, "version": null, "poStringJSON": null, "altPoStringJSON": null, "aisSessionCookie": "W3XmCk8k6vhb3H-dwxSdBpCGZWAb7kh5D4gzemFoqoFqcoWgwqF_!-1217528743!1412608708388" }
Form Request Attributes
The following list contains a description of the form request attributes. For an example of a form request, see Example - Form Request.
maxPageSize. (optional) If you do not specify a value, then AIS will return a maximum of 100 rows. The maximum number you can enter for this setting is 500.
Starting with EnterpriseOne Tools 9.2.1, there is no maximum limit for rows returned to the grid. However, a maximum value is required. If you want to retrieve all records, enter
No Max
for this attribute.The value in the "DB Fetch Limit in the Web Runtime Interactivity" setting in the Web Runtime Interactivity section of the EnterpriseOne HTML Server configuration file (jas.ini) supersedes the maxPageSize setting. The "DB Fetch Limit in the Web Runtime Interactivity" setting is typically set to a higher value (2000 is the default), but you might have to modify it if your results are not as expected. See "Configuration Groups" in the JD Edwards EnterpriseOne Tools Server Manager Guide for more information on how to modify server configuration settings.
returnControlIDs. (optional) Indicates which form and grid fields the service passes back. Grid is always 1 and has an array of fields. Form fields are bar delimited after grid, for example 1[19,20,50,48]|54|55. For power forms, indicate the control ID of the subform and then underscore and the control within the subform, for example 1_20|1_22[23,34].
formInputs. (optional) Collection of ID value pairs that represent the form interconnect input to the form. Associate a string for the FI ID with the value to be passed into that FI.
version. The version of the application, for example ZJDE0001.
formName. (required) Application and form name, for example P01012_W01012B.
formServiceAction. (optional) The CRUD operation the form will perform.
token. (required) The EnterpriseOne token that was returned from the tokenrequest service.
environment. (optional) EnterpriseOne environment that was used to request the token.
role. (optional) The EnterpriseOne role used to request the token.
findOnEntry. (optional) Valid values are TRUE or FALSE. Performs a find automatically when the EnterpriseOne application launches. In the EnterpriseOne application this autofind event occurs after post dialog initialized.
ignoreFDAFindOnEntry. (optional) Valid values are TRUE or FALSE. Applies to applications that have the box checked for "Automatically Find on Entry" in the gird in FDA. Allows the form service caller to control if that flag is used or not.
formActions. (optional) A set of actions to be performed on the form, in the order listed. The actions can include entering a value into a form field, QBE field, selecting a radio button, pressing a button, and selecting a check box value.
Example - Form Request
{ "token": "044RnByWbW3FbLzpxWjSg55QzZWguAGnYqUNMlyB30IgyU=MDE5MDA2ODg0MDE5NjYwNzM1ODcyNDA5NlNvYXBVSTEzODc0ODc4OTEzNTc=", "maxPageSize": "10", "returnControlIDs": "1[19,20]58|62", "version": "ZJDE0001", "formInputs": [ { "value": "E", "id": "2" } ], "formActions": [ { "value": "E", "command": "SetQBEValue", "controlID": "1[50]" }, { "value": "Al*", "command": "SetControlValue", "controlID": "58" }, { "value": "on", "command": "SetCheckboxValue", "controlID": "62" }, { "value": "on", "command": "SetCheckboxValue", "controlID": "63" }, { "command": "DoAction", "controlID": "15" } ], "role": "*ALL", "environment": "JDV910", "formsServiceAction":"R", "deviceName": "RESTclient", "formName": "P01012_W01012B" }
Calling FormService on Local EnterpriseOne HTML (JAS) Server through the AIS Server
You have the option to use this technique if you have FDA changes locally and want to test the JSON output while still accessing the AIS Server. This is the closest approximation of how the mobile application will call the REST services.
Configure your local EnterpriseOne HTML Server to accept requests from the AIS Server. To do so:
Locate the jas.ini file on the local EnterpriseOne Windows client (development client) machine:
C:\E910_1\system\OC4J\j2ee\home\applications\webclient.ear\webclient\WEB-INF\classes\jas.ini
Add or modify the form service section like this:
#specify hosts allowed to call the form service and media object service [FORMSERVICE] allowedhosts=127.0.0.1|10.123.456.7
The two preceding entries are the local host IP address and the IP address of the AIS Server. This enables you to make calls through the AIS Server to your local EnterpriseOne HTML Server. For the AIS Server, you can also use
allowedhosts=*
if you do not know the AIS Server IP address or want to allow access for any AIS Server.Restart the EnterpriseOne Windows client.
Test the configuration by repeating the preceding steps, but include the following change to the JSON requests:
For tokenrequest: Indicate the JAS server, which is your local EnterpriseOne HTML Server. Also, Oracle recommends that you always include the environment and role because the defaults stored on the AIS Server may not work with a local instance (such as JDV910 vs DV910).
{"username":"JDE", "password":"jde", "deviceName":"RESTclient", "jasserver":"http://dnnlaurentvm1:8888", "environment":"DV910", "role":"*ALL" }
Understanding Text Media Object Attachments
The AIS Server provides a method to get and update the first text attachment stored for a particular media object data structure key in EnterpriseOne.
The JDEMobileFramework API provides the following two services for managing text media object attachments in mobile applications:
"User-Generated Data Structures" in the JD Edwards EnterpriseOne Tools Data Structure Design Guide for more information about the function of media object data structures in EnterpriseOne
gettext Service
The URL for getting text media objects is:
http://<ais-server>:<port>/jderest/file/gettext
Only the first text media object is returned; it does not handle multiple text attachments. Only plain text is supported. While the original text media object is stored in HTML or RTF format (based on the settings on the EnterpriseOne HTML Server), the tags will be removed and the response will be in plain text with line breaks in Unicode (UTF-8) format.
The following table describes the expected JSON input for the gettext service:
Field |
Value Description |
Example |
---|---|---|
token (String) |
The token you received when you executed a token request. |
"044TqjlQVSNHKvokvhWFKa8MYckPgG…" |
moStructure (String) |
The Media Object Structure |
"ABGT" or "GT0801A" |
moKey (Array of Strings) |
The key to that media object structure. |
["7"] or ["2015","283", "2"] |
formName (String) |
The form where this media object is used. |
"P01012_W01012B" |
version (String) |
The version of the app where this media object is used. |
"ZJDE0001" |
deviceName (String) |
The device making the call to the service. |
"FUSE" or "iPhoneSimulator" |
Example - gettext Service Input
{ "token": "044TqjlQVSNHKvokvhWFKa8MYckPgGJdrd3CEDkzz2YjLQ=MDE5MDA2Nzg3NjEzOTA2MTY1MzIwMTkyMFNvYXBVSTEzOTk1ODA5MzQ0OTg=", "moStructure": "ABGT", "moKey": [ "7" ], "formName": "P01012_W01012B", "version": "ZJDE0001", "deviceName": "RESTclient" }
Example - gettext Service Response
{ "text": "9.1.4.6 \\u000aFirst Line \\u000aSecond Line \\u000aThird Line \\u000aFourth Line \\u000aFifth line", "isRTF": false }
updatetext Service
The URL for updating text media objects is:
http://<ais-server>:<port>/jderest/file/updatetext
Only plain text is supported.
The following table describes the expected JSON input for the updatetext service:
Field |
Value Description |
Example |
---|---|---|
token (String) |
The token you received when you executed a token request. |
"044TqjlQVSNHKvokvhWFKa8MYckPgG…" |
moStructure (String) |
The media object structure. |
"ABGT" or "GT0801A" |
moKey (Array of Strings) |
The key to the media object structure. |
["7"] or ["2015","283", "2"] |
formName (String) |
The form where this media object is used. |
"P01012_W01012B" |
version (String) |
The version of the application where the media object is used. |
"ZJDE0001" |
deviceName (String) |
The device making the call to the service. |
"RESTClient" or "iPhoneSimulator" |
inputText (String) |
The text you are updating for the first text media object. |
"Update Text" |
appendText (Boolean) |
A flag to indicate if the text should append to (true) or replace (false) the existing first text attachment. |
true or false |
Example - Update Text Service Input
{ "token": "044X9NgLP5VHqIW0zJcWseFjMtjrnZ35TUFmVV3NW9a9g4=MDE5MDA2NDY5MzQ1NjkzNDM1MjE3NjEyOFNvYXBVSTE0MDE3MTc4MDkzNTk=", "moStructure": "ABGT", "moKey": [ "7" ], "formName": "P09E2011_W09E2011A", "version": "ZJDE0001", "inputText": "\nFirst Line \nSecond Line \nThird Line \nFourth Line \nFifth line", "appendText": false, "deviceName": "RESTclient" }
Example - Update Text Service Response
{ "updateTextStatus": "Success" }
JDEMobileFramework API Methods for Managing Text Media Objects
The MediaObjectOperations class in the JDEMobileFramework API provide methods for managing text media objects from mobile applications. The same two methods described in the preceding sections, getText and updateText, are exposed in this API.
MediaObjectOperations Class
The following table describes the methods in the MediaObjectOperations class:
Return |
Method |
Description |
---|---|---|
MediaObjectGetTextResponse |
getTextMediaObject(MediaObjectGetTextRequest mediaObgetTextRequest) throws Exception |
Takes a MediaObjectGetTextRequest, calls the get text service, replaces unicode returns and line feeds with system line separator and returns a MediaObjectGetTextResponse with the resulting text attachment value. |
MediaObjectUpdateTextResponse |
updateTextMediaObject(MediaObjectUpdateTextRequest mediaObgetUpdateTextRequest) throws Exception |
Takes a MediaObjectUpdateTextRequest, calls the update text service and returns result in MediaObjectUpdateTextResponse. |
Example - Get Example
public void getText() { MediaObjectGetTextRequest moGetText = new MediaObjectGetTextRequest(); moGetText.setFormName(formName); moGetText.setVersion(version); moGetText.setMoStructure(moStructure); //set mo key moGetText.addMoKeyValue(mokey); try { MediaObjectGetTextResponse response = MediaObjectOperations.getTextMediaObject(moGetText); this.setFirstText(response.getText()); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e, AdfException.ERROR); throw adfe; } }
Example - Append Example
public void appendText() { MediaObjectUpdateTextRequest moUpdateText = new MediaObjectUpdateTextRequest(); moUpdateText.setFormName(formName); moUpdateText.setVersion(version); moUpdateText.setMoStructure(moStructure); //set mo key moUpdateText.addMoKeyValue(mokey); moUpdateText.setAppendText(true); moUpdateText.setInputText(this.getFirstText()); try { MediaObjectUpdateTextResponse response = MediaObjectOperations.updateTextMediaObject(moUpdateText); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e, AdfException.ERROR); throw adfe; } }
Example - Update Example
public void updateText() { MediaObjectUpdateTextRequest moUpdateText = new MediaObjectUpdateTextRequest(); moUpdateText.setFormName(formName); moUpdateText.setVersion(version); moUpdateText.setMoStructure(moStructure); //set mo key moUpdateText.addMoKeyValue(mokey); moUpdateText.setAppendText(false); moUpdateText.setInputText(this.getFirstText()); try { MediaObjectUpdateTextResponse response = MediaObjectOperations.updateTextMediaObject(moUpdateText); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e, AdfException.ERROR); throw adfe; } }
Understanding URL Media Object Attachments
You can use the addURLMediaObject method to include URL media object attachments in a mobile application. A URL media object attachment provides a link to a web page or a file located on a server. In EnterpriseOne, a URL media object displays the target of a URL in the Media Object Viewer.
The addURLMediaObject method uses a media object data structure key to identify the record to which the attachment belongs.
The following is a description of the method and the fields that make up the request and the response of the method:
- Method - addURLMediaObject
- Description - Adds a media object of the type URL.
- Returns - MediaObjectAddUrlResponse
- Parameters - MediaObjectAddUrlRequest
MediaObjectAddUrlRequest
Field |
Type |
Description |
---|---|---|
moStructure |
String |
The media object structure ID, for example GT0801, GT48100. |
moKey |
ArrayList <String> |
The set of key values, as strings, that is the key of the media object. The API will handle formatting into a bar delimited set. Use the JDEmfUtilities.convertMillisecondsToYMDString() method to pass dates. |
formName |
String |
The application and form usually associated with this media object structure, for example P01012_W01012B. This is for security purposes. Security for media objects is based on the form being used. |
version |
String |
The version of the application noted in the formName. This is for security purposes. Security for media objects is based on the form being used. |
urlText |
String |
The text of the URL, for example www.oracle.com or http://www.oracle.com |
MediaObjectAddUrlResponse
Field |
Type |
Description |
---|---|---|
urlText |
String |
The text of the url, for example www.oracle.com or http://www.oracle.com |
saveUrl |
String |
The url as it was saved in the media object table F00165. |
sequence |
int |
The sequence number for the newly added url type media object. |
Example - URL Media Object - JSON Request and Response
The following code is an example of a JSON request:
{ "moStructure": "ABGT", "moKey": [ "4242" ], "formName": "P01012_W01012B", "version": "ZJDE0001", "token": "044BPeneep/jkkldafjdkla", "urlText": "http://www.oracle.com", "deviceName": "RESTclient" }
The following code is an example of a JSON response:
{ "saveURL": "http://www.oracle.com", "urlText": "http://www.oracle.com", "sequence": 5 }
Example - URL Media Object - Mobile Framework API
The following is an example of API code for a URL media object.
public void addURL() throws Exception { //set request info include URLs so they don't have to be fetched later MediaObjectAddUrlRequest mediaObjectAddUrlRequest = new MediaObjectAddUrlRequest(); mediaObjectAddUrlRequest.setFormName("P01012_W01012B"); mediaObjectAddUrlRequest.setVersion("ZJDE00001"); mediaObjectAddUrlRequest.setMoStructure("ABGT"); mediaObjectAddUrlRequest.addMoKeyValue("4242"); mediaObjectAddUrlRequest.setUrlText("http://www.oracle.com"); MediaObjectAddUrlResponse mediaObjectAddUrlResponse = new MediaObjectAddUrlResponse(); try { //get the list of available files for this media object mediaObjectAddUrlResponse = MediaObjectOperations.addUrlMediaObject(mediaObjectAddUrlRequest); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException("Media Object addURL Failed " + " " + e, AdfException.ERROR); throw adfe; } }
Understanding the Media Object API for Photo Media Object Attachments
You can incorporate photo attachments into native Oracle MAF mobile applications using the JDEMobileFramework.jar, which is a JDE Mobile Helper. The JDEMobileFramework.jar contains a Media Object API that provides classes and methods that enable access to media objects from EnterpriseOne. It works in conjunction with the AIS Server and the MediaObjectRequest capability of the EnterpriseOne HTML Server.
MediaObjectOperations is an abstract class that contains all of the static methods needed to manage media objects. This section describes the following four main operations:
List
- Method - getMediaObjectList
- Description - Returns a list of Media Object details based on the information provided in the request.
- Returns - MediaObjectListResponse
- Parameters - MediaObjectListRequest
MediaObjectListRequest
Field |
Type |
Description |
---|---|---|
moStructure |
String |
The Media Object structure ID (such as GT0801, GT48100) |
moKey |
ArrayList <String> |
The set of key values, as strings, that is the key of the media object. The API will handle formatting into a bar delimited set. Use the JDEmfUtilities.convertMillisecondsToYMDString() method to pass dates. |
formName |
String |
The application and form usually associated with this media object structure (e.g. P01012_W01012B). This is for security purposes. Security for media objects is based on the form being used. |
version |
String |
The version of the application noted in the formName. This is for security purposes. Security for media objects is based on the form being used. |
includeURLs |
boolean |
When true, the response will include the JAS URL for each file type media object. |
includeData |
boolean |
When true, the response will include the Base64 encoded data for a 40 X 40 size of the image in the data field of the response. |
moTypes |
ArrayList <String> |
Valid types are 1 and 5, which are the two file type media objects. Type 1 file attachments are from a Media Object Queue. Type 5 attachments are files uploaded individually to the EnterpriseOne HTML Server. |
extensions |
ArrayList |
Use this field to further reduce the data set by indicating the extensions of the files you want to be included in the response (such as "jpg","gif","png","pdf"). |
thumbnailSize |
<String> int |
Use this in conjunction with the includeData flag. When data is included in the response you can pass an integer value in this field to control the size of the thumbnail returned in the data field. A value of 0 will return the default size of 40x40. The maximum size is 200, any value over 200 will return images 200x200. |
MediaObjectListResponse
Field |
Type |
Description |
---|---|---|
mediaObjects |
MediaObjectListItem [ } |
An array of media object list items. |
MediaObjectListItem
Field |
Type |
Description |
---|---|---|
downloadUrl |
String |
When true, the response will include the JAS URL for each file type media object. |
file |
String |
When true, the response will include the Base64 encoded data for any image file in the data field of the response. For text type media objects the text will be include in the data field of the response. |
itemName |
String |
A user given name for the media object item. When viewing media objects on JAS this is the name shown directly under each media object item in the left panel of the MO control. |
link |
String |
|
moType |
int |
Type 1 file attachments are from a Media Object Queue. Type 5 attachments are files uploaded individually to the JAS server. |
queue |
String |
For type 1 file attachments from a Media Object Queue the name of the queue. |
sequence |
int |
The sequence the number of that individual attachment in the set of attachments. |
updateDate |
String |
The date that the media object was last updated. |
updateHourOfDay |
int |
The hour that the media object was last updated. |
updateMinuteOfHour |
int |
The minute that the media object was last updated. |
updateSecondOfMinute |
int |
The second that the media object was last updated. |
updateUserID |
String |
The user that last updated that media object. |
hasValidTimestamp |
boolean |
Indicates if time stamp was valid. |
isDefaultImage |
boolean |
Indicates if image is default image. |
isMisc |
boolean |
<unknown> |
isOLE |
boolean |
Is an OLE attachment. |
isShortCut |
boolean |
<unknown> |
isText |
boolean |
Is a text type attachment. |
isUpdated |
boolean |
<unknown> |
isURL |
boolean |
Is a URL type attachment. |
data |
String |
For an image file this is the Base64 encoded string of the image data for a 40x40 size of the image. |
thumbFileLocation |
String |
The location of the thumbnail (40x40) saved on the device. A file is written for each image that has Base64 data included. Files are only written if data is requested. |
Download
- Method - downloadMediaObject
- Description - Downloads a full sized media object to a file on the device, based on the key information provided in the request.
- Returns - MediaObjectDownloadResponse
- Parameters - MediaObjectDownloadRequest
MediaObjectDownloadRequest
Field |
Type |
Description |
---|---|---|
moStructure |
String |
The Media Object structure ID, for example GT0801, GT48100. |
moKey |
ArrayList <String> |
The set of key values, as strings, that is the key of the media object. The API will handle formatting into a bar delimited set. Use the JDEmfUtilities.convertMillisecondsToYMDString() method to pass dates. |
formName |
String |
The application and form usually associated with this media object structure, for example P01012_W01012B. This is for security purposes. Security for media objects is based on the form being used. |
version |
String |
The version of the application noted in the formName. This is for security purposes. Security for media objects is based on the form being used. |
downloadURL |
String |
The downloadURL provided in the list response. When this value is already known, provide it so the service will not do the extra work of getting the URL. |
fileName |
String |
This will be the name of the file saved on the device file system. It is easiest (and uniqueness is guaranteed) to pass the file provided in the list response. |
sequence |
int |
The sequence number of this individual file in the set of attachments. |
height |
int |
When a value is passed in this field, the image will be scaled to this size before it is returned. If you provide only height, the width will be scaled to maintain the aspect ratio. |
width |
int |
When a value is passed in this field, the image will be scaled to his size before it is returned. If you provide only width, the height will be scaled to maintain the aspect ratio. |
FileAttachment
Field |
Type |
Description |
---|---|---|
fileName |
String |
The name of the file as stored in the database. |
fileLocation |
String |
The location of the file saved to the device file system. This includes the "file://" prefix so it can be directly used in image tags in an amx page. |
itemName |
String |
A string value the user may provide as the name of the attachment (if not supplied the file name will be used.) |
sequence |
int |
The sequence number of this individual attachment. |
thumbFileLocation |
String |
The file location of the thumbnail image (this value is not updated when the download method is called). |
downloadUrl |
String |
The JAS URL of the file attachment (this value is not populated when the download method is called). |
Upload
- Method - uploadMediaObject
- Description - Uploads a single file to the media object database based on key values provided in the request.
- Returns - MediaObjectUploadResponse
- Parameters - MediaObjectUploadRequest
MediaObjectUploadRequest
Field |
Type |
Description |
---|---|---|
moStructure |
String |
The Media Object structure ID (such as GT0801, GT48100). |
moKey |
ArrayList <String> |
The set of key values, as strings, that is the key of the media object. The API will handle formatting into a bar delimited set. Use the JDEmfUtilities.convertMillisecondsToYMDString() method to pass dates. |
formName |
String |
The application and form usually associated with this media object data structure (such as P01012_W01012B). This is for security purposes. Security for media objects is based on the form being used. |
version |
String |
The version of the application noted in the formName. This is for security purposes. Security for media objects is based on the form being used. |
file |
FileAttachment |
The resulting downloaded file with the name, fileLocation, sequence and itemName fields updated. |
FileAttachment
Field |
Type |
Description |
---|---|---|
fileName |
String |
The name of the file as stored in the database. (This value is not required for upload.) |
fileLocation |
String |
The location of the file saved to the device file system. This includes the "file://" prefix so it can be directly used in image tags in an amx page. |
itemName |
String |
A descriptive name. If not passed, the filename will be used. The extension will be added automatically. |
sequence |
int |
The sequence number of this individual attachment (this value is not required for upload). |
thumbFileLocation |
String |
The file location of the thumbnail image (this value is not required for upload). |
downloadUrl |
String |
The JAS URL of the file attachment (this value is not required for upload). |
MediaObjectUploadResponse
Field |
Type |
Description |
---|---|---|
itemName |
String |
A user given name for the media object item. When viewing media objects on JAS, this is the name shown directly under each media object item in the left panel of the MO control. The extension will be added automatically. If not passed, the file name is used. |
sequence |
int |
The sequence number of this individual attachment (assigned during the upload). |
Delete
- Method - deleteMediaObject
- Description - Deletes the file in the media object database based on key values provided in the request. Deletes the file on the device file system also.
- Returns - MediaObjectDeleteResponse
- Parameters - MediaObjectDeleteRequest
MediaObjectDeleteRequest
Field |
Type |
Description |
---|---|---|
moStructure |
String |
The Media Object structure ID (e.g. GT0801, GT48100). |
moKey |
ArrayList <String> |
The set of key values, as strings, that is the key of the media object. The API will handle formatting into a bar delimited set. Use the JDEmfUtilities.convertMillisecondsToYMDString() method to pass dates. |
formName |
String |
The application and form usually associated with this media object structure (e.g. P01012_W01012B). This is for security purposes. Security for media objects is based on the form being used. |
version |
String |
The version of the application noted in the formName. This is for security purposes. Security for media objects is based on the form being used. |
sequence |
int |
The sequence number of this individual file in the set of attachments. |
fileLocation |
String |
The location of the file on the device file system. |
MediaObjectDeleteResponse
Field |
Type |
Description |
---|---|---|
deleteStatus |
String |
The value 'Success' will be returned for successful deletes. Any other value is a failure. |
error |
String |
In the case of failure details of the error will be included here. |
Understanding the Processing Option Service
The processing option service is an AIS service for handling processing options.
The URI for the service is:
http://<AIS Server>:<port>/jderest/poservice
The input JSON is:
{ "token": "044uZUG2Uk1Vd6hzmAhPfILitA2pVLDVKLOYdh4HR71D7s=MDE5MDA2ODM3NTQ3NzU4MDMwNTg2MzY4MFNvYXBVSTEzOTcwNTYxMTIxMTE=", "applicationName":"P01012", "version":"ZJDE0001", "deviceName":"RESTclient" }
The response JSON is like this:
{ "application": "P01012", "version": "ZJDE0001", "processingOptions": { "GoToSupplierMaster_5": { "type": 1, "value": " " }, "GoToCustomerMaster_6": { "type": 1, "value": " " }, "GoToCSMS_8": { "type": 1, "value": " " }, "HideTax_4": { "type": 1, "value": " " }, "SearchTypeDefault_7": { "type": 2, "value": " " }, "cTypeCode_11": { "type": 1, "value": "A" } }, "errors": "" }
Using the AIS Service for Processing Options in a Mobile Application
You can call the processing option service passing an application and version. You can obtain the version from the mobile application processing options, which specify the version of the EnterpriseOne application the mobile application uses. For more information about the processing options for mobile applications, see the JD Edwards EnterpriseOne Applications Functionality for Mobile Devices Implementation Guide.
If you use the processing option service, you must add "processingOption" to the list of required capabilities in the about.properties. If you do not do this, you will receive an error at runtime. See Understanding AIS Server Capabilities for more information.
ProcessingOptionRequestpoRequest = new ProcessingOptionRequest(); poRequest.setEnvironment(ApplicationGlobals.getInstance.getLoginResponse().getEnvironment()); poRequest.setRole(ApplicationGlobals.getInstance.getLoginResponse().getRole()); poRequest.setJasserver(ApplicationGlobals.getInstance.getLoginResponse().getJasserver()); poRequest.setToken(ApplicationGlobals.getInstance.getLoginResponse().getUserInfo().getToken()); poRequest.setApplicationName("P5648203"); poRequest.setVersion("GNJ001"); try { JSONObject jsonObject = (JSONObject) JSONBeanSerializationHelper.toJSON (poRequest); String postData = jsonObject.toString(); //send in po Request json, POST and poservice String response = JDERestServiceProvider.jdeRestServiceCall(postData, poRequest.POST, poRequest.PO_SERVICE); //response can be serialized to ProcessingOptionSet class ProcessingOptionsSet poSet = (ProcessingOptionsSet) JSONBeanSerializationHelper. fromJSON (ProcessingOptionsSet.class, response); if (poSet != null) { //get the individual option and cast it to a variable of matching type String attachmentAllowed = (String)poSet.getOptionValue ("szAttachmentAllowed_1")); }
Remember to inspect the "errors" element of the response in case an error was encountered when trying to fetch the processing options you requested.
There are six supported data types. These are based on the data item used in the Processing Option Design Aid for each option.
You can get the type of the option before attempting to cast it, which is the recommended method. Or you can just cast it to the type you expect, because it is unlikely to change. The default is String, so you will always be able to get to a string version of the option value.
Type Code |
Type Constant |
Java Type |
JDE DD Type |
---|---|---|---|
1 |
STRING_TYPE |
String |
String |
2 |
CHAR_TYPE |
String |
Character |
9 |
BIG_DECIMAL_TYPE |
BIG Decimal |
Math Numeric |
11 |
DATE_TYPE |
Date |
Date |
15 |
INTEGER_TYPE |
Integer |
Integer |
55 |
CALENDAR_TYPE |
Calendar |
Utime |
Understanding the Application Stack Service
The application stack is a service that enables interactive communication with applications running on the EnterpriseOne web client. By using the application stack service, you can perform form interconnects to receive data from the resulting form. You can perform more complex interactions with applications that have cross-form transaction boundaries, for example where you do not want the header saved until the details are added and so forth. Also, with the application stack, you can implement a record reservation in mobile applications that corresponds to a record reservation in the web application.
The purpose of application stack processing is that it enables you to establish a session for a specific application and maintain that session across calls. So you initiate a session or 'open' it with one service call, then you can have any number of service calls to 'execute' actions against the currently running application. Finally, you 'close' the session with a service call.
To accomplish this stateful model, some additional data is managed for each service call, including stack ID, state ID, and rid. Also, each request to execute actions against the running application must be sent with the formOID to ensure the form you are expecting is indeed the currently running form.
Service Endpoint
The application stack service is exposed by the AIS Server at the endpoint:
http://<aishost>:<port>/jderest/appstack
Capability
The application stack capability is exposed in the default configuration as "applicationStack." You must add this to your used or required capability lists within your mobile application to use this capability.
Prerequisite
The AIS Server must be configured to "Keep JAS Sessions Open" so that the session can be maintained across service calls.
JSON Example of an Application Stack Request
This section shows an example of JSON code that performs the following actions:
Accessing the Address Book application to find a record.
Taking the row exit to the Phones form.
Adding a phone number.
Saving and closing the application stack.
Open Application: Request and Response
Example - Open Application - Request shows an example of the application stack request. It contains all of the other environment and credential information that is included in a form service request. After this information, it contains a single instance of a form service request called formRequest. You can use this to include any action you want to take on this original form, just like a normal form service request. Most important is the action, which is "open" in this case. This tells the EnterpriseOne web client to keep the form open so that you can interact with it on future requests.
So for this request with the Address Book (P01012), the search type is set to "E to perform a "find" and retrieve the first five records.
Example - Open Application - Request
{ "token": "044J57pHCCB3AzH7/W6Vetm0+yVG6pnKOPl823587SfY6o=MDE5MDA2MTYxOTE0NTE0NjE2OTEyNTg4OFNvYXBVSTE0MDEyMTA5MDE1MDM=", "action": "open", "formRequest": { "returnControlIDs": "54|1[19,20]", "maxPageSize": "5", "formName": "P01012_W01012B", "version": "ZJDE0001", "findOnEntry": "TRUE", "formInputs": [ { "value": "E", "id": "2" } ] }, "deviceName": "RESTclient" }
Example - Open Application - Response
{ "fs_P01012_W01012B": { "title": "Work With Addresses", "data": { … condensed…. }, "errors": [], "warnings": [] }, "stackId": 1, "stateId": 1, "rid": "e51b593df7a884ea", "currentApp": "P01012_W01012B_ZJDE0001", "sysErrors": [] }
The response contains the data (including the 5 rows, which are not shown), along with additional information used for all subsequent interactions with the open application.
Execute Actions on Application: Request and Response
Next, the JSON code should contain commands to select one of the records returned and access the row exit to Phones (through a form interconnect). With this service call, make sure to pass in the values for stack ID, state ID and rid from the last call, along with the token. Also, indicate an action of "execute," so it knows you are interacting with an open application.
This execute type request contains an actionRequest which can include returnControlIDs for the form you expect to end on and an array of formActions to execute on the form indicated by formOID.
Example - Execute Actions on Application - Request
{ "token": "044DCcituJDHbxBhPcgOuhCb0Av/xnNiUFxqPTVD6hDfnU=MDE5MDA2MTc1NjYwMzYwMzk0MTE0OTY5NlNvYXBVSTE0MDEyMTkzOTIxMzA=", "stackId": 1, "stateId": 1, "rid": "e51b593df7a884ea", "action": "execute", "actionRequest": { "returnControlIDs": "32|7|1[28,29,66]", "maxPageSize": "4", "formOID": "W01012B", "formActions": [ { ".type": "com.oracle.e1.jdemf.FormAction", "command": "SelectRow", "controlID": "1.0" }, { ".type": "com.oracle.e1.jdemf.FormAction", "command": "DoAction", "controlID": "65" } ] }, "deviceName": "RESTclient" }
Example - Execute Actions on Application - Response
{ "fs_P0115_W0115A": { "title": "Phone Numbers", "data": { ….condensed.. "summary": { "records": 3, "moreRecords": false } } }, "errors": [], "warnings": [] }, "stackId": 1, "stateId": 2, "rid": "e51b593df7a884ea", "currentApp": "P0115_W0115A_ZJDE0001", "sysErrors": [] }
Notice that the state ID has increased after each service call. Also notice that the "currentApp" has changed, and the JSON is representing the Phones application.
Adding a Phone Number
Example - Adding a Phone Number - Request shows how to execute an additional action on this stack that adds a phone number. You can do this as many times as you want, incrementing the state ID each time. The action does not include saving the information; it only populates the grid.
Example - Adding a Phone Number - Request
{ "token": "044DCcituJDHbxBhPcgOuhCb0Av/xnNiUFxqPTVD6hDfnU=MDE5MDA2MTc1NjYwMzYwMzk0MTE0OTY5NlNvYXBVSTE0MDEyMTkzOTIxMzA=", "stackId": 1, "stateId": 2, "rid": "e51b593df7a884ea", "action": "execute", "actionRequest": { "formOID": "W0115A", "formActions": [ { "gridAction": { "gridID": "1", "gridRowInsertEvents": [ { "gridColumnEvents": [ { "value": "720", "command": "SetGridCellValue", "columnID": "28" }, { "value": "12345", "command": "SetGridCellValue", "columnID": "29" }, { "value": "CAR", "command": "SetGridCellValue", "columnID": "27" } ] } ] } } ] }, "deviceName": "RESTclient", "ssoEnabled": true }
Execute Close Application: Request and Response
Lastly, the JSON code should contain commands to press the Save button and close the application stack. This saves all phone records that were added to the grid.
Example - Execute Close Application - Request
{ "token": "044DCcituJDHbxBhPcgOuhCb0Av/xnNiUFxqPTVD6hDfnU=MDE5MDA2MTc1NjYwMzYwMzk0MTE0OTY5NlNvYXBVSTE0MDEyMTkzOTIxMzA=", "stackId": 1, "stateId": 3, "rid": "e51b593df7a884ea", "action": "close", "actionRequest": { "formOID": "W0115A", "formActions": [ { "command": "DoAction", "controlID": "4" } ] }, "deviceName": "RESTclient", "ssoEnabled": true }
Example - Execute Close Application - Response
{ "fs_P0115_W0115A": { "title": "Phone Numbers", "data": { ….condensed… ], "summary": { "records": 4, "moreRecords": false } } }, "errors": [], "warnings": [] }, "stackId": 0, "stateId": 0, "rid": "", "currentApp": "P0115_W0115A_ZJDE0001", "sysErrors": [] }
When the stack is closed, the stack ID, state ID, and rid are cleared, indicating you can no longer interact with that stack.
Mobile Application Example
The application manages the alternate addresses for the 0 contact of an address number. It lists the first 10 "E" type records in the Address Book, and allows the user to select a record where they can add, update, or delete alternate addresses. Notice that the framework handles all of the stack maintenance for you within the ApplicationStack object. You do not need to manually manage the rid, stack ID, or state ID in your mobile application. The API does that for you.
An ApplicationStack variable is defined in the main DC class. You should define one of these for each stack you want to maintain. For example:
ApplicationStack appStackAddress = new ApplicationStack();
When the mobile application opens, it retrieves the Address Book records and saves the response in a data control variable for the P01012_W01102B form.
public void getABRecords() { // Retrieve a list of customers from the P03013_W03013A form. LoginResponse lr = getLoginResponse(); FormRequest formRequest = new FormRequest(); formRequest.setReturnControlIDs("1"); formRequest.setFormName("P01012_W01012B"); formRequest.setReturnControlIDs("54|1[19,20]"); formRequest.setFormServiceAction("R"); formRequest.setMaxPageSize("10"); FSREvent findFSREvent = new FSREvent(); String name = lr.getUsername(); findFSREvent.setFieldValue("54", "E"); findFSREvent.doControlAction("15"); // Find button formRequest.addFSREvent(findFSREvent); try { //open P01012_W01012B String response = appStackAddress.open(formRequest); p01012_W01012B_FormParent = (P01012_W01012B_FormParent)JSONBeanSerializationHelper.fromJSON(P01012_W01012B_FormParent.class, response); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { throw new AdfException(e.getMessage(), AdfException.ERROR); } }
When an Address Book record is selected in the mobile application, the mobile application performs a service call to perform the row exit on the open application. It checks to make sure the interconnect happened, and then performs a second interconnect to Work with Alternate Addresses form. Finally, it checks that it is on the addresses form and then deserializes the response to the data control variable for the addresses form. The Address Book application has a multi-select grid, and taking a row exit when multiple records are selected causes issues; therefore the action is to deselect all, and then select the correct one.
public String goToAltAddress() { String nav = ""; ActionRequest getAddressAction = new ActionRequest(); FSREvent selectEvent = new FSREvent(); try { getAddressAction.setFormOID("W01012B"); Integer rowIndex = (Integer)AdfmfJavaUtilities.evaluateELExpression("#{pageFlowScope.selectedABIndex}"); if (rowIndex != null) { selectEvent.unselectAllGridRows("1"); //select the row they chose selectEvent.selectRow("1", rowIndex.intValue()); //deselect the previous row (W01012B has multi select grid and we are only viewing one at a time selectEvent.doControlAction("67"); //whos who exit getAddressAction.addFSREvent(selectEvent); String response = appStackAddress.executeActions(getAddressAction); if (appStackAddress.getLastAppStackResponse().checkSuccess("P0111_W0111A")) { selectWhosWho(); if (appStackAddress.getLastAppStackResponse().checkSuccess("P01111_W01111E")) { nav = "to_Addresses"; } } } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { throw new AdfException(e.getMessage(), AdfException.ERROR); } public void selectWhosWho() { if (appStackAddress.getLastAppStackResponse().checkSuccess("P0111_W0111A")) { try { //send another request to go to alt address ActionRequest selectAction = new ActionRequest(); FSREvent findEvent = new FSREvent(); //findAction.setReturnControlIDs("32|7|1[28,29,66]"); selectAction.setFormOID("W0111A"); findEvent.selectRow("1", 0); //first whos who row findEvent.doControlAction("148"); selectAction.addFSREvent(findEvent); String response = appStackAddress.executeActions(selectAction); if (appStackAddress.getLastAppStackResponse().checkSuccess("P01111_W01111E")) { p01111_W01111E_FormParent = (P01111_W01111E_FormParent)JSONBeanSerializationHelper.fromJSON(P01111_W01111E_FormParent.class, response); } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { throw new AdfException(e.getMessage(), AdfException.ERROR); } } } new AdfException(e.getMessage(), AdfException.ERROR); } return nav; }
The user can then navigate to an individual address to change or delete it. They can also add a new one.
This method handles saving an existing address or adding a new one. It also handles any errors that were returned from the service.
public String saveAddress() { String nav = ""; String formMode = (String)AdfmfJavaUtilities.evaluateELExpression("#{pageFlowScope.formMode}"); ActionRequest addAction = new ActionRequest(); FSREvent saveEvent = new FSREvent(); Integer rowIndex = null; if (formMode.equals("A") && this.getArrayError().size() > 0) { //there was an error on a previously added one, it may be at the form level so we can't easily identify the record to fix, close the form and open it again cancelAddress(); } //clear errors each time to try again setArrayError(new ArrayList()); try { addAction.setFormOID("W01111E"); GridAction gridAction = new GridAction(); if (formMode.equals("A")) { GridRowInsertEvent gri = new GridRowInsertEvent(); //set the column values gri.setGridColumnValue("34", singleAddressRow.getSAddressType_34().getValue()); gri.setGridColumnValue("26", singleAddressRow.getSAddressLine1_26().getValue()); gri.setGridColumnValue("22", singleAddressRow.getSCity_22().getValue()); gri.setGridColumnValueDate("18", singleAddressRow.getDtBeginDate_18().getDate()); //add the row gridAction.insertGridRow("1", gri); } else { if (rowIndex == null) { rowIndex = (Integer)AdfmfJavaUtilities.evaluateELExpression("#{pageFlowScope.selectedAddressIndex}"); } GridRowUpdateEvent gru = new GridRowUpdateEvent(); //set the column values gru.setGridColumnValue("34", singleAddressRow.getSAddressType_34().getValue()); gru.setGridColumnValue("26", singleAddressRow.getSAddressLine1_26().getValue()); gru.setGridColumnValue("22", singleAddressRow.getSCity_22().getValue()); gru.setGridColumnValueDate("18", singleAddressRow.getDtBeginDate_18().getDate()); //update the row gridAction.updateGridRow("1", rowIndex.intValue(), gru); } //add the grid action to the events saveEvent.addGridAction(gridAction); saveEvent.doControlAction("12"); //OK //addAction.setReturnControlIDs("32|7|1[28,29,66]"); addAction.addFSREvent(saveEvent); String response = appStackAddress.executeActions(addAction); //after save it returns to whos who, open it again to get final list if (appStackAddress.getLastAppStackResponse().checkSuccess("P0111_W0111A")) { selectWhosWho(); if (appStackAddress.getLastAppStackResponse().checkSuccess("P01111_W01111E")) { nav = "__back"; } } else { if (appStackAddress.getLastAppStackResponse().checkSuccess("P01111_W01111E")) { P01111_W01111E_FormParent tempW0111E = (P01111_W01111E_FormParent)JSONBeanSerializationHelper.fromJSON(P01111_W01111E_FormParent.class, response); //check for errors on the form if (tempW0111E.getFs_P01111_W01111E() != null && tempW0111E.getFs_P01111_W01111E().getErrors() != null && tempW0111E.getFs_P01111_W01111E().getErrors().length > 0) { //show error addErrors(tempW0111E.getFs_P01111_W01111E().getErrors()); } } } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { throw new AdfException(e.getMessage(), AdfException.ERROR); } return nav; }
The following sample code shows an example of the method to delete the address. After deleting and saving, the EnterpriseOne form closes, so you have to open it again with the selectWhosWho method.
public String deleteAddress(int key) { String nav = ""; ActionRequest deleteActionRequest = new ActionRequest(); FSREvent deleteEvent = new FSREvent(); deleteActionRequest.setFormOID("W01111E"); //deleteActionRequest.setReturnControlIDs("32|7|1[28,29,66]"); deleteEvent.selectRow("1", key); //press Delete button deleteEvent.doControlAction("41"); //press OK button deleteEvent.doControlAction("12"); //add the FSR event to the request deleteActionRequest.addFSREvent(deleteEvent); try { String response = appStackAddress.executeActions(deleteActionRequest); if (appStackAddress.getLastAppStackResponse().checkSuccess("P0111_W0111A")) { selectWhosWho(); if (appStackAddress.getLastAppStackResponse().checkSuccess("P01111_W01111E")) { nav = "__back"; } else { //erors on delete? } } else if (appStackAddress.getLastAppStackResponse().checkSuccess("P01012_W01012B")) { nav = "to_AB"; } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } return nav; }
After the application finishes working with the set of addresses, the application stack can be closed, as shown in the following example:
appStackAddress.close();
ApplicationStack Methods
The following table describes the ApplicationStack methods:
Modifier and Type |
Method |
Description |
---|---|---|
|
|
Opens a form, allowing further interactions with subsequent service calls. |
|
|
Executes actions on an already open form. |
|
|
Closes all applications in the application stack, after executing the actions requested |
|
|
Closes all applications in the application stack, without doing any further actions |
|
|
Use this to set the default feature if you are using an ApplicationStack from a re-usable component. Similar to how you have to override the default feature for a form service call. Do this call before other requests. |
|
|
Returns the last response which includes the stack ID, state ID, rid and system errors. |
ApplicationStackResponse Methods
The following table describes the ApplicationStackResponse methods:
Modifier and Type |
Method |
Description |
---|---|---|
|
|
Returns true if the last response was for the appForm (for example P01012_W01012B) if the form does not match it returns false. |
Data Service (Release 9.1.5.5)
The AIS Server provides an endpoint called "dataservice" for data query or count requests over tables or business views.
Data service calls are made using the DataRequest object. If you use the data service, you must include the "dataservice" capability in the required or used capabilities list.
Table Data Service Request Required Parameters
Parameter |
Description |
Values |
---|---|---|
targetName |
The name of the table or view to count or query. |
Example values: F0101 or V4210A |
targetType |
The object type to count or query: table or business view. |
DataRequest.TARGET_TABLE DataRequest.TARGET_VIEW |
dataServiceType |
The type of operation to be performed: count or query (represented by the value BROWSE). |
DataRequest.TYPE_COUNT DataRequest.TYPE_BROWSE |
Table Data Service Request Optional Parameters
Parameter |
Description |
Values |
---|---|---|
findOnEntry |
This parameter determines if the service performs an automatic find. |
FormRequest.TRUE FormRequest.FALSE |
returnControlIDs |
Columns to be returned in the form of Table.Column. |
Example values: F0101.AN8|F0101.PA8|F0101.ALPH |
maxPageSize |
The maximum amount of records to return for a browse operation |
|
query |
A query, using the column names (F0101.AN8) for a complex select operation. The only difference between this and the query described in Query Events, is the way the control IDs are passed in. |
Example - Data Service Example
This example requests either a count or records (browse) from the F0150 table, using a query for a specific structure type (ES) and parent (PA8). For a count, it uses the helper to get the count value. For the browse, it de-serializes the response into a generated class (generated for data request).
public void executeDataRequest(boolean count) { try { //created the data request DataRequest children = new DataRequest(); //it is a count type if(count){ children.setDataServiceType(DataRequest.TYPE_COUNT); } else{ children.setDataServiceType(DataRequest.TYPE_BROWSE); children.setReturnControlIDs("F0150.AN8|F0150.OSTP"); } //over the F0150 table children.setTargetName("F0150"); //indicate table type children.setTargetType(DataRequest.TARGET_TABLE); //create a query Query childrenQ = new Query(); //set it to do a find childrenQ.setAutoFind(true); //match all conditions childrenQ.setMatchType(Query.MATCH_ALL); //first condition is value of ES in the OSTP column childrenQ.addStringCondition("F0150.OSTP", StringOperator.EQUAL(), "ES"); //second condition is value of 7500 in the PA8 column childrenQ.addStringCondition("F0150.PA8", StringOperator.EQUAL(), "7500"); //set the query to the request children.setQuery(childrenQ); //send the request in, indicatging the data service uri String response = JDERestServiceProvider.jdeRestServiceCall(children, JDERestServiceProvider.POST, JDERestServiceProvider.DATA_SERVICE_URI); if(count){ //marchal the response to the CountResponse class f0150CountResponse childrenCount = (f0150CountResponse) JSONBeanSerializationHelper.fromJSON(f0150CountResponse.class, response); setCount(childrenCount.getDs_F0150().getCount()); } else{ setF0150fp( (DATABROWSE_F0150_FormParent) JSONBeanSerializationHelper.fromJSON(DATABROWSE_F0150_FormParent.class, response)); } } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
Data Service Data Aggregation (API 2.2.1 and EnterpriseOne Tools Release 9.2.0.2)
Data service data aggregation provides the capability to request an aggregation of values in a data service request. To perform aggregation functions over records from tables or business views, you must add both dataservice
and dataServiceAggregation
to the used capabilities list before using the aggregation APIs.
The following aggregation information is sent in the DataRequest object attribute:
aggregation, AggregationInfo object
An aggregation consists of the following three arrays of objects:
aggregations array.
An array of columns with their associated aggregation type.
groupBy array.
An array of columns to group by.
orderBy array.
An array of columns to order by with the direction.
You can also order by an aggregation result.
having array.
An array of aggregations with conditions to reduce the result based on aggregation values.
The following table describes the seven column-specific aggregation types that are available. You can combine more than one type in a single request. Based on the results of a find or query, multiple aggregations can be performed over multiple columns.
Table Column-specific Aggregation Types
Aggregation |
Constant |
---|---|
Sum |
|
Minimum |
|
Maximum |
|
Average |
|
Count Distinct |
|
Average Distinct |
|
Sum Distinct |
|
In addition, there is an aggregation type for performing a count called Count* that is available through the following API:
AggregationInfo_addCount();
There are two possible directions to order by:
Ascending, which uses the following constant:
OrderByDirection.ORDER_DIRECT_ASCENDING()
Descending, which uses the following constant:
OrderByDirection.ORDER_DIRECT_DESCENDING()
Example - Calling an Aggregation Type Data Request shows how to call an aggregation type data request. In the example, two data requests are sent in a single batch to the AIS Server. The first one is an aggregation of columns in V0101 without a Groupby array. The second is an aggregation request over F060116 with a Groupby array.
At the end of the data request, the AggregationResponseHelper methods are used to get the specific aggregations from the responses. If there is a Groupby array in the response, the helper will return a JDONArray, which you will have to iterate with to get individual aggregate values for each group. Specific AggregationResponseHelper methods are provided for consuming a batch response.
Example - Calling an Aggregation Type Data Request
public void dataRequestBatchAggregation() { /*** One ****/ DataRequest dataAggregation = new DataRequest(); dataAggregation.setDataServiceType(DataRequest.TYPE_AGGREGATION); dataAggregation.setTargetName("V0101"); dataAggregation.setTargetType(DataRequest.TARGET_VIEW); AggregationInfo aggregation = new AggregationInfo(); aggregation.addAggregationColumn("AN8", AggregationType.AGG_TYPE_SUM()); aggregation.addAggregationColumn("AN8", AggregationType.AGG_TYPE_AVG()); aggregation.addAggregationColumn("AT1", AggregationType.AGG_TYPE_COUNT_DISTINCT()); aggregation.addCount(); dataAggregation.setAggregation(aggregation); Query an8Query = new Query(); an8Query.setAutoFind(true); an8Query.setMatchType(Query.MATCH_ALL); an8Query.addNumberCondition("F0101.AN8", NumericOperator.LESS(), 6001); dataAggregation.setQuery(an8Query); /****TWO*****/ DataRequest dataAggregation2 = new DataRequest(); dataAggregation2.setFindOnEntry(true); dataAggregation2.setDataServiceType(DataRequest.TYPE_AGGREGATION); dataAggregation2.setTargetName("F060116"); dataAggregation2.setTargetType(DataRequest.TARGET_TABLE); AggregationInfo aggregation2 = new AggregationInfo(); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_SUM()); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_AVG()); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_AVG_DISTINCT()); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_MAX()); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_MIN()); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_SUM_DISTINCT()); aggregation2.addCount(); aggregation2.addAggregationColumn("AN8", AggregationType.AGG_TYPE_COUNT_DISTINCT()); aggregation2.addAggregationGroupBy("HMCO"); aggregation2.addAggregationGroupBy("HMCU"); aggregation2.addAggregationOrderBy("HMCO", OrderByDirection.ORDER_DIRECT_DESCENDING()); dataAggregation2.setAggregation(aggregation2); BatchDataRequest batchDataRequest = new BatchDataRequest(); batchDataRequest.getDataRequests().add(dataAggregation); batchDataRequest.getDataRequests().add(dataAggregation2); String response = JDERestServiceProvider.jdeRestServiceCall(batchDataRequest, JDERestServiceProvider.POST, JDERestServiceProvider.DATA_SERVICE_URI); JSONArray array = AggregationResponseHelper.getAggregateValuesArrayBatch(response, "F060116", 1); setSalaryChartList(new ArrayList<salaryChart>()); setCountChartList(new ArrayList<CountChart>()); for (int i = 0; i < array.length(); i++) { JSONObject aGroup = array.getJSONObject(i); JSONObject groupByInfo = (JSONObject) aGroup.get(AggregationResponseHelper.GROUP_BY); Double average = (Double) aGroup.get("SAL_AVG"); Integer count = (Integer) aGroup.get("COUNT"); salaryChartList.add( new salaryChart( average, groupByInfo.get("HMCU").toString().trim())); countChartList.add( new CountChart( count, groupByInfo.get("HMCU").toString().trim())); } setAverage(AggregationResponseHelper.getSimpleAggregateValueBatch(response, "V0101", 0, AggregationType.AGG_TYPE_AVG(), "AN8")); }
Example - Having Example
This example shows how to reduce the data set with conditions based on the aggregate values, by using a having clause.
public void dataRequestHaving() DataRequest dataAggregation2 = new DataRequest(); dataAggregation2.setFindOnEntry(true); dataAggregation2.setDataServiceType(DataRequest.TYPE_AGGREGATION); dataAggregation2.setTargetName("F060116"); dataAggregation2.setTargetType(DataRequest.TARGET_TABLE); //create aggregation info object and add desired aggregations AggregationInfo aggregation2 = new AggregationInfo(); aggregation2.addAggregationColumn("SAL", AggregationType.AGG_TYPE_AVG()); aggregation2.addCount(); //add desired group by columns aggregation2.addAggregationGroupBy("HMCU"); //add order by average sal dec and hmcu dec with direction aggregation2.addAggregationOrderBy("SAL", AggregationType.AGG_TYPE_AVG(), OrderByDirection.ORDER_DIRECT_DESCENDING()); aggregation2.addAggregationOrderBy("HMCU", OrderByDirection.ORDER_DIRECT_DESCENDING()); //add having average salary greater than 50,000 Having having = new Having(); having.addNumberCondition("SAL", AggregationType.AGG_TYPE_AVG(), NumericOperator.GREATER(), 50000); dataAggregation2.setHaving(having); //set the aggregation info in the request dataAggregation2.setAggregation(aggregation2); String response = JDERestServiceProvider.jdeRestServiceCall(dataAggregation2, JDERestServiceProvider.POST, JDERestServiceProvider.DATA_SERVICE_URI); //use helper to get array of values (add them to a list) JSONArray array = AggregationResponseHelper.getAggregateValuesArray(response, "F060116"); setSalaryChartList(new ArrayList<salaryChart>()); setCountChartList(new ArrayList<CountChart>()); for (int i = 0; i < array.length(); i++) { JSONObject aGroup = array.getJSONObject(i); JSONObject groupByInfo = (JSONObject) aGroup.get(AggregationResponseHelper.GROUP_BY); Double average = (Double) aGroup.get("SAL_AVG"); Integer count = (Integer) aGroup.get("COUNT"); salaryChartList.add( new salaryChart( average, groupByInfo.get("HMCU").toString().trim())); countChartList.add( new CountChart( count, groupByInfo.get("HMCU").toString().trim())); } }
Understanding the Preferences Service (API 2.2.1 and EnterpriseOne Tools Release 9.2.0.2)
The preferences service enables the caller to save and retrieve EnterpriseOne user-level information that is stored by user, role, or *PUBLIC in the User Overrides Table (F98950) in EnterpriseOne.
The keys to the information are the Type (UOTY), User ID (USER), Sequence (SEQ) and Object Name (OBNM). The data is a string and is stored in the blob column BINDTA. All preference records are written with Type=PS.
The JDEMobileFramework API enables you to save a serialized HashMap of data to this table using the methods in the PreferencesService object. For the get operation, the data is de-serialized to a HashMap and returned.
It is important to note that the system stores the data as serialized values. For example, a Date object will be stored as a formatted string, which you must convert back to a date after the response is returned.
If a mobile application has multiple sets of data that need to be saved separately, a sequence field is available as a key. The default sequence value is zero if you do not specify a sequence.
Set and put actions are performed on behalf of the logged in user, with user records stored in the USER column. You can use the User Overrides application (P98950) in EnterpriseOne to manage the records. In P98950, you can copy records to different roles including *PUBLIC. The record will be retrieved from P98950 based on the user, role, or *PUBLIC hierarchy.
Preference Service Endpoint
The preference service is exposed by the AIS Server at the endpoint:
http://<aishost>:<port>/jderest/preference
Capability
The preference service capability is exposed in the default configuration as "preferenceService." You must add this to your used or required capability list within your mobile application to use this capability.
JSON Example of a Preference Service Request
The preferenceData element can contain any string. In the examples in this section, the strings are serialized HashMap objects storing name-value pairs for several different preference values.
Get Preferences: Request and Response
Example - Get Preferences - Request and Example - Get Preferences - Response show the JSON representation of the Get Preferences request and response.
Example - Get Preferences - Request
{ "token": "0440rV4RxUjDA4wDISJAvbhHtIXvju74FHMak7lM64gdsU=MDE5MDEwMTIzNDI0ODcwNTc1Mjg5MTEyNFJFU1RjbGllbnQxNDQ1ODg5ODY0MTYw", "action": "GET", "objectName": "M55100", "sequence": 0, "preferenceData": "{\"pref2\":15.45,\"pref1\":\"Preference 1 String\",\"pref3\":8,\"pref4\":1443645908933}", "deviceName": "RESTclient" }
Example - Get Preferences - Response
{ "objectName": "M55100", "type": "PS", "preferenceData": "{\"pref2\":15.45,\"pref1\":\"Preference 1 String\",\"pref3\":8,\"pref4\":1443645908933}", "sequence": 0 }
Put Preferences: Request and Response
Example - Put Preferences - Request and Example - Put Preferences - Response provide an example of the JSON representation of the Put Preferences request and response.
Example - Put Preferences - Request
{ "token": "0440rV4RxUjDA4wDISJAvbhHtIXvju74FHMak7lM64gdsU=MDE5MDEwMTIzNDI0ODcwNTc1Mjg5MTEyNFJFU1RjbGllbnQxNDQ1ODg5ODY0MTYw", "action": "PUT", "objectName": "M55100", "preferenceData": "{\"pref2\":15.45,\"pref1\":\"Preference 1 String\",\"pref3\":8,\"pref4\":1443645908933}", "deviceName": "RESTclient" }
Example - Put Preferences - Response
{ "objectName": "M55100", "type": "PS", "preferenceData": "{\"pref2\":15.45,\"pref1\":\"Preference 1 String\",\"pref3\":8,\"pref4\":1443645908933}" }
Examples of APIs Used to Enable Preferences in a Mobile Application
A mobile application can manage storage of preferences as needed by using the APIs. Also, remember that the "preferenceService" capability must be added to the used or required capability list in the mobile application's about.properties to support this functionality.
Example - Preference Variables, HashMap, and Preference Key
This example shows several variables designed to hold preference values along with a HashMap for serializing and saving the values. The key to these preferences is the mobile application ID, which is M55100, as shown here:
private String pref1Str; private Integer pref2Int; private BigDecimal pref3BigD; private Date pref4Date; private HashMap<String, Object> preferenceMap = new HashMap<String, Object>(); private static final String PREF_KEY = "M55100";
Example - Get Preferences API
A method is defined to retrieve preferences, calling the API with the key. When the method is called, the values will be populated based on the data saved.
public void retrievePreferences() { try { PreferenceService prefService = new PreferenceService(); this.setPreferenceMap(prefService.getPreferences(PREF_KEY)); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
Example - Get Preferences API
A method is defined to save preferences, calling the API with the key. When the method is called, the values in the variables will be saved in the database for that user.
public void putPreferences() { try { PreferenceService prefService = new PreferenceService(); prefService.setPreferences(PREF_KEY, this.getPreferenceMap()); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
In the setter for the hash map, the individual variables are updated with values from the map.
public void setPreferenceMap(HashMap<String, Object> preferenceMap) { this.preferenceMap = preferenceMap; this.pref1Str = (String) preferenceMap.get("pref1Str"); this.pref2Int = (Integer) preferenceMap.get("pref2Int"); //Big decimal serialized using Double, use Double to de-serialize this.pref3BigD = new BigDecimal((Double) preferenceMap.get("pref3BigD")); //dates are serialized using this format, use the same to de-serialize SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); String dateString = (String) preferenceMap.get("pref4Date"); try { this.pref4Date = sdf.parse(dateString); } catch (Exception e) { AdfException adfe = new AdfException(e.getMessage(), AdfException.ERROR); throw adfe; } }
In the getter for the hash map, the individual variables are set in the map and returned.
public HashMap<String, Object> getPreferenceMap() { this.preferenceMap = new HashMap<String, Object>(); preferenceMap.put("pref1Str", this.pref1Str); preferenceMap.put("pref2Int", this.pref2Int); preferenceMap.put("pref3BigD", this.pref3BigD); preferenceMap.put("pref4Date", this.pref4Date); return preferenceMap; }