10 Using Web Services

This chapter describes how to integrate a third-party web service into the ADF Mobile AMX application feature implementation.

This chapter includes the following sections:

10.1 Introduction to Using Web Services

Web services allow applications and their features to exchange data and information through defined application programming interfaces. Using web services you can expose business functionality irrespective of the platform or language of the originating application. For more information, see the "Introduction to Web Services in Fusion Web Applications" section in Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

ADF Mobile supports both SOAP and REST web services and allows you to integrate a third-party web service into your ADF Mobile AMX application feature.

10.2 Creating a Web Service Data Control

The most common way of using web services in an application feature developed with ADF Mobile is to create a data control for a web service. Typically, this is done for the following reasons:

  • To add functionality that is readily available as a web service, but which would be time-consuming to develop within the application.

  • To provide access to an application that runs on a different architecture.

  • To enable reuse of components created by ADF Mobile to make them available as web services for other applications.

For more information about web service data controls and their usage, see the following:

10.2.1 How to Create a Web Service Data Control Using SOAP

JDeveloper lets you create a data control for an existing SOAP web service using only the Web Services Description Language (WSDL) file for the service. You can either browse to a WSDL file on the local file system, locate one in a Universal Description, Discovery and Integration (UDDI) registry, or enter the WSDL URL directly.

Note:

If you are working behind a firewall and you want to use a web service that is outside the firewall, you must configure the Web Browser and Proxy settings in JDeveloper. For more information, see the "Setting Browser Proxy Information" section in Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

To create a SOAP web service data control:

  1. In the Application navigator, right-click the application name, and then select File > New from the main JDeveloper menu.

  2. In the New Gallery dialog, expand the Business Tier node on the left and select Web Services. From the Items list on the right select Web Service Data Control (see Figure 10-1), and then click OK.

    Figure 10-1 Creating a New SOAP Web Service Data Control

    Creating a New Web Service Data Control
  3. Follow the wizard instructions to complete creation of the data control.

Note:

ADF Mobile supports the following encoding styles for both SOAP 1.1 and 1.2 versions:

  • Document/literal

  • Document/wrapped

  • RPC

After the web service data control has been created, the web service operations and return values of the operations are displayed in the Data Control palette allowing you to drag and drop the objects returned by the web service operations as appropriate ADF Mobile AMX UI components in the page. For more information, see Section 7.3.2.4, "Adding Data Controls to the View." When data returned from a web service operation is displayed, the following object types are handled:

  • Collections.

  • Complex objects returned by a web service operation.

  • Nested complex objects returned by a web service operation.

Using a web service operation, data can be updated (including both the standard data types and complex objects) and deleted.

10.2.2 How to Create a Web Service Data Control Using REST

JDeveloper lets you create a data control for an existing REST web service.

Note:

If you are working behind a firewall and you want to use a web service that is outside the firewall, you must configure the Web Browser and Proxy settings in JDeveloper. For more information, see the "Setting Browser Proxy Information" section in Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

You can associate a REST web service data control (also known as URL service data control) with one or more HTTP methods using the same connection. You should be able to access custom operations exposed by a REST service beyond the standard HTTP methods. These custom operations map to one of the HTTP methods and allow you to create a data control to expose these custom operations on the client.

To use security and notifications functionality on mobile devices, you can add custom headers and custom values to standard HTTP headers for use with specific operations exposed by the REST data control.

Before you begin:

Ensure that you have access to the REST web service that the data control is to access.

To create a REST web service data control:

  1. In the Application navigator, right-click the application name, and then select File > New from the main JDeveloper menu.

  2. In the New Gallery dialog, expand the Business Tier node on the left and select Data Controls. From the Items list on the right, select URL Service Data Control (see Figure 10-2), and then click OK.

    Figure 10-2 Creating a New REST Web Service Data Control

    Creating a New REST Web Service Data Control
  3. Follow the Create URL Service Data Control wizard instructions to complete creation of the data control, keeping in mind the following:

    • ADF Mobile supports only basic authentication for web services (see Section 10.5, "Accessing Secure Web Services"). When completing the Connection page, select Basic in the Authentication Type field.

    • ADF Mobile supports all HTTP method types: GET, POST, PUT, and DELETE. You can select any of these method types when completing the Http Method field on the Connection page.

      Note:

      You can include all four methods using the same connection and the same REST web service data control.

    • ADF Mobile supports all settings listed on the Parameters page.

    • ADF Mobile does not support the delimiter separated values in the spread sheet data and the XSL for the XML data formats. When completing the Data Format page, specify either XML or XSD for the XML format.

    • By specifying a local XSD file for the URL Service data control definition, you create a file URI reference for the Schema field.

      Note:

      Since ADF Mobile creates internal definitions for the XSD structures at compile time, the XSD should not change after the application has been compiled. Therefore, it is recommended to reference the XSD file locally. Using the remote XSD negatively affects performance because ADF Mobile retrieves the XSD with each run of the application.

After the REST web services data control has been created by following the preceding steps, it behaves identically to its Oracle ADF counterpart. For more information, see the section on URL services in Oracle Fusion Middleware Fusion Developer's Guide for Oracle Application Development Framework.

For information on how to use REST web services through Java bypassing data controls, see Section 10.6.1, "How to Use REST Web Services Adapter."

10.3 Creating a New Web Service Connection

The connection information for the web service is stored in the connections.xml file along with the other connections in your application. You do not need to explicitly create this file, as it is generated in the.adf/META-INF directory by the New Web Service Data Control wizard at the time when the web service data control is created (see Section 10.2, "Creating a Web Service Data Control").

You modify the connection settings by editing the connections.xml file.

10.4 Adjusting the Endpoint for a Web Service Data Control

After creating a web service data control, you can modify the endpoint of the URI. This is useful in such cases as when you migrate the feature from a test to production environment.

You modify the endpoint by editing the connections.xml file.

10.5 Accessing Secure Web Services

ADF Mobile supports both secured and unsecured web services, as well as basic authentication (BASIC_AUTH) over HTTP and HTTPS.

For more information, see the following:

To access secured web services from your ADF Mobile application, you may need to configure web service data controls included in the application.

10.5.1 How to Enable Access to SOAP-Based Web Services

The following security policies are supported for SOAP-based web services:

  • oracle/wss_http_token_client_policy

  • oracle/wss_http_token_over_ssl_client_policy

  • oracle/http_basic_auth_over_ssl_client_policy

  • oracle/wss_username_token_client_policy

  • oracle/wss_username_token_over_ssl_client_policy

If a SOAP web service is secured, you can access it by configuring the web service data control with either oracle/wss_http_token_over_ssl_client_policy or oracle/wss_http_token_client_policy. To do so, use the Edit Data Control Policies dialog that Figure 10-2 shows. You can open this dialog as follows:

  • In the Navigator, select the .dcx file.

  • In the Structure pane, right-click the web service data control that you would like to configure, and then select Define Web Service Security from the context menu.

Figure 10-3 Editing Web Service Data Control Policies

Editing Web Service Data Control Policies

10.5.2 How to Enable Access to REST-Based Web Services

Since only one security policy is supported for REST-based web services, ADF Mobile automatically adds oracle/wss_http_token_over_ssl_client_policy for REST web service over HTTPS, or oracle/wss_http_token_client_policy for REST web service over HTTP protocol to enable Oracle Web Services Manager (OWSM) Lite Mobile ADF Application Agent to inject a proper security header.

10.5.3 What You May Need to Know About Credential Injection

For secured web services, the user credentials are dynamically injected into a web service request at the time when the request is invoked. This process is similar for SOAP and REST web services.

ADF Mobile uses Oracle Web Services Manager (OWSM) Lite Mobile ADF Application Agent to create and configure proxies, as well as to request services through the proxies. The user credentials are injected into the OWSM enforcement context when proxies are configured. The credential injection is handled by OWSM proxies. For more information, see Oracle Fusion Middleware Java API Reference for Oracle Web Services Manager.

Before web services are invoked, the user must respond to an authentication prompt triggered by the user trying to invoke a secured ADF Mobile application feature or to start the application controlled by the access control service (ACS). In the latter case, the application must define a default login server with ACS URL, as well as to have at least one feature with a constraint that depends on the user.role setting. The user credentials are stored in a credential store called IDM Mobile credential store—a device native and local repository used for storing credentials associated with the authentication provider's server URL and the user. At run time, ADF Mobile assumes that all credentials have already been stored in the IDM Mobile credential store before the time of their usage.

ADF Mobile supports authentication against the web service endpoint URL only. In the connections.xml file, you have to specify the login server connection name in the credentialStoreKey attribute of the web service connection reference in order to associate the login server to the web service security (see Example 10-1 and Example 10-2).

Note:

To edit the connections.xml file, use the Source editor as this configuration is not exposed in the JDeveloper's Designer.

Example 10-1 shows the definition of the web service connection referenced as credentialStoreKey="MyAuth", where MyAuth is the name of the login connection reference.

Example 10-1 Defining the Web Service Connection

<Reference name="URLConnection1"
           className="oracle.adf.model.connection.url.HttpURLConnection"
           credentialStoreKey="MyAuth"
           xmlns="">
   <Factory className="oracle.adf.model.connection.url.URLConnectionFactory"/>
   <RefAddresses>
      <XmlRefAddr addrType="URLConnection1">
         <Contents>
            <urlconnection name="URLConnection1"
                           url="http://myhost.us.example.com:7777/
                                SecureRESTWebService1/Echo">
               <authentication style="challange">
                  <type>basic</type>
                  <realm>myrealm</realm>
               </authentication>
            </urlconnection>
         </Contents>
      </XmlRefAddr>
      <SecureRefAddr addrType="username"/>
      <SecureRefAddr addrType="password"/>
   </RefAddresses>
</Reference>

Example 10-2 shows the definition of the login connection, where MyAuth is used as the credential store key value in the login server connection.

Example 10-2 Defining the Login Connection

<Reference name="MyAuth"
           className="oracle.adf.model.connection.adfmf.LoginConnection"
           adfCredentialStoreKey="MyAuth"
           partial="false"
           manageInOracleEnterpriseManager="true"
           deployable="true"
           xmlns="">
   <Factory className="oracle.adf.model.connection.adfmf.LoginConnectionFactory"/>
   <RefAddresses>
      <XmlRefAddr addrType="adfmfLogin">
         <Contents>
            <login url="http://172.31.255.255:7777/
                        SecuredWeb1-ViewController-context-root/faces/view1.jsf"/>
            <logout url="http://172.31.255.255:7777/
                    /SecuredWeb1-ViewController-context-root/faces/view1.jsf"/>
            <accessControl url="http://myhost.us.example.com:7777/
                           UserObjects/jersey/getUserObjects" />
            <idleTimeout value="10"/>
            <sessionTimeout value="36000"/>
            <cookieNames>
               <cookie name="JSESSIONID"/>
            </cookieNames>
            <userObjectFilter>
               <role name="testuser1_role1"/>
               <role name="testuser2_role1"/>
               <privilege name="testuser1_priv1"/>
               <privilege name="testuser2_priv1"/>
               <privilege name="testuser2_priv2"/>
            </userObjectFilter>
         </Contents>
      </XmlRefAddr>
   </RefAddresses>
</Reference>

If a web service request is rejected due to the authentication failure, ADF Mobile returns an appropriate exception and invokes an appropriate action (see Section 18.5, "Using and Configuring Logging"). If none of the existing exceptions correctly represent the condition, a new exception is added.

The connections.xml file is deployed and managed under the Configuration Service. For more information, see Section 10.7, "Administering Web Services."

connection.xml files in FARs are aggregated when the ADF Mobile application is deployed. The credentials represent deployment-specific data and are not expected to be stored in FARs.

10.5.4 Limitations of Secure WSDL File Usage

Since an ADF Mobile application must make a WSDL file accessible at run time without authentication, you cannot use a secure WSDL file with a SOAP web service secured by the basic authentication.

If your intention is to secure the WSDL, consider the following: since the WSDL file is fetched by the GET method of the web service, if you secure each web service method, except the GET method, you can use a secure WSDL. If you secure the GET method, you should not secure the WSDL.

10.6 Invoking Web Services From Java

In your ADF Mobile application, you can invoke the web services layer (both REST and SOAP) from the Java code and use the results in Java methods.

ADF Mobile provides the GenericTypeBeanSerializationHandler utility class that you can use to perform conversions between POJOs (JavaBeans objects) and ADF Mobile's GenericType objects based on the following set of conversion rules:

  1. When converting from POJO to GenericType objects:

    • Standard JavaBeans reflection rules are used for determining properties.

    • Transient properties are ignored in the conversion process.

    • Readable properties are converted into a GenericType attribute.

    • Array properties are represented as repeated attributes in the GenericType.

    • Map properties are represented as individual attributes in the GenericType.

    • Non-primitive properties are represented as nested GenericType objects.

  2. When converting from GenericType objects to POJO:

    • Standard JavaBeans reflection rules are used for determining properties.

    • Transient properties are ignored in the conversion process.

    • Writable properties are converted from GenericType attributes.

    • Repeated attributes in the GenericType are converted into an array object.

    • If the POJO implements the Map interface, then any properties that cannot be set through standard accessors are set in the POJO through the set method of the Map.

    • Non-primitive attributes are represented as nested POJO objects.

The advantage of using this helper API is that it allows you to take the response received from a web service and convert it to a JavaBean in a single call.

For example, a web service passes back and forth an Employee object that needs to be reused throughout the business logic. This object has the following set of properties:

  • name of type String

  • address: a complex object with street, city, state, and zipcode attributes

  • id of type long

  • salary of type float

  • phone of type String, and there could be more than one phone

  • password of type String, and the password should never be transmitted to the back-end web service

Example 10-3 shows a potential code for the Employee object.

Example 10-3 Employee Object

public class Employee {

   protected String name;
   protected Address address;
   protected long id;
   protected float salary;
   protected String[] phone;
   protected transient String password;

   public String getName() {
      return name; 
   }

   public void setName(String name) {
      this.name = name;  
   }

   public Address getAddress() {
      return address;
   }

   public void setAddress(Address address) {
      this.address = address; 
   }

   public long getId() {
      return id; 
   }

   public void setId(long id) {
      this.id = id;
   }

   public float getSalary() {
      return salary; 
   }

   public void setSalary(float salary) {
      this.salary = salary; 
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public void setPassword(String password) {
      this.password = password; 
   }

   public String[] getPhone() {
      return phone;  
   }

   public void setPhone(String phone) {
      this.phone = phone;  
   }

Example 10-4 shows the potential code for the Address object of the Employee class.

Example 10-4 Address Object

public class Address {

   protected String street;
   protected String city;
   protected String state;
   protected String zipcode;

   public String getStreet() {
      return street; 
   }

   public void setStreet(String street) {
      this.street = street;  
   }

   public String getCity() {
      return city; 
   }

   public void setCity(String city)  {
      this.city = city;  
   }

   public String getState() {
      return state; 
   }

   public void setState(String state) {
      this.state = state;  
   }

   public String getZipcode() {
      return zipcode; 
   }

   public void setZipcode(String zipcode)  {
      this.zipcode = zipcode;  
   }

Keeping in mind the conversion rules, note the following:

  1. Since the password is defined as transient, it is ignored with respect to the conversion algorithm.

  2. Since name, address, id, and salary all have get and set methods, they will all be converted to and from the GenericType.

  3. Based on the property type, properties can be coerced between types, as defined in the coerceToType(Object, Class) method of the oracle.adfmf.misc.Converter class.

  4. Complex objects, such as address, are recursed by the conversion algorithm to either build the child GenericType or to create and populate the POJO complex object depending on the direction of the conversion.

  5. Since phone is an array of String objects each representing a unique phone number and since the cardinality of this element is greater than one, the conversion algorithm will find all matches of the phone attribute in the GenericType object, present them as an array, and invoke the setPhone method on the bean. The toGenericType method of the GenericTypeBeanSerializationHandler will take each array element and append it to the toGenericType as an individual phone attribute.

With the following defined:

final String EMPLOYEE_VIRTUAL_BEAN_NAME = "EmployeeDC.Types.Employee";
Employee emp = getEmployee();
GenericType gt = null;
  • The Employee object is converted to the GenericType as:

    gt = GenericTypeBeanSerializationHelper.toGenericType
                         (EMPLOYEE_VIRTUAL_BEAN_NAME, emp);
    
  • The GenericType is converted to the Employee object as:

    emp = GenericTypeBeanSerializationHelper.fromGenericType
                          (Employee.class, gt, null);
    

For successful conversion, consider the following:

  • Typically, POJOs closely follow their associated GenericType structure.

  • When deviating from the GenericType structure, one of the following strategies should be followed:

    1. Additional bean properties should be declared transient.

    2. Optional properties can be excluded from the POJO, provided that the backing service can handle the missing data if used as an operation parameter.

  • The GenericType is only exposed in SOAP data controls. The virtual types have an associated virtual bean name that is passed into the toGenericType method. You can access the virtual bean name by hovering over the virtual type in the Data Controls window of JDeveloper. The typical name format is <DCName>.Types.<methodName>.<argName>.

For more information, see Oracle Fusion Middleware Java API Reference for Oracle ADF Mobile.

10.6.1 How to Use REST Web Services Adapter

You can use the RestServiceAdapter interface to access data (that could be presented as JavaScript Object Notation, for example) sent across a REST call. The RestServiceAdapter interface lets you trigger execution of web service operations without the need to create a web service data control or interact with it directly.

To use the RestServiceAdapter interface in your ADF Mobile application, ensure that the connection exists in the connections.xml file (see Section 10.3, "Creating a New Web Service Connection"), and then add your code to the bean class, as the following examples show.

Example 10-5 demonstrates the use of the RestServiceAdapter for the GET request.

Example 10-5 Using RestServiceAdapter for GET Request

RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

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

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

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

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

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

String response = "";

// Execute SEND and RECEIVE operation
try {
   // For GET request, there is no payload
   response = restServiceAdapter.send("");
}
catch (Exception e) {
   e.printStackTrace();
}

Example 10-6 demonstrates the use of the RestServiceAdapter for the POST request.

Example 10-6 Using RestServiceAdapter for POST Request

String id = "111";
String name = "TestName111";
String location = "TestLocation111";
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("RestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_POST);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/WebService/Departments");

String response = "";

// Execute SEND and RECEIVE operation
try {
   String postData = makeDepartmentPost("DEPT", id, name, location);
   response = restServiceAdapter.send(postData);
}
catch (Exception e) {
   e.printStackTrace();
}
System.out.println("The response is:  " + response);

private String makeDepartmentPost(String rootName, String id, 
                                  String name, String location) {
   String ret = "<" + rootName + ">";
   ret += "<DEPTID>" + id + "</DEPTID>";
   ret += "<NAME>" + name + "</NAME>";
   ret += "<LOCATION>" + location + "</LOCATION>";
   ret += "</" + rootName + ">";
   return ret;
}

Example 10-7 demonstrates the use of the RestServiceAdapter for the PUT request.

Example 10-7 Using RestServiceAdapter for PUT Request

String id = "111";
String name = "TestName111";
String location = "TestLocation111";
RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("RestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_PUT);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/WebService/Departments");

String response = "";

// Execute SEND and RECEIVE operation
try {
   String putData = makeDepartmentPut("DEPT", id, name, location);
   response = restServiceAdapter.send(putData);
}
catch (Exception e) {
   e.printStackTrace();
}
System.out.println("The response is:  " + response);

private String makeDepartmentPut(String rootName, String id, 
                                  String name, String location) {
   String ret = "<" + rootName + ">";
   ret += "<DEPTID>" + id + "</DEPTID>";
   ret += "<NAME>" + name + "</NAME>";
   ret += "<LOCATION>" + location + "</LOCATION>";
   ret += "</" + rootName + ">";
   return ret;
}

Example 10-8 demonstrates the use of the RestServiceAdapter for the DELETE request.

Example 10-8 Using RestServiceAdapter for DELETE Request

RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("RestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_DELETE);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/WebService/Departments/44");

String response = "";

// Execute SEND and RECEIVE operation
try {
   // For DELETE request, there is no payload
   response = restServiceAdapter.send("");
}
catch (Exception e) {
   e.printStackTrace();
}

System.out.println("The response is:  " + response);

When you use the RestServiceAdapter, you should set the Accept and Content-Type headers to ensure that your request and response payloads are not deemed invalid due to mismatched MIME type.

Note:

The REST web service adapter only supports UTF-8 character set on mobile applications. UTF-8 is embedded in the adapter program.

10.6.1.1 Support for Non-Text Responses

You can use the RestServiceAdapter to handle binary (non-text) responses received from web service calls. These responses can include any type of binary data, such as PDF or video files. The RestServiceAdapter method to use is sendReceive.

Example 10-9 shows how to send a request for a file to a REST server, and then save the file to a disk (see Example 10-10).

Example 10-9 Sending Request for File

RestServiceAdapter restServiceAdapter = Model.createRestServiceAdapter();

restServiceAdapter.clearRequestProperties();
restServiceAdapter.setConnectionName("JagRestServerEndpoint");
restServiceAdapter.setRequestType(RestServiceAdapter.REQUEST_TYPE_GET);
restServiceAdapter.setRetryLimit(0);
restServiceAdapter.setRequestURI("/ftaServer/v1/kpis/123/related/1");

// Set credentials needed to access the REST server 
String theUsername = "hr_spec_all";
String thePassword = "Welcome1"; 
String userPassword = theUsername + ":" + thePassword;
String encoding = new sun.misc.BASE64Encoder().encode(userPassword.getBytes());

restServiceAdapter.addRequestProperty("Authorization", "Basic " + encoding);

// Execute the SEND / RECEIVE operation.
// Since it is a GET request, there is no payload.
try {
   this.responseRaw = restServiceAdapter.sendReceive("");
}
catch (Exception e) {
   e.printStackTrace();
}
System.out.println("The response is:  " + this.responseRaw);

// Write the response to a file
writeByteArrayToFile(this.responseRaw);

Example 10-10 demonstrates a method that is called by the code from Example 10-9. This method saves a byte[] response to a file on disk:

Example 10-10 Saving File to Disk

public void writeByteArrayToFile(byte[] fileContent) {
   BufferedOutputStream bos = null;
try {
   FileOutputStream fos = new FileOutputStream(new File(fileToSavePath));
   bos = new BufferedOutputStream(fos);

   // Write the byte [] to a file 
   System.out.println("Writing byte array to file");
   bos.write(fileContent);
   System.out.println("File written");
}
catch(FileNotFoundException fnfe) {
   System.out.println("Specified file not found" + fnfe);
}
catch (IOException ioe) {
   System.out.println("Error while writing file" + ioe);
}
finally {
   if(bos != null) {
      try {
         // Flush the BufferedOutputStream
         bos.flush();

         // Close the BufferedOutputStream
         bos.close();
      }
      catch (Exception e) {
      }
   }
}

10.6.2 What You May Need to Know About Invoking Data Control Operations

You can use the invokeDataControlMethod method of the AdfmfJavaUtilities to invoke a data control operation which does not have to be explicitly added as a methodAction in a PageDef file.

For more information and examples, see Oracle Fusion Middleware Java API Reference for Oracle ADF Mobile.

10.7 Administering Web Services

Using the Configuration Service provided by ADF Mobile, administrators can update web service connection endpoints for different ADF Mobile applications from a server, resulting in users obtaining a new connection the first time the ADF Mobile application is started. This is done by hosting and updating multiple connections.xml files for different applications. Subsequent application starts require you (the ADF Mobile application developer) to use the container utilities API to check for a new connection (see Section 6.2.3, "checkforNewConfiguration").

Administrators should designate connections.xml files as resources protected by basic authentication (see Chapter 17, "ADF Mobile Application Security").

A client application can use the Configuration Service to check for updates.

The Configuration Service dialog allows you to do the following:

  • Update the Configuration Service URL and save the update for this application.

    You can seed the Configuration Service URL with a URL value that assists in completing the Configuration Service dialog (see Example 10-11). If that preference ID exists, it is seeded into the Configuration Service dialog.

    The connections.xml file must be present at the Configuration Service URL. If the Configuration Service is enabled, this file is obtained and used from the Configuration Server rather than from the application bundle. For more information, see Section 10.7.1, "What You May Need to Know About the URL Construction."

  • Enter the user name and password, which are saved in the keystore.

Administrators can use a setting in the adf-config.xml file for the application to define whether or not to call the Configuration Service at the application startup time (see Example 10-11). If the application starts for the first time, the dialog is displayed and the credentials are cached in the keystore. On subsequent starts (not including resume), you need to instruct your application to check for modifications against the server and to trigger the display of the Configuration Service dialog. ADF Mobile provides an API whereby you can specify a place in the application where the check for updates should be performed and against which the client API should be called to invoke the Configuration Service dialog. After the update, the application should run correctly (and be restarted if necessary).

Example 10-11 shows the use of the use-configuration-service-at-startup property, whose default value is false. In addition, this example shows the adfmf-configuration-service-seed-url property that is used to seed the endpoint URL in the user prompt for the Configuration Service connection information.

Example 10-11 Configuration Service Settings in adf-config.xml File

<adf:adf-properties-child xmlns="http://xmlns.oracle.com/adf/config/properties">
   <adf-property name="use-configuration-service-at-startup" value="true"/>
   <adf-property name="adfmf-configuration-service-seed-url"
                 value="http://myhost.us.example.com:7777/
                        ConfigServerWebDavFolder/"/> 
</adf:adf-properties-child>

The Configuration Service performs the following steps when the application starts:

  1. It starts at the application startup time.

  2. It checks the Documents directory for a copy of the managed files. If they are found, the Configuration Service finishes its process.

    If the Configuration Service does not locate configuration files in the Documents directory, the following takes place:

    • If the adf-config.xml file indicates that the Configuration Service is not in use, then the Configuration Service copies the managed files from the application bundle to the Documents directory managed folder, and then the Configuration Service finishes its process.

    • If the adf-config.xml file indicates that the Configuration Service is in use, then the Configuration Service tries to download the managed files.

  3. It checks for stored credentials from the secure store. If the credentials are found and they provide access to the Configuration Server, then the connections.xml file is downloaded and placed in the Documents directory managed folder, and at this point the Configuration Service finishes its process.

    If the credentials are not found or the stored credentials fail to provide access to the Configuration Server, the user is prompted for the connection information (user name, password, and endpoint URL).

  4. The Configuration Service reattempts the prompt or download five times before failing and dropping out of the application.

  5. After a successful connection has been made to the Configuration Server, the connections.xml file is downloaded and the connection information is stored for later use.

Figure 10-4 shows the Configuration Service prompt dialog on an iPhone.

Figure 10-4 Configuration Service Dialog on iPhone

Configuration Service Dialog on iPhone

10.7.1 What You May Need to Know About the URL Construction

The URL to each of the Configuration Service-managed resources is constructed. It contains the application ID and the file name as follows:

If the user provides the URL of http://my.server.com:port/SomeFolderLocation and the application ID of com.mycompany.appname, the following URL will be used to download the configuration file:

http://my.server.com:port/SomeFolderLocation/com.mycompany.appname/connection.xml