24 Displaying Error Messages in MAF Applications

This chapter describes how to use the AdfException class to invoke errors and how to localize error messages.

This chapter includes the following sections:

24.1 Introduction to Error Handling in MAF Applications

MAF can manage errors that occur in applications and display messages to end users in response to these errors.

Errors arising from mobile applications might be unexpected, such as a failed connection to a remote server. Other errors, such as a violation of an application business rule, may be expected. Errors or exceptions might occur in the primary request thread or in a secondary thread that runs a background task. If the application supports multiple languages, then it must display the error message in the user's language.

To enable a MAF application to throw an exception, use oracle.adfmf.framework.exception.AdfException class. See Java API Reference for Oracle Mobile Application Framework.

The following code enables MAF to handle an exception as expected. A popup message, similar to the one shown in Figure 24-1 displays within the application and shows the severity and provides explanatory text.

throw new AdfException("My error message", AdfException.ERROR);

Figure 24-1 An Error Message

This image is described in the surrounding text

Note:

Similar error messages display within an application when the exception is thrown within a managed bean or a data control bean.

24.2 Displaying Error Messages and Stopping Background Threads

You can enable an application to stop a thread and display an error message by using MAF APIs.

The MessageUtils class, illustrated in the following example, enables an application to stop a thread and display an error by first making a JavaScript call (invokeContainerJavaScriptFunction) and then throwing an exception. The addMessage method enables the error to display. For information, see How Applications Display Error Message for Background Thread Exceptions. See also invokeContainerJavaScriptFunction.

The MessageUtils class uses the BundleFactory and Utility methods for retrieving the resource bundle and the error message and dynamically checks if a thread is running in the background. Using this class, you can move code from the main thread to the background thread.

package oracle.errorhandling.demo.mobile;
 
import java.util.ResourceBundle;
 
import oracle.adfmf.framework.api.AdfmfContainerUtilities;
import oracle.adfmf.framework.api.AdfmfJavaUtilities;
import oracle.adfmf.framework.exception.AdfException;
import oracle.adfmf.util.BundleFactory;
import oracle.adfmf.util.Utility;
 
public class MessageUtils {

   public static void handleError(AdfException ex) {
      handleMessage(ex.getSeverity(), ex.getMessage());
   }

   public static void handleError(String message) {
      handleMessage(AdfException.ERROR, message);
   }
   public static void handleError(Exception ex) {
      handleMessage(AdfException.ERROR, ex.getLocalizedMessage());
   }

   public static void handleMessage(String severity, String message) {
      if (AdfmfJavaUtilities.isBackgroundThread()) {
         AdfmfContainerUtilities.invokeContainerJavaScriptFunction(
                                 AdfmfJavaUtilities.getFeatureName(),
                                 "adf.mf.api.amx.addMessage",
                                 new Object[] {severity,
                                 null,
                                 null});
         if (AdfException.ERROR.equals(severity)) {
            // need to throw an exception to stop background thread processing
            throw new AdfException(message,severity);
         }
      }
      else {
         throw new AdfException(message,severity);
      }
   }

   public static void addJavaScriptMessage(String severity, String message) {
      AdfmfContainerUtilities.invokeContainerJavaScriptFunction(
                              AdfmfJavaUtilities.getFeatureName(),
                              "adf.mf.api.amx.addMessage",
                              new Object[] {severity,
                              message,
                              null,
                              null });
   }

}

24.2.1 How Applications Display Error Message for Background Thread Exceptions

Applications do not display error messages when exceptions are thrown for background threads. To enable error messages to display under these circumstances, applications call the addMessage method. The addMessage method takes the following parameters:

  • The severity of the error

  • The summary message

  • The detail message

  • a clientComponentId.

The following example illustrates how you can enable the application to alert the user when an error occurs in the background by using the addMessage method.

Runnable runnable = new Runnable() {
   public void run() {
      AdfmfContainerUtilities.invokeContainerJavaScriptFunction(
                              AdfmfJavaUtilities.getFeatureName(),
                              "adf.mf.api.amx.addMessage", new Object[] {AdfException.ERROR,
                              "My error message for background thread",
                              null,
                              null });
   }
};
Thread thread = new Thread(runnable);
thread.start();

Because the adf.mf.api.amx.addMessage JavaScript function is the same method that is used when the application throws AdfException in the primary request thread, users receive the same popup error message whether the error message is referring to exceptions in the main thread or from a background thread.

Note:

As illustrated in the preceding example, the detail message and the clientComponentId can be a Null value. A detail message displays on a new line in the same font size as the summary message.

However, you can prevent an error message from appearing if you place the code within a piece of Java logic that runs in a background thread, as illustrated in the following example. Using the method illustrated in the first example of Localizing Error Messages enables the background thread to stop silently without notifying the user.

Runnable runnable = new Runnable() {
   public void run() {
      // this exception will be lost because no popup error
      // message will display in the MAF application
      throw new AdfException("My (lost) error message in background",
                              AdfException.ERROR);
   }
};
Thread thread = new Thread(runnable);
thread.start();

24.3 Localizing Error Messages

MAF uses standard Java resource bundles to display an exception error message in the language of the application user.

As illustrated in the following example, the resource bundle name (the .xlf file) and bundle message key is passed to the AdfException constructor method to enable the error message to be read from a resource bundle.

private static final String XLF_BUNDLE_NAME=
                            "oracle.errorhandling.mobile.ViewControllerBundle";
   throw new AdfException(AdfException.ERROR, 
                          XLF_BUNDLE_NAME,
                          "MY_ERROR_MESSAGE",
                          null);

To ensure that the application does not throw an MissingResourceException error, use the oracle.adfmf.util.BundleFactory method to retrieve the resource bundle and then use the oracle.adfmf.util.Utility method to retrieve the error message, as illustrated in the following example.

ResourceBundle bundle = BundleFactory.getBundle(XLF_BUNDLE_NAME);
String message = Utility.getResourceString(bundle, "MY_ERROR_MESSAGE",null);
throw new AdfException(message,AdfException.ERROR);

The following example illustrates using the adf.mf.api.amx.addMessage JavaScript function to display the localized error message when an exception is thrown from a background thread.

ResourceBundle bundle = BundleFactory.getBundle(XLF_BUNDLE_NAME);
String message = Utility.getResourceString(bundle, "MY_ERROR_MESSAGE_BG",null);
AdfmfContainerUtilities.invokeContainerJavaScriptFunction(
                              AdfmfJavaUtilities.getFeatureName(),
                              "adf.mf.api.amx.addMessage",
                              new Object[] {AdfException.ERROR,
                                            message,
                                            null,
                                            null });