Tuesday Mar 31, 2015

How to implement push notifications in MAF 2.1.1

Push notifications are a fantastic way to notify your users of relevant information in a timely fashion, even when your mobile app is running in the background or not running at all.

The MAF 2.1.1 extension provides two sample applications – PushDemo, which demonstrates how to receive push notifications in a MAF app, and PushServer, which demonstrates how to send push notifications to a MAF app.

This blog post will provide an introduction to push notifications and a detailed description of how to configure the PushDemo and PushServer sample applications, as a vehicle for learning about push notifications. Readers can use the lessons learned to implement push notifications in their own applications.

How push notifications work

Although technically different, the logical push notifications architecture is similar for mobile apps running on both Android and iOS, with Google and Apple each providing a cloud-based Push Notifications service that acts as the go-between your server application and your mobile app.

The flow of push notifications is also similar: including a registration process followed by the sending of a notification to one or more devices, as follows:


Each time a push-enabled mobile app starts, it registers with the Apple Push Notifications service (APNs) or Google Cloud Messaging (GCM), based on the device type.  The registration request includes an identifier. Successful registration results in a registration token being returned that uniquely identifies this mobile app running on this device.

The push notification will originate from a server application, so the mobile app must register with the server application, providing enough information for the server application to be able to uniquely identify the user associated with the app on this device. This registration with the server application would typically be done following successful authentication of the user and must include the registration token.

Having completed the registrations, when an event occurs later on that requires a push notification to be sent to one or more users, the server application reviews all the registrations and sends a push notification to the user’s registered device(s) via APNs, GCM, or both. Each push notification message includes the unique registration token for the target device.

Required push notifications setup

APNs

Apple requires you to create an explicit App ID that enables push notifications and a corresponding client SSL certificate. 

The App ID is used to create a provisioning profile that is embedded into your mobile app.  This provisioning profile informs APNs that your mobile app is a trusted app.

The client SSL certificate is used by your server application when communicating with APNs.   It informs APNs that your server application is a trusted application and that it is permitted to send push notifications to your mobile app.

For more information refer to Apple Push Notification Service and Configuring Push Notifications.

GCM

Google requires you to create a Google API project and obtain an API Key.

The project number is used by your mobile app as the Sender ID when registering with GCM. It indicates to GCM which server application (or server applications, since more than one Sender ID can be specified) is permitted to send push notifications to your mobile app.

The API Key is used by your server application as the Sender Auth Token when communicating with GCM. It gives your server application access to Google services and ensures that push notifications originating from your server application are targeted to your mobile app.

For more information refer to Google Cloud Messaging Overview and Getting Started on Android.

About the PushDemo sample app

The PushDemo sample app is a MAF app that works in conjunction with the PushServer sample app to demonstrate registration for, sending and receipt of push notifications. (More details about the sample apps provided within each MAF release and where to find them are provided here.)

The PushDemo sample app has three functions:

  • Each time you launch the PushDemo sample app, it automatically registers with GCM or APNs, as appropriate for your device, and receives a registration token.
  • It provides a registration page for you to initiate registration with a running instance of the PushServer sample app.  In a real-world app, this step would normally be automatically handled by the client app following a user login, or retrieval of stored user details.
  • It provides a page for displaying the message received when a push notification is received by the PushDemo sample app.

About the PushServer sample app

The PushServer sample app is a server application that uses a GCM client library provided by Google (refer to the Android Developer site for details of how to install it) for connecting to the GCM server, and sample code for connecting to APNs as described on the Apple Developer site.

GCM and APNs have different policies regarding push notification error handling and de-registration of devices.  The PushServer sample app does not provide any special handling, but you should be aware of these policies when designing your server application if it will support push notifications. To review these policies, refer to Implementing GCM Server and Provider Communication with Apple Push Notification Service.

There are two components to the PushServer sample app:

  • A registration servlet that enables an instance of the PushDemo sample app running on a mobile device to register with the server application.  The registration request includes the registration token received from GCM or APNs, the mobile app’s Bundle ID, the user ID entered into the registration page of the mobile app and the device type.  These are stored in a database on the server for later sending of push notifications to the user’s mobile device.
  • A push notification page displays the registered devices and enables you to enter a message to push to a selected device.

How to configure and run the PushServer sample app

Apple and Google registration

To implement push notifications, the app must be registered with Apple and/or Google, depending on the device(s) you wish to use for testing.

If you are an Oracle employee, this has already been done for you and you can retrieve the necessary signing artifacts by clicking on the link “How to use the PushDemo sample app” found on the internal MAF uptake guide wiki.

Otherwise for customers, you will need to register your app with Apple and/or Google and retrieve the necessary signing artifacts, as described above under Required Push Notifications Setup.

Database setup

The PushServer sample app requires a database for storing the mobile device registration details. A dummy database connection called “pushServerDB” is provided in the connections.xml.

If you are an Oracle employee intending to run the server application on the Oracle intranet, you can configure the PushServer sample app to connect to a hosted database as described on the internal MAF uptake guide wiki.

Otherwise for customers, you must install a database, create the required schema using the pushschema.sql script found in the PushServer sample app’s Model/database folder and modify the properties of the “pushServerDB” database connection in the connections.xml file as follows.  If your database is not an Oracle database, you may also need to modify certain properties of the Application Modules that are configured in the bc4j.xcfg file.  The configuration steps are described below.

Server application configuration

Follow these steps to configure the server application:

  1. Open the PushServer sample app in JDeveloper 12.1.3 with MAF 2.1.1 extension.
  2. Modify the dummy database connection as follows:
    1. Expand Application Resources > Connections > Database to reveal pushServerDB.
    2. Right-click on pushServerDB and select Properties.
    3. Enter all the required properties for the database you intend to use.
    4. Verify the entered details by clicking on Test Connection.
    5. Save the entered details by clicking on OK.
  3. If you are using a non-Oracle database, you may need to update certain properties of the configured Application Modules as follows:
    1. Open Projects > Model > Application Sources > oracle.adfmf.demo > push > model > RegistrationModule > RegistrationModel.xml.
    2. Open the Configurations tab.
    3. Click on the link for bc4j.xcfg.
    4. For each listed Application Module, select it and click on the Edit icon, open on the Properties tab, modify the relevant properties and click OK.  For example, to connect to a MySQL database, change the jbo.SQLBuilder property to “SQL92”.
  4. Open the MessageBean.java file under Projects > ViewController > Application sources > oracle.adfmf.demo > push.
  5. Set the GOOGLE_APIKEY variable to your Google project’s API Key.
  6. Set the IOS_KEYFILE variable to the full path to your iOS keystore (.p12 file).
  7. Set the IOS_KEYPWD variable to the password you set on your iOS keystore.
  8. If you will run the server application on a corporate intranet, such as the Oracle network, set the PROXY_HOST and PROXY_PORT variables appropriately.
  9. Otherwise, leave both the PROXY_HOST and PROXY_PORT variables set to null.
  10. Save all your changes.

WebLogic Server configuration

The server application must be deployed to a running WebLogic Server (WLS) instance.  The most convenient option for developers is to configure and run the embedded WLS within JDeveloper as follows:

  1. If you are on a corporate intranet, such as the Oracle network, configure the JDeveloper proxy settings in Preferences > Web Browser and Proxy > Proxy Settings.
  2. Start an instance of the embedded WLS in JDeveloper via Run > Start Server Instance.
  3. You will be prompted to enter and confirm a password.  At this point, you may also change the listening address or port.  I recommend you keep the default settings, which should be to listen on All Available Addresses using port 7101, with port 7102 for SSL.
  4. Once the WLS has started, open http://localhost:7101/console in your preferred browser.  This is the WLS console.
  5. Login to the WLS console as user “weblogic” and the password you entered in step 3.
  6. Turn off hostname verification in the WLS console via Domain Configurations > Environment > Servers > Default Server > Configuration > SSL > Advanced. By setting “Hostname Verification” to None.
  7. Click on Save.

Deploy the server application

Deploy both components of the server application within JDeveloper as follows:

  1. Expand Projects > ViewController > Application Sources > oracle.adfmf.demo > Push to reveal RegistrationServlet.java.
  2. Right-click on RegistrationServlet.java and select Run.
  3. You can ignore the error reported by the servlet, since it was launched without any parameters.
  4. Expand Projects > ViewController > Web Content to reveal pushregistration.jspx.
  5. Right-click on pushregistration.jspx and select Run.

How to configure and run the PushDemo sample app

Client app configuration

Configure the PushDemo sample app as follows:

  1. Open the PushDemo sample app in JDeveloper 12.1.3 with MAF 2.1.1 extension.
  2. Open the adf-config.xml file found in Application Resources > Descriptors > ADF META-INF.
  3. Select the Source tab and enter your Google project number into the value for the gcmSenderId property.
  4. Open the connections.xml file also found in Application Resources > Descriptors > ADF META-INF.
  5. Modify the url for the PushServiceConn connection by changing “127.0.0.1” to the relevant value for your server application, based on the network that will be shared by your server application and your mobile client app.
  6. Save all your changes.

Deploy the client app

Follow these steps to deploy and run the PushDemo app:

  1. Configure JDeveloper with the name of your push-enabled iOS provisioning profile and corresponding signing identity in Preferences > Mobile Application Framework > iOS Platform.
  2. Deploy the PushDemo app to your Android or iOS device, or Android emulator (you must use a “Google APIs” target).  Push notifications do not work on the iOS simulator.
  3. Ensure that your mobile device can access the Internet via a mobile data plan or wifi network.  Note for Oracle employees that push notifications are blocked on the “clear” wifi network, even with VPN enabled.  If you have no access to a mobile data plan or corporate wifi connection, you can setup a local wifi on the machine that is running the server application and connect to that.
  4. Launch the app and it will automatically register with APNs or GCM, as appropriate. 
  5. Switch to the Register feature and it should advise that registration was successful.
  6. If you have not registered your device with the server application previously, you will need to do this now.  If you are running your server application on a corporate intranet, such as the Oracle network, you will need to establish a VPN connection on your mobile device before communicating with the server application. 
  7. To register your device, enter a unique User ID into the client app and tap on the Register button.  A success or error message will be displayed below the Register button. 
    1. Note: The server application does not handle duplicate entries for one device and APNs or GCM may return a different token, so you may need to delete the old entry for your device from the database and try again.
  8. If you are using an Android device and you have established a VPN connection, you must close this VPN connection now to ensure that you can receive push notifications.
  9. Switch to the Message feature, which will display any message received via push notifications.

How to send a push notification to the PushDemo sample app

When you deployed the server application's Push Registration page, it should have been displayed in your default browser.  You can send a push notification to the PushDemo sample app running on your mobile device from this page as follows:

  1. Select the entry for your mobile device.
  2. Enter a message into the Message field.
  3. Click the Push Message button.

Your mobile device should receive the push notification as follows:

  • If the PushDemo sample app is running in the foreground, the message you entered should be displayed on the Message feature’s main page.
  • Otherwise, your mobile device’s operating system should display the push notification in the standard manner. On Android, a notification banner is presented for a short time and the notification can be viewed in the Notification Drawer. On iOS, depending on your notification settings, a banner or alert may be displayed and the notification can be viewed in the Notification Center.
  • If you tap on a notification displayed by your device’s operating system, the PushDemo sample app should be launched and/or moved to the foreground and the message should be displayed on the Message feature’s main page.

Conclusion

The PushDemo sample app demonstrates how to register for and receive push notifications using MAF 2.1.1. It works in conjunction with the PushServer sample app that demonstrates techniques for registering with GCM and APNs and sending push notifications using these services.

By following the steps described above, you should be able to send push notifications from a deployed instance of the PushServer sample app to your mobile device with the PushDemo sample app installed.

Based on the information and links provided in this blog post and the hands-on experience gained from configuring and using the provided sample apps, you should be able to implement push notifications in your own server application and MAF-based mobile app.

Monday Mar 30, 2015

Oracle MAF 2.1.1 Released

We are happy to announce the release of Oracle MAF 2.1.1.

This release adds a couple of new features and includes bug fixes - for the full details see the Oracle MAF documentation page.

One key new feature in this release is support for local notifications.

Oracle MAF local notifications originate within the MAF application and are received by the same application. The notifications are delivered to the end user through standard mechanisms supported by the mobile device platform (for example, banner, sound) and can work when the application is either in the foreground, background or not running at all. 

Focusing on simplifying development, you can schedule, receive and cancel local notification through the declarative device feature data control palette, as well as through Java and JavaScript APIs. More here.

You can get the new Oracle MAF 2.1.1 extension through the help->check for updates in JDeveloper. 

Monday Mar 16, 2015

Oracle University Now Offering - Oracle MAF 2.1 Courses

We are happy to announce that you can now get official Oracle University training on Oracle MAF

Check out the new course - Oracle Mobile Application Framework 2.1: Develop Mobile Apps 

Available both as an in class training and a virtual class training - so you can take it from anywhere.

logo

This is a great first step on your way to become a certified Oracle Mobile Developer.

The course covers the following topics:

  • Design, build and deploy mobile applications
  • Provide and persist data for mobile applications
  • Leverage on-device features in a mobile application
  • Add access control and authentication functionality to mobile applications
  • Test, debug and determine the type of deployment before releasing your application 

This new course joins the many other ways to learn Oracle MAF - so no more excuses ;-)

Wednesday Mar 04, 2015

Oracle MAF 2.1 Now in Eclipse Too

We are happy to announce the release of a new version of Oracle Enterprise Pack for Eclipse (OEPE)- the Oracle Eclipse tooling offering - with support for the latest Oracle MAF 2.1.

Download the new OEPE 12.1.3.4 with MAF 2.1 Support Here.

This new version of OEPE is based on the latest Eclipse Luna SR2, and adds support for the full set of MAF 2.1 features including support for Java 8 compact profile 2, the new Xcode  and Android SDKs, and Cordova 3 plugin integration.

One unique feature added to the OEPE design time experience is a simplified way to interact with REST/JSON services. REST/JSON services are the preferred way to exchange information between your mobile application and remote server. A new wizard based interface in OEPE allows you to easily test REST URLs and then generate a simple set of POJO Java classes that access those services and working with the data types they use. You can then expose those classes as data controls and simply drag and drop them to the AMX pages to create the mobile UI.

Here is a 5 minutes demo that shows you the new REST features in action:

For more about this new version see the OEPE blog entry.

The OEPE Blog also has new entries describing some of the new features including:

 

Wednesday Feb 25, 2015

How-to create a select one choice list-of-values bound to the AMX binding layer

MAF Version 2.1

Problem Statement

Oracle Mobile Application Framework (MAF) allows you to declaratively build list of values. To create a list of values, you need a list binding that provides the list of selectable values and a iterator that holds the object to update. Though the list is created and configured declaratively in MAF using collections exposed on the MAF data control, there is something you need to know before adding the select list component: How to expose the list source collection through the binding layer?

Solution

To create a list of values in MAF using the AMX binding layer you need to create an Accessor Iterator for the list source collection before dragging the attribute to update as a select one choice to the AMX page.

Implementation

The image below shows the data control panel of the sample workspace you can download. The CustomerDC data control, which is a JavaBean data control, exposes two collections: countries and customers. The countries collection is the list source. The customer collection exposes customer row objects to update in a MAF input form. 

Data Control Panel

To build an input form from a collection, customers in this case, you

  1. Select the collection in the data controls panel
  2. Drag the collection to the AMX page
  3. Drop the collection as a MAF input form
The sample workspace that is available for download has the edit form added in its EditCustomer.amx page. A previous page, SelectOneChoice.amx contains a list view created from the same customer collection. At runtime, selecting a customer on the first page automatically navigates to the edit form page. When you create a MAF input form, the MAF binding layer (PageDef file) is created and populated with bindings for each property of the customer object. To access the bindings you click the "Bindings" tab at the bottom of the AMX page editor.  

Switch the MAF editor view to the "Bindings" tab to create a new Accessor Iterator binding. In the binding editor, click the green plus icon above the "Executable" section and select the "accessorIterator" binding item. Then click OK.

Create Accessor Iterator

Select the data control that holds the collection with the values you want to show in the list of values. In the sample, the data control is the same as for the customer collection, but the collection is "countries". Click OK to create the iterator and switch back to the source view of the MAF page editor.

Configure Accessor Iterator with List Source collection

In the MAF page source editor, select the complete markup (af:inputText) for the customer property that you want to create a list of values for ("countryId" in the sample) and hit the delete key. Then, expand the collection (customers in the sample) and drag the property for which you deleted the markup to the AMX page (countryId in this example). The context aware popup shows the "Single Selection" menu item, which hosts the "MAF Select One Choice" sub item. Select the MAF Select One Choice item in the menu to bring up the MAF list binding dialog.

Add amx:selectOneChoice to AMX page

In the "Edit List Binding" dialog, keep the default settings for the Base Data Source and the Dynamic List and change the "List Data Source"  configuration to <data control>.root.<collection name>, which in the sample is CustomersDc.root.countries. The target attribute that will be updated through the list of value is selected automatically and all you need to do is to select the list attribute that provides the value for it.

Configure List

Note the "Display Attribute" property that can be set to any of the list collection attribute or a combination of attribute. In the sample, the display was changed to show the countryId and the country name as you can see in the following screen shots.

Note: the list edit dialog allows you to map multiple properties for update. This however is not yet supported in MAF and only the first mapping will be used at runtime. If you need to update multiple form properties then you do this programmatically. Have a look at this previous blog entry to get an idea of how to do this.

After you downloaded the sample application and opened it in JDeveloper 12.1.3, select the SelectOneChoice.amx page and choose "Run" from the  context menu. This will bring up the iOS simulator or Android Emulator (you may have to configure the deployment profile as it is set to iOS). On the first page, shown below, select a customer entry to edit.

Select Customer at Runtime

This leads you to the form page where you now can change the country ID field using the select one choice component (the screen shot shows the iOS simulator rendering, if you run this on Android the list of values may look different)

Select Country in ChoiceList

Summary

This blog article stepped you through creating a single select choice list of values based on the AMX binding layer in MAF. To build such a list declaratively you need to create the accessor iterator manually in the binding, which needs to be done before you create the list component. This article showed you how.

Sample Download

The sample is pretty simple and is focussed on the list only. The data it displayed is saved in a JavaBean so that there is no need for you to configure a web service connection or use the local SQLite database. 

MAF 2.1 Workspace

--------------

Disclaimer

The sample explained in the blog and provided for this blog entry is provided as is. The sample will not be upgraded automatically to newer versions of MAF and is also not supported by Oracle world wide customer support. Samples are community efforts that we support in a community effort: If you experience problems or have questions, please post a note to the MAF community forum on OTN: https://community.oracle.com/community/oracle-mobile/oraclemaf/content?customTheme=otn

Thursday Feb 19, 2015

How-to Access Selected Values in a Multi Select List

MAF Version: 2.1

Problem Statement

Using multi-item-select components, like amx:selectManyCheckbox, in a MAF application does not directly write the values back to the model but saves an array of selected row indexes in the inputValue attribute of the list binding. In addition, when users start selecting items in a muli-select list, each time they click on an item, the component valueChangeListener fires notifying the event listener in the managed bean about the selection. Both leads to the question of how to access the underlying data object (the row) for each selected item to read its properties.

For example, the assumed requirement for the sample application you can download at the end of this blog entry is to display the name of selected customers in a text box below the list component on the AMX page.

The Solution

The best part of a trip often is the journey because its where you see things and learn new skills. The same is true for the solution to the above challenge, as you will see when going through the implementation. For this solution, the decision was made to use the valueChangeListener and - for each selection - print the actual list values.

As shown in the image below, each selection in the list of customers is immediately mirrored in the text field below the list.

Multi Select List Sample Screen Shot

Note: If you don't need this information on each selection you would read the selected index values from the attribute binding (list binding) inputValue property upon e.g. a press on a button. In this case the code shown in this blog will guide you the way.

The implementation in the sample performs the following steps

  1. A valueChangeListener tracks all user item selection and de-selection
  2. For the selected items, the managed bean code reads the indexes from the component event
  3. The indexes are then changed from an array of String to List of Integer
  4. The list binding in the pageDef file (the binding) is accessed to obtain access to the list iterator
  5. For each index in the list of selected items, the iterator current row is set and then read

Note: Keep in mind that multiple binding artifacts may point to the same iterator. If you change the current row of a shared iterator, make sure to first read the current row key or index so it can be set back at the end of your action. In the sample the iterator is not shared and therefore the current row doesn't need to be set back.

Implementation Steps

The implementation is based on a POJO model, as this model is the most common in MAF. POJO models are usually created for REST services (using the REST Service Adapter in MAF), or when accessing the SOAP DC from Java, or when exposing the local SQLite database to the UI. In each of the cases mentioned before, you create a Java bean that then is exposed as a Data Control for use in MAF. From the data control you then create the UI using drag and drop from the Data Controls panel in JDeveloper or Oracle Enterprise Package for Eclipse (OEPE).

Note: This sample has customer data contained in the POJO data control (so to not require any dependency to a service, database or SQLite in MAF)

AMX view

The sample uses a single AMX view in the feature (which is good for demos and sample. For real MAF applications my personal preference is to use bounded task flows as the feature content). The page source of the list and the item mirroring the selections is shown below

<amx:selectManyCheckbox value="#{bindings.customers.inputValue}" 
         label="#{bindings.customers.label}" id="smc1"
         valueChangeListener="#{viewScope.SelectHelper.onValueChange}">
    <amx:selectItems value="#{bindings.customers.items}" id="si1"/>
</amx:selectManyCheckbox>
<amx:inputText label="Selected Values" id="it1" rows="7" inputType="text"
                   value="#{viewScope.SelectHelper.selectedValues}"/> 

To explain the important bits:

#{viewScope.SelectHelper.onValueChange} 
" valign="top"> Managed bean reference to the value change listener.  The managed bean doesn't hold state and thus is in the smallest scope available for MAF, which is viewScope
#{bindings.customers.items}
The customers reference is the list binding in the AMX pageDef file. Items gives you access to a list of items that then are iterated over by the component. This part doesn't need to be manually created by you and is generated by JDevelper or OEPE
#{bindings.customers.inputValue}
The inputValue property exists on the list binding and holds the value of the selected items (for the use case in which you need to access the selected row indexes in response to a command button or link action. As you see, the value is EL accessible and as such can be referenced from Java too using the AdfmfJavaUtilities class in MAF
#{viewScope.SelectHelper.selectedValues}

This EL is added to the input text field that shows the selected customer name and references a set/get method pair (bean properties) in the managed bean. The value change listener associated with the select component calls the set-method to post changes to the text field. A property change event is used notify the UI field to refresh


Note: most of the AMX page configuration is created for you when dragging and dropping a collection from the data control panel to the page. The only manual step is the creation of the value change listener and the input text field referencing the managed bean properties.

Managed Bean

The value change listener method - onValueChange(...) - in the managed bean is doing the real work. This is where the journey starts becoming exciting. The important parts of the code - in addition to the code comments, are explained further at the end

public void onValueChange(ValueChangeEvent valueChangeEvent) {

 //the newValue property of the valueChangeEvent shows an array of Strings 
 //with the selected values. This array is updated with each new selection 
 //or de-select
 Object[] newVal = (Object[]) valueChangeEvent.getNewValue();

 //the oldValue property of the valueChangeEvent shows an array of Strings 
 //with the values of the previous selection. This property allows you to 
 //tell what exactly has been changed within a new selection
 Object[]  oldVal = (Object[]) valueChangeEvent.getOldValue();

 //converting array of Strings to list of Integer to read the real 
 //objects from the list binding iterator
 ArrayList<Integer> selectedCustomers = new ArrayList<Integer>();      
 for (int i = 0; i < newVal.length; i++) {
     selectedCustomers.add(new Integer((String)newVal[i]));
 }

 //lists are represented by the  AmxAttributeBinding
 AmxAttributeBinding customerList = (AmxAttributeBinding) AdfmfJavaUtilities
                               .evaluateELExpression("#{bindings.customers}");

 StringBuffer selectedCustomerNames = new StringBuffer();

 //access the list iterator to first set the current row by the indexes obtained 
 //from the value change event and then read the row object, which in this sample
 //represents a customer
 AmxIteratorBinding amxListIterator =  customerList.getIteratorBinding();
 
 //the basic iterator in the AmxIteratorBinding is what we need to work with
  BasicIterator      basicIterator = amxListIterator.getIterator();
        
  for (Integer customerIndx : selectedCustomers) {
     //set new current row in list iterator
     basicIterator.setCurrentIndex(customerIndx.intValue());
     //get current row. Note that for POJO models you call getDataProvider and cast to 
     //the entity. For SOAP models you call getCurrentRow and cast it to GenericType 
     Customer customer = (Customer) basicIterator.getDataProvider();
     //for this sample, print selected customers into a text field on the page
     selectedCustomerNames.append("Customer on index  " + (customerIndx.intValue() + 1) + ": " + customer.getName()+"\n");
  }
  
  //update the input text field with the selection. The set-method of the 
  //selectedValue property uses the PropertyChane listener in MAF to trigger
  //the field to refresh
  this.setSelectedValues(selectedCustomerNames.toString());

}

Following table contains further explanations for parts of the code

valueChangeEvent.getNewValue() The list component has a "ValueChange" property that can be linked to a managed bean that defines a public method with the ValueChangeEvent as the only argument. The event argument gives developers access to the current selected items as well as the previously selected items, allowing them to tell the change. In the sample, the selected list is used only to lookup the associated binding object (aka. model objects) for more details. The getNewValue() method returns an array of String, where each string represents the index of a selected item in the list. The index is the same as in the binding layer, which makes it easy to lookup the data object.
AmxAttributeBinding There is no list binding in MAF (and I used teh term for simplicity in the article). List binds are attribute bindings and allow access to the list of items and the iterator. The iterator is created from the collection that in this example displays customer information. The attribute binding however does not display the full customer object and only knows of a value property (usually you select this as the PK of a object) and one to any display properties.
AmxIteratorBinding The iterator is an instance of AmcIteratorBinding, which is a wrapper for BasicIterator, which is the object instance that gives access to the data provider, which in the POJO case represents the data object (entity) representing a row.
basicIterator.getDataProvider(); The getDataProvider() method works for POJO models (PojoDC) wheras getCurrentRow provides equivalent access to the current row object for the SOAP DC. The code in the sample sets the current row for each selected item (using the item index) before accessing the row data object (entity)

Summary

This blog article and its sample shows one possible solution to work with multi select  lists in MAF. The use case covered is where the application requirement is to respond to any selections users make in the list. The use case in which the selected list is read after all items are selected is not covered. The handling for this is to access the list binding (which now you know is an attribute binding) to access the inputValue property for the submitted values. You then iterate over the values and set the current row in the BasicIterator using the keys you find in the array you obtain from the inputValue. The rest then remains the same

Download the Sample

The sample for this blog entry has been written for MAF 2.1 using JDeveloper. The sample code can be download from http://www.oracle.com//technetwork/developer-tools/adf/learnmore/multiselectlist-2423622.zip . In JDeveloper, open the MAF workspace and run the AMX page contained within. When the application shows up in the simulator, emulator or on-device, select items in the list to see the customer name - which is not part of the list - displaying in the text field. 

--------------

Disclaimer

The sample explained in the blog and provided for this blog entry is provided as is. The sample will not be upgraded automatically to newer versions of MAF and is also not supported by Oracle world wide customer support. Samples are community efforts that we support in a community effort: If you experience problems or have questions, please post a note to the MAF community forum on OTN: https://community.oracle.com/community/oracle-mobile/oraclemaf/content?customTheme=otn


About

This blog is is dedicated to announcements,tips and tricks and other items related to developing, integrating, securing, and managing mobile applications using Oracle's Mobile Platform. It is created and maintained by the Oracle Mobile product development team.

Archive of past entries

Even More Mobile Development Blogs

Oracle A-Team Site - Mobile Related Entries

Code samples from the Community

Fusion Middleware Blogs

Search

Archives
« July 2015
SunMonTueWedThuFriSat
   
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
       
Today