6Appendix A - Creating a Sample Mobile Application
Before You Begin
Before following the instructions in this section, see Prerequisites in this guide to ensure you have completed the required prerequisites.
The prerequisites include the JDEMobileSampleApplication.zip. This zip file contains the components for running the same sample mobile application that this appendix describes how to create. You can use this sample for comparison purposes. To run this sample application, you must configure it with the JDEMobileFramework.jar and Login.jar as described in Including the JDEMobileFramework.jar and Including the Login.jar.
Remember, the files in the JDEMobileSampleApplication.zip are intended for reference purposes only.
In JDeveloper click the Help menu, About, and then click the Extensions tab.
In the "find" field, type
maf
and then press Enter. Scroll to the right to check the version.
Creating the Sample Address Book Mobile Application
This section contains the following topics:
Creating a New Mobile MAF Application
This section describes how to create a new sample mobile application entitled Address Book.
Launch JDeveloper.
Select the File menu > New > Application.
In the New Gallery, select Mobile Application Framework Application and click OK.
On "Name your application," enter AddressBook in the Application Name field, and then click Finish to skip the rest of the steps.
The application displays the Features list.
In the Features section, click the green plus sign to add a new feature to the list.
On Create MAF Feature, enter ABList in the Feature Name and Feature ID fields.
Click OK.
Select the Content tab.
Change the Content Type to MAF Task Flow.
Click the add button next to the File field.
On Create MAF Task Flow, use the default name in the File Name field for the task flow and click OK.
JDeveloper displays the new task flow.
In the Components window on the right, click the View button to add a new view to the task flow.
Name the new view ablist.
On the ViewController-task-flow.xml tab, double-click the new ablist view element to create the view page.
The new page opens automatically.
On the ablist.amx tab, change the
outputText value
to "Address Book" as shown in the preceding example. This is the title for the first page of the sample mobile application.Save your application.
Running the Mobile Application in the Simulator
To run the mobile application in the simulator:
![This image is described in surrounding text.](images/deploy_ab_app.png)
From the application drop-down, select Deploy > iOS1.
On Deployment Action, select Deploy application to simulator and click Finish.
Deployment details can be viewed in the deployment log. Wait for it to finish.
The simulator displays the application on the second page of the home screen.Click the application icon to launch it.
The page that you created appears with the header text "Address Book," as shown in the following example:
If your mobile application failed to build or deploy at this point, please refer to the Oracle Fusion Middleware Developing Mobile Applications with Oracle Mobile Application Framework documentation for more information:
http://docs.oracle.com/middleware/mobile200/mobile/develop/index.html
Using the JDE Mobile Helpers
This section describes how to incorporate the JDE Mobile Helpers into the sample mobile application.
See JDE Mobile Helpers for more information.
Including the JDEMobileFramework.jar
The JDEMobileFramework.jar provides a set of classes and API methods that enable the mobile application to manage (create, read, update, delete) data in EnterpriseOne through REST services.
To include the JDEMobileFramework.jar:
In JDeveloper, in the Projects panel, right-click the ApplicationController project and select Project Properties.
On Project Properties, select Libraries and Classpath.
Click the Add JAR/Directory button and select the JDEMobileFramework.jar that you downloaded to your local file system, and click Open.
If you do not have JDEMobileFramework.jar, see Prerequisites in this guide.
Click OK to save the properties. If you receive an error message, ignore it and click Cancel.
Including the Login.jar
The Login.jar provides a configuration page, login page, and a springboard. The springboard contains links to Legal Terms or the End User License Agreement (EULA), About, and Logout.
To include the Login.jar:
In JDeveloper, click the Applications drop-down menu and select Application Properties.
On Application Properties, select Libraries and Classpath, and then click the Add JAR/Directory button to add the Login.jar.
Click OK to save the properties.
In the Application Resources section, expand Descriptors > ADF META-INF, and double-click maf-application.xml to open it.
Click the Feature References tab, and then click the green plus sign to add a feature reference.
Click the Id drop-down menu and select com.oracle.e1.jdemf.login. If you receive an error message, ignore it and click Cancel.
Use the blue arrow on the right to move the login feature to the top of the list.
On the Application tab, clear the Show Navigation Bar on Application Launch check box.
In the Projects panel, expand ApplicationController > Application Sources > application and double-click LifeCycleListener.java to open it.
On the LifeCycleListener.java tab, place the following line of code in the existing start() method, as shown in the preceding example:
LoginConfiguration.setDefaultFeature("ABList");
This code directs the Login feature to navigate to the appropriate page after a successful login.
Save the LifeCycleListener.java.
Including the Javascript and CSS
The Javascript and CSS files are dependencies of the JDEMobileFramwork.jar and the Login.jar. The Javascript provides an animated icon to show that the mobile application is processing while making service calls. The CSS provides an extension to the styling skin provided by Oracle MAF. It enables you to make adjustments to the style of the configuration, login, and springboard pages of your mobile application.
To include the Javascript and CSS:
In the file system, copy the js folder provided in the JDEMobileFramework zip file, and save it to the
ViewController/public_html
directory.In the file system, copy the css folder provided in the JDEMobileFramework zip file, and save it to the
ApplicationController/public_html
directory.In the Projects panel in JDeveloper, expand ViewController > Application Sources >META_INF, and double-click the maf-feature.xml to open it.
Select the ABList feature, click the Content tab, and click the plus sign in the Includes section to add the jdemafJavascript.js file. This file is located in js folder.
Under ApplicationController > Application Sources > META-INF, open the maf-skins.xml and copy the following code into the file:
Note: Remove any code lines that might exist before you copy the following code into the file.<?xml version="1.0" encoding="UTF-8" ?> <adfmf-skins xmlns="http://xmlns.oracle.com/adf/mf/skin"> <skin id="s1"> <family>jdeCustomSkinFamily</family> <id>jdeCustomSkinFamily-v1.Android</id> <extends>jdeCustomSkinFamily</extends> <style-sheet-name>css/jdemfCustomStyles-Android.css</style-sheet-name> <version> <name>v1</name> <default>true</default> </version> </skin> <skin id="s2"> <family>jdeCustomSkinFamily</family> <id>jdeCustomSkinFamily-v1.iOS</id> <extends>jdeCustomSkinFamily</extends> <style-sheet-name>css/jdemfCustomStyles-iOS.css</style-sheet-name> <version> <name>v1</name> <default>true</default> </version> </skin> <skin id="s3"> <family>jdeCustomSkinFamily</family> <id>jdeCustomSkinFamily</id> <extends>mobileAlta-v1.1</extends> <style-sheet-name>css/jdemfCustomStyles-Base.css</style-sheet-name> <version> <name>v1</name> <default>true</default> </version> </skin> </adfmf-skins>
In the Application Resources panel, expand Descriptors > ADF META-INF, and open the maf-config.xml.
Enter jdeCustomSkinFamily for the <skin-family> and enter v1 for the <skin-version>, as show in the following example:
Including the Resource Bundle
The Resource Bundle contains text resources for the pages provided in the Login.jar.
To include the Resource Bundle:
Copy the jdemfResourceBundle.xlf file provided in the JDEMobileFramework zip file and save it to the following directory:
ApplicationController/src/com/oracle/e1/jdemf/bundle
You must add each directory in the path if it does not exist.
Note: The ViewController project is dependent on the ApplicationController project. Adding the bundle to the ApplicationController project will also make it available to the ViewController project.In JDeveloper, click the "refresh" button for the bundle to appear under com.oracle.e 1.
Right-click ViewController and select Project Properties.
On Project Properties, select Resource Bundle.
Set the Default Project Bundle Name to:
com.oracle.e1.jdemf.bundle.jdemfResourceBundle
Click OK to save the properties. If a warning message appears, ignore it and click Ok or Cancel to proceed.
Including Logo Images
You should include a logo image for the pages in the Login.jar. If you do not insert one, a question mark (?) appears in place of the image. Oracle provides the following image files as examples of the recommended size, quality, and color of images that you should use in your mobile application:
jde_transparent_no_jde_small.png
This is a 242 x 87 transparent image for the login page, intended for a white background.
jde_transparent_springboard.png
This is a 242 x 87 transparent image for the springboard, intended for a dark background.
You can use any image as long as it has the same dimensions as the example images. You can use the same name for the images and place them in the same location as instructed in the following steps.
To include logo images:
In the file system, copy the jde_transparent_no_jde_small.png file to the
ViewController/public_html/images
directory.Copy the jde_transparent_springboard.png to the
ViewController/public_html/images
directory.In JDeveloper, deploy the application.
You should see the configuration screen and login screen. After logging in, it should take you to your ABList feature with the page with the "Address Book" title.
The Login.jar also provides information screens if configuration or connection issues arise during login, for example:
Note: If you receive an error, under the Application Resources panel in JDeveloper, double-click maf-application.xml. In the maf.application.xml tab, make sure the Files and Network options are selected.
Enabling the Custom Springboard
The springboard provided in the Login.jar shows links to the About page, the EULA, and the Logout.
To enable the springboard:
Open the maf-application.xml.
In the Navigation section on the Application tab, clear the Show Navigation Bar on Application Launch check box.
For Springboard, select the Custom option
In the Feature drop-down menu, select com.oracle.e1.jdemf.springboard.
Select the Show Springboard Toggle Button check box.
For Springboard Animation, select the Slide option.
In the Slideout Width field, enter 150.
-
Clear any other check boxes and then click the Feature References tab.
In the Feature References section, click the green plus sign to add the springboard feature, and then select false for both the "Show on Navigation Bar" and "Show on Springboard" options.
Including the about.properties
The about.properties enables you to configure information displayed on the About page, including the application name, application version, and the application ID (which is used by EnterpriseOne application security for authorizing user access to the mobile application). If you enable the springboard, you should provide these values so that they appear on the About page.
To include the about.properties:
Copy the about.properties file provided in the JDEMobileFramework zip file and save it in the
ApplicationController/src
directory.-
In the Projects panel, expand Application Controller > Application Sources, and double-click about.properties to open it.
Modify the about.properties file with information for your application, as shown in the preceding example.
Click the Feature References tab.
In the Feature References section, click the green plus sign to add the com.oracle.e1.jdemf.about feature.
Including an End User License Agreement (EULA)
If you enable the springboard, you should include a EULA feature and EULA page so the Legal Terms link has a page to access. You can provide a license agreement for your application here.
To include a EULA:
Double-click the maf-feature.xml.
In the Features section, double-click the green plus sign to add a feature for the EULA.
On Create MAF Feature, enter EULA in the Feature Name field, give it a unique id, and then click OK.
After you create the EULA feature, select the Content tab.
Click the green plus sign next to the File field.
On Create MAF AMX Page, enter a name for the page in the File Name field.
Clear the Primary Action check box, and then click OK.
In the new eula.amx page, you can design your EULA page as needed, as shown in the below example.
Example - Using the Verbatim Tag to Include HTML
The following sample code is an example of a page that uses the verbatim tag to include HTML. It also uses the configured resource bundle (loadBundle tag).
<?xml version="1.0" encoding="UTF-8" ?> <amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx" xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt"> <amx:loadBundle basename="com.oracle.e1.jdemf.bundle.jdemfResourceBundle" var="jdeBundle" id="lb1"/> <amx:panelPage id="pp1"> <amx:facet name="header"> <amx:outputText value="#{jdeBundle.LEGAL_TERMS}" id="ot1"/> </amx:facet> <amx:facet name="secondary"> <amx:commandButton text="#{jdeBundle.DONE}" id="cb1" actionListener="#{eulaBean.doneEULA}"/> </amx:facet> <amx:verbatim id="v1"> <![CDATA[ <p class="MsoNormal" style="margin-bottom: 0.0001pt; text-align: center; line-height: normal;"><b><span style="font-size: 12pt; font-family: "Arial","sans-serif"; color: black;">MY END USER LICENSE AGREEMENT</span></b> </p> Legal.... ]]> </amx:verbatim> </amx:panelPage> </amx:view>
Save the EULA page.
In the Projects panel, right-click ViewController and select Project Properties.
On Project Properties, select Dependencies, select the ApplicationController.jpr, and click the green plus sign button.
On Edit Dependencies, click the Build Output check box, click OK, and then click OK again to close the Project Properties.
Add code for the Done button, which returns the user to the application after viewing the EULA. To do so:
In the Projects panel, expand ViewController > Web Content, and double-click the eula.amx.
In the eula.amx code, highlight the commandButton element.
In the Button - Done - Properties window on the right, hover over the Action Listener field and click the "gear" button, and select Edit.
On "Edit Property: Action Listener," click the New button to create a new managed bean.
On Create Managed Bean, complete the following fields and then click OK:
-Bean Name: eulaBean
-Class Name: EulaBean
-Scope: pageFlow
Click the New button next to the Method field to create a new method for the bean.
On Create Method, enter doneEULA in the Method Name field and click OK.
On "Edit Property: Action Listener," click OK to accept the new bean and method.
This adds the new bean method to the action listener.
In the code, right-click the
doneEula
method name and select Go to Declaration.In the new method, replace the
//add event code here...
comment with this line of code:JDEmfUtilities.goToDefaultFeature();
Your new method should look like this:
In the Projects panel, expand Application Controller > Application Sources > application, and double-click the LifeCycleListenerImple.java.
Add the following line of code to the start() method to set the EULA Feature, and make sure to use the feature ID that you used to create the feature. If you do not remember it, you can find the ID in the maf-feature.xml.
LoginConfiguration.setEULAFeature("jdemf.example.EULA");
The following example shows the line in the LifeCycleListenerImple.java:
Deploy the application again. You should see a springboard launch icon.
The page displays the About, Legal Terms, and Logout links. The About page shows the information in about.properties; the Legal Terms page shows the eula.amx page:
Connecting to the EnterpriseOne Application Interface Services (AIS) Server
After you configure the Login.jar, the application displays a configuration screen for connecting to the AIS Server.
To connect to the AIS Server:
On the first page in the mobile application, enter the URL to the AIS Server and click OK:
Note: If you are using Oracle Mobile Cloud Service (MCS) to host your mobile applications, instead of entering the URL to the AIS Server, enter the URL to your MCS Instance. See Generating a New Mobile Application from a Mobile Application Archive for more information.If the connection is successful, enter your EnterpriseOne user name and password in the following login page:
Based on the AIS Server configuration, the Environment, Role, and JAS Server fields, as well as the "Use Single Sign On" check box, may or may not be displayed here.
Click Login.
If the application takes you to the ABList feature, you have successfully established a session with the AIS Server. Your mobile application can make service calls.
AIS Client Class Generator
The AIS Client Class Generator is a JDeveloper extension that generates Java classes to store data returned from the REST service calls.
You must configure the AIS Client Class Generator before you can use it to generate classes. See "Configuring the AIS Client Class Generator" in the JD Edwards EnterpriseOne Application Interface Services Server Reference Guide.
Reading EnterpriseOne Data
The JDEMobileFramework.jar includes APIs that enable the mobile application to make service calls to EnterpriseOne and read data from EnterpriseOne.
You use the AIS Client Class Generator to generate classes to hold the data returned from those calls. To do so, perform the following tasks:
Configure the AIS Client Class Generator to generate classes in a custom package.
Create a new Java class in the application package.
Call the AIS service for populating the data in the Data Control.
Create a UI for displaying the data.
To use the AIS Client Class Generator to generate classes in a custom package:
In JDeveloper, select the Tools menu, Preferences.
Select AIS Client Class Generator from the list on the left.
In the Java Package field, enter a valid package name, and then click OK.
In the Projects panel, click ApplicationController to highlight it. You must make sure that this is highlighted before generating classes.
Select the Tools menu, AIS Client Class Generator to launch it.
In the AIS Client Class Generator, complete these fields to generate classes for the W01012B form in the P01012 application:
Username. Enter an EnterpriseOne username.
Password. Enter the EnterpriseOne password.
Application Name. Enter P01012.
Form Name. Enter W01012B.
Make sure the following check boxes are selected, and then click the Generate button.
DemoMode
Generate for Mobile Application
The Preview JSON Data and Keep JSON Files check boxes are optional. If you select the Preview JSON Data check box, the JSON displays a preview of the JSON, as shown in the following example:
On JSON Data Preview, make sure the preview shows at least one grid record, and then click Continue.
After receiving confirmation that the generation was a success, click OK.
In the Projects panel, click the "refresh" button so that the new classes appear in the ApplicationController tree.
To create a new Java class in the application package:
In the Projects panel, expand ApplicationController > Application Sources, right-click application, and then select New > Java Class.
On Create Java Class, enter AddressBookDC in the Name field and then click OK.
This will be the main data control for the application.
Add a member to the AddressBookDC class of the P01012_W01012B_FormParent type. This will hold the data returned from the service call.
The placement of the following code for the member is shown in the image that follows:
P01012_W01012B_FormParent p01012_W01012B_FormParent = new P01012_W01012B_FormParent();
Right-click on the page and select Generate Accessors to generate accessors for the new member variable.
On Generate Accessors, select the check box next to the AddressBookDC method and click OK.
Under Application Controller > Application Sources > application, right-click AddressBookDC.java and select Create Data Control.
On Choose Bean Class, accept the defaults and click Next.
On Bean Data Control Options, accept the defaults and click Finish.
JDeveloper displays the new Data Control in the panel on the left.
To populate the data in the Data Control by calling the AIS service:
In the Projects panel, open the AddressBookDC.java class, and add the following code, which adds a new method to call the service and put the data in the member variable form parent:
public void getAddressBookList(){ FormRequest formRequest = new FormRequest(); formRequest.setFormName("P01012_W01012B"); formRequest.setVersion("ZJDE0001"); formRequest.setFormServiceAction("R"); FSREvent w01012BFSREvent = new FSREvent(); w01012BFSREvent.setFieldValue("54","C"); //set search type to customer w01012BFSREvent.doControlAction("15"); // Trigger the Find Button formRequest.addFSREvent(w01012BFSREvent); //add the events to the form request try { //Serialize the form request to JSON String JSONObject jsonObject = (JSONObject)JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); // Call to JDERestServiceProvider with parameters JSON string String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST,JDERestServiceProvider.FORM_SERVICE_URI); //deserialize the response to the class for the W01012B form 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); } }
Call this new method from the constructor (for now).
public AddressBookDC() { super(); getAddressBookList(); }
To create a UI to display the data:
Under ViewController > Web Content, open the ablist.amx page.
In the Data Controls panel, locate the rowset in the data control, which is located under p01012_W01012B_FormParent > fs_P01012_W01012B > data > gridData.
Drag the rowset to the ablist.amx page after the
</amx:facet>
end tag.Select MAF List View, and in the ListView Gallery, select the Start-End type of the list view.
For the Start Text, select SAlphaName_20.value, and for the End Text, select mnAddressNumber_19.value.
Click OK.
Locate the amx:cellFormat element and change the cell format that contains the alpha name to 80%. Change the cell format that contains the address number to 20%. See Figure 1 for an example.
In the Projects panel, expand ViewController > Application Sources > mobile.pageDefs, open the ablistPageDef.xml, and select the Source tab.
In the <AttrName> element, add the following line of code:
<Item Value="value"/>
Deploy and run the application.
After logging in, it should automatically populate the list with customer names as shown in the following example:
Implementing Filter Fields
Implement a Name (string) filter. To do so:
Select the AddressBookDC.java tab, and add the following code to add a member variable:
String nameFilter;
Right-click on the page and select Generate Accessors.
Add the following code to the getAddressBookList() method to use the new filter value:
if(nameFilter!=null && nameFilter.trim().length()>0){ //set filter name in QBE w01012BFSREvent.setQBEValue("1[20]","*" + nameFilter.trim() +"*"); }
The following example shows the code in the method:
Remove the call to getAddressBookList() in the constructor. Later in these steps, you will call this method from the search button instead.
Change the code after the response is retrieved. This will enable the data to refresh after a new search is performed.
//deserialize the response to the class for the W01012B form P01012_W01012B_FormParent temp_p01012_W01012B_FormParent = (P01012_W01012B_FormParent)JSONBeanSerializationHelper.fromJSON(P01012_W01012B_FormParent.class, response); p01012_W01012B_FormParent.getFs_P01012_W01012B().getData().getGridData().setRowsetWithList (temp_p01012_W01012B_FormParent.getFs_P01012_W01012B().getData().getGridData().retrieveRowsetList());
The following example shows the code:
Under ViewController > Web Content, open ablist.amx.
In the Data Controls panel, expand AddressBookDC and locate the new nameFilter field.
Drag the nameFilter to the amx page before the start of the list view and after the end of the secondary facet.
On the context menu, select Text > MAF Input Text w/Label.
Change the label to:
label= "Name"
Remove the existing button in the secondary facet.
In the Data Controls panel, locate the getAddressBookList() method in the AddressBookDC data control.
Drag the method inside the secondary facet in the amx page, and click MAF Button in the context menu to create a button.
To name the new button, change the text attribute to:
text="Search"
Add a panelFormLayout around the name input field, which will delineate it from the list with a box, as shown in the following example:
<amx:panelFormLayout labelPosition="start" fieldHalign="start"> <amx:inputText value="#{bindings.nameFilter.inputValue}" label="Name" id="it1"/> </amx:panelFormLayout>
Deploy the application and perform a search by entering a value in the Name field, which should return matching results, as shown here:
Updating Data in EnterpriseOne
Next, use the details form to update the values in the database.
To update the values:
In the AddressBookDC class, add the following new method to update the values:
public void updateAddressBookDetail(String addressNumber) { FormRequest formRequest = new FormRequest(); formRequest.setFormName("P01012_W01012A"); formRequest.setVersion("ZJDE0001"); formRequest.setFormServiceAction("U"); formRequest.addToFISet("12", addressNumber); FSREvent w01012AUpdateFSREvent = new FSREvent();//set all the field values w01012AUpdateFSREvent.setFieldValue("28", p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtAlphaName_28().getValue()); w01012AUpdateFSREvent.setFieldValue ("40",p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtAddressLine1_40().getValue() ); w01012AUpdateFSREvent.setFieldValue ("52",p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtCity_52().getValue() ); w01012AUpdateFSREvent.setFieldValue("54", p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtState_54().getValue()); w01012AUpdateFSREvent.setFieldValue("50", p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtPostalCode_50().getValue()); w01012AUpdateFSREvent.doControlAction("11"); // Trigger the OK Button formRequest.addFSREvent(w01012AUpdateFSREvent); //add the events to the form request try { //Serialize the form request to JSON String JSONObject jsonObject = (JSONObject) JSONBeanSerializationHelper.toJSON(formRequest); String postData = jsonObject.toString(); // Call to JDERestServiceProvider with parameters JSON string String response = JDERestServiceProvider.jdeRestServiceCall(postData, JDERestServiceProvider.POST, JDERestServiceProvider.FORM_SERVICE_URI); //after the call navigate back to the list page AdfmfContainerUtilities.invokeContainerJavaScriptFunction("ABList", "adf.mf.api.amx.doNavigation", new Object[]{"__back"}); } catch (JDERestServiceException e) { JDERestServiceProvider.handleServiceException(e); } catch (Exception e) { throw new AdfException(e.getMessage(), AdfException.ERROR); } }
Open the abdetail.amx page.
Select the updateAddressbookDetail(String) method from the data control.
Drag it between the secondary facet (remove the existing button first).
On Edit Action Binding, set the parameter value to: #{bindings.value.inputValue}
This is the binding value that corresponds to the address number.
Run the application in the simulator to test the following actions:
Change the values.
Click Save.
Search on a new name.
Handling Errors
Some of the fields may potentially have errors such as an invalid state code. This section describes how to handle those errors.
Add the following items to the AddressBookDC class:
An error array member variable.
A property change support member variable.
A provider change member variable.
Setters and getters.
Provider change support methods.
This code also provides a getter for an errorCount, which is set when the array is set using the property change listener, as shown in the following code sample:
FormErrorWarningMobile[] errors; private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); protected transient ProviderChangeSupport errorChangeSupport = new ProviderChangeSupport(this); public void addProviderChangeListener(ProviderChangeListener l) { errorChangeSupport.addProviderChangeListener(l); } public void removeProviderChangeListener(ProviderChangeListener l) { errorChangeSupport.removeProviderChangeListener(l); } public void setErrors(FormErrorWarningMobile[] errors) { int oldCount = 0; if(this.errors!=null){ oldCount = this.errors.length; } int newCount = 0; if(errors != null){ newCount = errors.length; } this.errors = errors; errorChangeSupport.fireProviderRefresh("errors"); propertyChangeSupport.firePropertyChange("errorCount", oldCount,newCount); } public FormErrorWarningMobile[] getErrors() { return errors; } public int getErrorCount() { if(errors != null){ return errors.length; }else{ return 0; } } public void addPropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.removePropertyChangeListener(l); }
Modify the code in the updateAddressBookDetail method of the AddressBookDC class. Instead of always navigating back to the list first, check the errors and then return to the list.
Replace this line:
//after the call navigate back to the list page AdfmfContainerUtilities.invokeContainerJavaScriptFunction("ABList", "adf.mf.api.amx.doNavigation", new Object[]{"__back"});
With this code:
//deserialize the response to the class for the W01012A form P01012_W01012A_FormParent temp_p01012_W01012A_FormParent = (P01012_W01012A_FormParent) JSONBeanSerializationHelper.fromJSON(P01012_W01012A_FormParent.class, response); clearErrors(); if(temp_p01012_W01012A_FormParent.getFs_P01012_W01012A().getErrors() != null && temp_p01012_W01012A_FormParent.getFs_P01012_W01012A().getErrors().length > 0 ){ //set error list setErrors(temp_p01012_W01012A_FormParent.getFs_P01012_W01012A().getErrors()); }else{ //no errors navigate back AdfmfContainerUtilities.invokeContainerJavaScriptFunction("ABList", "adf.mf.api.amx.doNavigation", new Object[]{"__back"}); } public void clearErrors(){ setErrors(null); }
Open abdetail.amx.
In the Data Controls panel, select errors under AddressBookDC and drag it to the page, placing it after the last facet to create a list view.
On the context menu, select MAF List View.
On ListView Gallery, select the default view.
On Edit List View, select MOBILE from the Text drop-down menu and click OK.
In the Data Control panel, locate the errorCount under AddressBookDC.
Drag errorCount onto the page and in the context menu, select Text > MAF Output Text.
Remove the list view and output text that you previously added; they were just added to create bindings.
After the last facet, insert the following list view code:
<amx:listView var="row" value="#{bindings.errors.collectionModel}" fetchSize="#{bindings.errors.rangeSize}" styleClass="adfmf-listView-insetList" id="lv1" rendered="#{bindings.errorCount.inputValue gt 0}"> <amx:listItem showLinkIcon="false" id="li1"> <amx:panelGroupLayout> <amx:inputText rows="3" value="#{row.MOBILE}" id="ot3" inlineStyle="color:Red;word-wrap:break-word;" readOnly="true"/> </amx:panelGroupLayout> </amx:listItem> </amx:listView>
Run the application in the simulator and test the following tasks in the application:
Enter an invalid state code.
Click Save.
The simulator should display the "not found" error as shown in the following example:
If you correct it with a valid value and click Save, the application will successfully save the record.
Device Integration
This example shows how to enable the mobile application user to add a record they are viewing to the contacts list on the device. To do so:
Open the maf-application.xml and select the Plugins tab.
Select the check box next to Contacts to enable access to the Contacts on the device.
Add a member variable to the AddressBookDC.java class to hold the confirmation message.
Generate accessors with property change support.
After defining the member variable and generating accessors, the resulting code should look like this:
private String addContactResultMsg = null; public String getAddContactResultMsg() { return addContactResultMsg; } public void setAddContactResultMsg(String addContactResultMsg) { String oldAddContactResultMsg = this.addContactResultMsg; this.addContactResultMsg = addContactResultMsg; propertyChangeSupport.firePropertyChange("addContactResultMsg", oldAddContactResultMsg, addContactResultMsg); }
Add the following new method, which enables the record to be added to the device's contacts list:
public void createDeviceContact() { String resultMessage = "Contact Exists"; // Call FindContacts to determine if the contact already exists on device. String contactSearchName = p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtAlphaName_28().getValue(); try { Contact[] foundContacts = DeviceManagerFactory.getDeviceManager().findContacts("name", contactSearchName, true); if (foundContacts != null && foundContacts.length == 0) { Contact newContact = new Contact(); // Assign contact name. ContactName name = new ContactName(); name.setFormatted(contactSearchName); name.setGivenName(contactSearchName); newContact.setName(name); // Assign address to contact. ContactAddresses[] addresses = new ContactAddresses[1]; ContactAddresses address = new ContactAddresses(); address.setStreetAddress(p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtAddressLine1_40().getValue()); address.setLocality(p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtCity_52().getValue()); address.setPostalCode(p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtPostalCode_50().getValue()); address.setRegion(p01012_W01012A_FormParent.getFs_P01012_W01012A().getData().getTxtState_54().getValue()); addresses[0] = address; newContact.setAddresses(addresses); try { // Add contact to device. DeviceManagerFactory.getDeviceManager().createContact(newContact); // Device contact now exists. resultMessage = "Contact Added"; } catch (Exception e) { throw new AdfException(e.getMessage(), AdfException.ERROR); } } } catch (Exception e) { // Unable to interact with device's contact list - display error. resultMessage = "Unable to Add Contact"; } setAddContactResultMsg(resultMessage); }
Open the abdetail.amx page and locate the new method called createDeviceContact under the AddressBookDC data control.
Drag the method to the page as a button, and then delete the button.
This creates the bindings.
Locate the addContactResultMsg under the AddressBookDC data control.
Drag it to the page as an output text, and then delete the output text.
This creates the bindings.
Enter the following code for the footer after the end of the panel form layout (
</amx:panelFormLayout>
):<amx:facet name="footer"> <amx:panelGroupLayout id="pgl6" layout="horizontal" halign="end"> <!-- Add Contact To Device--> <amx:commandButton actionListener="#{bindings.createDeviceContact.execute}" text="Create Device Contact" disabled="#{!bindings.createDeviceContact.enabled}" id="cb4"> <amx:showPopupBehavior id="spb1" popupId="p1" align="overlapTopCenter" alignId="it2"/> </amx:commandButton> </amx:panelGroupLayout> </amx:facet>
Enter the following code for the popup message after the end panel page tag (
</amx:panelPage>
):<!-- display add contact result message. --> <amx:popup id="p1" autoDismiss="true"> <amx:panelGroupLayout id="pgl3" halign="center" valign="middle"> <amx:commandLink text="#{bindings.addContactResultMsg.inputValue}" id="cl3" inlineStyle="white-space:pre;font-size:larger;color:black;text-decoration:none;"> <amx:closePopupBehavior id="cpb1" popupId="p1"/> </amx:commandLink> </amx:panelGroupLayout> </amx:popup>
Run the application in the simulator to test performing the following tasks in the application:
Open a record and click the Create Device Contact button in the footer, which displays the "Contact Added" message.
Go to the device's contacts and you can see the contact listed with the address, as shown in the following example:
If you attempt to add it again, you get the contact exists message, as shown in the following example: