28 Testing and Debugging MAF Applications

This chapter provides information on testing and debugging MAF applications.

This chapter includes the following sections:

28.1 Introduction to Testing and Debugging MAF Applications

To test or debug your MAF application, deploy it in debug mode to a device on one of the platforms (Android, iOS, or Universal Windows Platform) that MAF supports.

MAF and the respective platforms provide tools that let you connect the JDeveloper development environment with the MAF application executing on a device or a virtual device. For example, if you want to test your MAF application on an Android device, you deploy your MAF application in debug mode from JDeveloper to an Android device or to an Android Virtual Device (AVD). The Universal Windows Platform and iOS provide similar tools.

The high-level steps to debug a MAF application include the following tasks:

  1. Configure the deployment profile that you use to deploy the MAF application to the test environment so that it deploys the MAF application in debug mode.

  2. Configure the MAF application’s maf.properties file to enable debugging.

  3. Deploy the MAF application to the test environment.

  4. Use the appropriate tools for the debugging task that you want to complete. If, for example, you want to debug Java code in your MAF application, use the tools that JDeveloper provides. If you want to debug the code that renders the user interface (HTML, CSS, or JavaScript) of your MAF application, use the tools that each platform provides for this task.

MAF provides other features to assist testing your application. These include the ability to monitor your application’s performance, plus send analytics and diagnostic information to Oracle Mobile Cloud service (if your application accesses resources from that service).

28.2 Testing MAF Applications

You can test a MAF application on a mobile device, emulator or simulator.

There are two approaches to test a MAF application:

  1. Testing on a mobile device: this method always provides the most accurate behavior, and is also necessary to gauge the performance of your application. However, you may not have access to all the devices on which you want to test, making device testing inconclusive.

  2. Testing on a mobile device emulator or simulator: this method usually offers better performance and faster deployment, as well as convenience. However, even though a device emulator or simulator closely approximates the corresponding physical device, there might be differences in behavior and limitations on the capabilities that can be emulated.

Typically, a combination of both approaches yields the best results.

28.2.1 How to Perform Accessibility Testing on iOS-Powered Devices

You should use a combination of the following methods to test the accessibility of your MAF application developed for iOS-powered devices:

  • Testing with the Accessibility Inspector on an iOS-powered device simulator.

    For detailed information, see the Test Accessibility on Your Device with VoiceOver section in the Accessibility Programming Guide for iOS available through the iOS Developer Library.

  • Testing with the VoiceOver on an iOS-powered device.

    For information, see the Using VoiceOver to Test Your Application section in the Accessibility Programming Guide for iOS available through the iOS Developer Library.

28.3 Configuring JDeveloper and MAF Applications to Debug Code

JDeveloper is equipped with debugging mechanisms that allow you to execute a Java program in debug mode and use standard breakpoints to monitor and control execution of an application.

Since a MAF application cannot be run inside JDeveloper, the debugging approach is different: you can use the JDeveloper debugger to connect to a Java Virtual Machine instance on a mobile device or simulator and control the Java portions of your deployed MAF application.

MAF automatically configures the project properties for debugging. The following are the steps you need to take to use JDeveloper to debug the Java code in your MAF application:

To test or debug an application:

  1. From JDeveloper's main menu, click Run > Choose Active Run Configuration to select an active run configuration.

  2. In the Applications window, right-click on any file that you want to test and choose Run.

    Alternatively, choose Debug if you want to run the application with debugging enabled.

    Tip:

    You can also open any file in the MAF application in Source view, right-click on it, and then select Run or Debug.

    Note:

    If you are using an existing application that does not have the predefined set of run configurations, you can create new run configurations.

See What You May Need to Know About the Debugging Configuration.

28.3.1 What You May Need to Know About the Debugging Configuration

When a new MAF application is created, the creation wizard automatically configures the application properties for debugging. This includes the creation of default run configurations that may be used to run or debug the MAF application on an iOS simulator or Android emulator or device. These run configurations allow you to build, deploy, run, or debug a MAF application by clicking the JDeveloper Run or Debug buttons. When you click the Run or Debug button in JDeveloper and select a MAF run configuration, the deployment profile associated with the run configuration is executed to build and deploy the application to the targeted device. Once the application has been deployed, it automatically starts. If the Debug button was selected, the application will start with the debugger.

For information on how to create and edit run configurations, see Creating and Configuring a Run Configuration.

28.3.1.1 Creating and Configuring a Run Configuration

To create a new configuration or to modify an existing one, complete the Edit Run Configuration dialog (as shown in figure) as follows:

  1. From JDeveloper's main menu, click Application > Project Properties to open the Project Properties dialog.
  2. In the Project Properties dialog, select the Run/Debug node from the tree on the left.

    Alternatively, choose Run > Choose Active Run Configuration > Manage Run Configurations.

  3. Create a new configuration or modify an existing one.

    If using Shared Settings, click Edit Shared Settings to open a dialog that allows you to create or edit new MAF run configurations. If using Project Settings, click New or Edit. With shared settings, the run configurations are shared across all projects. Use Shared Settings is the default option so you can use the MAF run configurations that exist at the time the project was added.

  4. Complete the Edit Run Configuration dialog as follows:
    • Select Mobile Run Configuration from the tree on the left.

    • Select your target platform.

    • Select a deployment profile.

    • Enter the port number, up to five digits long. This number is initially seeded with the value of the java.debug.port property contained in the maf.properties file and appears as hint text. If a value is not specified for the port, the seeded value is used.

    • For iOS, set the following options:

      • Application Arguments—Enter arguments that can be passed to the MAF application upon startup for customizing the runtime behavior of the application. For example, -consoleRedirect=/<path>/<to>/log.txt directs the log output to the file specified. The path must be an absolute path to receive the log file. The location must be writable for the current user.

      • Simulator—Choose which simulator you are deploying the application to. The options depend on which versions of the iOS SDK have been installed.

      • iOS version—Choose which version of iOS the simulator should use. The the drop-down menu displays the iOS versions that the selected device supports.

    • For Android, set the following options:

      • Target—Select the deployment target (Emulator or Device).

      • Max Attempts—Choose the maximum number of connection attempts to allow.

      • Interval (seconds)— Choose the length of time in seconds between connection attempts.

        Tip:

        If the Android device or emulator is slow or times out, try increasing the Max Attempts or the Interval to allow sufficient time for Java to initialize and to force the Android starter to wait longer or try more attempts before quitting.

    Figure 28-1 Mobile Run Configuration Dialog

    Description of Figure 28-1 follows
    Description of "Figure 28-1 Mobile Run Configuration Dialog"

28.3.2 How to Enable Debugging of Java Code and JavaScript

A maf.properties file allows you to specify startup parameters for the JVM and web views of MAF to enable debugging of the Java code and JavaScript. The maf.properties file is automatically created and placed in the Descriptors/META-INF directory under the Application Resources (see Using and Configuring Logging), which corresponds to the <application_name>/src/META-INF location in your application file system.

When you execute a MAF run configuration, the following debugging properties are automatically set in the maf.properties file:

  • java.debug.enabled: Set to true if doing a debug session; set to false if doing a run session.

    Caution:

    When java.debug.enabled is set to true, the JVM waits for a debugger to establish a connection to it. Failure of the debugger to connect will result in the failure of the MAF AMX application feature to load.

  • java.debug.port: Set to the port number configured in the MAF run configuration being executed.

  • javascript.debug.enabled: Set to true if doing a debug session; set to false if doing a run session. Applies to Android only.

    Note:

    The javascript.debug.enabled property is not required for enabling JavaScript debugging when the MAF application is running on an iOS-powered simulator or iOS-powered device.

The contents of the maf.properties file may be similar to the following:

java.debug.enabled=true
java.debug.port=8000

javascript.debug.enabled=true

For information on how to use JDeveloper to debug the Java code, see Debugging MAF Applications.

28.3.3 How to Debug the MAF AMX Content

If your MAF application includes the MAF AMX content, after you configure the device or emulator, you can set breakpoints, view the contents of variables, and inspect the method call stack just as you would when debugging other types of applications in JDeveloper.

Note:

You can only debug your Java code and JavaScript (see How to Enable Debugging of Java Code and JavaScript). Debugging of EL expressions or other declarative elements is not supported.

28.4 Debugging MAF Applications Deployed on the Android Platform

Describes how to debug the Java and UI code of MAF applications that you deploy to Android.

To debug Java code, you configure the maf.properties file in your application and create a run configuration in JDeveloper. For information about these tasks, see How to Enable Debugging of Java Code and JavaScript and Configuring JDeveloper and MAF Applications to Debug Code. Once you complete these tasks, you can deploy your MAF application in debug mode to debug your Java code, as described in How to Debug Java Code on the Android Platform.

To debug UI code (JavaScript, HTML, and CSS), you configure the maf.properties file in your application (javascript.debug.enabled=true). Once you complete this task, you can debug your UI code, as described in How to Debug UI Code on the Android Platform.

28.4.1 How to Debug Java Code on the Android Platform

To debug a MAF application’s Java code on the Android platform using JDeveloper, follow the debugging procedure described in Configuring JDeveloper and MAF Applications to Debug Code.

For information on how to configure an Android-powered device or emulator and how to deploy a MAF application for debugging, see How to Deploy an Android Application to an Android Emulator.

To allow debugging of a MAF application running on an Android-powered device or its emulator, verify that the Network Information plugin is enabled, as described in Introduction to Using Plugins in MAF Applications.

28.4.2 How to Debug UI Code on the Android Platform

When developing a MAF application, you may need to debug code that renders the user interface (UI) of your application on an Android device. The code that renders the UI can include JavaScript, HTML, and CSS. You can debug this code using Google’s Chrome DevTools (as shown in figure) when you deploy the MAF application from your development machine to the Android device.

Figure 28-2 Chrome DevTools Inspecting an AMX Page from a MAF application

Description of Figure 28-2 follows
Description of "Figure 28-2 Chrome DevTools Inspecting an AMX Page from a MAF application"

For information on the Chrome DevTools, including the requirements to use it, see Remote Debugging on Android with Chrome DevTools on the Google Developers’ site.

See also the “Debugging HTML in Oracle MAF Applications on Android” video on the Oracle Mobile Platform YouTube channel for an overview of how to debug UI code on Android. Note that the latter video makes reference to a cvm.properties file. This file has been renamed to maf.properties in the current release.

To deploy a MAF application to an Android device to debug its UI code, you need to:

28.5 Debugging MAF Applications Deployed on the iOS Platform

Describes how to debug the Java and UI code of MAF applications that you deploy to iOS.

Before you can debug Java code, you configure the maf.properties file in your application and create a run configuration in JDeveloper. For information about these tasks, see How to Enable Debugging of Java Code and JavaScript and Configuring JDeveloper and MAF Applications to Debug Code. Once you complete these tasks, you can deploy your application in debug mode to the iOS device and debug your Java code. For information about how to deploy in debug mode, see How to Debug Java Code on the iOS Platform.

To debug UI code (JavaScript, HTML, and CSS), you configure the maf.properties file in your application (javascript.debug.enabled=true). Once you complete this task, you can debug your UI code, as described in How to Debug UI Code on the iOS Platform.

28.5.1 How to Debug Java Code on the iOS Platform

To debug a MAF application’s Java code on the iOS platform using JDeveloper, follow the debugging procedure described in Configuring JDeveloper and MAF Applications to Debug Code.

For information on how to configure an iOS-powered device or simulator and how to deploy a MAF application for debugging, see the following:

28.5.2 How to Debug UI Code on the iOS Platform

If you are working with the iOS platform, you can use the Safari browser to debug JavaScript. To do so, open the Safari preferences, select Advanced, and then enable the Develop menu in the browser by selecting Show Develop menu in menu bar.

When the Develop menu is enabled, select either iPhone Simulator or iPad Simulator, as shown in figures, and then select a UIWebView that you are planning to debug.

Note:

Whether the Develop menu displays an iPhone Simulator or iPad Simulator option depends on which device simulator is launched.

Use the featureContentDelay additional build argument to record log messages and errors from your custom JavaScript before the first page from your application loads. This argument specifies a delay before the WebView is populated with content. Set the additional build argument -featureContentDelay to 20. For information about setting additional build arguments, see Defining the iOS Build Options.

Figure 28-3 Using Develop Menu on Safari Browser for Debugging on iPhone Simulator

Description of Figure 28-3 follows
Description of "Figure 28-3 Using Develop Menu on Safari Browser for Debugging on iPhone Simulator"

Figure 28-4 Using Develop Menu on Safari Browser for Debugging on iPad Simulator

Description of Figure 28-4 follows
Description of "Figure 28-4 Using Develop Menu on Safari Browser for Debugging on iPad Simulator"

Figure 28-5 Using Develop Menu on Safari Browser to Select UIWebView

Description of Figure 28-5 follows
Description of "Figure 28-5 Using Develop Menu on Safari Browser to Select UIWebView"

Figures show the CSS, DOM, and HTML Safari Remote Web Inspector in action.

Figure 28-6 Remote Web Inspector

Description of Figure 28-6 follows
Description of "Figure 28-6 Remote Web Inspector"

Figure 28-7 AMX Page Analyzed by Remote Web Inspector at Runtime

Description of Figure 28-7 follows
Description of "Figure 28-7 AMX Page Analyzed by Remote Web Inspector at Runtime"

Figures show JavaScript debugging using breakpoints inside the Safari browser.

Figure 28-8 JavaScript Debugging in Safari Browser

Description of Figure 28-8 follows
Description of "Figure 28-8 JavaScript Debugging in Safari Browser"

Figure 28-9 AMX Page Debugged at Runtime

Description of Figure 28-9 follows
Description of "Figure 28-9 AMX Page Debugged at Runtime"

28.6 Debugging MAF Applications Deployed on the Universal Windows Platform

Describes how to debug the Java and UI code of MAF applications that you deploy to the UWP.

You can debug the Java code in MAF applications that you deploy to the UWP using JDeveloper’s debugging tools. See How to Debug Java Code on the Universal Windows Platform.

Use Visual Studio to debug the JavaScript, HTML, and CSS code in your MAF application, as described in How to Debug UI Code on the Universal Windows Platform.

28.6.1 How to Debug Java Code on the Universal Windows Platform

Describes how to debug Java code in a MAF application that you deploy to the Universal Windows Platform (UWP).

Perform the following steps so that you can debug Java code in a MAF application that you deploy to the UWP:

  1. Configure the MAF application’s maf.properties file entries to enable debugging. Ensure that the following values appear in the maf.properties file.

    java.debug.enabled=true
    java.debug.port=8000
    java.debug.mode=client
    java.debug.host=localhost
    
    

    For information about the maf.properties file, see How to Enable Debugging of Java Code and JavaScript.

  2. Configure the Windows deployment profile for the MAF application to use Debug mode, as shown in Figure 28-10. Click Application > Application Properties > Deployment to access this dialog.

    Figure 28-10 Enabling Debug Mode for the MAF Application

    The surrounding text describes the image.
  3. Add a custom project to your MAF application so that it can access the standard JDeveloper application run/debug configuration dialogs. Once you add this custom project to your MAF application, enable the Remote Debugging option with a connection that listens for the JPDA protocol. Start a debug listener in the custom project. For information about these tasks, see How to Enable Remote Debugging of a MAF Application on the Universal Windows Platform.

  4. Deploy the MAF application using the local Windows machine option. See Deploying a MAF Application to the Universal Windows Platform.

Once you deploy the MAF application using the Windows Local Machine deployment option, the application starts and establishes a debug session with JDeveloper.

28.6.1.1 How to Enable Remote Debugging of a MAF Application on the Universal Windows Platform

Add a custom project to your MAF application to expose the Run/Debug configuration panels that the MAF application creation template does not display when you create a MAF application.

Using these configuration panels, you can enable remote debugging for a MAF application that you deploy to the UWP. After you add and configure the custom project, you start the debug listener from the custom project.
To add a custom project to enable remote debugging of a MAF application on the UWP:
  1. From JDeveloper’s main menu, click File > New > Project, select Custom Project in the New Gallery dialog and click OK.
  2. Click Finish in the Create Custom Project to create a custom project named Project 1.
    The new custom project (Project 1) appears in the Projects panel of your MAF application between the ApplicationController and ViewController projects.
  3. Select the project, and from JDeveloper’s main menu select Application > Project Properties.
  4. In the Run/Debug page of the Project Properties dialog, select the Default run configuration and click the Pencil icon to display the Launch Settings dialog where you select Remote Debugging checkbox.
  5. Navigate to Tool Settings > Debugger > Remote and configure the following properties, as illustrated in figure:
    1. Protocol: Select Listen for JPDA from the dropdown menu.
    2. Port: Enter the port number that you have configured for java.debug.port in the maf.properties file.
    3. Timeout: specify the number of seconds to time out. 0 means do not time out.
    4. Local address: localhost.

    Figure 28-11 Enable Remote Debugging of a MAF Application Deployed to the UWP

    Description of Figure 28-11 follows
    Description of "Figure 28-11 Enable Remote Debugging of a MAF Application Deployed to the UWP"
  6. Click OK to close the open dialogs.
  7. In the Applications window’s Project panel, right-click the custom project (for example, Project 1) and choose Debug from the context menu that appears.
  8. In the Listen for JPDA dialog, review the connection information to confirm it is correct and click OK.
  9. From JDeveloper’s main menu, click Windows > Processes to verify that the debug listener starts, as shown in figure.

    Figure 28-12 Debug Listener Started in MAF Application

    Description of Figure 28-12 follows
    Description of "Figure 28-12 Debug Listener Started in MAF Application"
Once you deploy the MAF application using the Windows Local Machine deployment option, the application starts and establishes a debug session with JDeveloper.

28.6.2 How to Debug UI Code on the Universal Windows Platform

When developing a MAF application on the Universal Windows Platform (UWP), you may need to debug code that renders the user interface (UI) of your application. The code that renders the UI can include JavaScript, HTML, and CSS. You debug this code using Visual Studio.

For information about installing Visual Studio for use in MAF application development, see Setting Up Development Tools for the Universal Windows Platform in Installing Oracle Mobile Application Framework.

Use Visual Studio to debug and inspect your application’s code if your application runs on the Windows platform. Deploy your application on your Windows machine and attach the process for the application to the Visual Studio debugger, as described in Microsoft’s documentation.

MAF applications run in an instance of the wwahost.exe process on Windows, so multiple instances of the wwahost.exe process appear in the Attach to Process dialog if you have more than one application running. Use the Title column of the Attach to Process dialog to select the correct application to attach, as illustrated by the following image where an application named FixItFast is selected.

Figure 28-13 Attach to Process Dialog

The surrounding text describes the image.

After you have attached your application, use the Visual Studio debugger, as described in Microsoft’s documentation, to debug your application.

28.7 Using and Configuring Logging in MAF Applications

You can enable logging on all supported platforms through JavaScript and embedded code by configuring the logging.properties file so that MAF directs the log output to a single file. This log output includes the output produced by System.out.println and System.err.println statements.

The default MAF's logging process is as follows:

  • The logging begins at application startup.

  • The existing log file from the previous application run is deleted, so only the contents of the current run are available.

  • When you run your application on an iOS-powered device simulator, you can only access the Java logging output through a file of whose name and location you are notified as soon as the output redirection occurs and the file is generated. One of the typical locations for this file is /Users/<userid>/Library/Developer/CoreSimulator/Devices/<device_id>/data/Containers/Data/Application/<container_id>/application.log, where <device_id> and <container_id> references represent long UUID strings created by iOS during the installation of the application. The values of these references cannot be predicted and when multiple simulators or applications are installed, it is difficult to determine which folder corresponds with the simulator used during deployment. When using JDeveloper for deployment, the -consoleRedirect option is automatically set to direct the log output to a known location. If you set it on a MAF run configuration for iOS using the Edit Run Configuration > Mobile Run Configuration dialog and that run configuration is used to deploy or run the MAF application on an iOS-powered device simulator, the log file is created at the configured location and its contents is displayed on a console in JDeveloper. If you do not set the value using the Edit Run Configuration > Mobile Run Configuration dialog or you choose to perform a regular deployment (for example, such that it does not use a MAF run configuration for iOS), the log file is created in the <appRoot>/<deployRoot>/<iOSProfileName>/log<appName>.log file and its contents is displayed on a console in JDeveloper. See Creating and Configuring a Run Configuration.

    Note:

    The path must be an absolute path to receive the log file and the location must be writable for the current user.

    When you are running your application on an iOS-powered device, the console output is redirected to an application.log file that is placed in the Documents/logs directory of your application. You can access this directory as follows on your iOS-powered device:

    1. Navigate to Xcode > Devices.
    2. Select the application from the list in the Installed Apps section.
    3. Click the gear icon.
    4. Select Download Container.
    5. Right-click the downloaded *.xcappdata file and select Show Package Contents.
    6. Open AppData > Documents > Logs.
    7. Double-click the application.log file.

    On Android, the output is forwarded to a text file with the same name as the application. The output file location is /sdcard/Android/data/<app.package>/files/<app.name>.txt. If this location is not present or is configured as read-only, the log output is rerouted to the application's writable data directory at /data/data/<package>/files/<AppName>.txt. On Android devices that use Android 6.0 +, MAF writes the log output to /data/data/<package>/files/<AppName>.txt unless the end user grants Storage permission to the MAF application, as shown in the following image. If the end user grants Storage permission, MAF writes the log output to /sdcard/Android/data/<app.package>/files/<app.name>.txt. MAF applications request that users enable the Storage permission by enabling the Storage Access plugin described in Introduction to Using Plugins in MAF Applications.

    Figure 28-14 Granting Storage Permission to MAF Application on Android

    Description of Figure 28-14 follows
    Description of "Figure 28-14 Granting Storage Permission to MAF Application on Android"

    MAF provides a number of APIs that you use in your MAF application to manage storage permissions. The following code examples demonstrate how to use these APIs. MAF ignores these APIs on non-Android platforms. For information about the APIs, see Java API Reference for Oracle Mobile Application Framework.

    // Check if the Storage permission is granted:
    import oracle.maf.api.platform.android.Permissions;
    import oracle.maf.api.platform.android.PermissionGroup;
    ...
    Permissions.getInstance().hasPermissions(PermissionGroup.Storage);
    ...
    
    // Check if a UI should be shown to the user with a rationale for the Storage permission:
    import oracle.maf.api.platform.android.Permissions;
    import oracle.maf.api.platform.android.PermissionGroup;
    ...
    Permissions.getInstance().shouldShowRequestPermissionRationale(PermissionGroup.Storage);
    ...
    
    // Request Storage permission:
    import oracle.maf.api.platform.android.Permissions;
    import oracle.maf.api.platform.android.PermissionGroup;
    import oracle.maf.api.platform.android.PermissionsCallback;
    
    public class AndroidPermissionsBean
      implements PermissionsCallback
    {
      public void checkStoragePermission()
      {
        //
        // Set "this" as the permission callback handler.
        //
        Permissions.getInstance().setPermissionsCallbackHandler(this);
    
        //
        // Asynchronously request permissions.
        //
        Permissions.getInstance().requestPermissions(PermissionGroup.Storage);
      }
    
      @Override
      public void onPermissionsResponse(PermissionGroup permissionGroup, boolean hasPermissions)
      {
        //
        // Remove "this" as the permission callback handler.
        //
        Permissions.getInstance().setPermissionsCallbackHandler(null);
    
        //
        // Asynchronously handle the permission result callback below.
        //
      }
    }
    

    The contents of the log file is replicated in the Android Logcat utility (see http://developer.android.com/tools/debugging/debugging-log.html). JDeveloper displays the logging output from the Logcat when you use JDeveloper to deploy your MAF application to an Android-powered device or emulator.

  • For both iOS and Android, the logging output appears in JDeveloper’s run or debug Log page immediately after the deployment. In case of a regular deployment, the deployment log is displayed in the Deployment Log page, whereas the application log is displayed in a separate Log page. If you use a Run/Debug run configuration to build, deploy, and launch the MAF application, the Terminate option in the Processes tab of the Applications window terminates the MAF application along with the process that performs the log redirection. The View Log option enables you to see the log page, as the following illustration shows.

    Description of term_process.png follows
    Description of the illustration term_process.png

    If you use a deployment profile to build, deploy, and launch the MAF application, the Terminate option in the Processes tab terminates only the log redirection process, whereas the MAF application remains running.

  • The logging.properties file is automatically created and placed in the Descriptors/META-INF directory under the Application Resources (see Using and Configuring Logging), which corresponds to the <application_name>/src/META-INF location in your application file system. In this file, it is defined that all loggers use the java.util.logging.ConsoleHandler and SimpleFormatter, and the log level is set to SEVERE. You can edit this file to specify different logging behavior (see How to Configure Logging Using the Properties File).

    Note:

    In your MAF application, you cannot use loggers from the java.util.logging package.

MAF loggers are declared in the oracle.adfmf.util.Utility class as follows:

public static final String APP_LOGNAME = "oracle.adfmf.application";
public static final Logger ApplicationLogger = Logger.getLogger(APP_LOGNAME);

public static final String FRAMEWORK_LOGNAME = "oracle.adfmf.framework";
public static final Logger FrameworkLogger = Logger.getLogger(FRAMEWORK_LOGNAME);

The logger that you are to use in your MAF application is the ApplicationLogger.

You can also use methods of the oracle.adfmf.util.logging.Trace class.

See Java API Reference for Oracle Mobile Application Framework.

28.7.1 How to Configure Logging Using the Properties File

The following example shows the logging.properties file that you use to configure logging.

# default - all loggers to use the ConsoleHandler
.handlers=java.util.logging.ConsoleHandler
# default - all loggers to use the SimpleFormatter
.formatter=java.util.logging.SimpleFormatter

oracle.adfmf.util.logging.ConsoleHandler.formatter=
             oracle.adfmf.util.logging.PatternFormatter
oracle.adfmf.util.logging.PatternFormatter.pattern=
             [%LEVEL%-%LOGGER%-%CLASS%-%METHOD%]%MESSAGE%

#configure the framework logger to only use the adfmf ConsoleHandler
oracle.adfmf.framework.useParentHandlers=false
oracle.adfmf.framework.handlers=oracle.adfmf.util.logging.ConsoleHandler
oracle.adfmf.framework.level=SEVERE

#configure the application logger to only use the adfmf ConsoleHandler
oracle.adfmf.application.useParentHandlers=false
oracle.adfmf.application.handlers=oracle.adfmf.util.logging.ConsoleHandler
oracle.adfmf.application.level=SEVERE

The oracle.adfmf.util.logging.ConsoleHandler plays the role of the receiver of the custom formatter.

The oracle.adfmf.util.logging.PatternFormatter allows the following advanced formatting tokens that enable log messages to be printed:

  • %LEVEL%—the logging level.

  • %LOGGER%—the name of the logger to which the output is being written.

  • %CLASS%—the class that is being logged.

  • %METHOD%—the method that is being logged.

  • %TIME%—the time the logging message was sent.

  • %MESSAGE%—the actual message.

The following logging levels are available:

  • SEVERE: this is a message level indicating a serious failure.

  • WARNING: this is a message level indicating a potential problem.

  • INFO: this is a message level for informational messages.

  • FINE: this is a message level providing tracing information.

  • FINER: this level indicates a fairly detailed tracing message.

  • FINEST: this level indicates a highly detailed tracing message.

Caution:

When selecting the amount of verbosity for a logging level, keep in mind that by increasing the verbosity of the output at the SEVERE, WARNING, and INFO level negatively affects performance of your application.

The logger defined in the logging.properties file matches the logger obtained from the oracle.adfmf.util.Utility class (see Using and Configuring Logging). The logging levels also match. If you decide to use the logging level that is more fine-grained than INFO, you must change the ConsoleHandler's logging level to the same level, as the following example shows.

oracle.adfmf.util.logging.ConsoleHandler.formatter=
             oracle.adfmf.util.logging.PatternFormatter
oracle.adfmf.util.logging.ConsoleHandler.level=FINEST
oracle.adfmf.util.logging.PatternFormatter.pattern=
             [%LEVEL%-%LOGGER%-%CLASS%-%METHOD%]%MESSAGE%

28.7.2 How to Use JavaScript Logging

JavaScript writes the output to the console.log or.error/.warn/.info. This output is redirected into the file through the System.out utility.

You customize the log output by supplying a message. The following JavaScript code produces "Message from JavaScript" output:

<script type="text/javascript" charset="utf-8">
   function test_function() { console.log("Message from JavaScript"); }
</script>

To make use of the properties defined in the logging file, you need to use the adf.mf.log package and the Application logger that it provides.

The following logging levels are available:

  • adf.mf.log.level.SEVERE

  • adf.mf.log.level.WARNING

  • adf.mf.log.level.INFO

  • adf.mf.log.level.CONFIG

  • adf.mf.log.level.FINE

  • adf.mf.log.level.FINER

  • adf.mf.log.level.FINEST

To trigger logging, use the adf.mf.log.Application logger's logp method and specify the following through the method's parameters:

  • the logging level

  • the current class name as a String

  • the current method as a String

  • the message string as a String

The following example shows how to use the logp method in a MAF application.

adf.mf.log.Application.logp(adf.mf.log.level.WARNING,
                            "myClass",
                            "myMethod",
                            "My Message");

Upon execution of the logp method, the following output is produced:

[WARNING - oracle.adfmf.application - myClass - myMethod] My Message

See JSDoc Reference for Oracle Mobile Application Framework.

28.7.3 How to Use Embedded Logging

Embedded logging uses the java.util.logging.Logger, as illustrated in the following example. The EmbeddedClass represents a Java class defined in the project.

import java.util.logging.Level;
import java.util.logging.Logger;
import oracle.adfmf.util.logging.*;
...
   Utility.ApplicationLogger.logp(Level.WARNING, 
                                  EmbeddedClass.class.getName(),
                                  "onTestMessage",
                                  "embedded warning message 1");
   Logger.getLogger(Utility.APP_LOGNAME).logp(Level.WARNING,
                    this.getClass().getName(),
                    "onTestMessage",
                    "embedded warning message 2");
   Logger.getLogger("oracle.adfmf.application").logp(Level.WARNING,
                                                this.getClass().getName(),
                                                "onTestMessage",
                                                "embedded warning message 3");

The preceding code produces the following output:

[WARNING - oracle.adfmf.application - EmbeddedClass - onTestMessage] embedded warning message 1
[WARNING - oracle.adfmf.application - EmbeddedClass - onTestMessage] embedded warning message 2
[WARNING - oracle.adfmf.application - EmbeddedClass - onTestMessage] embedded warning message 3

28.7.4 How to Use Xcode for Debugging and Logging on the iOS Platform

Even though it is not recommended to manipulate your MAF projects with Xcode because you can lose some or all of your changes during the next deployment with JDeveloper, you may choose to do so in exceptional circumstances.

Before you begin:

Deploy the application to the iOS simulator from JDeveloper.

To open the generated project directly in Xcode:

  1. Navigate to the workspace_directory\deploy\deployment profile name\temporary_xcode_project\.

  2. Open the Xcode project called Oracle_ADFmc_Container_Template.xcodeproj.

If you are debugging your MAF application using Xcode, you cannot see the Java output in the IDE (on neither JDeveloper console nor Xcode console). Instead, the output is redirected to a file (see Using and Configuring Logging). By adding the following argument to your application's schema, you can disable this behavior and enable access to the Java, JavaScript, and Objective-C log output in Xcode in real time when debugging on either an iOS-powered device or simulator:

-consoleRedirect=FALSE

28.7.5 How to Access the Application Log

You can retrieve the application log file for your MAF application from a user’s device to analyze issues that occur with your MAF application. One way to accomplish this is to copy the application log file from its on-device location to a directory from where the application can then send the file from the device.

The following example demonstrates how you access the application log file location and copy it to a location from where it can be attached to an email message to send to a recipient who can analyse the content of the log file.

import java.nio.file.FileSystems;
import java.nio.file.Path;
import oracle.adfmf.util.Utility;

// Get path to application log file
private static Path getPathToLogFile() {
  String pathStr = Utility.getStorageLocations().getLogFileLocation();
  return FileSystems.getDefault().getPath(pathStr);
}


// Create an instance of device manager to access the device’s email functionality later
DeviceManager dm = DeviceManagerFactory.getDeviceManager();

//Construct path to application log file
String logFilePath = getPathToLogFile().toString();
...


//1. Determine device location to save a copy of the log file 
String mailAccessiblePath =  Utility.ensureTrailingForwardSlash(AdfmfJavaUtilities.getDirectoryPathRoot(AdfmfJavaUtilities.DeviceOnlyDirectory));
String targetFileNameAndPath = mailAccessiblePath + appName + ".log";

//2. Copy file to a location accessible from a mail client
try {
    Utility.copy(new File(logFilePath), new File(targetFileNameAndPath));
} 
catch (IOException e) {
    // If something goes wrong, log the failure to copy.
    Utility.ApplicationLogger.logp(Level.SEVERE, this.getClass().getSimpleName(), "sendLogAsMail", "Could not copy file " + logFilePath + " to " + targetFileNameAndPath);
    Utility.ApplicationLogger.logp(Level.SEVERE, this.getClass().getSimpleName(), "sendLogAsMail", e.getLocalizedMessage());
}

//3. Set the attachment property referenced by sendEmail(...)
this.setMailAttachment(targetFileNameAndPath);

//4. Send mail: open the mail client
dm.sendEmail(mailTo, mailCc, mailSubject, mailBody, mailBcc, mailAttachment, mailMimeType);

Note:

If you deploy your application from JDeveloper to a virtual device (iOS simulator or Android emulator), MAF writes the log output to JDeveloper’s Log window instead of to the application log file.

Once you obtain the location of the application log file, choose a mechanism to send it from the user’s device to the server side. Options to consider include uploading the file using a REST web service to a specific server-side location that is associated with your application. This option may offer a more consistent user experience to the alternative option of transmitting the log file as an email attachment. The latter option can exhibit different behaviors based on the platform device (iOS, Android, UWP) or how the email client is configured on the device.

The level of detail that the MAF application’s log file captures depends on the configuration entries in the logging.properties file unless you change the logging level dynamically at runtime by, for example, using an API as demonstrated in the following example:

Logger l = Utility.ApplicationLogger;
// Select a new log level. Note that OFF disables logging. In our example, we select ALL.
// Level newLevel = Level.<ALL | CONFIG | INFO | FINE | FINER | FINEST | OFF | SEVERE | WARNING>
Level newLevel = Level.ALL;
l.setLevel(newLevel);

28.7.6 How to Disable Logging

You can prevent the logging output from being directed to the application log file, in which case the log file either remains blank or is not created in the first place. When logging is disabled, trace statements are absent from the application log and any output directed to stderr and stdout is redirected to either a null location or other location that is not accessible to the end user.

To disable all logging, set the disableLogging property to true in the application's adf-config.xml file, as follows:

<adf-property name="disableLogging" value="true"/>

By default, logging is enabled in MAF applications and the disableLogging property is set to false.

For information on the adf-config.xml file, see Introduction to MAF Application and Project Files.

28.8 Measuring MAF Application Performance

MAF assists you in monitoring and measuring the performance of your MAF application. You can, for example, measure the time it takes for the following events in your application to complete:

  • An action that a button invokes to complete

  • A page to load

  • A REST call to return a response

In addition, you can print statistics that show the mean and standard deviation time of operations that you monitor in your MAF application.

You enable performance measurement by configuring logging levels for the following performance loggers in your application’s logging.properties file. The values assigned to the loggers in the following example are for illustrative purposes. See Table 28-1 for descriptions of all possible values.
oracle.adfmf.amx.useParentHandlers=false
oracle.adfmf.amx.handlers=oracle.adfmf.util.logging.ConsoleHandler
oracle.adfmf.amx.level=SEVERE

# used to control what monitors are captured in the list of monitors
oracle.maf.performance.monitor.captured.level = FINEST

# used to control what monitors are reported in the dumpStatistics
oracle.maf.performance.monitor.reported.useParentHandlers=false
oracle.maf.performance.monitor.reported.handlers=oracle.adfmf.util.logging.ConsoleHandler
oracle.maf.performance.monitor.reported.level = FINEST

# used to control what monitor observations (start/stop times) are logged.
oracle.maf.performance.monitor.observations.reported=false
oracle.maf.performance.monitor.observations.reported.handlers=oracle.adfmf.util.logging.ConsoleHandler
oracle.maf.performance.monitor.observations.reported.level = FINEST

Once performance measurement completes, you can review the data that MAF collected while it measured the performance of your application. You can review the data by invoking the PerformanceMonitorGraph.jar tool described in Viewing MAF Application Performance Data or opening the application log file in your preferred log file editor. The following example shows an extract of the output that MAF produces after it monitors performance. In the example, the monitor observed 5 occurrences of a Process AMX event that had a mean completion time of 1435.5 milliseconds with a standard deviation of 1990.567….

[INFO - oracle.maf.performance.monitor.reported - MonitorFactory - dumpStatistics] 
PERFMON-JAVA STATS: Monitor 'com.company.WorkBetter.**Perf_Monitor**.Springboard.Container.Process AMX event' description: 
'Time to process event'  observations: 5  mean: 1435.4 standard deviation: 1990.5674567821106

Table 28-1 describes the available performance monitor levels that you can set in the logging.properties file.

Table 28-1 Performance Monitor Levels

Level Description
Level.INFO

This is the coarsest monitor level. It monitors events and actions. Using this level, you can, for example, monitor the loading of a page or the completion of an end user action, such as a button click. Use of this monitor level has minimal impact on performance.

Level.FINE
This level monitors more performance indicators that it orders into the following categories:
  • JavaScript and rendering (System Level)

  • Business logic processing (Application Level)

  • Framework processing (System Level)

  • External data access

    • REST Calls (System Level)

    • Database access (System Level)

Use of this monitor level impacts the performance of your application and should not be enabled by default. Consider using this level to gain insight into how your code executes with a view to restructuring or refining your application.

Level.FINER Use to monitor significant performance issues, such as how it long it takes to process nodes in an AMX page, data change events or EL expressions.
Level.FINEST Use this monitor level to debug the performance of your application.
The monitor level that you specify in logging.properites takes effect when you first start the application.

Note:

MAF provides a number of setPerformanceMonitor methods in the oracle.adfmf.framework.api package’s PerfMon class that enable you to change the performance monitor level at runtime. See the Java API Reference for Oracle Mobile Application Framework.

In addition to specifying a monitor level in the logging.properties file, you can add monitors to your application to collect the performance data. MAF uses the Java class, oracle.adfmf.performance.Monitor (monitor), to collect performance data. A monitor is a stop watch that can be started, stopped and can add observations. By adding observations, you can use monitors to gain insights, such as the standard deviation for a given measurement. Each monitor has a unique ID and an optional description.

Monitor exposes a number of addObservation() methods that enable a monitor to measure the duration of an event or the number of occurrences of an event. When measuring duration, start the monitor before the event. After the event occurs, invoke an addObservation() method from the monitor. This stops the monitor. Duration is the time between the start() and the addObservation() method. You can restart a monitor that was never stopped. As you might expect, you cannot stop a monitor that was never started. An attempt to stop such a monitor logs an error.

A monitor that measures the number of occurrences of an event does not need to be started or stopped. Use the addObservation(double duration) method that does not stop the monitor, as demonstrated in the following example that counts the number of occurrences of JSON serialization in the application where you monitor performance. The duration parameter specifies the time since the monitor last added an observation.

The following example demonstrates how you create a monitor to measure the duration of an event. The example also shows a sample of the statistical information that this monitor produces.

import oracle.adfmf.performance.Monitor;
....

 public void measurePerformance()
  {
    Monitor monitor = null;

    try
    {
      //// Check that the appropriate monitor level is set before you create the monitor
      if (Utility.PerformanceMonitorCaptured.isLoggable(Level.INFO))
      {
        monitor = MonitorFactory.getInstance().getMonitor("REST call", Level.INFO, "REST call timing");
        monitor.start();
      }

      //
      // Perform your custom logic here:
      //
    }
    finally
    {
      if (monitor != null)
      {
        monitor.addObservation();
      }
    }
  }

  public void countCalls()
  {
    Monitor monitor = null;

    try
    {
      if (Utility.PerformanceMonitorCaptured.isLoggable(Level.FINE))
      {
        monitor = MonitorFactory.getInstance().getMonitor("Call count", Level.FINE, "Count number of calls");
        monitor.start();
      }

      //
      // Perform your custom logic here:
      //
    }
    finally
    {
      if (monitor != null)
      {
        monitor.addObservation(1);
      }
    }
  }

To create a monitor that collects performance data in your application, you configure the logging.properties file to enable the performance monitor capture level to collect the data. In the example above, MAF will not collect performance data for the monitor if the application’s logging.properties file does not contain the following entry:

# used to control what monitors are captured in the list of monitors
oracle.maf.performance.monitor.captured.level = FINEST

For information about monitor (oracle.adfmf.performance.Monitor), see Java API Reference for Oracle Mobile Application Framework.

In addition to monitor, MAF also provides oracle.adfmf.performance.Story (story). A story allows you to start and end the collection of performance data. Once you end collection of the performance data for a story, MAF presents a hierarchical view of the collected performance data using a story ID that you assigned when you started the story. The hierarchical view shows the individual timing measurements for events that took place during the story. In addition, MAF performs a health of the system (HOTS) checkpoint at the end of the story. As part of this HOTS checkpoint, standard deviations for all of the monitor data collected during the story will be computed, so you can gain insight into how individual story events measure up statistically. All monitor data will then be cleared from the MonitorFactory.

Note:

You can perform a HOTS checkpoint independently of a story by invoking the oracle.adfmf.util.HOTS.checkpoint() method. This determines information for your application, such as total memory used by the JVM, free memory, used memory (total minus free), and the number of active features. The following shows a sample of the data returned by checkpoint():
HOTS.memory.used (N/A) count: 1.0335056E7
HOTS.memory.free (N/A) count: 1.365112E7
HOTS.memory.total (N/A) count: 2.3986176E7
HOTS.memory.max (N/A) count: 4.9152E7
HOTS.threads.active (N/A) count: 20.0
HOTS.features.active (N/A) count: 6.0

The following example shows a managed bean that exposes methods to start a story with a story ID (**Perf_Monitor**) and stop the story. This story could be started and ended from a button in the UI of the application that you want to measure the performance. For example, you may want to measure the loading of a page, so you expose a UI button that enables you to start the story prior to navigating to the page and another button that ends the story once the page loads.

package mobile;

import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.performance.Story;

public class PerfBean
{
  public PerfBean()
  {
    super();
  }
  public void startStory(ActionEvent ae)
  {
    Story.startStory("**Perf_Monitor**");
  }
  
  public void endStory(ActionEvent ae)
  {
    Story.endStory();
  }

}

The performance monitor level that you specify in the logging.properties file determines how much data the story captures. That is, a logging.properties file entry of oracle.maf.performance.monitor.reported.level = FINEST produces a more verbose story than an entry of INFO. When the story ends, all performance data captured during a story is sorted based on timing. This sorting presents monitor observations corresponding to JavaScript events at a correct time, since the time when these observations were recorded might be different from the time when the measured events took place. MAF then iterates through the sorted records and produces indented output, as demonstrated in the following example.

MAF writes the story into the application log file. A sample output for an application that navigates from one AMX page to another AMX page might look like the following:

Example 28-1 MAF Performance Monitor Data Generated using Story

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - start] 
                      PERFMON-JAVA START: **Perf_Monitor**.Navigation.Embedded.Story **Perf_Monitor** (Story Book) at 1452728427473

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - start] 
                      PERFMON-JAVA START: **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                      /view1.amx event of type action on node cb2 (Time to process event) at 1452728427416

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - stop] 
                      PERFMON-JAVA STOP:  **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                      /view1.amx event of type action on node cb2 (Time to process event) took: 14897.0ms 
                      (started at 1452728427416)

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - start] 
                      PERFMON-JAVA START: **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                      /view1.amx event of type action on node cb1 (Time to process event) at 1452728442323

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - stop] PERFMON-JAVA STOP:  
                      **Perf_Monitor**.Navigation.Container.Process AMX event Page:
                      /view1.amx event of type action on node cb1 (Time to process event) took: 
                      586.0ms (started at 1452728442323)

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - start] PERFMON-JAVA START:
                      **Perf_Monitor**.Navigation.Container.Load page /view2.amx
                      (Time to fully render the page) at 1452728442441

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - stop] PERFMON-JAVA STOP: 
                       **Perf_Monitor**.Navigation.Container.Load page /view2.amx 
                      (Time to fully render the page) took: 468.0ms (started at 1452728442441)

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - start] PERFMON-JAVA START: 
                       **Perf_Monitor**.Navigation.Embedded.Evaluate method expression #{myBean2.endStory} 
                       (UserSpace) at 1452728450665

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - stop] PERFMON-JAVA STOP:  
                       **Perf_Monitor**.Navigation.Embedded.Evaluate method expression #{myBean2.endStory} 
                       (UserSpace) took: 78.0ms (started at 1452728450665)

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - start] PERFMON-JAVA START: 
                       **Perf_Monitor**.Navigation.Container.Process AMX event Page: /view2.amx 
                       event of type action on node cb2 (Time to process event) at 1452728450626

[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - stop] PERFMON-JAVA STOP:  
                       **Perf_Monitor**.Navigation.Container.Process AMX event Page: /view2.amx 
                       event of type action on node cb2 (Time to process event) 
                       took: 85.0ms (started at 1452728450626)
[INFO - oracle.maf.performance.monitor.observations.reported - Monitor - stop] PERFMON-JAVA STOP:  
                       **Perf_Monitor**.Navigation.Embedded.Story **Perf_Monitor** (Story Book) 
                       took: 23367.0ms (started at 1452728427473)

[INFO - oracle.maf.performance.monitor.reported - MonitorFactory - dumpStatistics] PERFMON-JAVA STATS: 
                       Monitor 'com.company.aPerfMonDocApp.**Perf_Monitor**.Navigation.Container.Process AMX event' 
                       description: 'Time to process event'  observations: 3  
                       mean: 5189.333333333333 standard deviation: 8410.817102596711

[INFO - oracle.maf.performance.monitor.reported - MonitorFactory - dumpStatistics] PERFMON-JAVA STATS: 
                       Monitor 'com.company.aPerfMonDocApp.**Perf_Monitor**.Navigation.Container.Load page' 
                       description: 'Time to fully render the page'  observations: 1  
                       mean: 468.0 standard deviation: NaN

[INFO - oracle.maf.performance.monitor.reported - MonitorFactory - dumpStatistics] PERFMON-JAVA STATS: 
                       Monitor 'com.company.aPerfMonDocApp.**Perf_Monitor**.Navigation.Embedded.Evaluate 
                       method expression' description: 'UserSpace'  observations: 1  mean: 78.0 
                       standard deviation: NaN

[INFO - oracle.maf.performance.monitor.reported - MonitorFactory - dumpStatistics] PERFMON-JAVA STATS: 
                       Monitor 'com.company.aPerfMonDocApp.**Perf_Monitor**.Navigation.Embedded.Story' 
                       description: 'Story Book'  observations: 1  mean: 23367.0 standard deviation: NaN

1452728427473  0001.0001 [0000] Start: **Perf_Monitor**.Navigation.Embedded.Story **Perf_Monitor** (INFO)
1452728442323    0002.0002 [0001] Start: **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                                                      /view1.amx event of type action on node cb1 (INFO)

1452728442441      0003.0003 [0002] Start: **Perf_Monitor**.Navigation.Container.Load page /view2.amx (INFO)
1452728442909      0003.0003 [0002] Stop: **Perf_Monitor**.Navigation.Container.Load page /view2.amx 
                                                              (took = 468.0) started at 1452728442441 (INFO)

1452728442909    0002.0002 [0001] Stop: **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                                                /view1.amx event of type action on node cb1 (took = 586.0) 
                                                started at 1452728442323 (INFO)

1452728450626    0004.0002 [0001] Start: **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                                                /view2.amx event of type action on node cb2 (INFO)

1452728450665      0005.0003 [0004] Start: **Perf_Monitor**.Navigation.Embedded.Evaluate 
                                                method expression #{myBean2.endStory} (INFO)

1452728450711    0004.0002 [0001] Stop: **Perf_Monitor**.Navigation.Container.Process AMX event Page: 
                                                /view2.amx event of type action on node cb2 (took = 85.0) 
                                                started at 1452728450626 (INFO)

1452728450743      0005.0003 [0004] Stop: **Perf_Monitor**.Navigation.Embedded.Evaluate method 
                                              expression #{myBean2.endStory} (took = 78.0) 
                                              started at 1452728450665 (INFO)

1452728450840  0001.0001 [0000] Stop: **Perf_Monitor**.Navigation.Embedded.Story **Perf_Monitor** 
                                              (took = 23367.0) started at 1452728427473 (INFO)

28.9 Viewing MAF Application Performance Data

MAF provides a Performance Monitor Graph tool that graphically displays the MAF application performance data that you collect when you measure the performance of your MAF application.

Before you can use the tool, you configure your application’s logging.properties file to monitor your application’s performance and collect performance data, as described in Measuring MAF Application Performance. You then use the application log file that collected the performance data as an input to the tool. The tool outputs the performance data in a HTML file with a timeline that helps you to visualize when and what MAF events took place when the application was running. The figure below displays the HTML file, test.html in the default browser.

The tool parses the log messages in the application log file that follow the default format specified by the logging.properties file. It will not parse message in other formats. The default format is:

oracle.adfmf.util.logging.ConsoleHandler.formatter=oracle.adfmf.util.logging.PatternFormatter

oracle.adfmf.util.logging.PatternFormatter.pattern=[%LEVEL% - %LOGGER% - %CLASS% - %METHOD%] %MESSAGE%

Hover your mouse over each of the controls in the upper part of the tool’s page to view an explanation of the control’s function and follow the other instructions that appear on screen to view details about the performance data that the tool displays.

The tool is packaged in a JAR file by MAF in the following location:

\jdeveloperInstall\jdev\extensions\oracle.maf\tools\PerformanceMonitorGraph.jar

Invoke the following command to render the performance data you have collected using the tool:

PathToJDK\java.exe –jar \jdeveloper\jdev\extensions\oracle.maf\tools\PerformanceMonitorGraph.jar PathToLogFileWithPerformanceData.txt –o OutputFileName

where OutputFileName is the filename for the HTML file that the tool produces and writes to the current directory from where you invoke the above command. The tool itself appends the .HTML file extension to the filename. It is not necessary for you to do so.

The output file can be specified using either -o or --output-file.

28.10 Inspecting Web Service Calls in a MAF Application

If your MAF application accesses REST services that were configured using the design-time support for the creation of the client data model, you can add a reusable application feature to view the request and response details of every REST call made by the application.

For information about the client data model, see Creating the Client Data Model in a MAF Application. To add this feature to your application, perform the following steps:

  1. In JDeveloper, go to the Application menu, and select the Application Properties... option. The Application Properties dialog is displayed.
  2. In the Application Properties dialog, click the Libraries and Classpath option, as shown in figure.

    Figure 28-16 Application Properties dialog

    Description of Figure 28-16 follows
    Description of "Figure 28-16 Application Properties dialog"
  3. In the Application Properties dialog, click the Add JAR/Directory button. The Add Archive or Directory dialog is displayed.
  4. In the Add Archive or Directory dialog, navigate to the directory ./jdevinstall/jdeveloper/jdev/extensions/oracle.maf/FARs/CDM and select the WebServiceCallsFeature.jar file and click the Open button, as shown in figure.

    Figure 28-17 Add Archive or Directory dialog

    Description of Figure 28-17 follows
    Description of "Figure 28-17 Add Archive or Directory dialog"
  5. The WebServiceCallsFeature.jar file appears under Library and Classpath. Click OK to close the Application Properties dialog.
  6. Open the maf-application.xml file in the editor and select the Feature References option. Click the green plus icon on the right and select oracle.maf.impl.cdm.wscalls from the Feature Id dropdown list, shown in figure.

    Figure 28-18 maf-application.xml file

    Description of Figure 28-18 follows
    Description of "Figure 28-18 maf-application.xml file"
  7. Deploy your MAF application to view the application feature that allows you to inspect web service calls, shown in figure.

    Figure 28-19 View Rest Calls

    Description of Figure 28-19 follows
    Description of "Figure 28-19 View Rest Calls"
  8. You can click on one of the REST call in the list to view all request and response details.