TIBCO® General Interface - Enterprise Edition Developer Guide

Software Release 3.9.1 April 2012 Important Information SOME TIBCO EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR BUNDLED TIBCO SOFTWARE IS SOLELY TO ENABLE THE FUNCTIONALITY (OR PROVIDE LIMITED ADD-ON FUNCTIONALITY) OF THE LICENSED TIBCO SOFTWARE. THE EMBEDDED OR BUNDLED SOFTWARE IS NOT LICENSED TO BE USED OR ACCESSED BY ANY OTHER TIBCO SOFTWARE OR FOR ANY OTHER PURPOSE. USE OF TIBCO SOFTWARE AND THIS DOCUMENT IS SUBJECT TO THE TERMS AND CONDITIONS OF A LICENSE AGREEMENT FOUND IN EITHER A SEPARATELY EXECUTED SOFTWARE LICENSE AGREEMENT, OR, IF THERE IS NO SUCH SEPARATE AGREEMENT, THE CLICKWRAP END USER LICENSE AGREEMENT WHICH IS DISPLAYED DURING DOWNLOAD OR INSTALLATION OF THE SOFTWARE (AND WHICH IS DUPLICATED IN TIBCO GENERAL INTERFACE INSTALLATION) OR IF THERE IS NO SUCH SOFTWARE LICENSE AGREEMENT OR CLICKWRAP END USER LICENSE AGREEMENT, THE LICENSE(S) LOCATED IN THE "LICENSE" FILE(S) OF THE SOFTWARE. USE OF THIS DOCUMENT IS SUBJECT TO THOSE TERMS AND CONDITIONS, AND YOUR USE HEREOF SHALL CONSTITUTE ACCEPTANCE OF AND AN AGREEMENT TO BE BOUND BY THE SAME. This document contains confidential information that is subject to U.S. and international copyright laws and treaties. No part of this document may be reproduced in any form without the written authorization of TIBCO Software Inc. TIB, TIBCO, TIBCO Adapter, Predictive Business, Information Bus, The Power of Now, TIBCO General Interface, TIBCO General Interface Framework, TIBCO General Interface Builder, TIBCO General Interface Performance Profiler, and TIBCO General Interface Test Automation Kit are either registered trademarks or trademarks of TIBCO Software Inc. in the United States and/or other countries. EJB, Java EE, J2EE, and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. All other product and company names and marks mentioned in this document are the property of their respective owners and are mentioned for identification purposes only. THIS SOFTWARE MAY BE AVAILABLE ON MULTIPLE OPERATING SYSTEMS. HOWEVER, NOT ALL PLATFORMS FOR A SPECIFIC SOFTWARE VERSION ARE RELEASED AT THE SAME TIME. SEE THE README.TXT FILE FOR THE AVAILABILITY OF THIS SOFTWARE VERSION ON A SPECIFIC OPERATING SYSTEM PLATFORM. THIS DOCUMENT IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THIS DOCUMENT COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION HEREIN; THESE CHANGES WILL BE INCORPORATED IN NEW EDITIONS OF THIS DOCUMENT. TIBCO SOFTWARE INC. MAY MAKE IMPROVEMENTS AND/OR CHANGES IN THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THIS DOCUMENT AT ANY TIME. THE CONTENTS OF THIS DOCUMENT MAY BE MODIFIED AND/OR QUALIFIED, DIRECTLY OR INDIRECTLY, BY OTHER DOCUMENTATION WHICH ACCOMPANIES THIS SOFTWARE, INCLUDING BUT NOT LIMITED TO ANY RELEASE NOTES AND "READ ME" FILES. U.S. Patent No. 8,136,109 Copyright © 2001-2012 TIBCO Software Inc. ALL RIGHTS RESERVED. TIBCO Software Inc. Confidential Information 1

General Interface Developer Guide

General Interface Developer Guide

Software Release 3.9

March 2010

Chapter 1 Introduction to General Interface Chapter 2 General Interface Builder Basics Chapter 3 General Interface Framework Basics Chapter 4 Handling Application Data Chapter 5 Communicating with Data Services Chapter 6 Communicating with a Web Service Tutorial Chapter 7 Using CDF Form Mapping Tutorial Chapter 8 Optimizing Application Performance Chapter 9 Accessing Data Across Subdomains Chapter 10 Adding and Debugging JavaScript Code Chapter 11 Class Inheritance and Introspection Chapter 12 Extensions to JavaScript Exception Handling Chapter 13 General Interface JavaScript Documentation Compiler Chapter 14 Protecting Namespaces in Multiple Application Environments Chapter 15 Implementing Context-Sensitive Help Chapter 16 Logging and Application Monitors Chapter 17 Internationalizing and Localizing Applications Chapter 18 Deploying Applications Chapter 19 Optimizing Load Performance Chapter 20 Asynchronous Modular Platform Chapter 21 Asynchronous Programming Utilities Chapter 22 Using the Test Recorder Appendix A General Interface Builder Menus, Toolbars, Dialogs, and Tools

Copyright © TIBCO Software Inc. All Rights Reserved. 2

Chapter 1 Introduction to General Interface

This chapter provides an introduction to General Interface software, which includes General Interface Framework and General Interface Builder.

General Interface Files and Folders Further Information on General Interface Topics

General Interface Files and Folders

General Interface consists of two components:

General Interface Framework The distributable runtime framework for running browser-based General Interface applications. The framework is located in the JSX directory. General Interface Builder A browser-based, visual development environment for developing General Interface applications that use the General Interface Framework. General Interface Builder is itself a General Interface application. General Interface Builder is located in the GI_Builder directory.

Although the installation directory is different for Enterprise Edition and Professional Edition, the contents of the directories are the same. The figure shows the directory structure and its contents.

Copyright © TIBCO Software Inc. All Rights Reserved. 3

Further Information on General Interface Topics

For more information, see the following topics:

Workspace and projects: Managing Projects General Interface Builder preferences: Customizing the IDE Logging system configuration file: Logging and Application Monitors Parameterized launch : Deploying as a Full Console Application

Copyright © TIBCO Software Inc. All Rights Reserved. 4

Chapter 2 General Interface Builder Basics

This chapter provides an overview of General Interface Builder features and the user interface.

Using Palettes Customizing the IDE Managing Projects Work Area Editors Component Libraries Palette and the Online Repository Data and Cache Management Data Connection and Mapping Jabber Support General Interface Documentation Further Information on General Interface Basics

Using Palettes

This section describes the General Interface Builder palettes that you use as you work with your application.

Project Files Palette A list of all files referenced by an application are displayed in the Project Files palette. Files can include GUI components, XML and XSL documents, JavaScript files, CSS files, dynamic properties files, properties files, mapping rules files, and other files, such as text files. The file and folder hierarchy reflects where the files are located in relation to the project directory.

For more information on projects, see Managing Projects. For definitions of toolbar buttons, see Project Files Palette Toolbar.

Copyright © TIBCO Software Inc. All Rights Reserved. 5

Component Libraries Palette The Component Libraries palette, shown in the figure, provides predefined GUI prototype objects for adding functionality to your application. Components are organized in folders according to function. For example, objects in the Containers folder such as Dialog, Layout, and Tabbed Pane, act as containers for other objects. Form Elements objects, such as Text Area, , and Select, collect user input.

These object libraries not only reduce the time required to build applications, they also allow object behavior and look-and-feel to be easily customized.

Prototype objects can be dragged from the Component Libraries palette to any object in the work area or to the Component Hierarchy palette. A new object of the selected type is created as a child of the object where it's dropped if the parent object accepts children.

You can also create, manage, and share your own libraries of components. Saving a component definition to the workspace /prototypes directory adds it to the User folder in the Component Libraries palette. The custom component can then be reused like any other prototype component.

The Addins folder contains any prototypes defined in an add-in, such as Charting. You can also create your own custom add-ins. Add-ins must be enabled on the Add-Ins panel before they display in the Addins folder. For more information, see General Interface Component Guide.

For more information on components and tutorial on custom add-ins, see the General Interface Component Guide.

Copyright © TIBCO Software Inc. All Rights Reserved. 6

Component Hierarchy Palette The Component Hierarchy palette, shown in the next figure, lets you view and manage the hierarchical model of objects in your application.

Objects can contain other objects. For example, a LayoutGrid component could include Text Box, Label, and Button objects, as well as other components. Applications usually consist of multiple components that work together using JavaScript logic.

Using the Component Hierarchy palette, you can select objects and then modify them using other palettes, such as Properties Editor palette, Events Editor palette, and so on. Once you've defined a component or object, you can also clone it to quickly make multiple copies. Objects can also be exported to reuse in other applications or imported from another project into the current one. For more information about working with components, see General Interface Component Guide.

Use Ctrl+click to select multiple components. Use Shift+click to choose a range of components.

For definitions of toolbar buttons, see Component Hierarchy Palette Toolbar.

Properties Editor Palette Each object has a predefined set of properties that define look-and-feel, on-screen position, and other characteristics. When a component is selected, its properties display in the Properties Editor palette. As you can see in the next figure, properties are name-value pairs.

Copyright © TIBCO Software Inc. All Rights Reserved. 7

To modify a property, do one of the following in the Properties Editor palette:

Type a value in the Value column. Right-click and choose a dynamic property value from the menu, if available. For more information, see Dynamic Properties Files. Type a dynamic property key or a properties bundle key in the Value column. See Dynamic Properties Files and Properties Bundle Files. Click the down arrow in the Value column and select a value from the list, if available.

To learn more about properties in the Properties Editor palette, hover the mouse over the property name or see General Interface GUI Property Reference (Help > API Documentation > GUI Property Reference).

To modify a common property for multiple components, select multiple components in the Component Hierarchy palette using Ctrl+click or Shift+click and set the property value. In the following example, the three selected components have a common width property of 120. If property values are different, [multiple values] displays in the value field.

Copyright © TIBCO Software Inc. All Rights Reserved. 8

For more information on properties, see General Interface Component Guide.

Events Editor Palette In addition to properties, objects can have model events. Model events are published in response to user actions, allowing your application to respond to user input. For example, when a user clicks a Cancel button in a dialog, an event specifies that the dialog closes and data is discarded

The Events Editor palette, as shown in the next figure, provides a set of model events for each object. Events are name-value pairs, where the value is a JavaScript statement.

To learn more about events in the Events Editor palette, hover the mouse over the event name or see General Interface GUI Event Reference (Help > API Documentation > GUI Event Reference).

For more information, see General Interface Component Guide and Associating Code with an Event.

Copyright © TIBCO Software Inc. All Rights Reserved. 9

Attributes Editor Palette You can use the Attributes Editor palette to add and edit HTML attributes for the component selected in the Component Hierarchy palette.

HTML attributes change how the component is rendered when it's displayed in the browser. After using the Attributes Editor palette, you can view your changes in the Rendered HTML (Read Only) view of the work area.

If, for example, you add an attribute of name foo and value bar to a block, this HTML markup is added to the rendered HTML markup for the component selected in the Component Hierarchy palette:

XSL Parameters Palette The XSL Parameters palette is only available for components that implement jsx3.xml.Cacheable, such as Menu, Tree, and Matrix components. The XSL Parameters palette allows you to add and edit XSL parameters that are passed to the XSL template, which renders the component as HTML.

To add an XSL parameter, complete these steps:

1. Select a component that implements jsx3.xml.Cacheable in the Component Hierarchy palette or in the work area. 2. Choose Palettes > XSL Parameters Palette to open the palette. 3. Choose a predefined parameter from the drop-down list or type the name of a new parameter in the Name field.

4. Type a value in the Value field. Copyright © TIBCO Software Inc. All Rights Reserved. 10

4. Type a value in the Value field. 5. Click the Add Attribute button .

To change an existing XSL parameter, select the Value field, change the value, and press Enter.

To remove a parameter, right-click a row and choose Remove Parameter.

For example, the XSL for the Matrix List prototype defines two parameters: jsx_rowbg1 and jsx_rowbg2. These parameters control the background of odd and even numbered rows respectively.

To learn more about XSL parameters, see General Interface XSL Parameter Reference (Help > API Documentation > XSL Parameter Reference).

Recycle Bin palette When you delete components from the work area or the Component Hierarchy palette, they're sent to the Recycle Bin and held in memory until the project is closed or the Recycle Bin is emptied. You can open the Recycle Bin from the Palettes menu and recover the components at any time during the project session.

Each open component editor maintains its own Recycle Bin, which is only visible when the component is active. Whenever you close a component editor, close a project, choose Save and Reload, Revert, Revert All, or navigate to another project in General Interface Builder, the Recycle Bin is emptied and the components can't be recovered.

To delete a single component, select a component in the Live Component view or the Component Hierarchy palette. Press Ctrl+Delete or use the Recycle button on the Component Hierarchy palette toolbar.

To recover components from the Recycle Bin palette, choose Palettes > Recycle Bin, select the component to recover, and click the Restore Recycled Object button on the toolbar. The components are restored to the Component Hierarchy palette and the Live Component view.

Copyright © TIBCO Software Inc. All Rights Reserved. 11

Local Data Cache Palette The Local Data Cache palette provides access to all cached XML and XSL files for inspection and updates. The Local Data Cache palette allows you to view and edit cached files. Modified files can be saved and reloaded with a single command.

For more information on caching, see Handling Application Data.

For definitions of toolbar buttons, see Local Data Cache Palette Toolbar.

System Log Palette General Interface Builder uses the System Log palette to display system out messages from the system, as well as any logging messages in your JavaScript code. The system log handler, defined in the logging system configuration file, prints logging messages to the General Interface Builder System Log palette in the IDE. For more information, see Understanding the Logging System Configuration File.

Copyright © TIBCO Software Inc. All Rights Reserved. 12

The System Log palette has the following features:

Docking options Adjustable log levels, such as OFF, FATAL, ERROR, WARN, INFO, DEBUG, or TRACE Support for sound for messages Color coding of messages, such as red for error messages

For definitions of toolbar buttons, see System Log Palette Toolbar.

For more information about logging, see Logging and Application Monitors.

Enabling Sound for Messages The System Log palette supports sound for messages. This is turned off by default but can be enabled in the logging system configuration file, GI_HOME/logger.xml.

To enable sound for messages,

1. Open logger.xml , located in the GI_HOME directory. 2. Change the beepLevel property for the ide handler from jsx3.util.Logger.OFF to a logging level, such as jsx3.util.Logger.ERROR. Sound is played for the specified logging level and higher. For example, if the beepLevel property is jsx3.util.Logger.ERROR, a sound plays whenever error and fatal messages are reported. See Log Levels.

Firefox requires a plug-in that can play .wav files.

3. Save logger.xml.

Customizing the IDE

General Interface Builder offers a fully customizable integrated development environment (IDE). You can modify IDE settings in the IDE Settings dialog. You can also customize the position of the General Interface Builder palettes.

Copyright © TIBCO Software Inc. All Rights Reserved. 13

Specifying IDE Settings In the IDE Settings dialog, you can modify General Interface Builder IDE preferences for the visual authoring environment. The options in this dialog allow you to customize the IDE, modify and add keyboard shortcuts for menus, and set paths. Settings in this dialog are saved to workspace/settings/builder.xml.

To open the IDE Settings dialog, choose Tools > IDE Settings.

The IDE Settings dialog has several panels:

IDE Settings Panel IDE Hot Keys Panel Paths Panel GIPP and GITAK Panel

This section discusses some but not all of the available options. For more information, see IDE Settings Dialog.

IDE Settings Panel On the IDE Settings panel, you can modify options for character encoding, set warnings, modify the snap-to spacing, and so on.

Character Encoding General Interface Builder provides support for writing files in a specified character encoding, such as UTF-8 or UTF-16. The ability to choose a character encoding is particularly useful for developing and localizing applications for multilingual environments.

General Interface Builder allows you to specify an encoding for all project files, as well as separately specify an encoding for XML files.

Copyright © TIBCO Software Inc. All Rights Reserved. 14

General Interface Builder settings in the IDE Settings dialog allow you to:

Specify character encoding for all project files Specify character encoding for XML files Specify whether to add character encodings to XML declarations Specify the output line separator Test the specified encodings to verify they can be written

For applications loaded from the local disk, such as General Interface Builder, reads non-XML files that are encoded in a standard 8-bit encoding. Firefox can read local XML files in any encoding supported by the host system only if the encoding is included in the XML declaration.

Modifying encoding options To modify encoding options, complete the following steps:

1. Enter an encoding in the Output character encoding field. Click the Test button to verify that the specified encoding is available on the system and can be written. If this field is empty, the default is used. This default is system-dependent. 2. Select an output line separator. If this field is empty, the default is used. This default is system-dependent. 3. Check the Instead encode XML file as checkbox if you want to use a different encoding for XML files. Enter an encoding. Click the Test button to verify that the specified encoding can be written and that it's available on the system. If this option is unchecked, XML files are written in the same encoding as specified in the Output character encoding field or the default system encoding if that field is empty. 4. Check the Add character encoding to XML declaration if you want the encoding in the XML declaration. 5. Click Save or Apply to save your changes.

For , encoding behavior varies according to Windows updates and security settings, which might need to be modified. UTF-16 and the default system encoding should be supported regardless. If the test fails for other encodings, you might need to enable the ADODB.Stream object. See "How to disable the ADODB.Stream object from Internet Explorer" at http://support.microsoft.com/default.aspx?kbid=870669 and reverse the instructions to enable it.

For descriptions of options on this panel, see IDE Settings Panel.

IDE Hot Keys Panel On the IDE Hot Keys panel, you can add new hot keys and modify existing hot keys for General Interface Builder menus. Hot keys are keyboard shortcut commands that activate menus. For example, pressing Ctrl+N executes this menu command, File > New > GUI Component.

To add or modify a hot key,

1. Double-click a row in the Menu list. Copyright © TIBCO Software Inc. All Rights Reserved. 15

1. Double-click a row in the Menu list. 2. Press the keys you want for the hot key, such as Ctrl+Alt+m. 3. Click Set. 4. Click Save to save the changes and close the dialog or click Apply. 5. Use the browser reload button to restart General Interface Builder for the changes to take effect.

To revert to the default hot key, double-click a row and choose Use Default.

Paths Panel On the Paths panel, you can set the workspace path for your projects and the HTTP base path for running applications from a local HTTP server.

Workspace The workspace is the directory that contains your projects, custom add-ins and prototypes, and your user settings for General Interface Builder.

To modify the workspace path,

1. Open the IDE Settings dialog and click the Paths button. 2. Click the Browse button next to the Workspace field to open the Choose Folder dialog. 3. Navigate to a folder, select it, and click Choose. Click Choose again to close the Choose Folder dialog. You can also use the New Folder button to create a new folder. 4. Click Save to save the changes and close the IDE Settings dialog or click Apply. 5. Click OK at the Restart Required prompt and use the browser reload button to restart General Interface Builder.

HTTP Base The path in the HTTP Base field is used when you select Project > Run Project From HTTP. To use this feature, you must have an HTTP web server, such as Apache, hosting both the General Interface installation directory and your workspace directory.

To add an HTTP base, enter the base URI for the General Interface directory on a local HTTP server. If this field is empty and you choose Project > Run Project From HTTP, you are prompted to enter a path.

If the relative path between the workspace directory and the General Interface directory isn't the same on the HTTP server as on disk, you must enter the relative path to the workspace directory in the WS Path field.

GIPP and GITAK Panel On the GIPP and GITAK panel, you can specify the installation paths for the General Interface Performance Profiler (GIPP) and General Interface Test Automation Kit (GITAK). GIPP is a JavaScript profiling tool for benchmarking the performance of General Interface applications, and GITAK is a functional testing tool for testing General Interface applications. For more information, see the General Interface Performance Profiler Guide and the General Interface Test Automation Kit User Guide.

Copyright © TIBCO Software Inc. All Rights Reserved. 16

Chat Panel On the Chat panel, you can specify server and login settings for the Jabber client in General Interface Builder. See Jabber Support.

Setting Palette Docking Options

Most palettes have a Docking Options button for customizing the palette. The options include moving the palette to a different quadrant of the General Interface Builder user interface, floating the palette, and closing the palette. The System Log palette, which has slightly different docking options, can be displayed at the bottom of the IDE, floated, opened in a separate browser , or closed.

Docking settings are saved in your user settings and reloaded each time you open General Interface Builder.

To access docking options, click the down arrow next to the Docking Options button .

To hide all the palettes, click the Show Edit Pane button on the General Interface Builder taskbar.

Managing Projects

All development work in General Interface Builder is done in a project in the workspace. Projects are collections of files you create and edit in General Interface Builder. Project files are displayed in the Project Files palette and stored in the workspace.

Choosing a Workspace The workspace is the directory that contains your projects, custom add-ins, custom prototypes, and your user settings for General Interface Builder.

The first time General Interface Builder launches after installation, a dialog prompts you to create or select a workspace directory. You can create a new directory, select an existing directory, or choose the default workspace directory. The default workspace location is C:\Documents and Settings\username\My Documents\TibcoGI. You can use multiple workspaces for your projects, as well as change workspaces.

For more information, see General Interface Getting Started.

Changing a Workspace You can keep all of your projects in one workspace or use multiple workspaces. You can modify the workspace location in the IDE Settings dialog. See Workspace.

Copyright © TIBCO Software Inc. All Rights Reserved. 17

Creating Projects When you create a project, default files are created and opened in the work area: logic.js and appCanvas.xml. The JavaScript file, logic.js, is an empty file that you can add JavaScript code to. The default GUI component file, appCanvas.xml, is where you can begin designing your application user interface.

To create a project, complete these steps:

1. Choose Project > New Project or click the Create a New Project link in the Welcome screen (Help > Welcome Screen) to open the new project wizard. 2. Choose General Interface Application as the project type, and click Next.

3. Choose the project template and click Next.

4. Specify a project path and click Finish. Copyright © TIBCO Software Inc. All Rights Reserved. 3.

18

4. Specify a project path and click Finish.

A new project is loaded in the browser window. Two default, empty files are open in the central work area.

While building this sample application, all project data is stored locally in browser memory. The application is not automatically saved to the file system. Save the project before you close or refresh the browser window. If you don't save the project, the data is lost.

Project Files and Folders When you create a project, a project folder is created in the workspace/JSXAPPS folder.

The top-level project folder has the same name as your project. All project folders include the default subdirectories and files listed in the following table. This default structure can be modified and additional folders can be created as needed. For example, you might create folders for image, WSDL, and CSS files.

Copyright © TIBCO Software Inc. All Rights Reserved. 19

Project Files Description

config.xml Contains application configuration data, such as project settings and file locations. See Modifying Project Settings.

launch. Launches the application in the . Use this file only during development, not at runtime.

launch_in_ide.html Launches the application in General Interface Builder. Use this file only during development, not at runtime.

To access project files and folders, click the JSXAPPS/project_name link in the General Interface Builder taskbar, located in the lower left area of the IDE.

Project Description Folders

components Contains the XML files for application components. Each component has an associated XML file with object definitions. For component files, use the .xml extension. When you create a new project, a default component named appCanvas.xml is created in this folder. See General Interface Component Guide.

js Contains included JavaScript files for your application. For JavaScript files, use the .js extension. When you create a new project, a default file named logic.js is created in this folder. See Adding and Debugging JavaScript Code.

jss Contains dynamic properties XML files. For dynamic properties files, use the .xml extension. See Dynamic Properties Files.

rules Contains mapping rules XML files for connecting to web services. Rules files define the mappings between GUI components and SOAP message elements. For mapping rules files, use the .xml extension. See Basic Steps for Communicating with Data Services.

xml Contains any XML files with content data, such as default values, for the application. For XML files, use the .xml extension.

xsl Contains any XSL files used for transforming application data. For XSL files, use the .xsl extension.

These project folder names are conventions only and not mandatory.

Saving Projects When you save project files, General Interface Builder saves them to a project directory in the JSXAPPS directory in the specified workspace directory. For example, workspace /JSXAPPS/project_name. For more information on workspaces, see General Interface Getting Started.

There are several ways to save files in a project:

Right-click a file tab in the work area and choose Save, Save and Reload, or Save As.

Choose File > Save, Save and Reload, Save As, or Save All. Copyright © TIBCO Software Inc. All Rights Reserved. 20

Choose File > Save, Save and Reload, Save As, or Save All. For a local data cache XML file, right-click a file tab in the work area and choose Save to Cache or Save a Copy to Disk.

For menu definitions, see File Menu.

Running Projects There are several ways to run a project:

Choose Project > Run Project. Choose Project > Run Project from HTTP. Double-click the default launch file, workspace/project_dir/launch.html, which is generated when you create the project. Use this file only during development, not during deployment.

To run deployed applications, see Deploying Applications.

Running Projects from HTTP To use this menu command, you must have an HTTP server, such as Apache, running locally and hosting both the General Interface installation directory and your workspace directory. For more information, see HTTP Base.

To run a project in a new browser window on a local HTTP server, choose Project > Run Project From HTTP. If the HTTP server isn't configured, you are prompted to configure it.

Opening Projects There are several ways to open a project:

Choose the Open an Existing Project link in the Welcome screen (Help > Welcome Screen) and choose a project from the list. Choose Project > User Projects and choose a project from the list. To open a General Interface sample project, choose Project > User Projects > Samples and choose a sample project from the list. Choose Project > Recent Projects and choose a recently opened project from the list. Double-click the default General Interface Builder launch file, workspace/ project_dir /launch_in_ide.html, which is generated when you create the project. Use this file to launch the project only during development, not at runtime.

You can also open multiple instances of the same project in different browsers, such as Internet Explorer and Firefox. However, because each instance is sharing the same preferences and settings files, competing changes to General Interface Builder preferences may not be persisted.

Closing Projects To close a project, simply close the browser.

Copyright © TIBCO Software Inc. All Rights Reserved. 21

Deploying Projects To deploy a project, set deployment options on the Deployment panel of the Project Settings dialog. Use the Deployment Utility to create a hyperlink to the deployed application. Then copy your application files and General Interface software to an HTTP or HTTPS web server.

For more information, see the following:

Deployment Panel Deploying Applications

Modifying Project Settings When you create a new project in General Interface Builder, a default configuration file is automatically created as part of the project in the project directory: workspace /JSXAPPS/project_dir/config.xml. The configuration file contains application configuration data, such as project settings and file locations. Project settings include deployment, add-ins, class path, and legacy settings.

You can modify the project settings in the Project Settings dialog. Any changes you make in the Project Settings dialog are saved to the configuration file.

If you edit this file manually, close General Interface Builder before editing.

To open the Project Settings dialog, choose Project > Project Settings. To save your changes in the Project Settings dialog, click the Apply or Save button.

Copyright © TIBCO Software Inc. All Rights Reserved. 22

The Project Settings dialog has several panels:

Deployment Panel Add-Ins Panel Classpath Panel Legacy Settings Panel

For more information on available options in the Project Settings dialog, see Project Settings Dialog.

Deployment Panel Settings on this panel control the behavior of the deployed application. For definitions of options not discussed here, see Project Settings Dialog. For more information on deployment, see Deploying Applications.

Namespace The General Interface runtime creates a single instance of a jsx3.app.Server for each loaded application. The application namespace, which is a unique JavaScript identifier for the jsx3.app.Server instance, provides access to the jsx3.app.Server instance.

When specifying a namespace, it's recommended that you use the reverse-domain naming convention with the dot symbol (.). For example com.tibco.APP. Using the reverse-domain naming convention reduces the likelihood that other JavaScript code will interfere with your application.

To specify the namespace, complete these steps:

1. Choose Project > Project Settings >Deployment to open the Deployment panel of the Project Settings dialog. 2. Type the namespace in the Namespace field. For example, set the namespace to eg.chart.APP.

You can also override the namespace per deployment using the jsxappns deployment parameter. See Deployment Parameters.

Mode The deployment mode for the deployed application can be set to Live or Static mode. Select Live mode if the application needs to be online and is connected over HTTP/S to a server for online data access.

Select Static mode when working offline. When in offline mode, the application can't access a server. Data is static and is referenced using static URLs stored in rules files. Choose Static when developing and testing an application offline or when a back-end web service isn't available.

The Mode setting is used by the j sx3.net.Service class.

Body Hot Keys Hot keys are keyboard shortcuts that an end user can use to interact with a GUI component, such as a button or menu, in a running application.

When the Body Hot Keys option is checked on the Deployment panel, any hot key event that bubbles up to the HTML body element is sent to the application. Even if the focus is in the Copyright © TIBCO Software Inc. All Rights Reserved. 23

bubbles up to the HTML body element is sent to the application. Even if the focus is in the browser window and not in the General Interface application, the application receives the hot key and responds to it. Choose this option for deployment of standalone console applications. See Deploying as a Full Console Application.

When the Body Hot Keys option is unchecked, hot keys only function if the focus is in the General Interface application. This deployment choice prevents your application from responding to hot keys initiated in other General Interface applications on the page. Choose this option for deployment of non-console applications that are a portion of a web page. See Deploying as a Non-Console Application.

onLoad Script Enter one or more JavaScript statements that you want executed when the application initializes. For example, you might want to execute a main method, communicate with a server, create controller objects by instantiating a controller class, or create the state of the application. For more information, see Executing Code When the Application Loads and Deployment Panel.

onUnload Script Enter one or more JavaScript statements that you want executed when the browser window is unloaded. The onUnload event allows you to save user state and do any final cleanup before exiting. For more information, see Executing Code When the Application Unloads and Deployment Panel.

For descriptions of other options on this panel, see Deployment Panel.

For more information on deployment, see Deploying Applications.

Add-Ins Panel Use the Add-Ins panel to enable the Charting add-in or custom add-ins for a project. Add-ins are disabled by default to accelerate load time of General Interface Builder and General Interface applications.

Enabling Add-ins To enable add-ins,

1. Choose Project > Project Settings to open the Project Settings dialog and click Add-Ins. 2. Check the add-in you'd like to enable on the Add-Ins panel. 3. Click Save to save the changes and close the dialog or click Apply. 4. Click OK at the Restart Required prompt and use the browser reload button to restart General Interface Builder.

After add-ins are enabled, their prototypes are available in the Component Libraries palette in General Interface Builder.

For more information on the Charting add-in, see General Interface Component Guide.

Custom Add-ins For custom add-ins to display on the Add-Ins panel, they must be saved to the JSX/addins or workspace/addins directory. Typically, add-ins to be used by a team of developers would be saved to the JSX/addins directory and posted by an administrator to a location accessible to the team. Add-ins for individual use can be saved to the workspace/addins directory.

Copyright © TIBCO Software Inc. All Rights Reserved. 24

For a tutorial on custom add-ins, see General Interface Component Guide.

Classpath Panel The project class path is used by General Interface to find custom classes that are dynamically loaded by your application.

To add a class path, complete the following steps:

1. Click in the Path field and type the path to the classes.

The class path is relative to the project directory. For example, entering js/ as the path would load the specified classes in the workspace /JSXAPPS/project_dir/js directory.

2. Press the Tab key and type the packages to load in the Packages field. For example, com.tibco.*. 3. Press Enter to commit the class path. 4. Click Save to save the changes and close the dialog or click Apply. 5. Use the browser reload button to restart General Interface Builder for the changes to take effect.

To delete a class path, click the Delete button next to the row.

Path Packages Description

js/ com.tibco.* Loads classes with three words beginning with com.tibco from the directory workspace/JSXAPPS/project_dir/js. For example, this would load the class file workspace /JSXAPPS/project_dir/js/com/tibco/Object.js.

js-ext/ com.tibco.ext.* Loads classes with four words beginning with com.tibco.ext from the directory workspace/JSXAPPS/project_dir/js-ext. For example, this would load the class file workspace /JSXAPPS/project_dir/js-ext/com/tibco/ext/Object.js.

js-foo/ com.foo.** Loads all nested classes of com.foo from the directory workspace /JSXAPPS/project_dir/js-foo/.

js-foo2/ com.foo.*.* Loads classes with four words beginning with com.foo from the directory workspace/JSXAPPS/project_dir/js-foo2.

Work Area Editors

General Interface Builder has built-in editors for creating and editing files. Editors are available for the following file types:

GUI components XML XSL JavaScript

CSS (Cascading Style Sheets) Copyright © TIBCO Software Inc. All Rights Reserved. 25

CSS (Cascading Style Sheets) Dynamic properties Properties bundle Mapping rules files GIPP test cases GITAK test cases

Working with Files To create a file, choose File > New and select the file type you'd like to create. A new untitled file tab opens in the work area.

To save the file,

1. Choose File > Save or Save As or right-click the file tab at the top of the work area and choose Save or Save As. 2. Optionally, browse to the recommended directory in the project. Choose components for GUI components, js for JavaScript, jss for dynamic properties files, xml for properties bundle files, rules for mapping rules files, xml for XML documents, and xsl for XSL documents. 3. Enter a file name and extension. Enter the .xml extension for GUI components, XML, dynamic properties, and mapping rules files. Enter the .xsl extension for XSL files. Enter the .js extension for JavaScript files and the .css extension for CSS files. 4. Choose Save to close the Save File dialog.

Work Area View Support The work area provides several views. The available views depend on what type of file is active in the work area.

The views include:

Live Component View Grid View Source View Formatted Source XML (Read Only) View Rendered HTML (Read Only) View Component Profile View

These views are available from the work area toolbar to the lower right of the work area as shown in the following figure.

Copyright © TIBCO Software Inc. All Rights Reserved. 26

Live Component View

The Live Component view is available for GUI components and is the graphical view of the components in one component file of your application. You can components from the Component Libraries palette into this view. You can also modify component properties in the Properties Editor palette and add event handlers in the Events Editor palette. The Component Hierarchy palette displays the hierarchical structure of the component file. For an example of how to work with components, see General Interface Getting Started.

Grid View

The Grid view is available for dynamic properties files and properties bundle files. You can use dynamic properties files, which are XML resource files, to create custom properties for components. Properties bundle files are XML resource files used to localize your application for a specific language and country.

For more information, see Dynamic Properties Files. See Properties Bundle Files and Internationalizing and Localizing Applications.

Source View

The Source view is available for all file types and displays the editable source for XML files and text files, such as JavaScript and CSS files. For components, the Source view displays the XML source of the component file.

Formatted Source XML (Read Only) View

The Formatted Source XML view displays XML source in an easy-to-read format with syntax highlighting. For example, attributes and values are in different colors than element names. This view is read-only and is available for all component files and XML files, including XSL, dynamic properties files, and properties bundle files.

Rendered HTML (Read Only) View

The Rendered HTML view displays the HTML that will be used to render the component(s) in the browser. This view is read-only and is available only for GUI components.

When running General Interface Builder in HTML and XHTML mode, well-formed HTML, Copyright © TIBCO Software Inc. All Rights Reserved. 27

When running General Interface Builder in HTML and XHTML mode, well-formed HTML, which is XHTML, is pretty-printed in the Rendered HTML (Read Only) view. If the markup isn't well-formed, pretty printing isn't used and a parsing error displays in the System Log palette.

For example, if you entered HTML without a closing element in the Text/HTML property for a label, such as My Label, a mismatched tag error message displays in the System Log palette and the Rendered HTML (Read Only) view isn't pretty-printed. If you entered valid XHTML with open and close elements, such as My Label, no error is reported and the Rendered HTML (Read Only) view is pretty-printed.

Component Profile View

The Component Profile view allows you to define the profile of a component. This view is available only for GUI components.

Here you can assign a name, description, and icon URL for the component. This is useful if you're creating custom components and exporting them to the Component Libraries palette ( workspace / prototypes). The icon displays next to the name of the component in the Component Libraries palette and the description displays as a tooltip.

Modifying a Component at Runtime The onBeforeDeserialization and onAfterDeserialization text areas can be used to specify JavaScript to execute before or after the object is deserialized. If the component is loaded at runtime, the code is executed immediately before the XML is converted into JavaScript objects or after the JavaScript objects are instantiated and bound to the GUI model.

Executing JavaScript code before an object is deserialized is useful when the runtime needs to be prepared before the component is loaded, such as preloading data for the component. Executing JavaScript code after an object is deserialized is useful when the component needs to be initialized with information only available at runtime. For example, you might want to modify the CDF for a Matrix list component and then re-populate the list after it displays on-screen.

JavaScript code entered in the onBeforeDeserialization text area has access to the objXML context variable, which is an instance of jsx3.xml.Document. The objXML context variable represents the serialization file in-memory and the jsx1 namespace prefix resolves to the namespace for the file (in this case, urn:tibco.com/v3.0).

For example, if you have a Block in your serialization file named foo and you want to change the background color to red, you could put the following code in the onBeforeDeserialize event:

objXML.setSelectionNamespaces("xmlns:jsx1='" + jsx3.app.Model.CURRENT_VERSION + "'"); var objNode = objXML.selectSingleNode("//jsx1:object\[@type='jsx3.gui.Block']/ jsx1:strings\[@name='foo']"); if(objNode) { objNode.setAttribute("jsxbgcolor","red"); }

The onAfterDeserialize event provides direct access to the actual model objects, after they are deserialized but before they are rendered on-screen. In this example code, the background of

Block foo is rendered in red after the object is created: Copyright © TIBCO Software Inc. All Rights Reserved. 28

Block foo is rendered in red after the object is created:

var objBlock = objJSX.getDescendantOfName("foo"); if(objBlock) { objBlock.setBackgroundColor("red"); }

Note that the objJSX variable, which is an instance of jsx3.app.Model, points to the root object in the serialization file.

For more examples, see Executing Code Before or After Deserialization.

Dynamic Properties Files Dynamic properties are XML resource files that contain externalized strings as name-value pairs. This feature enables you to organize the styles and text used by the application in a centralized location for easier application maintenance. Dynamic properties can be used for localization and for IDE lookup values. Properties bundle files are also used for localization. For more information, see Properties Bundle Files.

When authoring dynamic properties and properties bundle files using non-ASCII characters and non-western languages, save the file in a format that supports such characters, such as UTF-8 or UTF-16. See Character Encoding.

General Interface has built-in dynamic properties that you can use. These built-in dynamic properties begin with an @ symbol. You can also create your own custom dynamic properties files using the Dynamic Properties editor.

General Interface and custom dynamic properties are available on the context menu in the Properties Editor palette as shown in the following figure. To assign a dynamic property, right-click in the Properties Editor palette and select a dynamic property. You can also type the property key (ID) in the Value cell, such as @Dialog BG for the BG Color property. After a dynamic property is selected, the explicit value displays in the Value field next to the name of the dynamic property.

Copyright © TIBCO Software Inc. All Rights Reserved. 29

Creating Dynamic Properties Files To create a dynamic properties file in General Interface Builder,

1. Choose File > New > Dynamic Properties File. A visual editor displays in the work area. 2. Enter a name for the property in the ID field. 3. To select a type, click in the Type column and choose a type from the drop-down list or begin typing the name, such as jsxb, to see the list of matches.

Copyright © TIBCO Software Inc. All Rights Reserved. 3.

30

4. Enter a value for the type in the Value field. If the value is JavaScript code, check the Eval checkbox. Values can be text or JavaScript code. For more information on entering JavaScript code, see Specifying Code in Dynamic Properties. For information on CSS values, see General Interface Component Guide. For example, you might want to add a custom color for the BG Color property. Enter a name for the property, such as bluebgcolor. Select jsxbgcolor as the type and enter a color value, such as #6E6CEF. You can use the Color Picker to choose a color. Choose Tools > Color Picker or click the Color Picker button in the Properties Editor palette. 5. Continue to edit values and do the following as needed to set up the list of properties: To add a new row, press Enter, click the Add button , or right-click a row and choose Insert New Record. To delete a row, select a row and click the Delete button . 6. Choose File > Save and Reload or right-click the work area tab and choose Save and Reload. 7. Browse to the jss folder of your project and enter a file name with the .xml extension.

For dynamic properties files, be sure to use the .xml extension as some servers won't recognize the .jss extension used in previous releases. By default, General Interface, version 3.2 and higher, supports the .xml extension, which is the recommended file extension.

8. Click Save in the Save File dialog.

Loading and Using the Dynamic Properties File To load the dynamic properties file and apply properties to a component, complete the following steps:

1. Set the dynamic properties file to automatically load with the application, so the new Copyright © TIBCO Software Inc. All Rights Reserved. 31

1. Set the dynamic properties file to automatically load with the application, so the new properties are always available. Right-click the dynamic properties file in the Project Files palette and choose Auto Load. 2. Return to the Live Component View and select the component you want to apply the property to in the Component Hierarchy palette or in the work area. 3. Find the property you added in the Properties Editor palette, such as BG Color, and right-click the Value cell to invoke the lookup list of property values. The property value you added displays on the list.

Properties Bundle Files The Properties Bundle editor is used to create and edit properties bundle files, which are used to localize your application for a specific language and country. A locale is a region of the world that shares a common language, writing, , and so on.

When authoring dynamic properties and properties bundle files using non-ASCII characters and non-western languages, save the file in a format that supports such characters, such as UTF-8 or UTF-16. See Character Encoding.

Properties bundle files, also known as resource bundles, contain locale-specific objects, such as menu and button labels in the application user interface. When these strings are externalized in the properties bundle files, it's easier to translate applications into other languages. The application simply loads the locale-specific resource appropriate for the user's locale. For more information on localizing, see Internationalizing and Localizing Applications.

Mapping Rules Files Mapping rules files are XML files that define mappings between application objects and data elements or CDF documents and data elements. Mapping rules files are created with the XML Mapping Utility. For more information, see Communicating with Data Services.

GIPP Test Cases GIPP test cases are used with the General Interface Test Recorder. For more information, see Using the Test Recorder.

GITAK Test Cases GITAK test cases are used with the General Interface Test Recorder. For more information, see Using the Test Recorder.

Component Libraries Palette and the Online Repository

General Interface Builder provides an interface for the online component repository hosted on GeneralInterface.org. This repository allows you to share components with the GeneralInterface.org community. You can upload components to the repository for subsequent download and use by other developers and you can browse and download components uploaded by other developers from around the world.

The interface to the component repository is in the Component Libraries palette in Builder. The Component Libraries palette includes the following tabs: Copyright © TIBCO Software Inc. All Rights Reserved. 32

Component Libraries palette includes the following tabs:

System tab: A tree that shows all of the built-in system components. These files are stored at the path GI_HOME/GI_Builder/prototypes. User tab: A tree that shows the components that the current user has created in their local GI workspace. Components downloaded from GeneralInterface.org are also saved here. These files are stored at the path GI_WORKSPACE/prototypes.

Online tab: List of the shared components that have been previously uploaded to GeneralInterface.org.

Saving a Component to the Workspace

A component must exist in the GI workspace before you can upload it to the online repository. To save a component to the GI workspace:

1. Open an existing component or create a new component in General Interface Builder. 2. Choose File > Save a Copy to Library. 3. Enter a name for the file and save it in the prototypes directory. You can save it to any nested folder as long as it is contained within prototypes. 4. To display the component in the Users tab of the Component Libraries palette, click the Reload icon.

The component is now available for upload.

To create new component folders in your workspace, click the New Folder icon and enter the folder name. To remove components, select the components and click the Delete icon.

Copyright © TIBCO Software Inc. All Rights Reserved. 33

Uploading a Component to the Online Repository

For each component that you upload, you must agree to the General Interface terms of service http://www.generalinterface.org/terms.html.

To upload a component to the GeneralInterface.org online repository

1. Select the component on the User tab in the Component Libraries palette. 2. Click the Upload Component icon. 3. Enter a name and description. 4. Select the check box to agree to the General Interface terms of service. To review the terms of service, click the underlined link. 5. Click Upload. 6. If you are not already logged in, you will be prompted to enter your user name and password. Log in, then click Upload again.

The component is uploaded and summary infomation is presented. If you have any custom code in the application, Dojo Foundation staff will review the code before making it available to others.

To view an uploaded component, open the Online tab. Click the Filters icon and choose filtering option as needed to display the component.

Downloading Components from the Online Repository

To download previously uploaded components:

1. Open the Online tab in the Component Libraries palette. 2. Click the Filters icon and to choose how to filter the list of components. 3. Drag and drop the component to the canvas or to the desired level in the Component Hierarchy.

Using the Online Tab

The Online tab of the Prototype Libraries palette supports the options described in this section.

Refreshing the Display Clickt the Refresh icon on the User or Online tab to reload the current list of components.

Displaying Component Details On the Online tab, you can display component details by double-clicking the component entry. To return to the component list, click the List icon.

Using Filters

The following filter options are available by clicking the Filters icon.

Function Description

Copyright © TIBCO Software Inc. All Rights Reserved. 34

All Show all available components.

Featured Show the components that the Dojo Foundation is currently featuring.

Rating Show the user ratings along with the component name.

Downloads Show the number of times that the component has been downloaded.

User Show the login name of the user who uploaded the component.

Date Show the date that the component was uploaded.

Using Feeds

The following options are available by clicking the Feeds icon. To view these options, you must be subscribe to Live Bookmarks. If you are not subscribed, you are prompted to do so when you first choose a Feeds option on the Online tab.

Function Description

Top Rated Show the components with the highest user ratings.

Most Popular Show the components that have been downloaded most frequently

Most Recent Show the components that were uploaded most recently

Data and Cache Management

At the most basic level, a General Interface application consists of files stored on the file system. The formats of application files are industry-standard, such as XML, XSL, and CSS. You can use viewing and editing features built into General Interface Builder or you can use external editors.

General Interface Builder provides the following XML editing and management features:

Access to all component XML files for inspection and updates. Buttons to the lower right of the work area provide multiple views of each component, including an editable XML view. Component definitions can be refreshed using the toolbar on the Component Hierarchy palette. Access to all cached XML and XSL files for inspection and updates. The Local Data Cache palette allows you to view and open cached files for editing. Modified files can be saved and reloaded with a single command.

Copyright © TIBCO Software Inc. All Rights Reserved. 35

XML/XSL Merge Tool is used for testing the text, HTML, or XML output from a merge operation. You can view both the parsed output and its source. If parsing errors occur, error notification is provided. You can open multiple instances of this tool.

Character-level debugging that helps you identify the location of any XML parsing errors.

Data Connection and Mapping

General Interface software is designed to interface with industry-standard web protocols.

XML Mapping Utility The XML Mapping Utility provides a visual environment for configuring and testing data services including data mapping, testing, and off-line development.

To open the XML Mapping Utility, choose Tools > XML Mapping Utility. Copyright © TIBCO Software Inc. All Rights Reserved. 36

To open the XML Mapping Utility, choose Tools > XML Mapping Utility.

For more information on the XML Mapping Utility, see Communicating with Data Services and Communicating with a Web Service Tutorial.

Visual Bindings The XML Mapping Utility provides a visual interface for mapping GUI components to data services. You can use drag-and-drop to create bindings for inbound and outbound SOAP messages and XML documents. XML elements can be bound to the values of GUI objects, nodes in XML documents, and JavaScript variables. All mapping information is stored in an XML file referenced in the project. If modifications are needed, you reopen this file in the XML Mapping Utility.

Testing When mappings are complete, the interaction with the data service can be tested. You can preview the outbound message before it is sent, test the message against the live service, preview the response message, and enter a callback script to execute when the response is received.

Decoupled Web Service Development For tight project timelines, avoiding sequential dependencies is critical to project success. General Interface Builder is designed to allow parallel development of back-end and front-end applications. Back-end data services do not need to be complete or accessible for application development to begin. You can save a representative snapshot of server data on the local file system. During testing, the live web service environment can be simulated using this stored data. An application can even be deployed using static data, then reconfigured when the back-end service becomes available.

Copyright © TIBCO Software Inc. All Rights Reserved. 37

Additional Visual Tools Additional protocols and interactions are supported using the General Interface . For more information on designing interactions, see the online API documentation in General Interface Builder.

For General Interface feature updates and examples to assist the application development process, visit Developer Network at http://www.generalinterface.org.

Jabber Support

General Interface Builder includes a Jabber client, allowing you to participate in chats from within Builder. The client is implemented on top of the Dojo XMPP library. It works with Jabber servers that support the Jabber HTTP Bind protocol, such as OpenFire.

An OpenFire server is available for use at http://chat.generalinterface.org. Sign in with your Dojo Foundation account credentials.

The Jabber client in Builder feature supports the following actions:

Adding and removing buddies

Assigning nicknames to buddies

One-to-one conversations

Online/away/offline buddy statuses

To configure your Jabber settings, open the IDE Settings window, as described in Customizing the IDE.

When Jabber is configured, you can open the Chat palette from the Palettes menu.

General Interface Documentation

General Interface provides the following documentation to assist you as you develop your General Interface applications:

Product documentation

Context-sensitive help

Spyglass help

API documentation

Online documentation, forums, samples, and other resources at http://www.generalinterface.org.

Copyright © TIBCO Software Inc. All Rights Reserved. 38

Product Documentation Product documentation is available online at http://www.generalinterface.org/docs/display/DOC/Learning+Center.

Context-sensitive Help To access context-sensitive help in General Interface Builder, move focus to an area of the IDE, such as a dialog, editor, or palette, and press Alt+F1 or click the Help button .

To implement context-sensitive help in your applications, see Implementing Context-Sensitive Help.

Spyglass Help Documentation is also available in a spyglass in various areas of General Interface Builder. A spyglass contains descriptive text in HTML and can contain more information than a tooltip. To invoke a spyglass, hover the mouse over the following areas in the IDE:

Property names in the Properties Editor palette

Model event names in the Events Editor palette

APIs icon in the Settings panel of the XML Mapping Utility

You can also add spyglass documentation to your own applications using the Spyglass event (jsxspy) and the spy methods in the jsx3.gui.Interactive interface. For more information, see General Interface API Reference.

API Documentation Online API documentation is available online at http://www.generalinterface.org/docs/display/DOC/API+Documentation.

Further Information on General Interface Basics

For more tutorials and sample applications, see:

General Interface samples — workspace/JSXAPPS/samples Developer Network at http://www.generalinterface.org Sample Projects Video Tutorials

Copyright © TIBCO Software Inc. All Rights Reserved. 39

Chapter 3 General Interface Framework Basics

This chapter discusses the basics of General Interface Framework, which is the runtime for General Interface applications.

Class Loading in General Interface URI Resolution Custom Document Formats Common Data Format (CDF) Flexible CDF Schema Common Interface Format (CIF) Common Exchange Format (CXF)

Class Loading in General Interface

General Interface Builder uses dynamic class loading for increased performance and accelerated load time. Dynamic class loading causes classes to be loaded as they're needed at the last possible moment. Since only statically loaded classes are loaded at application startup, the application loads much faster.

The classes distributed with General Interface are partitioned into two categories:

Statically loaded classes that are always loaded by General Interface at application startup Dynamically loaded classes

For a list of statically loaded system classes, see General Interface Framework Classes.

How Classes are Loaded As a General Interface application loads, General Interface Framework statically loads a subset of the system classes. Next, application classes and application code using the Auto Load option are statically loaded. Finally, all other classes are loaded using the dynamic class loading mechanism. The following table provides an overview of how classes are loaded.

Copyright © TIBCO Software Inc. All Rights Reserved. 40

Class General Interface Application Classes Application Code Loading Classes Type

Statically Classes automatically Auto Load enabled. Auto Load enabled. loaded loaded by General Interface. See the next table.

Dynamically Load other General Auto Load disabled. Add Auto Load disabled. loaded Interface classes using custom classes to class path. Load code using jsx3.require() or Load class using Server.loadResource(). automatically with jsx3.require() or deserialization. automatically with deserialization.

General Interface Framework Classes The General Interface runtime system, General Interface Framework, always statically loads the classes listed in the following table as the application initializes.

All other system classes, such as Matrix, must be loaded dynamically using the require() method or through deserialization. See jsx3.require() Method.

jsx3.app.AddIn jsx3.app.Cache jsx3.app.DOM

jsx3.app.Model jsx3.app.Properties jsx3.app.PropsBundle

jsx3.app.Server jsx3.app.Settings jsx3.gui.Alerts

jsx3.gui.Alerts jsx3.gui.Block jsx3.gui.Event

jsx3.gui.Heavyweight jsx3.gui.HotKey jsx3.gui.Interactive

jsx3.gui.Painted jsx3.lang.Class jsx3.lang.Exception

jsx3.lang.Method jsx3.lang.NativeError jsx3.lang.Object

jsx3.lang.Package jsx3.net.Request jsx3.net.URI

jsx3.net.URIResolver jsx3.util.DateFormat jsx3.util.EventDispatcher

jsx3.util.List jsx3.util.Locale jsx3.util.Logger

jsx3.util.MessageFormat jsx3.util.NumberFormat jsx3.xml.CDF

jsx3.xml.Document jsx3.xml.Entity jsx3.xml.Template

Application Classes To statically load your application class files as the application loads, enable the Auto Load option for the JavaScript files in the Project Files palette. For more information, see Enabling the Auto Load Option.

To dynamically load custom application classes when the Auto Load option is off, classes must

meet the following requirements: Copyright © TIBCO Software Inc. All Rights Reserved. 41

meet the following requirements:

The classes must be on the class path, so the system class loader can find the classes. See Specifying Class Paths. The jsx3.require() method must be used to load classes explicitly that are not loaded automatically by the component through deserialization. See jsx3.require() Method.

Application Code To statically load your application code as the application initializes, enable Auto Load for the JavaScript files in the Project Files palette. For more information, see Enabling the Auto Load Option.

If you don't want the application code statically loaded, you can load it dynamically using the Server.loadResource() method. This method looks up a resource registered with the application by its id. The resource must be registered in the config.xml file of the application. For more information, see General Interface API Reference.

Enabling the Auto Load Option To statically load JavaScript files as the application initializes, you can enable the Auto Load option for individual JavaScript files in your project. When a JavaScript file is set to auto load, the file is statically loaded after the Framework classes are loaded.

To enable the Auto Load option for one or more JavaScript files in your project, complete these steps:

1. Right-click a JavaScript file in the Project Files palette. 2. Choose Auto Load from the context menu. The file name now displays in bold in the Project Files palette.

When you enable the Auto Load option, the onLoad attribute for the JavaScript file is set to true in the application configuration file (config.xml).

Copyright © TIBCO Software Inc. All Rights Reserved. 42

main_js script true js/logic.js jsx3.require() Method The jsx3.require() method can be used to load classes explicitly. Use the fully qualified class name when using the jsx3.require() method. For example,

jsx3.require("jsx3.net.Form");

Only classes that can be found by the system class loader are loaded. Custom classes can be added on the Classpath panel of the Project Settings dialog. See Specifying Class Paths.

When a component file is deserialized, the class of each object encountered in the file is dynamically loaded if it's not already loaded. Therefore, it's often not necessary to use the jsx3.require() method with classes that descend from jsx3.app.Model. However, if JavaScript code references these classes and if the code executes before a deserialization automatically loads the class, you must use the jsx3.require() method to explicitly load the class.

The jsx3.require() method must be called at least once before making these types of references:

A static reference to a class descending from jsx3.gui.Model (typically jsx3.gui.**). Any references to subclasses of Model that execute before the class is loaded through object deserialization.

Specifying Class Paths If you've created custom classes, you need to specify the class paths, so the system class loader can find the classes. Class paths are set on the Classpath panel of the Project Settings dialog. Class paths are saved as settings in the application configuration file, config.xml, and are deployed with the project.

For specifics on setting class paths, see Classpath Panel.

Classes must be located in the same directory structure as the package name. See Class Naming Conventions.

Copyright © TIBCO Software Inc. All Rights Reserved. 43

Class Naming Conventions The following file and directory naming conventions for classes are required only for dynamic class loading. For classes that aren't dynamically loaded, these naming conventions are a recommendation only.

The JavaScript class file name should be identical to the class name with a .js extension. For example, a class named SomeClass would be saved as SomeClass.js. The directory structure of the class file must match the package name that the class is in. For example, if SomeClass.js is in a com.tibco package and is saved to a js directory in the project, the class file location should be js/com/tibco/SomeClass.js.

URI Resolution

This section describes how URIs are resolved in General Interface. A Uniform Resource Identifier (URI) identifies or names a resource required by the application.

The URI functionality of General Interface has been updated to provide additional functionality and to simplify development. Project resources are now referenced by the project configuration file (config.xml) relative to the base directory of the project. Referencing resources in the configuration file allows you to rename and move project directories more easily.

Any relative URI that isn't of a legacy 3.1 format (beginning with JSX/ or JSXAPPS/) is resolved relative to a base URI that depends on the context of the URI. General Interface 3.1 applications perform as expected in version 3.2 and higher. However, it is strongly recommended that you update your applications to take advantage of the relative URI functionality.

Copyright © TIBCO Software Inc. All Rights Reserved. 44

Using URIs in General Interface Builder In General Interface, version 3.1, URIs that referenced resources contained in a project directory were of the following form:

JSXAPPS/appname/subfolders/filename.xml

The version 3.1 format is still valid in version 3.2 and higher, because URIs beginning with JSXAPPS/ are handled in a special manner. As of version 3.2, these URIs can be written relative to the base directory of the project. The previous example can now be written as follows to take advantage of relative paths:

subfolders/filename.xml

In General Interface Builder, version 3.2 and higher, any property editable in the Properties Editor palette can accept a relative URI, which is resolved relative to the project directory. For example, these properties accept relative URIs: the Image property for ToolbarButton and the XML URL property for List. URIs that appear in free form properties, such as Text/HTML for Block, are never resolved. URIs set as values of attributes in the Attributes Editor are also not resolved.

In summary, the URI requirements in General Interface Builder, version 3.2 and higher, include the following:

1. All properties editable in the Properties Editor palette that expect a path (XML URL, Image URL, and so on) can take an absolute path or a path relative to the project directory. 2. All other inputs (HTML attributes, free-form HTML) have to be pre- resolved statically or using the URIResolver API. See URI Resolvers.

Using dynamic properties is one way of externalizing these paths. Be certain that values stored in the dynamic property agree with the requirements described above, depending on how they are used.

To reference a resource that is located outside of the project directory, use a relative URI starting with one or more "../" tokens or one of the supported absolute URI formats. See URI Format Support.

Using URIs with the General Interface API When using URIs in JavaScript with the General Interface APIs, it's important to understand how each API resolves any URIs sent to it. For example, the jsx3.app.Model.load() method resolves URIs relative to the project directory of the application that the Model instance is owned by. For more information, see General Interface API Reference.

URI Format Support The following URI formats are considered to be absolute in General Interface. They always resolve to the same location regardless of what they are resolved against.

For more information on the script element, query parameters, and deployment parameters, see Deployment Parameters.

Copyright © TIBCO Software Inc. All Rights Reserved. 45

URI Format Description

JSX/... Legacy format for General Interface 3.1. Resolves relative to the parent of the JSX directory as determined by the location of the JSX30.js script. If multiple script elements are used in one HTML page, the URL for the JSX30.js script file must be the same.

JSXAPPS/... Legacy format for General Interface 3.1. Resolves relative to the parent of the JSXAPPS directory, as determined by the jsxapppath query parameter of the src attribute of the script element referencing the JSX30.js script. If multiple script elements are used in one HTML page, the applications must be located in the same JSXAPPS directory.

GI_Builder/... Legacy format for General Interface 3.1. Resolves as JSX/... when General Interface Builder is running. Applications should not reference any URIs of this format, because the GI_Builder directory can't be deployed under the standard licensing terms.

jsx:///... Format for General Interface 3.2 and higher. Resolves relative to the JSX directory as determined by the location of the JSX30.js script.

jsxaddin://addin/... Format for General Interface 3.2 and higher. Resolves relative to the base directory of the add-in specified by the host portion (addin) of the URI. The host portion of the URI follows the double forward slashes (//). The host of the URI should be the add-in key ( AddIn.getKey()) with any colon characters (:) replaced with an exclamation point (!). The add-in must be loaded for the URI to resolve correctly.

jsxuser:///... Format for General Interface 3.2 and higher. Resolves relative to the parent of the JSXAPPS directory (workspace). When General Interface Builder is running, this URI resolves relative to the workspace directory.

jsxapp://app/... General Interface 3.2 and higher format. If the Server instance corresponding to the host portion of the URI is loaded into memory, the URI is resolved relative to the application base directory ( jsxappbase). The host portion (app) of the URI is the relative path from the JSXAPPS directory to the application base directory containing the config.xml file with any forward slashes (\/) replaced with exclamation points (!). If the Server instance isn't loaded into memory, the URI resolves relative to the directory containing the config.xml of the application. Note: You can override the application base directory (jsxappbase). See Overriding the Application Base Directory.

Additionally, any URIs specifying a scheme or an absolute path (beginning with a forward slash) are also considered absolute and will not be modified.

Any other URI is considered relative and will be resolved by a URI resolver depending on the context in which it is encountered.

Copyright © TIBCO Software Inc. All Rights Reserved. 46

URI Resolvers General Interface, version 3.2, introduces a new interface, jsx3.net.URIResolver. An object that uses relative URIs must implement methods in the URIResolver interface to define a context against which those URIs are resolved. Two classes, jsx3.app.Server and jsx3.app.AddIn, implement this interface. The Server class uses the jsxapp: URI scheme and the AddIn class uses the jsxaddin: URI scheme described previously. Additionally, static resolvers are provided for the jsx: and jsxuser: schemes. For more information, see General Interface API Reference.

Custom Document Formats

General Interface applications use custom document formats to store and process data, store mapping rules, and to define GUI components.

Common Data Format Common Data Format (CDF) is used by General Interface to store data. A CDF document provides a common format for sharing data among components, transferring data between client controls, and performing data mapping. See Common Data Format (CDF). Support is also provided for flexible CDF schema. See Flexible CDF Schema.

Common Exchange Format Common Exchange Format (CXF), which is based on CDF, is used to store mapping rules to and from CDF and GUI components. CXF documents are created at design time by the XML Mapping Utility from source documents, such as WSDL, Schema, XML, and XHTML. CXF provides a common format for connecting to and exchanging data with disparate systems and services. At runtime, CXF is used to perform the actual interactions. See Common Exchange Format (CXF).

Common Interface Format Common Interface Format (CIF) is a serialization format used to define jsx3.gui components. The CIF format provides improved readability and smaller file size. See Common Interface Format (CIF).

Common Data Format (CDF)

Common Data Format (CDF) The Common Data Format (CDF) is an XML Schema that provides an abstraction layer for client data. It allows components of an application to use a single data format. Benefits include the ability to share data among components, reliably transfer data between client controls using drag-and-drop, and perform data mapping. Component data can be inserted or updated without using XSLT. The jsx3.xml.CDF interface also defines a common set of methods for manipulating data. The jsx3.xml.CDF.Document class, which implements the CDF interface, can also be used to expose the CDF convenience methods on an XML document.

Components that consume structured data require CDF. These components include:

Menu Copyright © TIBCO Software Inc. All Rights Reserved. 47

Menu Tree Select and Combo Matrix Charting

There are two ways to work with CDF documents:

Through a CDF component, such as Matrix and Tree Directly with the API. See the jsx3.xml.CDF.Document class in the online API help in General Interface Builder.

CDF Schema The CDF schema is described by the following XSD:

Copyright © TIBCO Software Inc. All Rights Reserved. 48

The CDF schema is an open schema that can be extended using custom entities and attributes. In the following example, the jsxtext and jsxid attributes are system attributes with special meaning. The jsxid attribute is required for a record in the CDF. This attribute acts as a key and should be a unique value. The number and name attributes are custom, developer-defined attributes.

Copyright © TIBCO Software Inc. All Rights Reserved. 49

CDF Structural Elements CDF documents consist of an XML declaration and a data element that contains all records. Usually, the data element also contains at least one record element with attributes.

Depending on the component, a record can represent a table row, a node in a tree, a menu item, and so on. Although the record element isn't required, at least one record is required for a CDF component to display data.

Hierarchical structures, such as submenus, can also be defined by nesting records within records. Entities by any other name, such as a node named lookup as opposed to record, are not displayed on-screen, but can be useful for organizing information within the CDF model. If additional hierarchies are described by nesting records, the view displays these where relevant. Currently, the Matrix, Menu, and Tree controls visualize hierarchical relationships, while the other controls flatten these out. Consider the following CDF structures and their visual representations as defined by the Menu class.

Copyright © TIBCO Software Inc. All Rights Reserved. 50

Underlying CDF Model On-screen View

rOj

Copyright © TIBCO Software Inc. All Rights Reserved. 51

CDF System Attributes System attributes are reserved attributes used by General Interface to render CDF components. Each component has an associated XSL file for transforming CDF code into HTML for display in your application. The system attributes listed in are referenced in the component XSL.

The jsxid attribute is required for all CDF components and must be a unique value. Support for optional attributes varies according to component. The jsxtext and jsximg attributes are commonly used and apply to most CDF components.

Copyright © TIBCO Software Inc. All Rights Reserved. 52

Attribute Component Description jsxdisabled Button, Checkbox, Disables the record so that a user cannot select it. ImageButton, Menu, The record text is displayed in a grey color. Specify a RadioButton, value of 1 to disable the record. ToolbarButton jsxdivider Menu Creates a linear divider between the current record and the preceding record. Specify a value of 1 to display the divider. jsxexecute Matrix, Menu, Tree, Allows an event to run a program function when the Table event fires. A function name or a string of JavaScript statements can be specified. Separate multiple statements with a semicolon (;) character. For example, jsxexecute="var a=12;var b='5';" jsxgroupname Matrix, Menu Adds the record to a group that can be used by multiple CDF records or components. Records in a group are mutually exclusive options. For example, a menu for selecting fonts allows only one font option to be chosen. jsxid all Uniquely identifies the CDF record. This value can be user-defined or automatically generated using the getKey() method (jsx3.xml.CDF). This attribute is required. jsximg Matrix, Menu, Tree, References a graphic file to use as an icon. Specify Table the file path relative to the project directory, for example, images/icon.gif. Image position depends on the component. For best results, use a 16x16 transparent GIF file. jsxkeycode Menu Defines a keyboard shortcut for calling the record. Specify any named key, such as Tab, Alt, Shift, or Ctrl, and use the plus character (+) as a delimiter. For example, jsxkeycode="ctrl+e". jsxnomask Button, Checkbox, Disables a visible mask (checkbox, radio button, ImageButton, Menu, menu, and so on) so it's hidden and a user can't RadioButton, select it. Specify a value of 1 to hide the mask for ToolbarButton that row. (when used as a Matrix mask) jsxselected Matrix, Menu, Tree, Specifies whether the record is selected or not Table selected by default. Specify a value of 1 to define the record as selected. jsxstyle Matrix, Menu, Tree, Applies a CSS style to this record. Specify any CSS Select, Table code. For example, jsxstyle="font-weight:bold;".

Copyright © TIBCO Software Inc. All Rights Reserved. 53

jsxtext Matrix, Tree, Select, Defines the visible text for the record. For example, Menu, Table in a menu component, the value of this attribute is the name of the menu item as displayed in the application.

jsxtip Matrix, Tree, Select, Defines the tooltip text to display when the cursor Menu, Table hovers over the record. For example, jsxtip="Type your address here".

jsxunselectable Matrix, Tree, Table Specifies whether a tree node or list item can be selected by end users. Specify a value of 1 to prevent the record from being selected. When the value of this attribute is 1, the execute method for the record cannot be called.

Any CDF attribute value of jsxtext, jsxtip, jsximg, jsxkeyode, jsxstyle, or jsxclass in the form of {xxx} is replaced with the dynamic property xxxif it exists. If the property doesn't exist, then the value isn't changed. Dynamic properties come from the server owning the CDF control. The conversion occurs when the XML document is retrieved from source and before it's placed in the cache. For more information, see the API for CDF.convertProperties().

CDF records can also include custom attributes. Custom attribute names can be any string except names of system attributes. To add attributes to a CDF record, call the insertRecordProperty() method. You can also manually edit the CDF document on the file system, or open the cached file in General Interface Builder.

Creating CDF Documents CDF documents are created both at design time and at runtime.

There are several ways to create CDF documents:

Create a new XML file that conforms to the CDF schema Create a new instance of a CDF component Instantiate a CDF using the API Map a parent element to a CDF in the XML Mapping Utility Transform an existing XML document using the API

Creating an XML File To create a new CDF document in your project,

1. Choose File > New > XML Document. 2. Select CDF Document from the list to add the basic template for a CDF document. 3. Press Ctrl+Spacebar again to add templates for attributes, additional records, or an XML header declaration.

Copyright © TIBCO Software Inc. All Rights Reserved. 54

Creating a new CDF Component When you drag a CDF component, such as Matrix or any other component that implements the jsx3.xml.Cacheable interface, to the work area in General Interface Builder, a CDF document is automatically created in the Local Data Cache palette. This document, which contains default data, is associated with the component for the length of the browser session.

If you do not explicitly set an XML Cache ID for a CDF-type control, such as matrix, menu, and select, an ID is automatically generated by the system. The naming convention is a concatenation of the control ID. For example, object.getId() plus an _XML suffix. An ID looks similar to the following: _jsx_1_5_XML.

Instantiating a CDF Document Using the API A CDF component isn't required for creating a CDF. Instead, you can instantiate a CDF directly using the factory method, jsx3.xml.CDF.Document.newDocument.

In this code example, a new XML document that represents an empty CDF document is created:

var oDoc = jsx3.xml.CDF.Document.newDocument(); var o = new Object(); o.jsxid = jsx3.xml.CDF.getKey(); o.jsxtext = "hello"; oDoc.insertRecord(o); oDoc; sampleWSDLMapping1.getCache().setDocument("foo",oDoc);

This is a good choice if a CDF component isn't required. For example, the Properties Editor palette in General Interface Builder uses the API to create the CDF on the fly at runtime and generate the list of available properties for the selected component in the work area.

For method details for the jsx3.xml.CDF.Document class, see the online API help in General Interface Builder.

Mapping a Parent Element to a CDF Document For outbound requests, map an element to the CDF Document option in the Type drop-down list in the Mappings table of the XML Mapping Utility. A new CDF document is automatically created when the response is received.

Transforming an existing XML Document You can use method calls to the jsx3.xml.Template class to transform an existing XML document. Using these methods, you can apply XSLT to an existing XML document to transform the XML into the CDF format. The following sample JavaScript code illustrates how to load and transform an XML file into CDF.

var myXML = new jsx3.xml.Document(); myXML.load("JSXAPPS/myProjectDir/xml/nonCDF.xml"); var myXSL = new jsx3.xml.XslDocument(); myXSL.load("JSXAPPS/myProjectDir/xsl/CDF.xsl"); myXSL.transform();

For method details, see the online API help in General Interface Builder.

Copyright © TIBCO Software Inc. All Rights Reserved. 55

Accessing CDF Data Data in CDF documents can be accessed using JavaScript object notation or XML record format.

Accessing a CDF Document Directly If you want to access the CDF document that belongs to a control, you simply call the {{getXML()}}method. The XML source document and the CDF source document are synonymous for the CDF controls, such as matrix, menu, select and so on. For example.

// get a handle to the matrix var objMatrix = myServer.getJSXByName("myMatrix"); var objCDF = objMatrix.getXML();

Getting a Handle to a CDF Document To access data in a CDF document of a CDF component, first get a handle to the document in one of the following ways:

From cache, by calling the getDocument() method (jsx3.app.Cache). This method takes the name of the cached CDF document as input, which is system-defined by default. For example,

myserver.getCache().getDocument("myDocument");

To avoid working with the system-defined name, use the XML Cache ID property to specify a name for the CDF document or access the CDF document through the object.

From an object, by calling the getXML() method (jsx3.xml.Cacheable). All CDF components implement the jsx3.xml.Cacheable interface, which provides this method. For example,

var objXML = myCdfControl.getXML();

The result of this method call is a jsx3.xml.Document instance.

If you've instantiated a CDF directly and aren't using a CDF component, you don't need to get a handle to the CDF document.

Accessing a Node You can access a record node within a CDF document in one of the following ways:

By calling the selectSingleNode() method (jsx3.xml.Entity) for the CDF document and passing the appropriate XSL query. The following code example returns the node with element name record and jsxid value of 12.

myCdfDocument.selectSingleNode(//record\[@jsxid='12']);

* From an object that implements the CDF interface, by calling the getRecordNode() method (jsx3.xml.CDF). For example,

myObject.getRecordNode(12);

Copyright © TIBCO Software Inc. All Rights Reserved. 56

Using CDF Methods This section gives an overview of CDF methods and describes how to use the methods to interact with a CDF document.

CDF Methods Overview The following table provides an overview of available methods defined by the jsx3.xml.CDF interface. For detailed method descriptions, including input and output information, see the online API help in General Interface Builder.

Copyright © TIBCO Software Inc. All Rights Reserved. 57

Method Summary

getKey Generates a unique identifier for use as the jsxidattribute for a CDF record. This value persists only for the length of the browser session. Unique values that persist across browser sessions must be generated by the developer.

newDocument A factory method for creating a new CDF document containing the following XML:

adoptRecord Transfers a CDF record between components. The record must have a unique jsxidvalue to be transferred. If no CDF document exists for the adopting parent, a document is created and added to the cache. If successful, this method returns a jsx3.xml.Entity instance, which is an object handle to the transferred record. The view for the record is automatically updated.

adoptRecordBefore Equivalent to adoptRecord, except that the to-be relationship is as a previousSibling to the CDF record identified by the parameter, strSiblingRecordId.

deleteRecord Deletes a CDF record from the component CDF document. If successful, this method returns a jsx3.xml.Entity instance, which is an object handle to the deleted record node. Updating the view for the record is optional.

deleteRecordProperty Deletes a specific property from a CDF record. The record must have a unique jsxid value. Do not call this method to delete the jsxid property.

getRecord Returns a JavaScript object that is a clone of the specified CDF record. Any updates to this clone doesn't affect the original record unless you call object.insertRecord() and pass the modified clone as the input parameter.

getRecordNode Returns a jsx3.xml.Entity instance representing the actual object handle to the CDF record. Updating this object also directly updates the model. To synchronize the view after an update, call the following: object.redrawRecord(strRecordId,jsx3.xml.CDF.UPDATE);

insertRecord Inserts a new record into the CDF document for the component. If no CDF document exists for the component, a document is created and added to the cache. If a record with the same jsxid value already exists, the existing record is updated.

insertRecordBefore Creates a new CDF record and inserts it into the CDF data source of this object, before the record identified by the parameter, strSiblingRecordId.

insertRecordNode Inserts a new record node into the control's XML-formatted data source. If no CDF document exists for the component, a document is created and added to the cache. If a record with the samejsxid value already exists, the existing record is updated. This function is for inserting records as XML node entities rather than JavaScript objects.

Copyright © TIBCO Software Inc. All Rights Reserved. 58

insertRecordProperty Inserts a new CDF attribute and corresponding value for the specified CDF record. The attribute can be one of the system attributes defined in CDF System Attributes or a custom attribute. Updating the view for the record is optional.

Adding Records Use the insertRecord() and insertRecordNode() methods to add records to a CDF document. The two methods are functionally equivalent, but insertRecord() takes a JavaScript object as input, while insertRecordNode() takes an XML entity. With insertRecord(), you specify the jsxid attribute, along with any other CDF attributes for the record, as properties of the object. insertRecord Example The following sample JavaScript code illustrates how to add records to a Matrix component using insertRecord() :

// get a handle to the matrix var objMatrix = myServer.getJSXByName("myMatrix");

// new CDF record var objRecord = new Object(); objRecord.jsxid = jsx3.CDF.getKey(); objRecord.Date = myServer.getJSXByName("dateEntry").getValue(); objRecord.Security = myServer.getJSXByName("securityEntry").getValue(); objRecord.Open = myServer.getJSXByName("openEntry").getValue(); objRecord.High = myServer.getJSXByName("highEntry").getValue();

// insert the record and pass true so it is redrawn without repaint objMatrix.insertRecord(objRecord, null, true);

In this example, the new CDF record object is objRecord. The first property defined for this object, jsxid, is a required system attribute that must be unique. The getKey() method is used to generate a unique jsxid value for this record. Other properties, Date, Security, Open, and High, become custom attributes of the CDF record. Values for these properties are provided by components in the application.

In addition to a JavaScript object, the insertRecord() call takes two parameters — the numeric identifier (jsxidvalue of a parent object) and an optional Boolean parameter for a redraw operation. When null is specified for the second parameter, as in this example, the record is added to the root element of the CDF document.

Since this example adds a single record, the overhead associated with redrawing the record is insignificant. When adding multiple records, such as in a loop, consider passing a value of false for this parameter and repainting the entire component after all records are added. For details, see Redrawing and Repainting Records.

Creating Record Hierarchies By default, the structure of a CDF document is flat without hierarchical relationships between records. To create an hierarchical CDF document, specify the optional strParentRecordId parameter when calling either insertRecord() or insertRecordNode(). This parameter takes the jsxid value of a parent record, and when a value is specified, the record is added as a child of the parent record.

Copyright © TIBCO Software Inc. All Rights Reserved. 59

Updating Records When you add a record that has the same jsxid value as an existing record in the CDF document, the existing record is replaced. Make sure jsxid values are unique before adding records. For details, see Generating Unique Identifiers.

You can use the insertRecordProperty() method to add attributes to an existing record in a CDF document. Specify the jsxidvalue of the record to modify, along with the attribute name and attribute value. The following sample illustrates how to add an attribute to an existing record within an ID (jsxid) of 58:

objList.insertRecordProperty("58","mypropname","mypropvalue");

The process of removing attributes is similar. Using deleteRecordProperty(), specify the jsxid value of the record to modify and the name of the attribute to remove. Although not specifically restricted by the API, do not remove the jsxid attribute from a record. The following sample JavaScript code illustrates how to remove an attribute from an existing record:

objList.deleteRecordProperty("11","jsximg");

In both of the preceding examples, the record is automatically refreshed to reflect the change in the application. You could also pass a value of false for the optional bRedraw parameter to prevent the redraw operation. For details on optimizing redraw and repaint operations, see Redrawing and Repainting Records.

Deleting Records Use the deleteRecord() method to delete a record from a CDF document. This method returns an object handle to the XML entity instance that was removed. The following sample JavaScript code illustrates how to delete an existing record:

var objMatrix = myServer.getJSXByName("myMatrix"); objMatrix.deleteRecord(strRecordId);

Generating Unique Identifiers The jsxid attribute must be unique among all records for the component. If users need to drag records from one component to another, the jsxid attribute must be unique across multiple components. There are several ways to ensure uniqueness.

If the content of the CDF document is built programmatically by your application, you can use the jsx3.xml.CDF.getKey() method to generate a unique value for the jsxid attribute. The generated value is guaranteed unique across multiple components for the browser session. For an example, see Adding Records.

If the content of the CDF document is built outside of your application, you can use any key value in an XML attribute as the jsxidvalue. If no key value exists in the original XML when transforming the XML into CDF, use the XPath generate-id function to generate a unique value.

Redrawing and Repainting Records After adding, modifying, or deleting records, the on-screen representation for the record will need to be synchronized. A changed record can be redrawn or the entire component can be repainted. Context and the impact on application performance determine which operation is more appropriate.

In general, repainting the component affects all records and is resource-intensive. Repainting Copyright © TIBCO Software Inc. All Rights Reserved. 60

In general, repainting the component affects all records and is resource-intensive. Repainting the component should be avoided unless a sizable number of records are modified. For example, if many records are added in an iterative manner, it can be more efficient to repaint the component once, after all additions have been made. To repaint a component, call the repaint() method for the specific component.

CDF methods, with the exception of the adoptRecord()}}method, accept an optional Boolean parameter that signifies whether the on-screen view should be immediately updated to reflect the update to the in-memory model. A value of {{true, which is the default value, redraws the record after modification. For the adoptRecord() method, both controls (the former and new parent) are redrawn.

Counting Records You can count the number of records in a CDF document by querying for all records and calling the getLength() method on the object that is returned. The following sample illustrates this for the List control.

var objXML = myList.getXML(); var objNodes = objXML.selectNodes("//record"); alert("The number of records is: " + objNodes.size());

First, call the getXML() method for the object, then the selectNodes() method (jsx3.xml.Entity) for the XML entity, passing the path for the nodes to select. This method returns a handle to the jsx3.util.List object containing all record nodes in the CDF document. Calling the getLength() method on this object returns the number of CDF records.

Flexible CDF Schema

The Common Data Format (CDF), enforces a standard XML data schema with a root element called data, nested elements called record and record attributes such as jsxid, jsxtext and jsximg. This schema applies to the classes that implement the jsx3.xml.CDF interface: Select, Tree, Menu, Table and Matrix (and previously List and Grid).

Standard CDF schema example ...

The flexible CDF schema feature allows these same classes to consume datasources that do not strictly follow CDF. This feature is particularly useful for consuming pre-existing XML datasources that were created without knowledge of CDF.

With the flexible CDF schema feature,

The core CDF schema elements and attributes data, record and jsxid can be renamed to anything A single data source can drive multiple CDF controls, each with its own view of the data

Copyright © TIBCO Software Inc. All Rights Reserved. 61

An alternative way of converting data sources to CDF is to use XSL Transformers. XSL Transformers allow you to define one or more XSL transformations to convert the source data to CDF before it is stored in the XML application cache and is used to render a CDF control. Whereas the flexible CDF schema feature supports only XML schemas that have a similar structure to CDF, the XSL transformers approach supports any arbitrary XML schema. Knowledge of XSL is required to use this approach. See the API documentation for jsx3.xml.Cacheable for more information on XML Transformers.

How Flexible CDF Schema Works

Each CDF control has a schema property of type jsx3.xml.CDFSchema. The value of this property defines how the control views its CDF datasource. If the schema property is not set then the control uses the default CDF schema.

Each CDF control first queries its schema for the name of the text attribute and then queries its datasource for that attribute of a record. For example, the implementation of jsx3.gui.Tree includes expressions such as

this.getRecordNode(id).getAttribute(this.getSchema().getProp("text"))

This additional level of indirection (this.getSchema().getProp("text") instead of "jsxtext") allows the CDFSchema object to control how each CDF control views its datasource. The default CDFSchema object returns "jsxtext" from a call to getProp("text"). However, you can modify the schema so that it returns "label" instead. This change would allow you to have a CDF datasource such as

...

Controlling Flexible CDF Schema in General Interface Builder

You can control flexible CDF schema from within General Interface Builder. To do so,

1. Open or create a component with a CDF control in it, such as Matrix, Tree or Menu. 2. Find the CDF Schema component in the Component Libraries palette and drag it onto the CDF control. It may be easier to drag it onto the corresponding node in the Component Hierarchy palette. 3. Modify the properties of the schema object in the Properties Editor.

The Properties Editor contains an editable property for each attribute in the default CDF schema. In general, the default value of property abc is jsxabc. CDFSchema also has a property called record. This property allows you to change the element name of the records in the datasource. You can choose another name, such as item or you can use set it to * to indicate than any XML element should be interpreted as a data record.

Copyright © TIBCO Software Inc. All Rights Reserved. 62

For the CDF schema shown in the screenshot, the datasource is

...

Using the same datasource for two different controls is simply a matter of defining a unique CDF schema for each control.

Click to download a sample project that uses the flexible CDF schema feature: GI-702.zip.

Common Interface Format (CIF)

Common Interface Format (CIF) The Common Interface Format (CIF) is a serialization format for storing General Interface component definitions. In the future, this format will replace the current serialization file format, which has the following namespace — xmlns="urn:tibco.com/v3.0". The CIF format provides improved readability and smaller file size.

The CIF format uses several new namespaces, the root of which is http://xsd.tns.tibco.com/gi/cif/2006. The new format is 100% compatible with the v3.0 serialization format. An XSLT is used for the conversion between CIF and v3.0 formats.

Currently, General Interface Builder can read but not save CIF files. Any edits made to a CIF file are saved in the old serialization format.

Copyright © TIBCO Software Inc. All Rights Reserved. 63

CIF Document Example Here is an example of a CIF document that represents a dialog component. The dialog contains a window bar with buttons, a splitter with a grid layout, and so on. Some of the key aspects of the CIF are indicated in bold. For definitions, see CIF Definitions.

"); ]]>

Copyright © TIBCO Software Inc. All Rights Reserved. 66

CIF Definitions Node Name Namespace Description

component http://xsd.tns.tibco.com/gi/cif/2006 Root level node. Supports child elements belonging to the same namespace. Any child element (excluding those named meta, which is a reserved name) is understood to be an instance of jsx3.app.Modeland is deserialized as part of the standard General Interface DOM. In other words, any object hierarchy communicated by the XML serialization format would be a true reflection of the General Interface DOM once the XML is deserialized.

@classpath http://xsd.tns.tibco.com/gi/cif/2006 This attribute can belong to any node belonging to the http://xsd.tns.tibco.com/gi/cif/2006 namespace except for meta nodes. If bound to the root node, component, this is the default class path for all GUI controls defined in the serialization file. Any GUI control that implements this attribute can override the root node setting.

meta Immediate child of the root node, component. Describes meta-related information about the component, including the following — name, icon, description, onAfterDeserailze, onBeforeDeserailize.

@name Attribute of the meta node. Defines the name of the meta attribute. For example, onAfterDeserialize.

data http://xsd.tns.tibco.com/gi/cif/2006 Inline data node. Allows for the serialization of data according to an open format. The default implementation of this node assumes that it contains CDATA content. However, this node could provide a handler-for attribute as a means for serializing and deserialization custom data types.

@href Provides the unique ID for the inline data node among all inline data nodes in the document.

@handler-for Provides the name of the JavaScript object that handles the deserialization of either the component or the data. Applies only to the data node that belongs to the namespace, http://xsd.tns.tibco.com/gi/cif/2006/inlinedata.

Copyright © TIBCO Software Inc. All Rights Reserved. 67

namespace-qualified xmlns:e= In order to ensure proper compatibility with the attributes "http://xsd.tns.tibco.com/ existing serialization format and provide for good gi/cif/2006/events" runtime deserialization performance, XML namespaces are used to uniquely identify how to xmlns:d= deserialize a given property on a standard General "http://xsd.tns.tibco.com/ Interface object definition. The use of namespaces gi/cif/2006/dynamics" allows the deserialized to quickly categorize the object properties. This prevents the need for expensive xmlns:p= runtime lookups and the possibility of namespace "http://xsd.tns.tibco.com/ collisions. For example, the drag property on a List gi/cif/2006/property" definition may belong to the property namespace ( [http://xsd.tns.tibco.com/gi/cif/2006/property]), xmlns:pe= specifying whether or not the given List supports drag-and-drop. It could also belong to the event "http://xsd.tns.tibco.com/ namespace gi/cif/2006/property.eval" ([http://xsd.tns.tibco.com/gi/cif/2006/events]) and relate to the handler code to fire when a drag event xmlns:x= fires on the List. It could also be a user-defined "http://xsd.tns.tibco.com/ property ([http://xsd.tns.tibco.com/gi/cif/2006] gi/cif/2006/xslparameters" /userdefined or [http://xsd.tns.tibco.com/gi/cif/2006/userdefined.eval]). xmlns:v= The drag property could also be a dynamic property. "http://xsd.tns.tibco.com/ gi/cif/2006/view"

xmlns:u= "http://xsd.tns.tibco.com/ gi/cif/2006/userdefined"

xmlns:ue= "http://xsd.tns.tibco.com/ gi/cif/2006/userdefined.eval"

Common Exchange Format (CXF)

Common Exchange Format (CXF) The Common Exchange Format (CXF) is an interface definition schema that describes how to interact with XML data within General Interface. By using CXF, General Interface is able to connect to disparate systems and services without being tied to a specific exchange format. At runtime, CXF is used by the jsx3.net.Service class to perform the actual interactions.

In much the same way that WSDL (an XML document format) defines SOAP transactions, General Interface employs a tree-like definition language of its own referred to as the Common Exchange Format (CXF). Using a common format for defining transactions allows General Interface to communicate with a myriad of systems without being tied to a particular interface definition. CXF documents are created at design time by the XML Mapping Utility using any number of formats as a starting point for creating the definition. Supported formats include WSDL, schema, XML, and XHTML. CXF documents are referred to as mapping rules files or rules files throughout the documentation.

Once parsed by the XML Mapping Utility, XML documents are persisted in CXF format. A CXF Copyright © TIBCO Software Inc. All Rights Reserved. 68

Once parsed by the XML Mapping Utility, XML documents are persisted in CXF format. A CXF rules document can then be mapped to application objects, such as CDF documents, text boxes, and nodes in the Local Data Cache palette.

Regardless of whether WSDL, Schema, or XML is used, all input formats result in the same transactional format. In practice, this means that the interactions with a SOAP service can be defined by using WSDL or a sample SOAP message, such as an Envelope, as a starting point. Ultimately, the source type (WSDL, Schema, or XML) used to create a CXF rules document is irrelevant once the CXF document has been created, as all formats are persisted using CXF.

Another way to think about CXF is to think of it as an interpretive language that is able to interface between the XML document formats used by a given web service and the native CDF and JavaScript formats used by General Interface. Just as it is important to be versed in CDF in order to know how data is used within General Interface, an understanding of CXF provides insight into how data is shared between General Interface and data services. While CDF provides the format for data while it is within the control of General Interface, CXF provides the bridge to convert this information to the format required by the given web service.

CXF Document Example The following CXF document was created by the XML Mapping Utility. The input document is Google's WSDL located at http://api.google.com/GoogleSearch.wsdl. After the XML Mapping Utility converts Google's WSDL to CXF, a few operations are removed for readability. What remains is a shortened description of the doGoogleSearch operation, with a sampling of the major CXF entities and attributes. If you're familiar with WSDL and Google's in particular, you should see similarities and differences between CXF and WSDL. CXF is more transactional and is designed to read more literally with less indirection. Therefore, it contains only a subset of the data contained in the original WSDL.

Copyright © TIBCO Software Inc. All Rights Reserved. 69

Copyright © TIBCO Software Inc. All Rights Reserved. 70

CXF Attribute Definitions CXF is an extension of CDF, meaning it adheres to the CDF format, while adding additional attributes and entities of its own. For more information on CDF, see Common Data Format (CDF).

The following table provides attribute definitions. Each of these attributes exists in one or more rule types, which are described in CXF Rule Types.

Copyright © TIBCO Software Inc. All Rights Reserved. 71

Attribute Description

datatype Data type for the node. For example, xsd:string. This is relevant to RPC Encoded WSDL inputs. When the final message is generated and sent to the remote service, this value is used to specify the encoding for a node in the message.

endpoint URL for the remote service to contact. Although WSDL binds the endpoint to the service (which can encapsulate one or more operations), CXF binds the endpoint to each individual operation.

groupref If equal to 1, the node is flagged as structural, which means that it isn't part of the generated message. The node appears in the rules tree as an organizing element but isn't generated and sent with the request, essentially removing the abstract node and appending its descendant structures to the structural node's immediate parent.

jsxid System ID for the record. This is assigned by the system and is unique for each node in the CXF document. This attribute is only relevant at design time.

jsxtext System text for the record. More importantly, this is the node name (for attributes and entities) in the message.

method The HTTP transport method: GET, POST, PUT, DELETE.

name Applies to records in the CXF that define mappings, HTTP headers, and restrictions. In the case of mappings, this is the map type (i.e., DOM, Script, CDF Document, and so on). For HTTP headers, this is the header name. For restrictions, this is the type of the restriction (enumeration, nillable, pattern, and so on).

onafterreceive JavaScript code to execute immediately after receiving the response message.

onbeforesend JavaScript code to execute immediately before sending the request message.

opname The name of the operation. This value is unique among all other operation nodes in the CXF document. In the case of a CXF that was created without a WSDL, there is only one operation for the CXF named jsxtransaction.

path The node path to find this item in the original source Schema used to create the CXF. This attribute is only used by WSDL and Schema input types and is only relevant at design time.

ref If equal to 1, this node will be flagged by the XML Mapping Utility as a referential node, pointing to a group or attributeGroupelement in the source WSDL/Schema. This attribute is only relevant at design time and is used to convert the indirection used by Schema to the concrete structures used by CXF.

repeat If this attribute exists, its value will be evaluated as JavaScript within the context of the jsx3.net.Service instance that is processing the given CXF. If the result evaluates to true, the given branch in the CXF will be processed again. This only applies to XML documents generated on the client. This value is ignored when processing a service response.

Copyright © TIBCO Software Inc. All Rights Reserved. 72

simple If equal to 1, the data type for this node is one of the simple types defined by Schema (http://www.w3.org/2001/XMLSchema-instance).

soapencstyle If equal to http://schemas.xmlsoap.org/soap/encoding/, the operation is designated as encoded, meaning each node will be tagged with its data type. This applies only to WSDL input types that use RPC encoding.

soaprpcns If an RPC Encoded message, the namespace for the remote procedure (the message).

soapstyle The SOAP style — document or rpc.

soapuse The SOAP use — encoded or literal.

src URL for the source document that is serving as the pattern master for generating the CXF. The pattern master is the input document that was used by the XML Mapping Utility to create the CXF (typically a WSDL). This attribute is only relevant at design time.

stubsrc URL for the base shell document. Also used for inbound messages (response nodes) when running in static mode.

stubpath The XSL Query for the node in the base shell document (stubsrc) to which the generated document will be appended.

tns If this value exists on a Rule node contained by an Input node, the Rule will be qualified and the value of the tnswill be appended to the root node in the response document. If it exists on a rule contained by the output or fault nodes, it defines a qualified namespace, meaning that it isn't enough for the node names to match for the rule to be applied; rather, the node's namespace must also match.

ttns Represents the target namespace for the data type and applies to rpc-encoded messages. For example, if the target namespace tns is abc.com and ttns is def.com, you would see something similar to the following in a message:

type The type of rule. For example, A, C, E, and so on. The most common type is E, which represents a mapping rule to an Entity node type in the CXF.

value Applies to records in the CXF that define mappings, HTTP headers, and restrictions. In the case of mappings, this is the map path/value. For HTTP headers, this is the header value. For restrictions, this is the value of the restriction.

CXF Rule Types Each node in the CXF document is known as a rule, each of which describes a specific step in the transaction. For example, an operation rule defines the location of the Service, while a Mapping rule defines what values will be sent to the Service. The following table describes each rule and the CXF attributes it implements.

Copyright © TIBCO Software Inc. All Rights Reserved. 73

CXF Rule Type Attribute Description

WSDL jsxid, jsxtext, This is the top-level node in a CXF document that //record[@type='W'] type, src, type resulted from a WSDL input. The most relevant attribute is src, which describes the location of the original WSDL in case the CXF document is in-edit and still needs a back-reference to the original WSDL.

Service jsxid, jsxtext, This is a second-level node in a CXF document //record[@type='S'] type, path, that resulted from a WSDL input. It is an soapstyle immediate child of the WSDL-type node. It describes a service to which one or more operations belong. Although the service does define an endpoint in the original WSDL, this information is saved to the Operation nodes for improved flexibility.

Operation jsxid, jsxtext, This is a third-level node in a CXF document that //record[@type='O'] type, endpoint, resulted from a WSDL input. It is an immediate method, child of the Service node. The operation describes opname, path the type of messages involved, including input, output, and fault.

Transaction jsxid, jsxtext, This is the top-level node in a CXF that resulted //record[@type='T'] type, endpoint, from a non-WSDL input. It is equivalent to the method, opname third-level Operation node that results from a WSDL input, except that it does not define a path. Instead, its child input and output rules define the path to their respective source documents.

Input jsxid, jsxtext, This node is the child of either an Operation or //record[@type='I'] type, Transaction node. It contains the rules necessary onbeforesend, to create the input (the document that will be sent path, as part of the request). When the immediate soapencstyle, parent is a Transaction node, the input will define soaprpcns, a src attribute, if relevant. soapuse, src, stubpath, stubsrc

Output jsxid, jsxtext, This node is the child of either an Operation or //record[@type='O'] type, Transaction node. It contains the rules necessary onafterreceive, to create the output (the response that will be path, processed). When the immediate parent is a soapencstyle, Transaction node, the output will define a src soaprpcns, attribute, if relevant. soapuse, src, stubsrc

Copyright © TIBCO Software Inc. All Rights Reserved. 74

Fault jsxid, jsxtext, This node is a child of an Operation node. It //record[@type='F'] type, path, defines an alternative ruleset for processing a soapencstyle, fault document returned from the Service. It is soaprpcns, executed only when the service responds with a soapuse non-202, 200, or -0 HTTP status code. It does not support the extra attributes that the Output node supports.

Rule jsxid, jsxtext, Rule nodes define the mappings and restrictions //record[@type='A' type, datatype, and are used to either generate a node in the or @type='C' or groupref, path, input message or process a node in the output. @type='D' or ref, repeat, Note the following definitions: A: attribute node @type='E'] simple,tns,ttns E: entity node D: CDATA node C: complex node (contains E, C, D, or A nodes)

Mapping jsxid, name, Mapping nodes are bound to an entity called //mappings/record value mappings, which, in turn, is bound to a given Rule node. There can be zero or more mappings for a given rule.

Restriction jsxid, name, Restriction nodes are bound to an entity called //restrictions/record value restrictions, which, in turn, is bound to a given Rule node. There can be zero or more restrictions for a given rule. The restrictions can be used to validate mapped input.

Header jsxid, name, Header nodes are bound to an entity called //headers/record value headers, which, in turn, is bound to a given Operation or Transaction node. There can be zero or more HTTP headers for a given operation.

Copyright © TIBCO Software Inc. All Rights Reserved. 75

Chapter 4 Handling Application Data

This chapter describes how to send, receive, and cache application data.

About Handling Application Data Sending Data Receiving Data Caching Data

About Handling Application Data

General Interface provides an in-memory local data cache where developers can store XML/XSL documents needed by the application. Some documents in the local data cache are placed there automatically by the system. Developers can also set their own documents in the local data cache. Having a centralized cache provides easier object cleanup, as well as a standardized method for sharing data across multiple components. The local data cache is a critical aspect of a stateful rich client experience when used in conjunction with asynchronous data access.

General Interface applications can send and receive any type of text data sent using HTTP/S. The jsx3.net.Request class is used for this exchange, providing a generic transport mechanism for text content, regardless of format. Data that is in XML format can be stored in the local data cache for repeated use by various objects within the application.

Sending Data

You can send data from an application using the methods: GET or POST. Depending upon the capabilities of the server being called, other methods like DELETE, PUT, and HEAD may also be called.

The following describes the general pattern for sending data:

1. Create a new jsx3.net.Request instance. 2. Call the open() method and specify the interaction type (GET, POST, and so on). 3. Call the send() method.

For a POST interaction, pass the string content as the only parameter to the send() method. For GET, use another content mechanism, such as an overloaded URL, as in this example:

Copyright © TIBCO Software Inc. All Rights Reserved. 76

//initialize and open

var req = jsx3.net.Request.open("GET","http://www.tibco.com?myQuery=1", true);

//create response callback and subscribe

function onResponse(objEvent) {

var req = objEvent.target;

alert(req.getResponseText());

};

req.subscribe(jsx3.net.Request.EVENT_ON_RESPONSE,onResponse);

//send

req.send();

General Interface applications perform best when they use asynchronous data access. However, there are times when you might want to synchronously access data. The above call made synchronously is shown in the following example:

//initialize and open

var req = jsx3.net.Request.open("GET","http://www.tibco.com?myQuery=1", false);

//send

req.send();

alert(req.getResponseText());

Receiving Data

The process for receiving data depends on whether the data is valid XML or another format.

Receiving XML Data To receive XML data, call the getResponseXML() method on the Request instance. This method returns a jsx3.xml.Document object, which is an XML document in a format that General Interface can use, as shown in the following example:

Copyright © TIBCO Software Inc. All Rights Reserved. 77

//initialize and open

var reqSocket = jsx3.net.Request.open("GET",jsx3.GO('myURLComponent').getValue(), false);

//send the request

reqSocket.send();

//get the XML response

var repXML = reqSocket.getResponseXML();

To save the response document for repeated access, use the setDocument function to load it into the local data cache as follows:

myApp.getCache().setDocument("MyCacheDocument", repXML);

Also note that the Request class has different methods for accessing data. The example shown above is the simplest of all data calls: a synchronous HTTP GET. In fact, requesting and caching data in this manner can be done with only one API call, openDocument as shown in the following example:

var repXML = someApp.getCache().openDocument(someURL,someCacheId);

The Cache class has different methods for accessing data more efficiently than the {{openDocument}} method just described. For example, the method {{getOrOpenDocument}} will first check the cache for the document before attempting to load it.

If the document is large or the server will respond with a known latency, fetch the document asynchronously, using {{getOrOpenAsync}}. This method returns the corresponding document synchronously if it already exists in the cache. If the document does not exist in the cache, then it is loaded asynchronously and the method returns a placeholder document. The namespace URI of this placeholder document is {{jsx3.xml.Cache.XSDNS}} and its root node name is {{loading}}.

Because the cache stores this placeholder document until the document finishes

Copyright © TIBCO Software Inc. All Rights Reserved. 78 loading, subsequent calls to synchronous APIs (such as {{getDocument() and getOrOpenDocument()}}) may also return the placeholder document. It is therefore important to check the namespace of the returned document when any code uses the asynchronous APIs.

Once a document finishes loading asynchronously the placeholder document is replaced with the loaded document. This change in value causes the cache to publish a pair of events of action {{Cache.CHANGE}}. If loading the document fails or times out, the placeholder document is instead replaced with another placeholder document. This document also has a URI namespace of {{Cache.XSDNS}}. Its root node name may be either {{error}} or {{timeout}}. If the root node name is {{error}} then the root node has an attribute, also named {{error}}, which contains the XML error message.

h4. Handling Failures

If the incoming XML can't be parsed by the {{Request}} instance, the {{getResponseXML}} call fails. One possible cause of failure is invalid XML, while another is an unrecognized content type specified in the HTTP header. The server must set this field in the HTTP header to {{text/xml}} or similar.

If the {{getResponseXML}} call fails but the content is valid XML, you can still parse it by calling the {{getResponseText()}} method and passing the XML string into a {{jsx3.xml.Document}} instance as follows:{code:lang=javascript}var objXML = new jsx3.xml.Document();

Copyright © TIBCO Software Inc. All Rights Reserved. 79

objXML.loadXML(XML_string);

if(!objXML.hasError()) alert("success:\n\n" + objXML.getXML());

For more details on the getResponseText() method, see Receiving Non-XML Data.

Receiving Non-XML Data To receive non-XML data, call the getResponseText() method for the Request instance. This method returns the body of the response as a string value, as shown in the following example:

var strText = objRequest.getResponseText();

window.alert(strText);

Non-XML data is useful in many situations. For example, non-XML data can be displayed in the application by setting it as the text property of a jsx3.gui.Block object, or it can be reformatted into CDF for use by a Matrix component. Also, if the data is converted to XML, it can be stored in the local data cache to facilitate data access and management.

Caching Data

Each General Interface application maintains a separate local data cache. If two applications are embedded on a single web page, each has its own cache. This local data cache should not be confused with the browser file cache for temporary Internet files. The General Interface local data cache is an in-memory, JavaScript hash of parsed XML documents that disappears when the browser window is closed. Any XML document, including XML, CDF, and XSL files, can be stored in the local data cache.

Controls that display XML data interface with the local data cache by way of the jsx3.xml.Cacheable interface. This class provides methods that link a GUI object and the local data cache data it needs. The GUI object never refers to the data by reference. Only the local data cache references the XML document object, facilitating improved dereferencing and object cleanup.

The Share Resources property is an important property of GUI classes that extend Cacheable (Menu, Tree, Matrix, and so on). When the Share Resources property is set to false (default setting) and the GUI object is removed from the General Interface DOM, the associated XML and XSL documents are also removed from the local data cache. Set this property to true if two GUI objects refer to the same document or if the document should remain in the local data cache after the GUI object is removed.

Accessing the Correct Cache To load files into the local data cache for use at runtime, call methods of the jsx3.app.Cache class. All cache method calls must be qualified with application namespace information. If the namespace for your application is app1, use the following syntax when storing and retrieving documents:

app1.getCache().method_name

You can cache any XML, CDF, or XSL document using the openDocument() method. The openDocument() method allows you to specify the URL of a file to load and parses the file into a jsx3.xml.Document instance. To cache the document, provide a second parameter to use as the Copyright © TIBCO Software Inc. All Rights Reserved. 80

jsx3.xml.Document instance. To cache the document, provide a second parameter to use as the cache ID as follows:

app1.getCache().openDocument ("http://ibiblio.org/bosak/coriolan.xml","someCacheId");

Because this method call is always synchronous, browser performance can be affected if the document is large.

To explicitly load a file into cache independently of the openDocument() method, use the setDocument() method.

To retrieve a file from cache, use the getDocument() method as follows:

app1.getCache().getDocument("myDocument");

Shared Global Cache If you need to share a cache document with other applications running in the same page, use the shared global cache that is provided by the General Interface system as follows:

var objSharedXML = jsx3.getSharedCache().getDocument("abc");

When a document is requested from the local data cache and the document isn't found, the General Interface system queries the shared global cache. For example, if the local data cache doesn't have a document named abc, each of the following calls is equivalent, assuming that the application namespace is app1:

var objXML = jsx3.getSharedCache().getDocument("abc");

or

var objXML = app1.getCache().getDocument("abc")';

Pre-caching XML Documents General Interface controls that implement the jsx3.xml.Cacheable interface will automatically load their associated XML document into the local data cache when first painted. Otherwise, loading XML data into the local data cache is typically the domain of the developer.

In General Interface Builder, project files can be configured to load automatically when the application loads. To manually specify which project files are automatically loaded into cache, right-click the file name in the Project Files palette and select Auto Load. Any type of project file except a GUI component and a mapping rule can be configured to automatically load. For more information on Auto Load options, see File Profile Dialog.

When you're working in General Interface Builder, XML and XSL project files can be manually loaded or reloaded into the local data cache by doing the following:

In the Project Files palette, right-click the file name and select Load/Reload. In the work area, right-click the associated tab and select Save and Reload after modifying an XML or XSL document.

To view the contents of the local data cache in General Interface Builder, choose Palettes > Local Copyright © TIBCO Software Inc. All Rights Reserved. 81

To view the contents of the local data cache in General Interface Builder, choose Palettes > Local Data Cache.

Copyright © TIBCO Software Inc. All Rights Reserved. 82

Chapter 5 Communicating with Data Services

This chapter describes how to communicate with data services in a General Interface application.

About Communicating with Data Services Basic Steps for Communicating with Data Services XML Mapping Utility User Interface Creating Mapping Rules Files Modifying Mapping Rules Files Mapping GUI Components to Mapping Rules Calling a Data Service Mapping Response Data to CDF GUI Components Testing Outbound and Inbound Messages Handling Errors and Timeouts

About Communicating with Data Services

General Interface applications are able to communicate with XML data services, such as SOAP, REST, or RSS, using the HTTP protocol. To simplify the exchange of information, General Interface provides an XML Mapping Utility that allows developers to visually bind nodes in the exchanged messages to objects in the application. The output from the XML Mapping Utility is an XML document format called the Common Exchange Format (CXF). CXF is analogous to XSLT in that it is an XML-based structure that is capable of transforming, creating, and processing XML documents.

For information on General Interface document formats, see Custom Document Formats.

CXF documents can also be used for internal transformations and mappings, making them useful even when a remote service isn't involved. The following figure depicts how CXF can be used to process and transform the messages exchanged with a remote service. The next figure shows how CXF can be used for internal mappings and transformations.

Processing External Data

Copyright © TIBCO Software Inc. All Rights Reserved. 83

Processing Internal Data

Because CXF is used to define how information is processed, CXF documents are commonly referred to as rules files. The XML Mapping Utility is the design-time tool that creates a rules file, and the jsx3.net.Service class is the runtime engine that executes a rules file. If the rules file specifies that a remote service is involved, the jsx3.net.Service class manages all communications, using its own instance of jsx3.net.Request for the HTTP communications.

Basic Steps for Communicating with Data Services

Communicating with data services in your application involves these basic steps:

1. Create mapping rules. See Creating Mapping Rules Files. 2. Map application GUI components to the rules file: Manual mapping. See Manually Mapping GUI Components and Input Mappings.

Automatic mapping. See Automatically Generating GUI Components and Input Mappings. For CDF mapping, see Map Response Elements to CDF Equivalents. 3. Test messages. See Testing Outbound and Inbound Messages. 4. Generate function code to run the rules file and invoke the service. See Generating Function Code. 5. Add events that will invoke function code in your application. See Invoking Function Code.

XML Mapping Utility User Interface

This section explains the XML Mapping Utility user interface.

To open the XML Mapping Utility, do one of the following:

Choose File > New > Mapping Rule. Choose Tools > XML Mapping Utility. Click the New button on the Project Files palette toolbar and choose Mapping Rule. Double-click an existing rules file in the Project Files palette.

The XML Mapping Utility prompts you to select one or more source documents to use as the starting point for the mapping rules file. After the source documents are parsed, the XML Mapping Utility user interface is displayed. Copyright © TIBCO Software Inc. All Rights Reserved. 84

Mapping Utility user interface is displayed.

The XML Mapping Utility has several panels and toolbars:

XML Mapping Utility Toolbar Rules Tree Panel Rules Tree Panel Toolbar Rule Profile Panel Settings Panel Mapper Log

For definitions of fields in the XML Mapping Utility, see XML Mapping Utility.

XML Mapping Utility Toolbar The XML Mapping Utility toolbar has buttons for creating, opening, and saving mapping rules.

For more information on toolbar buttons, see XML Mapping Utility Toolbar.

Rules Tree Panel After the source documents are parsed, the mapping rules file displays as a tree consisting of multiple rules in the Rules Tree panel. The rules tree contains a collection of input (request) and output (response) rules, which are executed in the order they appear in the tree.

The rules in the rules file can be edited independently of the source document. After the initial parse, you can add rules to and remove rules from the file as needed. For example, unmapped rules can be removed to minimize the size of the rules file. Additional rules can be defined to customize the service interaction or account for changes to the service over time.

Copyright © TIBCO Software Inc. All Rights Reserved. 85

Icon Rule Type Description

(small Attribute A rule that maps to an attribute node. pencil)

CDATA A rule that maps to a CDATA (character data) node.

A rule that maps to an element node and which has descendant element, attribute, or CDATA rules. Double-clicking the icon reveals additional rules that are defined by the source WSDL or Schema.

Complex A rule that maps to an element node and which has descendant Type element, attribute, or CDATA rules.

Data Type The XSD data type of the selected rule, such as string, boolean, decimal, and so on.

(large Element A rule that maps to an element node. pencil)

Input An input or request rule. (request)

Mapping A rule that has a mapping assigned to it.

Operation An operation or transaction rule.

Output An output or response rule. (response)

Repeat An input rule that repeats. See Repeat When. When

Restriction A rule that has a restriction assigned to it. Restrictions are used to validate and restrict user input. See Restrictions.

Schema or The root rule in the rules file. WSDL

Service The service, which is a collection of operations.

(1), (0 - 1), Inclusive minimum and maximum number of times this rule (1-unbounded) can appear in the XML message.

Rules Tree Panel Toolbar The Rules Tree panel offers a number of tools on the toolbar to edit and exercise mappings:

Test Invokes a tool to test the mappings. For more information, see Testing Outbound and Inbound Messages. Map Automatically maps the selected rules to GUI components and CDF elements. For more information, see Automatically Generating GUI Components and Input Mappings and Mapping Response Data to CDF GUI Components. Detach Removes mappings, restrictions, or HTTP headers for the selected rules. Delete Deletes the selected rules or all unselected sibling rules. Generate Generates the JavaScript code that will be needed to execute the rules file in the running application. See Calling a Data Service. Copyright © TIBCO Software Inc. All Rights Reserved. 86

running application. See Calling a Data Service.

For more information on toolbar buttons, see Rules Tree Panel Toolbar.

Rule Profile Panel The Rule Profile panel, which is below the Rules Tree panel, has two buttons:

Original Schema Source Displays the read-only Schema source for the selected rule. This binding can be updated by modifying the Source Path field in the Rule Profile panel. Maintaining this binding is only important at design time, particularly if the rule node may need to be reparsed from source. Rule Node Profile Displays profile information for the selected rule, such as target namespace, data type, and rule name. Some of these fields are editable. For more information on these fields and how to modify profiles, see Working in the Rule Profile Panel and Rule Profile Panel.

Settings Panel The Settings panel, to the right of the Rules Tree panel, displays fields pertinent to the type of rule selected in the rules tree. If no rule is selected in the rules tree or if multiple rules are selected, the Settings panel is blank. You can use the Settings panel to define how the rule is processed, such as add restrictions, mappings, JavaScript code, and so on.

For more information about fields in the Settings panel, see Settings Panel. For more information on using the Settings panel, see Working in the Settings Panel.

For additional information and API documentation, hover the mouse over the question mark icon and the APIs icon in the Settings panel.

Copyright © TIBCO Software Inc. All Rights Reserved. 87

APIs CDFCONTEXT (Direction: input, output)*---CDF record node being acted upon CDFRECORDS (Direction: input, output)* - CDF records collection being iterated RULENODE (Direction: input, output)* - Current node in the rules tree being processed MESSAGENODE (Direction: input, output)* - Node in the message being processed OBJECTTYPE (Direction: input, output)* - Deprecated. Now evaluates to 'Script' OBJECTNAME (Direction: input, output)* - Deprecated. Will always evaluate to what FILTER once evaluated to--namely the Script being evaluated FILTER (Direction: input, output)* - Deprecated. Do not use. setValue(strValue) (Direction: input)* - Equivalent to MESSAGENODE.setValue(strValue) setCDFContext(strXSLQuery) (Direction: input)* - Valid selection query to update CDFCONTEXT. Must return an object reference to a CDF Record node. setCDFRecords(strXSLQuery) (Direction: input)* - Updates record collection to be iterated. Must return a valid jsx3.util.Collection instance containing one or more CDF record nodes. disableNamedRule(strNodeName) (Direction: input)* - Disables the named child rule, so that it does not execute until enableNamedRule is called. enableNamedRule(strNodeName) (Direction: input)* - Re-enables the named child rule. disableReferencedRule(objRuleChild) (Direction: input)* - Disables the child rule, so that it does not execute until enableReferencedRule is called. enableReferencedRule(objRuleChild) (Direction: input)* - Re-enables the child rule.

*Contextual variables listed as inputs are available when creating input messages. Outputs are available when processing output messages.

Mapper Log The Mapper Log displays information about the outcome of parsing the starting source document(s). Different log levels can be selected by clicking on the Adjust Log Level button in the Mapper Log panel. Possible levels, from most detailed to least detailed, include Trace, Debug, Info, Warn, Error, and Fatal. The default level is Info and the XML Mapping Utility resets to this value when closed.

The Mapper Log can also be used to view the message exchange when using the Test Interface Tool.

For more information, see Mapper Log.

Mapper Log Toolbar The Mapper Log toolbar has buttons for selecting log levels and clearing the log. For more information, see Mapper Log Toolbar.

XML Mapping Utility Field Descriptions For more information about fields in the XML Mapping Utility, see XML Mapping Utility.

Copyright © TIBCO Software Inc. All Rights Reserved. 88

Creating Mapping Rules Files

Mapping rules files are XML files authored in Common Exchange Format (CXF). CXF defines how data is exchanged between objects, as well as how data is converted from one XML format to another. CXF can be viewed as a visual form of XSLT with additional support for HTTP-based communication to transport the XML. In fact, a rules file can be compiled into XSLT for faster performance. For information about CXF, see Common Exchange Format (CXF).

Mapping rules are individual rules within the mapping rules file. There are many types of mapping rules, each of which defines a particular aspect of the mapping process. For example, rules that descend from the output rule define how to process (read) a document in the local cache or returned from a remote service, while mapping rules that descend from an input rule define how to create (write) a node in an XML document.

Rules files created in an earlier version of General Interface are automatically updated to the latest CXF version when opened in the XML Mapping Utility.

The first step in mapping GUI components or CDF documents to a mapping rule is to create a mapping rules file.

The XML Mapping Utility accepts many types of source document formats to begin defining the mapping rules file, including WSDL, XML, XSD, XHTML, JSON, and well-formed HTML. Data in any of these formats can be parsed and used as a starting point for defining mappings. When the mapping rule will be used to not only read and write XML, but also communicate with a remote service, the HTTP methods, PUT, GET, POST, and DELETE are supported.

This section uses the General Interface WSDL Mapping 2 sample located in workspace/JSXAPPS/samples/WSDL_Mapping_2. By default, this sample runs in Static Mode, rendering the results of a sample message on screen. To run against the Xignite web service in Live Mode, register for a license key at http://www.xignite.com/xhistorical.asmx?op=xRegister. Then set the project to Live Mode on the Deployment panel of the Project Settings dialog (Project > Project Settings > Deployment) and reload your browser.

Choosing the File for the Rules File Starting Point The files you can use as the starting point for generating the mapping rules file in the XML Mapping Utility are WSDL Files; XML, XHTML, and Schema Files; and JSON Files.

WSDL Files Select WSDL if your source document is a WSDL that defines a Doc Literal or RPC Encoded SOAP service. Specify the location of the WSDL file in the URL field. See Specifying Paths in the XML Mapping Utility.

Copyright © TIBCO Software Inc. All Rights Reserved. 89

XML, XHTML, and Schema Files Select XML/XHTML/Schema if your source document is a data format other than WSDL or JSON.

Specify the location of source document(s) in the URL fields. See Specifying Paths in the XML Mapping Utility.

JSON Files Select JSON if your source document is in JavaScript Object Notation data interchange format. Specify the location of the source document in the URL field. See Specifying Paths in the XML Mapping Utility.

Copyright © TIBCO Software Inc. All Rights Reserved. 90

Specifying Paths in the XML Mapping Utility The XML Mapping Utility resolves paths to files relative to the project. It's recommended that you copy WSDLs and other source document(s) for rules files to a directory in your project. For example, create a wsdl folder in your project and copy the WSDL into the wsdl folder. Then enter wsdl/ wsdl_file.xml in the URL field of the XML Mapping Utility.

If you need to resolve a path to a source document outside of your project, use an absolute resolver, such as jsxuser:/// and jsxapp:///.

jsxuser:///... Resolves relative to the parent of the JSXAPPS directory, which is the workspace. When General Interface Builder is running, this URI resolves relative to the workspace directory.

jsxapp://app/... If the Server instance corresponding to the host portion of the URI is loaded into memory, the URI is resolved relative to the application base directory ( jsxappbase).

Creating a Rules File To create a new rules file:

1. Copy the file(s) to be used as the starting point for the mapping rules file to your project---a WSDL file, XML/HTML/Schema files, or a JSON file. This example uses Historicals.wsdl in workspace/JSXAPPS/samples/WSDL_Mapping_2/wsdl. 2. Open the XML Mapping Utility using one of these methods: Select File > New > Mapping Rule. Choose Tools > XML Mapping Utility. 3. Select the file type you are using as the starting point for the mapping rules file: WSDL, XML/XHTML/Schema, or JSON. See Choosing the File for the Rules File Starting Point. 4. Enter a URL and parse the document: a. Type the URL for a source document(s) to be used as the starting point for the rules file or click the Browse button to locate the file. See Specifying Paths in the XML Mapping Utility. For example, if the Historicals.wsdl is saved in a wsdl folder in your current project, type wsdl/Historicals.wsdl as the starting point for the rules file.

b. Click the Parse Document button to generate the mapping rules file. After you click Parse Document, a new rules file is created. The XML Mapping Utility looks similar to the following:

5. Modify the mapping rules file as desired. For example, remove any extraneous rules as Copyright © TIBCO Software Inc. All Rights Reserved. 4.

b.

91

5. Modify the mapping rules file as desired. For example, remove any extraneous rules as follows: a. Select a rule or rules in the rules tree. Use Shift+click or Ctrl+click to select multiple rules. b. Choose Delete > Delete Selected Rules to delete the rules you've selected. Or choose Delete > Unselected Sibling Rules to delete the unselected rules. For example, select GetHistoricalQuotes (not the singular GetHistoricalQuote) in the Rules Tree panel and choose Delete > Unselected Sibling Rules from the Rules Tree panel menu to remove the other operation rules that were defined by the source WSDL. This helps to reduce the size of your mapping rules file so that it only defines those operations that will be run. For more information, see Modifying Mapping Rules Files. 6. Save the rules file with the .xml extension.

Modifying Mapping Rules Files

The rules file is automatically created when the XML Mapping Utility first parses the source document(s). However, you can manually modify any individual rule to reflect structures not accurately reflected in the source documents.You can add rules, add mappings, delete rules, view sample messages, and so on.

There are several ways to modify the mapping rules file:

Choose menu commands in the Rules Tree panel. See Working in the Rules Tree Panel. Set rule profile values in the Rule Profile panel. See Working in the Rule Profile Panel. Set fields in the Settings panel. See Working in the Settings Panel. Use drag-and-drop to map application GUI components to rules in the Rules Tree panel. See Manually Mapping GUI Components and Input Mappings.

Working in the Rules Tree Panel The rules tree in the Rules Tree panel reflects the structure and order of the information being transformed---inputs that are being created to send to a remote service and outputs that will be processed to update information in General Interface applications. The source documents used to generate the rules tree, which are typically WSDLs and Schemas, define the structure of the rules tree. However, requirements do change and some interactions simply don't involve WSDL/SOAP.

In these situations, the tools in the Rules Tree panel help you manage the structure and relationship for each rule, including reordering rules using drag-and-drop, adding new rules, cloning existing rules, and removing existing rules.

Reordering Rules Because the rules tree is an execution tree, the order of the rules defines the order of execution. More specifically, the rules are traversed by depth and then breadth.

To reorder a rule, simply drag and drop it to a new location in the tree.

Copyright © TIBCO Software Inc. All Rights Reserved. 92

Adding Rules To add a rule to the rules file, right-click a rule in the rules tree and choose Add New Rule. Then choose a command from the submenu, such as Element, Attribute, or CDATA. Once you've created a rule, you can modify the profile in the Rule Profile panel. See Working in the Rule Profile Panel.

Cloning Rules It's also possible to clone any node in the rules tree, including its descendant content. To clone a rule, right-click a rule in the rules tree and choose Clone.

Deleting Rules If you only need to work with some of the rules that were automatically generated when the source document(s) were parsed, you can delete the unnecessary rules to reduce the clutter in the Rules Tree panel. Reducing the rules in the tree also optimizes the rules file for the web as it only contains necessary rules. This optimized rules file is a key advantage to using the XML Mapping Utility instead of the more verbose WSDL file. Note that deleting rules doesn't affect the source document.

To delete a rule and all of its children from the rules tree, select the rule(s) you want to delete and choose Delete > Selected Rules.

To delete all unselected sibling rules from the rules tree, select the rule(s) you don't want to delete and choose Delete > Unselected Sibling Rules.

Use Ctrl+click or Shift+click to select multiple rules.

Regenerating Rules The ability to reparse rules is helpful if you've deleted a rule by mistake or you want to remove the rule settings. Often, minor changes to the source WSDL can be handled by downloading a copy of the updated WSDL and replacing the local copy that you used to create the original rules file. Then, right-click the parent rule in the rules tree. Choose Reparse to re-parse from that rule down. When the Reparse Selected Branch dialog displays, click the Reparse button to reparse the rule. The rule is returned to its original state and all mappings are lost.

In some situations the reparse will fail. If that occurs, select the rule in the rules tree, choose the Rule Node Profile radio button, and write your own XPath in the Source Path field to recreate the binding between the rule in the rules tree and the Schema definition in the source document from which it originates.

For example, if you parse the default WSDL Address.wsdl, the ReturnCityState element maps to the Schema node at this address:

//jsx3:schema[@targetNamespace='http://ws.cdyne.com/']//jsx3:element[@name='ReturnCityState']

The above address is brittle, because if an additional element is added to the Schema, it can corrupt the absolute addressing. In such a case, simply edit the XPath to use an XPath address that is less brittle. For example,

//jsx3:element[@name='ReturnCityState']

Copyright © TIBCO Software Inc. All Rights Reserved. 93

When authoring your own XPath for a WSDL document, use the jsx1 prefix to point to any node in the source document belonging to the namespace, http://schemas.xmlsoap.org/wsdl/. Use jsx3 to resolve to the namespace, http://www.w3.org/2001/XMLSchema. For all other source document types (XHTML, Schema, XML, etc), the prefix is an incremented value (jsx1, jsx2, jsx3, etc) that reflects the order in which the namespace was first declared in the source document.

Adding Mappings Rules that descend from input or output rules can be mapped to GUI components, as well as to CDF documents, records, and attributes. For example, you can map user input in a text field to a rule in your rules file and then send this data to a web service in the outgoing message. Incoming data from the web service can then be mapped to a CDF document, allowing the server's response to be displayed in the user interface.

There are several ways to add mappings:

Drag and drop a GUI component from the Component Hierarchy palette to a rule in the Rules Tree panel. See Mapping GUI Components to Mapping Rules. Select a rule and create a mapping using the Map menu. See Mapping Response Data to CDF GUI Components. Select a rule and set the mapping in the Mapping table in the Settings panel. See Adding a Mapping to the Mappings Table.

For more information on mapping types, see Message Rules.

Detaching Mappings, Restrictions, and Headers You can remove existing mappings, restrictions, and headers from a rule in the Rules Tree panel. This is useful if you've made an error or you want to reduce the size of your rules file.

To remove mappings from a rule, select one or more rules that have a mapping and choose Detach > Mappings. Rules that have mappings are indicated with a Mapping icon . Mappings are displayed in the Settings panel on the right.

To remove restrictions from a rule, select one or more rules that have restrictions and choose Detach > Restrictions. Rules that only have maxoccur and minoccur restrictions don't have an icon in the rules tree. Rules that have additional restrictions are indicated with a Restriction icon . Restrictions are displayed in the Settings panel on the right.

Use Ctrl+click or Shift+click to select multiple rules.

To remove HTTP headers from a rule, select an operation rule that has HTTP headers and choose Detach > Headers. HTTP headers are displayed in the Settings panel on the right.

Working in the Rule Profile Panel After the physical structure of the rules tree is defined, you can use the Rule Profile panel to define attributes for a rule, such as the node name and target namespace.

To modify the rule profile in the rules tree, do the following: Copyright © TIBCO Software Inc. All Rights Reserved. 94

To modify the rule profile in the rules tree, do the following:

1. Select the rule you want to modify in the Rules Tree panel. 2. Select the Rule Node Profile radio button below the Rules Tree panel. 3. Click in the Value field next to the name you want to modify. 4. Type in a value. 5. Generate a test message to test the impact of changes to the rule profile. To generate a test message, right-click an input or output rule in the Rules Tree panel and choose Generate Sample Message.

For field definitions, see Rule Node Profile.

Working in the Settings Panel The most significant step in the mapping process is to create the actual mappings for each rule. To add and remove mappings, use the Settings panel, which provides a unique set of settings appropriate to the type of rule. For example, operation rules allow you to define the endpoint URL where an outbound request will be sent. Some of the most common settings can be set using shortcut methods in the Rules Tree panel. For more information, see Adding Mappings and Detaching Mappings, Restrictions, and Headers.

The Settings panel only displays fields pertinent to the selected rule. These four types of rules display fields in the Settings panel:

Operation or transaction rules Input rules Output rules Message rules

Modifying Operation Rules When you select an operation rule in the Rules Tree panel, the Settings panel displays the fields Endpoint URL, Method, and HTTP Headers.

Copyright © TIBCO Software Inc. All Rights Reserved. 95

For more information on these fields, see Operation Rules.

Using the SCRIPT Transport Method for JSON The default transport method for the XML Mapping Utility is POST. Other transport methods are supported, however, including a JSON-specific transport named SCRIPT.

When you use the SCRIPT method, the XML Mapping Utility uses a SCRIPT tag for the transport instead of the standard XMLHTTP control.

With the SCRIPT method, you can set an additional field to specify that the service uses JSONP (JSON with padding). When this field is set, the service class appends an additional parameter to the URL in the form

callback={method}

where {method} is a temporary callback function managed by the Service instance.

This allows for flexibility when using JSON Services that are also available as JSONP Copyright © TIBCO Software Inc. All Rights Reserved. 96

This allows for flexibility when using JSON Services that are also available as JSONP Services---you can use the same endpoint URL, but implement different behaviors. If the given JSONP Service expects the name of the callback parameter to be something different than callback, use the runtime API call, setJSONP, to pass the parameter name that is expected by the given JSON Service.

For example, Yahoo! Pipes supports the parameter name "_callback" for its implementation of JSONP. Therefore, when calling Pipes, make sure to set the true name of the callback before sending the request:

objService.setJSONP("_callback"); objService.doCall();

Note that the following two statements are equivalent, because the default JSONP name used by the system is " callback ":

objService.setJSONP(true); objService.setJSONP("callback");

You can also implement a callback of your own by directly modifying the endpoint URL to call the named function. In such situations, pass false to this method, so that the transport will not attempt any form of automated callback.

If you implement your own callback handlers, you must manually conclude the service call with a call to the Service method doRespond, by passing the JSON object returned from the Service back to the mapper.

Modifying Input Rules Input rules, also known as requests, can be modified in the Settings panel. To modify input rules, select an Input (request) rule in the Rules Tree panel. The Settings panel displays the following fields: Stub URL, Stub Path, and onBeforeSend.

Copyright © TIBCO Software Inc. All Rights Reserved. 97

For more information on fields in the Settings panel, see Input Rules.

Stub URL To enable the Stub URL field, click the Enable button next to the field.

The Stub URL field is typically used in conjunction with the Stub Path field to support SOAP-based web services. When SOAP is used, each request document is encapsulated by a SOAP Envelope. The XML Mapping Utility treats the Envelope as a static document into which the actual request is placed. For example, the default stub used by the XML Mapping Utility is as follows:

This document is generic enough to encapsulate the majority of SOAP messages and it's recommended that you use it.

However, if this default document does not contain enough information, you can specify the URL for a static stub of your own. For example, you might also need to include a SOAP Header in addition to a SOAP Body element in the Envelope.

Copyright © TIBCO Software Inc. All Rights Reserved. 98

The Stub URL value can be updated at runtime using the API call, setOutboundStubURL. If more control is needed over the stub document and its structures, you can provide a parsed jsx3.xml.Document instance of your own by calling the setOutboundStubDocument() method.

Stub Path When the stub document changes, it is often necessary to update the Stub Path to reflect the XPath address for the node in the Stub document to which the message will be appended. To enable the Stub Path field, click the Enable button next to the field.

Use the Stub Path field in conjunction with the Stub URL field. Type in a valid XSL query that describes where to place the generated document in the Stub document. For example, the following document is generated when the GetHistoricalQuotes operation is called in the WSDL Mapping 2 sample:

ibm,yhoo,goog,tibx Symbol 3-21-06

The combination of the default Stub URL(GI_HOME_/GI_Builder/JSX/stubs/soap.xml) and Stub Path(/SOAP-ENV:Envelope/SOAP-ENV:Body) results in the following document being sent:

ibm,yhoo,goog,tibx Symbol 3-21-06

This value can be updated at runtime using the API call, setOutboundStubPath. onBeforeSend Enter one or more JavaScript statements in this field to execute immediately before the request message is sent. For example, if you want to output the XML request to the System Log before sending it, you enter the following statement, where the keyword, this, refers to the jsx3.net.Service instance:

jsx3.log(this.getOutboundDocument().getXML());

Copyright © TIBCO Software Inc. All Rights Reserved. 99

Modifying Output Rules Output rules, also known as responses, can be modified in the Settings panel. To modify output rules, select an Output (response) rule in the Rules Tree panel. The Settings panel displays the following fields: Stub URL and onAfter Receive.

For more information on fields in the Settings panel, see Output Rules.

Stub URL The XML Mapping Utility provides a static mode that allows you to test against a typical service response. This is useful in situations where the service isn't built yet or is inaccessible. Use the Stub URL field to specify an XML document that contains a response for testing purposes.

To use the static mode feature, complete these steps:

1. Save a valid XML document (the typical response) and enter the URL in the Stub URL field. 2. Do one of the following to set the static mode: Choose Project > Project Settings and change the Mode option on the Deployment panel of the Project Settings dialog from Live to Static, and refresh the browser to reload the project. See Deployment Panel. Call setMode(0) on the jsx3.net.Service instance to make only that instance run in static mode while leaving the remainder of the project in live mode.

Now when transactions are run by a service, a request isn't sent. Instead the sample document is processed as if the remote service returned it. Copyright © TIBCO Software Inc. All Rights Reserved. 100

is processed as if the remote service returned it.

This URL can also be set at runtime using the API call, setInboundURL. onAfterReceive JavaScript statements entered in the onAfterReceive field execute immediately after the response message is received and before the mappings are applied. This script executes in context of the Service instance. This means that the keyword, this, refers to the Service instance. For example, if you want to output the XML response to the System Log palette each time the service responds, you could write: jsx3.log(this.getInboundDocument().getXML()); onAfterReceive multiRef Example Another example might be converting a multiRef format to a supported XML Mapping Utility format. This involves writing custom XSLT and running the XSLT on the incoming document to convert a multiRef formatted document to a concrete structure that the XML Mapping Utility understands. The custom XSLT might look similar to the following:

To implement the above transformation, assume the above stylesheet is named multiRefConverter.xsl. You would enter the following code in the onAfterReceive field for your given operation:

/* get the document just returned from the service */ var myXML = this.getInboundDocument();

/* load the xslt that will convert the axis multiref structure to a more concrete/literal format */ var myXSL = (new jsx3.xml.XslDocument()).load("multiRefConverter.xsl");

/* transform xml to filter */ var newXML = myXSL.transformToObject(myXML);

/* replace the server's document with the new, transformed document */ this.setInboundDocument(newXML);

Copyright © TIBCO Software Inc. All Rights Reserved. 101

Modifying Message Rules Message rules are rules that are included in the actual message structure and are identified by the following icons and types:

Element Complex Attribute CData

When a message rule is selected in the Rules Tree panel, the Settings panel displays a Mappings table, a Restrictions table, and a Repeat When field.

For more information on fields in the Settings panel, see Message Rules.

Adding a Mapping to the Mappings Table To add a mapping to the Mappings table, complete the following steps:

1. Select a message rule in the Rules Tree panel to display the Mappings table in the Settings panel. 2. Click the down arrow in a blank Type field of the Mappings table and select a type, such as DOM. 3. Type a value in the Value field, if required. For example, if you selected DOM, type the component object name. A Mapping icon now displays next to the rule in the rules tree.

Copyright © TIBCO Software Inc. All Rights Reserved. 102

For more information on mapping types, see Mappings.

For more information on mapping GUI components, see Mapping GUI Components to Mapping Rules.

For information on mapping response data, see Mapping Response Data to CDF GUI Components.

Restrictions When Schema or WSDL are used as the input, any restrictions in the input source file display in the Restrictions table of the Settings panel. Rules that have restrictions are indicated with a Restriction icon in the rules tree.

You can also add restrictions on a rule. For example, you might restrict user input to a five-digit number for a field that requires a zip code. To add a restriction:

1. Select a message rule in the Rules Tree panel to display the Restrictions table in the Settings panel. 2. Click the down arrow in a blank Type field of the Restrictions table and select a type, such as maxLength. 3. Type a value in the Value field, such as 5. This would limit user input to a maximum of five characters.

For more information on restriction types, see Restrictions.

Repeat When The Repeat When field is only applicable to outbound (input) messages. Enter one or more JavaScript statements in the Repeat When field. As long as this field evaluates to true, this specific rule is rerun.

The Repeat When field is typically used by mapping rules that convert a JavaScript array into an XML Node-set in the outgoing message. Conceptually, this feature is similar to a do-while loop, where execution will happen at least once and continue as long as the while (Repeat When) statement is true.

If your mapping rule was originally created from a source WSDL, you can easily identify message rules that are part of a collection by looking at the Restrictions table. The rule is a good candidate for using the Repeat When field if it declares a maxLength restriction with a value of unbounded, *, or greater than 1.

Example 1 For example, if you write a function similar to this:

Copyright © TIBCO Software Inc. All Rights Reserved. 103

window.iii= 1; window.getNext = function() { window.iii = window.iii+1; return window.iii<=3; }

and enter a call to the function in the Repeat When field for an addressToCheck rule in the WSDL Mapping 1 sample:

window.getNext();

the JavaScript code iterates through the function three times and three records are added to the XML message for the rule. This sample message shows the three added records.

*???* *???* *???*

Example 2 Another example might be if you have an array of ids that you need to send to a server. You can include a Repeat When statement, so that the XML Mapping Utility knows how to iterate through this array. For example, the given web service might expect the following XML, where the id field repeats to contain as many ids as necessary:

A simple approach is to use the Array.shift() method on a Script mapping that you will bind to the id rule. For example, if you have a global array named myArray, the Script mapping for the id rule would look like this:

setValue( myArray.shift() );

Now, place the following in the Repeat When field.

myArray.length > 0

Because the shift method will remove the array element as soon as it is read, you can be certain that the XML Mapping Utility will only loop as many times as it has array elements. This results in only one node in the outgoing message for each item in the array:

Copyright © TIBCO Software Inc. All Rights Reserved. 104

a b c

Also note that CDF mappings automatically repeat when necessary. For more information on CDF GUI components, see Mapping Response Data to CDF GUI Components.

Viewing Sample Messages After you've modified your rules file, it's helpful to see the sample messages that are generated. This is a quick way to determine if your messages are written as you expect. You can view the default sample message or you can test the service and see the actual messages with the data.

To view a sample message, select an Input (request) rule or an Output (response) rule and choose Sample Message.

To test the service, see Testing Outbound and Inbound Messages.

Copyright © TIBCO Software Inc. All Rights Reserved. 105

Mapping GUI Components to Mapping Rules

Before your application can communicate with a data service, you must define mappings between application objects and data elements. These mappings allow data exchange between application GUI objects and a data service. For example, a user might enter stock symbols in a text field of an application and click a button to request financial data. After receiving the request, the data service would send a response to the appropriate GUI objects, such as text fields or a Matrix, to display the financial data for the requested stocks.

Mapping GUI components to mapping rules involves two steps:

1. Create the mapping rules file. See Creating Mapping Rules Files. 2. Define mappings in the rules file to map GUI components to data elements.

There are two ways to define mappings in the XML Mapping Utility:

Manual Mapping See Manually Mapping GUI Components and Input Mappings Automatic Mapping See Automatically Generating GUI Components and Input Mappings.

Manually Mapping GUI Components and Input Mappings After creating the mapping rules file, you need to define mappings between GUI components and the rules in the mapping rules file.

This section uses the General Interface WSDL Mapping 2 sample located in workspace/JSXAPPS/samples/WSDL_Mapping_2. By default, this sample runs in Static Mode, rendering the results of a sample message on screen. To run against the Xignite web service in Live Mode, register for a license key at http://www.xignite.com/xhistorical.asmx?op=xRegister. Then set the project to Live Mode on the Deployment panel of the Project Settings dialog (Project > Project Settings > Deployment) and reload your browser.

To define mappings in the mappings rules file, complete these steps:

1. Expand the operation in the Rules Tree panel that you want to map to see the request and response rules. Then expand the Input (request) child rule. Double-click the rule with the blue down arrow to see the descendant rules. The blue down arrow indicates that there is more content to be mapped. For example, expand the GetHistoricalQuotes operation rule (not singular GetHistoricalQuote*)* in the rules tree. Expand the Input (request) child rule. Double-click the GetHistoricalQuotes rule with the blue down arrow to see its child rules.

Copyright © TIBCO Software Inc. All Rights Reserved. 1.

106

2. Arrange the Component Hierarchy palette and the Rules Tree panel so that components and elements are visible. 3. Drag objects from the Component Hierarchy palette and drop them onto a rule in the Rules Tree panel to bind GUI components to rules. Note that the mapped rule now

displays a Mapping icon in the rules tree. For example, drag the symbol component from the Component Hierarchy palette to the Identifiers rule in the Rules Tree panel of the XML Mapping Utility. A mapping is created between the GUI component and the target rule. Note the following changes in the Settings panel on the right: A mapping is added to the Mappings table on the right and default values are populated. The type of mapping is displayed in the Type column of the Mappings table. The value of the mapping is displayed in the Path/Value column of the Mappings table.

Other types of mappings can be created by selecting a mapping type and typing a value in the Path/Value field. For example, a rule could be mapped to a value specified by a JavaScript method call or to a CDF document, record, or attribute. For information on mapping types, see Message Rules. A Script mapping can be used to specify JavaScript code that manipulates message structure or field data. For more information on this type of mapping, see Using Code with Data Services. Structured rules are typically mapped to CDF documents, records, and attributes. For more information on this type of mapping, see Mapping Response Data to CDF GUI Components. 4. Save the rules file as follows: a. Click the Save button at the top of the XML Mapping Utility.

b. Navigate to the rules folder and type the filename with the .xml extension in the Copyright © TIBCO Software Inc. All Rights Reserved. 4. 107 a.

b. Navigate to the rules folder and type the filename with the .xml extension in the field at the bottom of the dialog. The rules folder is automatically created in your project folder. However, rules files can be stored in any location in the project directory. c. Click Save in the Save File dialog to save the file.

Now that you've defined the mappings between the GUI components and the data exposed by the service, you need to generate the JavaScript function to call the service. Then specify this event in the Execute event of a component, such as a button. To generate the JavaScript code, see Calling a Data Service.

Automatically Generating GUI Components and Input Mappings In addition to manually mapping existing GUI components to rules in the rules tree, it's also possible to generate GUI components and map them automatically. The XML Mapping Utility creates either a Text Box or a Select component, depending on field characteristics.

Automatically mapping GUI components to mapping rules involves several steps:

1. Select a component in the Component Hierarchy palette that is of type jsx3.gui.Block for the container of the GUI components. 2. Create the mapping rules file. 3. Automatically generate GUI components and mappings.

This section uses the General Interface WSDL Mapping 2 sample located in workspace/JSXAPPS/samples/WSDL_Mapping_2. By default, this sample runs in Static Mode, rendering the results of a sample message on screen. To run against the Xignite web service in Live Mode, register for a license key at http://www.xignite.com/xhistorical.asmx?op=xRegister. Then set the project to Live Mode on the Deployment panel of the Project Settings dialog (Project > Project Settings > Deployment) and reload your browser.

Automatically Defining Mapping in Rules Files To automatically generate and map simple GUI components and input mappings, do the following:

1. Select a component in the Component Hierarchy palette that is of type jsx3.gui.Block. This will be the container for the GUI components that will be automatically generated by the XML Mapping Utility. 2. Create the mapping rules files as described in Creating Mapping Rules Files. 3. Expand the operation rule in the Rules Tree panel that you want to map. Then expand the Input (request) child rule. Double-click the rule with the blue down arrow to see its child rules. The blue down arrow indicates that there is more content to be mapped.

If you don't want to map all the child rules to GUI components, use Ctrl+click or Shift+click to select the rules you want to map.

For example, expand the GetHistoricalQuotes operation rule (not singular GetHistoricalQuote*)* in the Rules Tree panel. Expand the Input (request) child rule.

Copyright © TIBCO Software Inc. All Rights Reserved. 3.

108

Double-click the GetHistoricalQuotes rule with the blue down arrow to see the rules.

4. Select Map > DOM (map and create) from the Rules Tree panel menu.

The XML Mapping Utility generates the components and a Mapping icon in the rules tree indicates that a rule is mapped.

5. Save the mapping rules file with the .xml extension.

You can also automatically map and generate simple GUI components for the Output (response) rule.

Now that the mappings between the GUI components and the data exposed by the service are defined, you need to generate the JavaScript function to call the service. Then specify this function in the Execute event of a component, such as a button. To generate the JavaScript code, see Calling a Data Service.

Copyright © TIBCO Software Inc. All Rights Reserved. 109

Calling a Data Service

Mapping rules typically define how to contact a data service and process the input and output messages. To simplify this common use case, the XML Mapping Utility generates the function code that invokes the service, which you add to your project in an included JavaScript file.

Generating Function Code To generate the function code that invokes the service and add it to your application, follow these steps:

1. Double-click the rules file in the Project Files palette to open it in the XML Mapping Utility. 2. Click the Generate button and choose the operation from the drop-down list. This copies the JavaScript code that implements the function to the clipboard. Click OK in the Code Generator prompt. 3. Minimize the XML Mapping Utility and open logic.js or any included JavaScript file in your project. 4. Position the cursor in the JavaScript file and press Ctrl+v to paste the function code into the JavaScript file. The function code has the following format:

Copyright © TIBCO Software Inc. All Rights Reserved. 4.

110

jsx3.lang.Package.definePackage( //the full name of the package to create "eg.service", //name the argument of this function function(service) {

//call this method to begin the service call //(eg.service.callGetHistoricalQuotes();\) service.callOperation_Name = function() { var objService = Server_Name.loadResource("Project_Resource_File_Id"); objService.setOperation("Operation_Name");

//subscribe and call objService.subscribe(jsx3.net.Service.ON_SUCCESS, service.onOperation_NameSuccess); objService.subscribe(jsx3.net.Service.ON_ERROR, service.onOperation_NameError); objService.subscribe(jsx3.net.Service.ON_INVALID, service.onOperation_NameInvalid); objService.doCall(); };

service.onOperation_NameSuccess = function(objEvent) { //var responseXML = objEvent.target.getInboundDocument(); objEvent.target.getServer().alert("Success","The service call was successful."); };

service.onOperation_NameError = function(objEvent) { var myStatus = objEvent.target.getRequest().getStatus(); objEvent.target.getServer().alert("Error","The service call failed.The HTTP Status code is: " + myStatus); };

service.onOperation_NameInvalid = function(objEvent) { objEvent.target.getServer().alert("Invalid","The following message node just failed validation:\n\n" + objEvent.message); };

} );

where Operation_Name is the name of the SOAP operation to invoke and Project_Resource_File_Id is the ID of the rules file. Function names and alert text can be customized. The function, service.call _Operation_Name_Success, is called when the data service responds. Communication between the application and the data service is asynchronous, so this function can be used for notification of a response.

5. Save the JavaScript file.

Copyright © TIBCO Software Inc. All Rights Reserved. 111

Generated Code Package Structure The code generated by the XML Mapping Utility demonstrates how to use packages to encapsulate the callback methods. By using definePackage (as well as defineClass), you can author web pages with the same architectural constructs used in developing the application back-end.

In addition to providing a mechanism for good coding practices, definePackage is also useful because it allows the code to be introspected. This means that when an error occurs in code, a stack trace can be run with relevant information about the call. Without this, only rudimentary error messages provided by the browser are available.

For example, if you were to use definePackage and an error occurred somewhere in your code, the System Log palette would display this information:

10:31:36.431 global (ERROR) - Uncaught Exception: 'xp' is undefined (line: 47, file: file://C:\tibco\gi\GI_Builder.hta) at eg.service#doCallYetAgain() at eg.service#doCallAgain() at eg.service#call()

From the above information, you know that an error occurred on line 47, within the function eg.service#doCallYetAgain(). You also know the order of the call stack and whether it involved static or instance methods. Had you not used definePackage, the output to the error log would look something like this:

10:36:13.443 global (ERROR) - Uncaught Exception: 'xp' is undefined (line: 47, file: file://C:\tibco\gi\GI_Builder.hta) at anonymous() at anonymous() at anonymous()

For more information on how to use General Interface package APIs, see jsx3.lang.Package in General Interface API Reference (Help > API Documentation).

Invoking Function Code To invoke this function code with a component event, enter the fully qualified name of the function into the appropriate field of the Events Editor palette:

1. Select the component in the work area or the Component Hierarchy palette. For example, in the WSDL Mapping 2 sample, select the Query button component. 2. Choose Palettes > Events Editor to open the Events Editor palette. 3. Enter the JavaScript statement that calls the function in the Execute field in the Events Editor palette. Be sure to enter the fully qualified name of the function:

eg.service.callOperation_Name();

For example, in the WSDL Mapping 2 sample, enter:

eg.wsdl2.callGetHistoricalQuotes();

Copyright © TIBCO Software Inc. All Rights Reserved. 3.

112

Mapping Response Data to CDF GUI Components

After receiving response data, you can map elements in the XML response to objects in the application. If the target object is a CDF component, the data must be transformed into CDF to be displayed in your application. A CDF document is created and stored in the local data cache where the component can access it.

Transformation is a two-step process:

1. Map response elements to the equivalent CDF structures. 2. Map GUI components to the CDF structures.

This section uses the General Interface WSDL Mapping 2 sample located in workspace/JSXAPPS/samples/WSDL_Mapping_2. By default, this sample runs in Static Mode, rendering the results of a sample message on screen. To run against the Xignite web service in Live Mode, register for a license key at http://www.xignite.com/xhistorical.asmx?op=xRegister. Then set the project to Live Mode on the Deployment panel of the Project Settings dialog (Project > Project Settings > Deployment) and reload your browser.

Map Response Elements to CDF Equivalents Response elements can be mapped to CDF structures using the XML Mapping Utility. In the WSDL Mapping 2 sample, the GetHistoricalQuotes operation includes a repeating rule in the response message named HistoricalQuote. When a concrete message is processed by this rule, a new CDF record is created for each repeating instance. Then, various fields in the concrete message are appended as attributes to the generated records.

Copyright © TIBCO Software Inc. All Rights Reserved. 113

To map response elements to CDF, complete the following steps:

1. In the Rules Tree panel of the XML Mapping Utility, select the immediate parent of the element that corresponds to a record in the CDF document. In this example, the parent element is GetHistoricalQuotesResult, because it contains the repeating HistoricalQuote elements that will map to records in the CDF document. 2. In the Mappings table of the Settings panel, select CDF Document from the drop-down list in the Type column of the Mappings table. 3. Type a cache ID string for the CDF document in the Path/Value column. For the WSDL Mapping 2 example, type historicals. This value becomes the cache ID of the CDF document, which appears in the Local Data Cache palette after the response is received and inbound mapping logic is applied. If the file exists, it's overwritten. If the file doesn't exist, a new file is created in the cache. In the WSDL Mapping 2 example, the rules file looks like this:

4. Select the element in the Rules Tree panel that corresponds to a record in the CDF document. In the WSDL Mapping 2 example, the element that corresponds to a CDF record is HistoricalQuote, which is the repeating rule. 5. Select CDF Record from the drop-down list in the Type column in the Mappings table. It's not necessary to specify a value in the Path/Value column for this exercise.

Copyright © TIBCO Software Inc. All Rights Reserved. 114

You can also select an element in the rules tree and choose Map > CDF Record.

Although the Path/Value field is not required, it can be used to support recursion or hand off processing to another rule. For example, if there is another rule in your mapping rules file that has a CDF Record mapping, you can enter the jsxid for that rule. To find the jsxid (Rule ID), select the rule that you wish to call and click the Rule Node Profile radio button.

When a repeating rule is mapped to a CDF record, by default the rules file automatically iterates through each corresponding node in the concrete message.

In the WSDL Mapping 2 example, the rules file looks like this:

1. Select an element to map in the Rules Tree panel. For example, select Date. 2. Select CDF Attribute from the Type drop-down list in the Mappings table. 3. Type a string value in the Path/Value field. This value becomes the attribute name in the CDF document. For example, type Date for the Date element.

You can also select an element in the Rules Tree panel and choose Map > CDF Attribute. The attribute name is automatically generated in the Path/Value field.

In the WSDL Mapping 2 example, the rules file looks like this:

4. Follow the same process to create mappings for other elements to include in the CDF document: select the element, select CDF Attribute as the Type, and enter a name for the Copyright © TIBCO Software Inc. All Rights Reserved. 115 4. document: select the element, select CDF Attribute as the Type, and enter a name for the corresponding CDF attribute.

To add multiple CDF attribute mappings at once, use Ctrl+click or Shift+click to select multiple rules and select Map > CDF Attribute in the Rules Tree panel menu.

In the WSDL Mapping 2 example, the rules file looks similar to this:

If the response has nested rules, you can replicate the nested structure using CDF Record and CDF Attribute mappings. The jsxid attribute, which is required in every CDF document, acts as a key. You can map an existing element that acts as a key value, such as a date or other unique value, to jsxid. If no such mapping exists, the XML Mapping Utility automatically adds a jsxid attribute to the CDF document and generates a unique value.

5. Save the mappings file.

Map GUI Components to CDF Equivalents After transforming the XML response to CDF, you need to map the CDF GUI components that will consume CDF data. This example uses a Matrix component to show how to create the mappings.

To map GUI components to CDF elements, complete these steps:

1. Select the top-level GUI object that will consume data in the Component Hierarchy palette. In the WSDL Mapping 2 example, the top-level object is a Matrix component, gridResults, with six columns. 2. Open the Properties Editor palette and specify the name of the cache document for the XML Cache ID property. In the XML Mapping Utility, this is the value in the Path/Value column for the CDF Document mapping. In this example, the value is historicals :

Copyright © TIBCO Software Inc. All Rights Reserved. 2.

116

3. Select the GUI object in the Component Hierarchy palette that will display the data series. In the WSDL Mapping 2 example, the object is a column in the matrix, such as date, security, open, and so on. 4. Open the Properties Editor palette and type the attribute name in the Value field of the Att Name property. In this example, choose date in the Component Hierarchy palette and type Date, the attribute name, in the Att Name field to map the date component to the CDF Date attribute.

5. Repeat the process for other GUI objects until all series mappings are complete: select each object in the Component Hierarchy palette and type the appropriate CDF attribute name in the Value field of the Att Name property.

Next, you need to test the rules file to be sure the mappings are correct. To test the rules file, see Running a Quick Test.

Copyright © TIBCO Software Inc. All Rights Reserved. 117

Testing Outbound and Inbound Messages

The XML Mapping Utility includes features for verifying inbound and outbound messages generated using a rules file. The entire test sequence consists of executing outbound mappings, generating the outbound message, sending the message, receiving the response, and executing inbound mappings. Outbound and inbound filtering logic can also be entered and verified.

The XML Mapping Utility supports one-way (request) and two-way (request/response) messaging for WSDLs. An example of a one-way message is a delete operation sent to the server.

Setting Up a Test To set up a test, specify values for each mapped element to simulate user input. There are two ways to simulate input:

Specify data in user input fields in the work area. Specify values in the Mappings table.

To specify values in the Mappings table, complete these steps in the XML Mapping Utility:

1. Select a rule in the Rules Tree panel. 2. In the Mappings table of the Settings panel, select Script from the drop-down list in the Type column. 3. Type the JavaScript setValue function in the Path/Value column and specify a value, setValue("value_") ; The setValue() method is useful for specifying constants normally specified by a user at runtime or a value that is calculated from user input. 4. When all values are specified, click the Save button.

Running a Quick Test To test your mappings in the rules file, complete these steps:

This section uses the General Interface WSDL Mapping 2 sample located in workspace/JSXAPPS/samples/WSDL_Mapping_2. By default, this sample runs in Static Mode, rendering the results of a sample message on screen. To run against the Xignite web service in Live Mode, register for a license key at http://www.xignite.com/xhistorical.asmx?op=xRegister. Then set the project to Live Mode on the Deployment panel of the Project Settings dialog (Project > Project Settings > Deployment) and reload your browser.

1. In the application work area, appCanvas.xml, simulate user input by entering data in the application. For example, enter stock symbols in the WSDL Mapping 2 example and choose a date. 2. Select an operation rule, such as GetHistoricalQuotes, in the Rules Tree panel of the XML Mapping Utility. Right-click the rule and select Execute (Quick Test).

When the response is received, a file with the specified name displays in the Local Data Copyright © TIBCO Software Inc. All Rights Reserved. 2. 118

When the response is received, a file with the specified name displays in the Local Data Cache palette. This file exists in the cache instance used by the current component. In the WSDL Mapping 2 example, the file name in the Local Data Cache palette is historicals. If you open this file, you'll see the response data from the service. 3. Return to the work area to see the updated information in the mapped component. If the updated information isn't displayed, complete these steps: a. Select the top-level GUI component that consumes the data in the Component Hierarchy palette. In the WSDL Mapping 2 example, select the gridResults component. b. Click the Repaint button in the Component Hierarchy palette.

Test Interface Tool

To use the Test Interface Tool, click the Test button on the Rules Tree panel toolbar. The Test Interface Tool displays.

The Test Interface Tool is designed to guide you through the test sequence. The Create, Send, Receive, and Apply tabs correspond to phases of sending and receiving XML messages. Clicking a tab displays data that is relevant to the current test phase.

Before running a test, you can set breakpoints at various steps in the test sequence or you can also test a rules file without breakpoints. For more information, see Setting Breakpoints.

Copyright © TIBCO Software Inc. All Rights Reserved. 119

Mapper Log You can also use the Mapper Log to view the results of a message exchange. Use the Adjust Log Level button to select a log level before you begin testing.

Running a Test To run a test in the Test Interface Tool, complete these steps:

1. Click the Test button on the Rules Tree panel toolbar to open the Test Interface Tool. 2. Select the operation to test from the Select drop-down list at upper left.

The Create tab displays in the Test Interface Tool.

Copyright © TIBCO Software Inc. All Rights Reserved. 2.

120

The Create tab displays mappings for the outbound message and the following fields: Rule Name contains the name of the element. Type shows the type of object that is mapped. Path/Value contains the GUI component name or any associated JavaScript code for this mapping. Post-Mapping Filter/Handler contains filter code to execute before sending the message. 3. Click the Start Test button next to the Outbound Mappings label to start the test. If you didn't set any breakpoints and there aren't any errors, the test runs and cycles through each tab: Send, Receive, and Apply. When the test is complete the Create tab displays again. 4. If a breakpoint was set, the test advances to the Send tab. For more information, see Setting Breakpoints.

The Send tab displays the outbound message and the following fields: URL contains the URL specified in the WSDL file. HTTP Headers contains header content for the message. The header text can be customized by editing this value.

Name and Password are used for services requiring HTTP authentication. Copyright © TIBCO Software Inc. All Rights Reserved. 4.

121

Name and Password are used for services requiring HTTP authentication. Method defines the method for contacting the Service. The most common are GET and POST.

The contents of the outbound and inbound messages can be saved to local files for testing purposes. By mapping the saved inbound file and specifying the application mode as Static on the Deployment panel of the Project Settings dialog (Project > Project Settings), you can continue developing your application without a data service connection. For more information, see Deployment Panel.

5. If a breakpoint was set, click the Resume button to advance to the next step. The outbound message is sent to the data service, and the response is displayed in the Receive tab. Because the Receive tab doesn't have a breakpoint, the test continues to the Apply tab. Click the Receive tab to see the response.

The Receive tab displays the following fields: HTTP Headers contains the HTTP headers. HTTP Status contains the message status, such as 200. Response contains the response. If the response isn't received, testing can still proceed with a simulated response

message. Click the Generate Alternate Inbound Message button to the left of the Response field. A response message for the specified operation is copied to the Response field. 6. If the Test Interface Tool doesn't automatically advance to the Apply tab, click the Apply tab to advance to the next step.

Copyright © TIBCO Software Inc. All Rights Reserved. 6.

122

The Apply tab displays the following fields: Pre-Mapping Filter/Handler contains filter code to execute on the inbound document. Inbound Mappings contains mappings of response rules to GUI components and inbound filtering logic, if any.

This is the final step in the testing process. If filtering logic and mappings executed without errors, the Create tab displays to allow you to start another testing cycle.

For a step-by-step example of running a test with the Address Lookup example, see Testing Mappings.

Setting Breakpoints Before running a test, you can set breakpoints for viewing request and response messages at each step in the process. Breakpoints can be set at the following steps:

Before applying filtering code, if specified, to the outbound message Before sending the outbound message to the data service Before applying filtering code, if specified, to the inbound message Before executing inbound mappings

You can also test a rules file without breakpoints. However, it is usually helpful to view the test results after each step. When advancing from one breakpoint to the next, you can return to the previous breakpoint to retest only that step in the process. After modifications to mapping rules, changes can be tested from the last breakpoint.

To set a breakpoint and run a test with breakpoints in the Test Interface Tool, complete these steps:

1. Click any tab that displays a Breakpoint button , such as the Create, Send, or Apply tab. 2. Click a Breakpoint button to set a breakpoint. 3. Click the Create tab and run the test as described in Running a Test. The test stops at any step that has a breakpoint set. 4. Click the Resume button to advance to the next step.

Copyright © TIBCO Software Inc. All Rights Reserved. 123 4. Click the Resume button to advance to the next step.

Setting Filters Filters can be applied to messages before an input message (request) is sent or after an output message (response) is received and before the mappings are applied. This is useful when you want to modify requests and responses.

You can enter JavaScript code to run as a filter on message rules. There are two ways to set a filter for message rules:

Input message rules Post-Mapping Filter/Handler field Enter JavaScript code in this field on the Create panel of the Test Interface Tool to filter the input message during testing. onBeforeReceive field Enter JavaScript code in this field of the Settings panel of the XML Mapping Utility. Code entered in this field is always run on the message. Note that code entered here is also automatically displayed on the Create panel of the Test Interface Tool and runs during testing. Output message rules Pre-Mapping Filter/Handler field Enter JavaScript code in this field on the Apply panel of the Test Interface Tool to filter the output message during testing. onAfterReceive field Enter JavaScript code in this field of the Settings panel of the XML Mapping Utility. Code entered in this field is always run on the message. Note that code entered here is also automatically displayed on the Apply panel of the Test Interface Tool and runs during testing.

Filters are useful for manipulating input and output messages as they travel between the client and the server. For example, the XML Mapping Utility doesn't support multiRef structures that are sometimes used to describe SOAP messages on Apache Axis servers. However, you can use the onAfterReceive event handler to manipulate the output message from the server before running the inbound mapping rules. Since you can't control your server environment, you could write an XSLT that would convert the multiref indirection to a supported XML Mapping Utility format. This transformation would occur on the client after the message is received. For more information on this multiRef example, see onAfterReceive multiRef Example.

Further Information For more tutorials and sample applications, see:

General Interface samples — workspace/JSXAPPS/samples Developer Network at http://www.generalinterface.org Sample Projects Video Tutorials

Handling Errors and Timeouts

Setting Timeout Intervals You can configure timeout intervals for a web service response using the setTimeout method on the Service instance. For more details, see the description of this method in the General Interface API Reference in General Interface Builder (Help > API Documentation).

Copyright © TIBCO Software Inc. All Rights Reserved. 124

Handling Errors When an operation generates an error, the error information is returned to the Request object for the response. You can write a JavaScript function that gets the error information, adds business logic for handling the error scenario, and displays the error to the user.

When errors occur, they can take several forms:

HTTP errors can be determined by calling getRequest on the Service instance and then querying the jsx3.net.Request object for its status (getStatus) and status description ( getStatusText). SOAP faults can be processed by mapping to the fault rules that are created by the XML Mapping Utility when the WSDL is parsed (assuming the WSDL defines them). Formatting errors, such as a string in a number field or an enumerated value not being entered, can be determined by subscribing to the ON_INVALID subject for the service instance. When an error is encountered during message generation, the specified callback function is notified. JavaScript errors display in the System Log palette for General Interface Builder.

Copyright © TIBCO Software Inc. All Rights Reserved. 125

Chapter 6 Communicating with a Web Service Tutorial

This tutorial demonstrates how to use a General Interface application to communicate with a web service.

About the Web Services Tutorial Creating the Mapping Rules File Defining Mappings Generating Function Code Invoking Function Code Testing Mappings Further Information on Tutorials and Sample Applications

About the Web Services Tutorial

This tutorial demonstrates how to use the XML Mapping Utility to map GUI components in an application to exposed data elements in a web service using the example application you created in General Interface Getting Started.

The example application allows a user to input a zip code and click a button to send the zip code data to the web service. The web service receives the user input and sends a response that returns the matching city and state.

The example application is also available as a General Interface sample. To open the sample, choose Project > User Projects > Samples > WSDL_Mapping_1.

Before you begin this tutorial, you must create the application in General Interface Getting Started.

In this tutorial, you'll complete the following tasks:

1. Create a mapping rules file that defines mappings between application objects and data elements. 2. Define mappings in the mapping rules file. 3. Generate the function code that calls the web service. 4. Invoke the function code. 5. Test the mappings.

For more information on mapping and the XML Mapping Utility, see Communicating with Data Services.

For an introduction to the General Interface Builder user interface, see General Interface Getting Started.

Copyright © TIBCO Software Inc. All Rights Reserved. 126

Creating the Mapping Rules File

Mapping rules files are XML files that define mappings between application objects and data elements. The XML Mapping Utility provides a simple drag-and-drop interface for creating mappings.

Rules files use the Common Exchange Format (CXF) for translating between application formats and web services. For information about CXF, see Common Exchange Format (CXF).

To create the mapping rules file, complete the following steps:

1. Create the application described in General Interface Getting Started. 2. Start General Interface Builder and open the myAddressLookup project. For information on starting General Interface Builder, see General Interface Getting Started. 3. Navigate to your project folder in your file system and create a wsdl folder in your project folder: workspace/JSXAPPS/myAddressLookup/wsdl. 4. Navigate to your General Interface installation in your file system and copy Address.wsdl from GI_HOME/GI_Builder/plugins/jsx3.ide.mapping/wsdl to workspace /JSXAPPS/myAddressLookup/wsdl. 5. Select File > New > Mapping Rule in General Interface Builder to open the XML Mapping Utility. 6. Select the WSDL radio button, remove the existing URL in the URL field, and enter wsdl/Address.wsdl. Click the Parse Document button.

After you click the Parse Document button, you see the Rules Tree panel as shown here:

Copyright © TIBCO Software Inc. All Rights Reserved. 6.

127

Defining Mappings

In this step, you'll define mappings between the GUI components of the myAddressLookup application and the data exposed by the web service.

The Address.wsdl file used in the myAddressLookup project defines several operations. Because you only use one operation for the myAddressLookup application, ReturnCityState , you can remove all other operations for the rules file as they aren't needed.

Defining Mappings for Input Data To define mappings between the GUI components and the input (request) data, complete these steps:

1. Select the ReturnCityState operation in the Rules Tree panel. Confirm that it's the correct rule by reading the Schema source in the pane below: 2. Delete all other operations by selecting Delete > Unselected Sibling Rules. 3. Arrange the Component Hierarchy palette and the Rules Tree panel so that components and mapping rules are visible. 4. Create a mapping between the txtZipcode component and the zipcode rule as follows: a. Expand the ReturnCityState rule in the Rules Tree panel. b. Expand the Input (request) rule and double-click the ReturnCityState child rule. The ReturnCityState request has two input rules: zipcode and LicenseKey. c. Drag the txtZipcode component from the Component Hierarchy palette to the zipcode rule in the Rules Tree panel. The following mapping is created in the Copyright © TIBCO Software Inc. All Rights Reserved. 4.

128 c. zipcode rule in the Rules Tree panel. The following mapping is created in the rules tree.

Notice in the Mappings table to the right that the Type is DOM (Document Object Model), representing a mapping between a GUI component and a rule in the rules tree. The value is txtZipcode, the name of the GUI component.

Next, you'll use the setValue() method to set the license key value to use the evaluation license ("0"). The evaluation license provides limited access to the service during testing. If the designated number of requests is exceeded, an error is returned. 5. Set the value for the license key as follows: a. Click the LicenseKey rule in the Rules Tree panel. b. Select Script from the drop-down list in the Type column of the Mappings table.

c. Type the following in the Path/Value field of the Mappings table:

setValue("0");

Copyright © TIBCO Software Inc. All Rights Reserved. 5.

c. 129

Because the license key value, zero, is a JavaScript string, it must be enclosed in quotation marks.

Defining Mappings for Output Data To define mappings between the application GUI components and the return (response) data, complete these steps:

1. Expand the Output (response) rule and double-click the ReturnCityStateResponse rule. 2. Double-click the ReturnCityStateResult rule to expand it to see all the children. You'll only use two of the output rules: City and StateAbbrev. 3. Select the output rules City and StateAbbrev, and delete all other operations by selecting Delete > Unselected Sibling Rules. 4. Drag the txtCity component from the Component Hierarchy palette and drop it on the City rule in the Rules Tree panel. 5. Drag the txtState component from the Component Hierarchy palette and drop it on the StateAbbrev rule in the Rules Tree panel. 6. Save the rules file as follows: a. Click the Save button at the top of the XML Mapping Utility. b. Open the rules folder in the Save File dialog and type GetCityandState.xml in the field at the bottom of the dialog. c. Click Save to save the file.

Now that you've defined the mappings between the GUI components and the data exposed by the service, you need to generate the JavaScript function to call the service. This is the same function that is defined for the button's Execute event in General Interface Getting Started.

Generating Function Code

A rules file defines the interaction between your application and the data service. Once the rules file is complete, the application also needs to invoke the service. The XML Mapping Utility generates the function code that invokes the service, which you add to your project in an included JavaScript file.

Recall that in one of the last steps of the "Creating an Application" tutorial in General Interface Getting Started, you configured the Find City and State button to execute the JavaScript function eg.service.callReturnCityState();. In this section, you generate the function code and add it to your project.

To generate the function code that invokes the web service, complete these steps:

1. Click the Generate button next to the Delete button in the XML Mapping Utility and choose ReturnCityState from the drop-down menu in the Rules Tree panel menu. Resize the Rules Tree panel if you don't see the button. The JavaScript code for invoking this operation is copied to the clipboard. The code defines a JavaScript function that creates a service instance. The service instance uses the rules file to create the XML request document as well as process the service's XML response document.

2. Click OK in the Code Generator prompt, which displays a message that the JavaScript Copyright © TIBCO Software Inc. All Rights Reserved. 130

2. Click OK in the Code Generator prompt, which displays a message that the JavaScript code has been copied to the clipboard. 3. Click the Minimize button in the XML Mapping Utility. 4. Click the logic.js tab in the General Interface Builder work area. This file contains business logic for your application. It should be empty except for a comment line. 5. Delete the comment line and press Ctrl+v to paste the contents of the clipboard into logic.js. The JavaScript code in the logic.js file should look like the following:

jsx3.lang.Package.definePackage( "eg.service", //the full name of the package to create function(service) { //name the argument of this function

//call this method to begin the service call //(eg.service.callReturnCityState();\)

service.callReturnCityState = function() { var objService = myAddressLookup.loadResource("GetCityandState_xml"); objService.setOperation("ReturnCityState");

//subscribe and call objService.subscribe(jsx3.net.Service.ON_SUCCESS, service.onReturnCityStateSuccess); objService.subscribe(jsx3.net.Service.ON_ERROR, service.onReturnCityStateError); objService.subscribe(jsx3.net.Service.ON_INVALID, service.onReturnCityStateInvalid); objService.doCall(); };

service.onReturnCityStateSuccess = function(objEvent) { //var responseXML = objEvent.target.getInboundDocument(); objEvent.target.getServer().alert("Success", "The service call was successful."); };

service.onReturnCityStateError = function(objEvent) { var myStatus = objEvent.target.getRequest().getStatus(); objEvent.target.getServer().alert("Error","The service call failed. The HTTP Status code is: " + myStatus); };

service.onReturnCityStateInvalid = function(objEvent) { objEvent.target.getServer().alert("Invalid","The following message node just failed validation:\n\n" + objEvent.message); };

} );

After the Find City and State button is clicked and the web service is called, the function displays an alert dialog containing the text The service call was successful.

6. Right-click the logic.js tab and select Save and Reload. Copyright © TIBCO Software Inc. All Rights Reserved. 131

6. Right-click the logic.js tab and select Save and Reload. This command saves the file with the modified contents and also loads the file into memory, making the methods available without requiring the browser window to be refreshed.

Invoking Function Code

In the "Creating an Application" tutorial in General Interface Getting Started, you added an Execute event for the Find City and State button in the Events Editor palette. The JavaScript statement you added invokes the function code that you just created.

Confirm that you entered the JavaScript statement that calls the function that invokes the web service.

1. Click the appCanvas.xml tab to return to the application. 2. Select the btnLookup button in the Component Hierarchy palette. 3. Choose Palettes > Events Editor to open the Events Editor palette. 4. Confirm that the following JavaScript statement is entered in the Value field of the Execute event in the Events Editor palette:

eg.service.callReturnCityState();

Next, you'll test the outbound and inbound messages.

Testing Mappings

The XML Mapping Utility includes features for verifying inbound and outbound messages generated using a rules file. The entire test sequence consists of executing outbound mappings, generating the outbound message, sending the message, receiving the response, and executing inbound mappings. Outbound and inbound filtering logic can also be entered and verified.

To test the address example, complete these steps:

1. Simulate user input by manually typing a valid 5-digit or 9-digit zip code in the Type Zip Code field in the work area. For example, type 11357 in the Type Zip Code field. 2. Select the LicenseKey input rule in the Rules Tree panel in the XML Mapping Utility. Confirm that you selected Script as the Type and entered setValue("0") in the Path/Value column of the Mappings table. If you haven't, refer to the instructions in Defining Mappings.

Copyright © TIBCO Software Inc. All Rights Reserved. 2.

132

3. Click the Test button on the XML Mapping Utility toolbar to open the Test Interface Tool. 4. Select ReturnCityState from the drop-down list at upper left. 5. Before testing the mappings, insert breakpoints for viewing request and response messages at each step in the process. a. Click the Send tab and click the Pause Before Sending the Message button to insert a breakpoint. b. Click the Apply tab and click the Pause Before Executing Inbound Mappings button next to the Inbound Mapping header to insert a breakpoint. 6. Click the Create tab. The Outbound Mappings panel lists the bound request parameters and mapping information.

7. Click the Start Test button next to the Outbound Mappings header to begin testing the mappings. When the message is generated, the message displays in the Send tab.

8. Verify the message matches the following:

Copyright © TIBCO Software Inc. All Rights Reserved. 8.

133

11357 0

The zip code you specified in the dialog should display as the contents of the jsx1:zipcode element. For example,

11357

If the message code is incorrect, return to the XML Mapping Utility and verify that bindings are correctly specified before proceeding. 9. Click the Resume Test (Send Message) button next to the URL field. The outbound message is sent to the web service. When a response is received, the message displays in the Receive tab and the XML Mapping Utility automatically advances to the Apply tab. 10. Click the Receive tab to view the inbound message. City and state information is returned in the City and StateAbbrev elements. However, this data has not yet been bound to any text boxes. If you view the application in the work area, the City and State fields are still blank.

11. Click the Apply tab. The Test Interface displays inbound mappings to text boxes.

Copyright © TIBCO Software Inc. All Rights Reserved. 11.

134

12. Click the Resume (Execute Inbound Mappings) button next to the Inbound Mappings header. In the work area, you can see that inbound mappings are applied to text boxes. The City and State fields have a blue background because the fields are disabled. This is to prevent users from entering data in these fields.

The testing cycle for this data service configuration is complete, and the XML Mapping Utility cycles back to the Create tab.

This concludes the tutorial. For other examples of connecting to web services, see samples in workspace/JSXAPPS/samples and on the Developer Network at http://www.generalinterface.org.

Further Information on Tutorials and Sample Applications

For more tutorials and sample applications, see:

General Interface samples — workspace/JSXAPPS/samples Developer Network at http://www.generalinterface.org Sample Projects Video Tutorials

Copyright © TIBCO Software Inc. All Rights Reserved. 135

Chapter 7 Using CDF Form Mapping Tutorial

General Interface 3.6 introduces a new CDF form mapping class, in jsx3.gui.CDF. This new class enables developers to map a CDF document in the local cache to on-screen form fields.

About CDF Form Mapping Creating the CDF Mapping Container Mapping XML Data to the CDF Container Using the APIs to Set CDF Mapping

About CDF Form Mapping

The CDF form mapping class, jsx3.gui.CDF, enables developers to map a CDF document in the local cache to on-screen form fields.

By combining the features of jsx3.gui.Block and jsx3.xml.Cacheable, this class enables developers to read and write cache data without the need to author additional JavaScript code. In other words, this new class is a visual container that knows how to bind the form fields it contains to values in a CDF document.

Creating the CDF Mapping Container

The CDF Mapping Container is a new control in the Form Elements component library.

To create a new CDF mapping container:

1. Create a new project. 2. Expand the Form Elements folder in the Components Library. 3. Drag the CDF Mapping Container icon to the Component Hierarchy to add the new element to the DOM:

Copyright © TIBCO Software Inc. All Rights Reserved. 3. 136

4. Add two text boxes to the mapping container---drag two text boxes from the Form Element component library to the cdf mapping container, and name them T1 and T2:

5. Look at the Properties Editor for the cdf element---the XML String property contains this Value:

Copyright © TIBCO Software Inc. All Rights Reserved. 5.

137

This is the default test document that is provided with the control. Like all other controls that implement the Cacheable interface, this control will parse this string of XML and set it in the local cache, using a unique ID (or one assigned by the developer if applicable).

6. Open the Local Data Cache, and you'll see that the CDF mapping container has put the _jsx_1_4_XML file there:

7. Double-click the XML file name to open it in the work area, then click the Formatted Source XML button to see the formatted XML:

Mapping XML Data to the CDF Container

Now you'll map the contents of the XML data in cache to the CDF container:

1. Select the text box named T1. 2. In the Properties Editor, type first in the Value field of the CDF Attribute Name. The name john appears in the T1 text box of the CDF mapping container, because the value john is assigned to the attribute first in the XML file.

Copyright © TIBCO Software Inc. All Rights Reserved. 2.

138

3. Click the text box named T2. 4. In the Properties Editor, type middle in the Value field of the CDF Attribute Name. The letter q appears in the T2 text box of the CDF mapping container, because the value q is assigned to the attribute middle in the XML file.

Cursoring CDF Records This exercise illustrates how the CDF mapping container can cursor through its records to display different values in its descendant fields.

1. Open the Local Data Cache and find the CDF document.

The name of this cache document is assigned by the system and is a combination of the CDF GUI control ID and the string "_XML").

2. Double-click the CDF file to open it for editing. 3. Select and copy the record containing CDF attributes. 4. Paste the record into the XML file, then change the record ID to 2, and the name of the attribute first to jane:

5. Right-click the XML file tab and select Save to Cache:

6. In the Properties Editor for the T1 component, change the CDF Record Id value from 1 to 2, to change the name in the T1 text box:

Copyright © TIBCO Software Inc. All Rights Reserved. 6.

139

This exercise illustrates how you can make each form be a separate data store---it always reads the value of the CDF Record Id, regardless of how the CDF control for the form is mapped.

A CDF container can:

Inherit a document from an ancestor CDF, or it can provide its own document. Map the records of an ancestor CDF, or provide its own mapping.

You can continue nesting components inside components in the CDF mapping container, so that each nested component becomes a separate data item. Whichever container is the last in the nested chain determines the final mapping.

Using the APIs to Set CDF Mapping

You can use the General Interface APIs to set mapping for CDF containers. To see the API for a property, hover the mouse cursor over the property name in the Properties Editor.

To use the API to set a property:

1. Open Tools > JavaScript Console. 2. Type the appropriate API syntax and values for the property.

In this example, the T1 text box originally contains the value of CDF record ID 2, which is jane. Using the API setCDFId, we change the T1 text box value from record 2 (jane) to record 1 (john ):

Copyright © TIBCO Software Inc. All Rights Reserved. 140

Chapter 8 Optimizing Application Performance

This chapter discusses best practices for optimizing application performance. Fast performance and a responsive user interface are critical to a good user experience.

For sample applications that demonstrate best practices, visit Developer Network at http://www.generalinterface.org.

Application Design List of Best Practices Faster Load Times JavaScript Code API Usage Components and Component Serialization Files Benchmarking Performance

Application Design

One of the critical phases of software design is application design. When designing your application, it's important to consider the following:

What are the end-user requirements? What tasks will the user need to accomplish? What is the work flow? How easy is the application to use?

Application design includes application architecture, user interface design, and component design. If this phase of application development is neglected, usability and performance can be adversely affected. For example, poor performance can occur if the application has a poorly designed, complicated user interface and if the application uses components that aren't designed properly. While designing your General Interface application, consider the following best practices.

Design Applications to be Asynchronous Whenever possible design your application to use asynchronous loading to improve performance and usability. Use the following techniques:

Load only those areas of the application that are viewable by the user and required for the user to begin using the application. For example, load the tab content for the first visible tab and load content of other tabs only when the user selects the tab. Specify an appropriate load type for your GUI components, such as Paint Asynchronously, Deserialize Asynchronously, and so on. For more information, see General Interface Component Guide. Load GUI components using Referenced - Asynchronous. For more information, see Component Hierarchy Palette Context Menu. Load XML data sources asynchronously. For more information, see General Interface Component Guide.

Load resources asynchronously Copyright © TIBCO Software Inc. All Rights Reserved. 141

Load resources asynchronously Asynchronously load JavaScript files using the jsx3.app.Server.loadInclude() method Asynchronously load an XML document and store it in the local data cache using the jsx3.app.Cache.getOrLoadAsync method Asynchronously load an XML document using the jsx3.xml.Document.setAsync() method Issue a request asynchronously by passing bAsync=true to the jsx3.net.Request.open() method For more information, see General Interface API Reference.

For more information, see General Interface Component Guide.

Reuse Existing Components Loading complex components can be one of the most expensive operations. Reuse components whenever possible instead of removing and recreating General Interface DOM nodes.

There are typically two use cases for reusing components:

1. Changing component properties reuse a component by simply changing a property programmatically, such as a column header or cell width. 2. Showing components intermittently if a component is used intermittently, such as a dialog or a tab, show and hide the component instead of destroying and recreating. However, remember that repainting a component repaints all children, even if they're hidden.

Don't Store Data in Form Elements Storing data in form elements, which is a typical HTML pattern, is not recommended for General Interface applications. Instead of hiding and showing form elements to access data, persist data separately in an XML/CDF document or JavaScript variable. Note that persisting data as XML is recommended, because memory management for XML is better than for JavaScript objects. Once data is persisted, load and unload components as needed without losing data. For example, persist login and username data from a dialog and remove the dialog from the General Interface DOM instead of hiding the dialog.

List of Best Practices

Use these best practices when developing your applications:

Application Design Design Applications to be Asynchronous Reuse Existing Components Don't Store Data in Form Elements Components and Component Serialization Files Eliminate Unnecessary Components Use Matrix and Paging API Usage Minimize Repainting Search Components in the DOM Efficiently Copyright © TIBCO Software Inc. All Rights Reserved. 142

Search Components in the DOM Efficiently Exclude Logging Messages JavaScript Code Remove Unused JavaScript Code Avoid Initializing Unused Variables Replace Old and Deprecated APIs with More Efficient APIs Replace JavaScript Manipulation of CDF with XSL Transformations Use jsx3.net.Service.compile() Avoid Excessive String Concatenations Identify Slow Functions Calls Faster Load Times Upgrade to the latest version of General Interface Upgrade Browsers Load from Cache Split CDF Documents Create Custom General Interface Builds Benchmarking Performance Review Component Statistics Use the General Interface Debug Build Use General Interface Performance Profiler Use JavaScript Profiling Tools Use General Interface Test Automation Kit

Faster Load Times

To improve the load time of your data and application, follow these best practices

Upgrade to the latest version of General Interface To improve application performance, General Interface 3.3 and later uses a configuration flag to disable the forced synchronization (re-fetching) of an XML document by the MSXML3 Document object. Therefore, XML files are retrieved from the browser cache instead of re-fetched from the HTTP server.

General Interface 3.4 includes a more efficient startup mechanism. General Interface 3.4 and 3.5 include significant performance enhancements, especially for Internet Explorer 6.

Upgrade Browsers When possible, use the latest browsers supported by General Interface. Also, as you develop your application, benchmark your application in all browsers and versions used by your end users. Benchmarking in all browsers prevents unexpected performance issues after deployment. For example, Internet Explorer 6 is slower than Firefox.

Note that subsequent Internet Explorer releases are significantly faster than Internet Explorer 6.

Copyright © TIBCO Software Inc. All Rights Reserved. 143

Load from Cache Whenever possible, use the jsx3.app.Model.loadAndCache() method to cache XML GUI components that need to be reloaded multiple times and reload them from the local data cache instead of fetching from the server each time.

Split CDF Documents Split large CDF documents to optimize data load times. For an example, see the Splitting CDF Documents sample at http://www.generalinterface.org.

Create Custom General Interface Builds To improve load performance for your application, you can use the General Interface Load Performance Optimization script to create a custom General Interface build that's optimized for a particular General Interface application. For more information, see Optimizing Load Performance.

JavaScript Code

Use the following best practices when developing JavaScript code for your application.

Remove Unused JavaScript Code Remove unused portions of code to make the JavaScript file smaller, speed up the JavaScript loading time, and make the code run faster.

Avoid Initializing Unused Variables Try to avoid initializing variables that might not be used. Initialize them after checking to see if they are needed. Logging messages, which are only needed during development, are a good example of unused variables.

Replace Old and Deprecated APIs with More Efficient APIs Replace old and deprecated APIs with new, more efficient APIs. For example, use the faster jsx3.xml.Entity.getChildIterator(),getAttributeNames(), and selectNodeIterator() methods instead of getChildNodes(), getAttributes(), and selectNodes() respectively.

Another example is to use jsx3.util.List instead of jsx3.util.Collection. Change the following use of Collection:

for (var i=0;i

to List:

for (var it = objList.iterator();it.hasNext();\){ var x = it.next(); }

Copyright © TIBCO Software Inc. All Rights Reserved. 144

For more information, see General Interface API Reference.

Replace JavaScript Manipulation of CDF with XSL Transformations Replace JavaScript manipulation of CDF with faster, more efficient XSL transformations. For example, if fifty customer records are returned from a jsx3.net.Request response, iterating through all the elements in JavaScript is less efficient than building an XSL template and applying it using the jsx3.xml.Template API.

GUI components that implement jsx3.xml.Cacheable have built-in properties for XSL transformations. See the XML Transformers property in the Properties Editor palette and jsx3.xml.Cacheable.setXMLTransformers() in General Interface API Reference.

Use jsx3.net.Service.compile() Use the jsx3.net.Service.compile() method to compile the CXF rules for a service instance to an equivalent XSLT document. This enables much faster performance than using the DOM-based iterator (default) to convert the XML response document into a CDF Document type. Call this method immediately before or after the doCall() method for best performance.

For more information, see jsx3.net.Service.compile() in General Interface API Reference.

Avoid Excessive String Concatenations In Internet Explorer, string concatenations are very expensive, especially with large strings. A better approach is to replace string concatenations with an array, push new strings to the array, and then use an Array.join() method call to get a single string. This approach essentially uses a string buffer instead of successive concatenations. For more information, see window.Array.join() in General Interface API Reference.

Identify Slow Functions Calls When possible, identify and optimize function calls that are taking excessive time. Use Firebug for Firefox and jsLex for Internet Explorer to profile your JavaScript code and identify slow functions.

In Internet Explorer 6, beware of String and RegExp literals in loops. For best performance, declare these literals statically or declare them outside of loops.

API Usage

When writing JavaScript code for your application, use the following best practices.

Minimize Repainting The on-screen rendering of HTML is often the slowest aspect of browser-based applications. Using efficient repaints can make your application faster and more responsive to user input.

Copyright © TIBCO Software Inc. All Rights Reserved. 145

Follow these best practices for repainting:

Look for unnecessary repaints in your JavaScript code and remove them. Use the General Interface debug build to identify multiple repaints. See Use the General Interface Debug Build. Repaint the smallest area of your application to obtain the desired effect. Understand how set methods may cause repaints and use them appropriately. See How Set Methods May Cause Repaints. Avoid redundant repaints on the same object. When calling any load APIs, such as the jsx3.app.Model.load(), jsx3.app.Model.loadAndCache(), and jsx3.app.Model.loadXML() methods, pass false as the second parameter to avoid a repaint if changes will be made to the component. Then repaint the component after changes are complete using the jsx3.gui.Painted.paintChild() method. Some methods, such as removeChild(), setChild(), and adoptChild(), can trigger repaints of the parent whose child is removed, set, or adopted. When possible, reuse components instead of removing and loading them. If removing multiple children at the same time, use the jsx3.app.Model.removeChildren() method to avoid multiple repaints. For Matrix components, call the repaintData() method if only the data has changed. The repaintData() method paints only the data rows and doesn't recalculate and re-profile the box profile and resulting XSLT. Therefore, the repaintData() method is more efficient than the repaint() method.

For more information, see General Interface API Reference.

How Set Methods May Cause Repaints Note that there are two types of painting in General Interface:

HTML DOM update: this is a fast, inexpensive paint, where a change to the General Interface DOM is transmitted directly to the browser DOM. Paint/repaint: this is a slower, more expensive paint, where the General Interface DOM is first serialized to an HTML string and then replaces part of the browser DOM.

Consider these basic rules when using set methods:

1. If the set method doesn't have a final boolean parameter (bRepaint), the component isn't repainted. For example, jsx3.gui.Block.setBackground(strBG). However, there are some exceptions. 2. If the set method has a final boolean parameter (bRepaint), you control the behavior. The default setting is false, meaning the component isn't repainted. For example, jsx3.gui.Block.setText(strText, bRepaint). If the final boolean parameter is set to true, the component is repainted, which is usually an inexpensive HTML DOM operation. However, in some cases a full repaint occurs.

If you're calling multiple set methods, follow these basic rules:

1. For methods that call inexpensive HTML DOM repaints, call each method with true. 2. If one of the methods calls a more expensive, full repaint, call that method last, while calling bRepaint=false to the preceding set methods.

For more information, see General Interface API Reference. Copyright © TIBCO Software Inc. All Rights Reserved. 146

For more information, see General Interface API Reference.

Search Components in the DOM Efficiently There are many ways to access objects in General Interface. The most common methods are the getJSXByName() and getJSXById() methods. These methods search an application index to quickly find the specific object in the General Interface DOM. Other methods are available, such as getJSX(), but are less specific and less efficient at locating objects.

Don't use jsx3.GO() to search the General Interface DOM, because it has access to all loaded General Interface applications and searches all of them for a DOM node of the given name. Recommended usage is in the General Interface Builder JavaScript Console only.

The following APIs are generally fast and memory safe:

jsx3.app.Server.getJSXByName() jsx3.app.Server.getJSXById()

The following APIs are slower but also memory safe:

jsx3.app.Model.getAncestorOfType() jsx3.app.Model.getDescendantOfName()

For example, you could use the getAncestorOfType() method in a dialog button execute event to close a dialog:

this.getAncestorOfType(jsx3.gui.Dialog).doClose();

General Interface also provides DOM methods that use familial relationships to locate objects. Depending on the location of the object you're searching for, it may be faster to use these methods. For example, calling

object.getChild('myblock');

only checks its direct children, so it might be much faster than calling

object.getDescendantOfName('myblock');

which checks all children, grandchildren, and so on.

Apply the appropriate call for your particular use case.

For more information on General Interface APIs, see General Interface API Reference. For information on how to search the General Interface DOM safely when deploying multiple applications in the same web page, see Protecting Namespaces in Multiple Application Environments.

Copyright © TIBCO Software Inc. All Rights Reserved. 147

Exclude Logging Messages To improve performance, don't build logging messages when logging is disabled. Only build logging messages when logging is enabled. When development is complete, configure the logger in your deployed application so fewer messages are generated by setting a more restrictive log level, such as WARN, ERROR, or OFF.

In this example, messages won't be generated if the com.tibco logger is configured as OFF:

var Logger = jsx3.util.Logger; var log = Logger.getLogger("com.tibco"); if (log.isLoggable(Logger.ERROR)) log.info(xmlDoc.toString()); // serializing XML may be // expensive

For more information, see Logging and Application Monitors and jsx3.util.Logger.isLoggable() in General Interface API Reference.

Components and Component Serialization Files

Use the following best practices when working with components and component serialization files.

Eliminate Unnecessary Components For cross-browser compatibility, General Interface abstracts the browser box model and calculations are handled by JavaScript instead of natively by the browser. Multiple JavaScript calculations can slow performance.

Follow these best practices to improve application performance:

Reduce the nestings and total number of blocks Don't use blocks for fillers. Use padding and margins instead of extra filler blocks for a lightweight and more efficient component. Design your application with the fewest blocks possible. Too many blocks can slow performance when resizing and repainting. Use layout components sparingly Only use layout components when appropriate. For example, don't use a layout component if there is only one child.

Use Matrix and Paging Use the Matrix components whenever possible to display large amounts of data. The Matrix component uses various paging models to improve overall rendering performance and paging tuners to provide greater control over how and when data is loaded. For more information, see General Interface Component Guide.

Copyright © TIBCO Software Inc. All Rights Reserved. 148

Benchmarking Performance

Use the following tools and General Interface features to assist you in benchmarking application performance.

Review Component Statistics As you work with components in General Interface Builder, you can view component statistics, such as component file size and time to paint, to assist you in evaluating and benchmarking application performance. For more information, see General Interface Component Guide.

Use the General Interface Debug Build As you develop your applications, use the General Interface debug build to detect and report such performance issues as multiple repaints, multiple box recalculations, times to perform various operations, and so on. The General Interface debug build is available from the download site at http://www.generalinterface.org.

Use General Interface Performance Profiler Use General Interface Performance Profiler to profile and benchmark your General Interface applications during development. The General Interface Performance Profiler is available from the download site at http://www.generalinterface.org.

Use JavaScript Profiling Tools During development, use JavaScript profiling tools to debug and profile JavaScript code, as well as expose performance issues.

For more information, visit these web sites:

Firebug http://www.getfirebug.com jsLex http://rockstarapps.com/pmwiki/pmwiki.php?n=JsLex.JsLex

Use General Interface Test Automation Kit Test your General Interface applications with General Interface Test Automation Kit, which is developed using the open source Selenium Core test tool, is a functional testing tool for testing General Interface applications.

The General Interface Test Automation Kit is available from the download site at http://www.generalinterface.org.

Copyright © TIBCO Software Inc. All Rights Reserved. 149

Chapter 9 Accessing Data Across Subdomains

This chapter describes how a General Interface application communicates with web servers across subdomains. A subdomain is a domain that is part of a larger domain. For example, About.com has several subdomains—antiques.about.com, autorepair.about.com, and so on.

There are two general scenarios for accessing a General Interface application, local provisioning and remote provisioning. Local provisioning doesn't require configuration if default browser security settings are used. Remote provisioning requires configuring proxy communication or modifying default browser security settings.

Local Provisioning Remote Provisioning

Local Provisioning

With local provisioning, the application files and the General Interface Framework are located on the same machine as the web browser. When the application is accessed, the browser loads required files into cache using a file URL, for example file:\\C:\tibco\gi\GI_Builder.html. With the default browser settings, there are no restrictions on communicating with web servers outside the subdomain.

Local Provisioning

Copyright © TIBCO Software Inc. All Rights Reserved. 150

Disabling Firebug in Firefox When using Firefox, cross-domain access is allowed when running from the file system. This allows easy testing of remotely provisioned services from within General Interface Builder. However, if the Firebug add-on is enabled for local files, a permission denied exception is thrown. To bypass this error, disable Firebug in Firefox (Tools > Firebug > Disable Firebug for Local Files).

Remote Provisioning

With remote provisioning, the deployed application files and the General Interface Framework are located on a web server. A browser on a remote machine accesses the files using an HTTP URL and loads files into cache. When an HTTP URL is used, default browser security settings prevent your application from communicating with web servers outside the subdomain. The following figure illustrates the remote provisioning scenario before any configuration is performed.

Remote Provisioning Before Configuration

Without configuration, an application can only communicate with www.mydomain.com. The browser prevents communication with other subdomains, such as inside.mydomain.com and rss.yahoo.com. However, the same application in a local provisioning scenario can communicate directly with web servers outside the subdomain.

Copyright © TIBCO Software Inc. All Rights Reserved. 151

Configuring Proxy Communication To enable proxy communication, you configure the web server where the application is deployed and the application. This allows the web server to broker interactions between the application and web servers outside the subdomain.

Remote Provisioning After Proxy Services Configuration

Configuring the Server Steps for configuring the web server vary according to vendor.

Apache Install and configure the mod_proxy module. Then use the ProxyPass directive to route responses through the General Interface application domain server, such as www.mydomain.com, rather than a web server outside the subdomain. For details, see the Apache HTTP Server documentation at http://httpd.apache.org. Microsoft IIS Install and configure the Microsoft Internet Security and Acceleration (ISA) Server. Write an ISAPI Filter to perform reverse-proxying or use an equivalent third-party product. The software must intercept an HTTP Request made to the General Interface application domain server, such as www.mydomain.com. Copy the entire HTTP header packet, change the HTTP Host header, and perform a new HTTP Request using the WinHttp API. For details, see http://www.microsoft.com/isaserver/default.mspx. Custom Write a server process, such as a servlet, .NET service, or web service, that acts as a proxy between the General Interface application domain server and other subdomains.

Copyright © TIBCO Software Inc. All Rights Reserved. 152

Configuring the Application There are two ways to retrofit a General Interface application so that it requests data from servers using a proxy:

Modify absolute URLs to refer to the proxy URL Convert non-proxied URLs to proxied URLs

Modify Absolute URLs The simplest way is to modify any absolute URLs in the project to refer to the proxy URL. Absolute URLs may exist in many types of project source files including JavaScript, service mapping rules, and component serialization files. Use your favorite text editor to perform a global search and replace in the project source files for strings matching "http://" or "https://".

Convert Non-proxied URLs to Proxied URLs The second way to retrofit a General Interface application so that it requests data through a proxy is more complicated but provides a mechanism for easily switching back and forth between proxied and non-proxied requests. This is accomplished by defining a function that converts a non-proxied URL to a proxied URL and then modifying any request before it is sent to use the proxied URL. Consider the following code sample as shown in the following example.

Copyright © TIBCO Software Inc. All Rights Reserved. 153

jsx3.Package.definePackage("eg.proxy", function(proxy) {

// switch, if true all URLs are converted to the proxied format proxy.PROXY = (window.location + "").indexOf("file") != 0;

// the domain of my proxy host proxy.PROXY_HOST = "proxy.eg.com";

// the path prefix of the proxied URLs proxy.PATH_PREFIX = "proxy/";

/** * Converts a non-proxied URI to a proxied URI if PROXY is true. *

* http://www.domain.com/service/op will be converted to * http://PROXY_HOST/PATH_PREFIX/www.domain.com/service/op * * @param strURI {String} the URI to convert * @returns {String} the converted URI */ proxy.convertURI = function(strURI) { if (proxy.PROXY) { var uri = new jsx3.net.URI(strURI); if (uri.getHost() != proxy.PROXY_HOST && (uri.getScheme() h1. "http" || uri.getScheme() "https")) { return jsx3.net.URI.fromParts(uri.getScheme(), null, proxy.PROXY_HOST,null, proxy.PATH_PREFIX + uri.getHost() + uri.getPath(), null, null).toString(); } else { return strURI; } } else { return strURI; } };

/** * Open all requests with this method to ensure that URLs are properly * converted for proxy. */ proxy.openRequest = function(strURL) { var objRequest = new jsx3.net.Request(); objRequest.open("GET", proxy.convertURI(strURL)); return objRequest; };

/** * Open all services with this method to ensure that URLs are properly * converted for proxy. */ proxy.openService = function(strRulesURL, strOpName) { var objService = new jsx3.net.Service(strRulesURL, strOpName); objService.setEndpointURL(proxy.convertURI(objService.getEndpointURL())); return objService; }; });

Copyright © TIBCO Software Inc. All Rights Reserved. 154

Modifying Internet Explorer Security Settings An alternative to configuring proxy services is to modify Internet Explorer security settings on each client machine that accesses the application.

This option is only available for Internet Explorer. For Firefox, you must configure proxy communications. See Configuring Proxy Communication.

When the security settings are set to accept the subdomain where the application is deployed as a trusted site, the browser allows direct communication with web servers outside the subdomain.

Remote Provisioning After Browser Configuration

To modify Internet Explorer browser settings on a client machine, complete these steps:

1. Exit General Interface Builder. 2. In Internet Explorer, select Tools > Internet Options from the browser menu. The Internet Options dialog displays. 3. Click the Security tab and click the Trusted Sites zone.

Copyright © TIBCO Software Inc. All Rights Reserved. 3.

155

4. Click the Custom Level button. 5. Enable the Access data sources across domains setting, then click OK. 6. Click the Sites button.

7. Type the name of the subdomain where the application is deployed in the Add this Web Copyright © TIBCO Software Inc. All Rights Reserved. 6.

156

7. Type the name of the subdomain where the application is deployed in the Add this Web site to the zone field, and then click OK. 8. Click OK again to close the Internet Options dialog.

Copyright © TIBCO Software Inc. All Rights Reserved. 157

Chapter 10 Adding and Debugging JavaScript Code

This chapter describes how to add and debug JavaScript code in your application.

About Debugging JavaScript Code Adding Code at the Component Level Adding Code at the Application Level Using Code with Data Services The JavaScript Console

About Debugging JavaScript Code

General Interface Builder allows you to add presentation logic to your application by writing custom JavaScript code. Presentation logic is any type of coding required to meet a user-specific requirement. For example, you can query a web service when a user clicks a button, or open a detail view in a list when a user selects a row.

There are several ways to add custom JavaScript to an application. The code is processed differently depending on how it's specified.

In General Interface Builder, fields where you can specify JavaScript code are distinguished visually with a light blue graph pattern background.

The following table shows the locations in General Interface Builder where you can specify code and the impact of each method.

Copyright © TIBCO Software Inc. All Rights Reserved. 158

Code What Code Does Location

Events Each event can be associated with JavaScript statements. Editor palette

Component JavaScript statements can be executed either before or after a component is Profile loaded in the application. view in work area

Dynamic JavaScript statements execute in application (server) context to set a dynamic properties property value. file

XML JavaScript statements execute in context of the mapped XML message node Mapping being processed or created. Utility

Project JavaScript statements execute during the onLoad event in application (server) Settings context immediately after the root and body canvases are drawn on-screen. dialog JavaScript statements execute during the onUnload event when the browser window is unloaded.

JavaScript A file containing JavaScript statements, method calls, constants, and so on can file be included in a project. Any static execution is evaluated before components included in are loaded. project

JavaScript Any JavaScript statements can be checked for errors before adding them to the Console application.

Adding Code at the Component Level

There are two ways to add code to components:

Associate code with the object's model event Execute code before or after the object is deserialized

Associating Code with an Event Each GUI component defines a set of model events. For example, a button component has an Execute event that fires when a user clicks the button. Events act as triggers for JavaScript code. When an event occurs, the associated code is executed. By binding JavaScript code to a component's event, user interactions can be captured, providing an event-driven interface.

To associate JavaScript code with an event, type the code in the Value field in the Events Editor palette, as shown here.

Copyright © TIBCO Software Inc. All Rights Reserved. 159

The statements doListClick() and doShowDetails() are defined in an included JavaScript file that is loaded when the browser first initialized. It is considered best practice to keep event binding code to a minimum, managing the bulk of the presentation logic in a JavaScript include. For more information, see Including JavaScript Files.

Executing Code Before or After Deserialization For any component, you can specify JavaScript to execute before or after the object is deserialized. The code is executed at runtime as well as in General Interface Builder, immediately before or after the associated serialization file is opened for edit.

Each component, which is represented by a tab in General Interface Builder, exposes a subset of fields within the Component Profile view. To execute JavaScript statements before or after

component deserialization, type the statements in the onBeforeDeserialize or Copyright © TIBCO Software Inc. All Rights Reserved. 160

component deserialization, type the statements in the onBeforeDeserialize or onAfterDeserialize field, as shown here.

Before Deserialization Example Before deserialization, the XML file can be accessed directly using the objXML variable. For example, typing alert(objXML); in the onBeforeDeserialize field displays the contents of the serialization file in an alert dialog.

Copyright © TIBCO Software Inc. All Rights Reserved. 161

Executing JavaScript statements before an object is deserialized is useful when the runtime needs to be prepared before the component is loaded. For example, when data that is used by a component needs to be preloaded.

After Deserialization Example After deserialization, the root-level object in the serialization file can be accessed directly using the objJSX variable. For example, typing alert(objJSX); in the onAfterDeserialize field lists object type, ID, and name of the root-level object in an alert dialog.

Executing JavaScript statements after an object is deserialized is useful when the component needs to be initialized with information only available at runtime. For example, the object ID (which is created after deserialization) can be displayed in the caption bar of a dialog. The most common use for serialization event bindings is to configure generic, reusable components with runtime-specific information.

In both cases, the JavaScript statements are executed only if the component is loaded at runtime.

Adding Code at the Application Level

There are several ways to add code at the application level:

Including JavaScript files. See Including JavaScript Files. Executing code to set a dynamic property value. See Specifying Code in Dynamic Copyright © TIBCO Software Inc. All Rights Reserved. 162

Executing code to set a dynamic property value. See Specifying Code in Dynamic Properties. Specifying the onLoad script. See Executing Code When the Application Loads. Specifying the onUnload script. See Executing Code When the Application Unloads.

Including JavaScript Files The most common way of adding custom code to an application is an included JavaScript file. JavaScript files can contain function definitions, method calls, constant declarations, and so on. Functions and other constructs defined in a file can be referenced in any other location where you can specify JavaScript code, such as the Events Editor palette. The file must be loaded into memory to be accessed by the application.

JavaScript files can be created in General Interface Builder and are automatically added to your project.

A default JavaScript file, logic.js, is created and included in your project when the project is created. This file initially contains no code, and can be deleted from the project as needed. You can add JavaScript code to logic.js, or create one or more new files, partitioning code among them. For smaller applications, a single included JavaScript file is usually sufficient. For larger, more complex applications, it can be helpful to divide the code among multiple files according to feature area, class, or functional role.

To add a JavaScript file to your project, select File > New > JavaScript File. A new tab is added to the work area for editing the file contents.

When saving files in the work area, you can save changes to disk (Save), save to disk and Copyright © TIBCO Software Inc. All Rights Reserved. 163

When saving files in the work area, you can save changes to disk (Save), save to disk and update changes in browser memory (Save and Reload), and load or reload from disk into browser memory (Load/Reload). Files must be loaded into memory to be part of the live application.

By default, logic.js is configured to automatically load after the General Interface system files have loaded but before the application initializes. Other included JavaScript files can also be loaded automatically by right-clicking the file in the Project Files palette and selecting the Auto Load option. If a file is required only for a specific module, you can load the file when needed using the loadResource() method of the Server class.

For more information on the Auto Load options, see File Profile Dialog. For information on dynamic class loading, see Class Loading in General Interface.

Specifying Code in Dynamic Properties Each dynamic property has an eval property that signifies if the contents of the Value field will be executed as JavaScript or simply treated as a string. This feature is useful for configuring a component when the value of a component property is determined by an external condition. For example, you could specify conditional logic in a JavaScript file included in your project, then reference the result in a dynamic property.

Dynamic properties files execute their contained JavaScript only once, when they are first loaded into the application. This means that the DateNow field in the above screenshot will reflect the date/time when the dynamic properties file first loaded.

To associate JavaScript code with a dynamic property,

1. Open an existing dynamic properties XML file or create a new one. See Creating Dynamic Properties Files. 2. Check the Eval checkbox for the property to indicate that the value should be evaluated as code. 3. Type one or more JavaScript statements separated with semicolons in the Value field.

For more information on dynamic properties, see Dynamic Properties Files.

Copyright © TIBCO Software Inc. All Rights Reserved. 164

Executing Code When the Application Loads You can execute JavaScript code immediately after the initial component has loaded but before it's painted on-screen. The Project Settings dialog includes the onLoad Script field for this purpose.

To execute JavaScript code when an application loads, select Project > Project Settings > Deployment and type the code in the onLoad Script field. In the following figure, init() is a global function defined in a JavaScript project resource.

Executing JavaScript code before the application loads is useful for performing tasks that should complete before a user accesses your application. For example, you could add code that checks for the presence of an HTTP cookie before displaying a login dialog.

Executing Code When the Application Unloads You can also execute JavaScript code when the browser window is unloaded. The Project Settings dialog includes the onUnload Script field for this purpose.

Copyright © TIBCO Software Inc. All Rights Reserved. 165

There are several ways to unload a browser window, including closing the window, refreshing the window, or navigating to another URL. The onUnload event allows you to save user state and do any final cleanup before exiting. This script can include one or more JavaScript statements which execute in context of the Server. The variable, this, references the jsx3.app.Server instance.

The onUnload event only fires when the browser is being unloaded. If you want to warn the user before the page is unloaded, use the onBeforeUnload event as defined for the given browser. For example,

jsx3.gui.Event.subscribe(jsx3.gui.Event.BEFOREUNLOAD, function(objEvent) { objEvent.returnValue = 'If you leave this page, your session will end.'; });

Using Code with Data Services

In the XML Mapping Utility, you can specify JavaScript code for performing tasks related to data service calls. For outbound mappings, the code is executed when the service call is made. For inbound mappings, the code is executed after the response is received.

To associate JavaScript code with a data service call, type the code in the Path/Value column in the Mappings table of the XML Mapping Utility and set the Type value to Script. In this context, the execution context is an instance of the jsx3.net.Service class. In the Path/Value column, you can execute any method of the jsx3.net.Service class using the syntax this.method_name.

When sending data to a data service, you can write code to specify a value that is unknown at design time. For example, you could specify the license key for using the data service at runtime, then you could pass the license key in the message using the setValue() method.

Copyright © TIBCO Software Inc. All Rights Reserved. 166

When receiving data, you can use this feature to filter and validate return values or parse data into the format required by your application. For example, you can extract the value of an outcome element in a response and use that value to control conditional execution in a component callback handler.

For a mapping tutorial, see Communicating with a Web Service Tutorial.

The JavaScript Console

General Interface Builder provides a JavaScript console to assist in executing and debugging JavaScript code. The JavaScript console:

Displays a running list of commands and command output. Allows you to drill down into nested data structures from command output.

The JavaScript console replaces the JavaScript Test Utility that was available prior to General Interface Release 3.9.

To open the JavaScript console, choose Tools > JavaScript Console in General Interface Builder.

In the console, you can use the up and down arrow keys to scroll through the command history. The history is saved even after General Interface Builder is closed and reopend. For example, if you enter the command document.body or jsx3 in the console, the string representation of an object is shown with a collapsed arrow to its left. You can click the arrow to expand the object. Any nested objects can also be expanded.

Property keys are shown in purple, except when the value of the property is inherited from the object's prototype, in which case the key is shown in gray. Function and Array outputs are also shown.

To clear the console history, type Ctrl+K or right-click inside the console and choose Clear Console.

By default, the console evaluates the input when you press Enter. The console supports multi-line input. You can paste the multi-line text at the prompt or type Shift+Enter to insert a carriage return.

Copyright © TIBCO Software Inc. All Rights Reserved. 167

Code Execution

All code evaluated by the JavaScript console is executed in window scope. For example, if you evaluate the following statement:

f = 1;

you have actually set the property f of the top-level object window. If you set a global variable in this way, it becomes available to subsequent expressions that you evaluate in the console.

The form var f = 1; does not have the same behavior as f = 1;. The value of f is not available to subsequent expressions if it is set in this way.

If the active editor is a JSX component editor then each DOM node in the component is exposed as a variable in the JavaScript console. For example, if the component contains an instance of jsx3.gui.TextBox whose name is set to "textBox," then the variable textBox will be equal to the TextBox instance when evaluated in the console. Please note that,

Only objects whose names are valid JavaScript variable names are exposed. The name must match [\$a-zA-Z_][\$\w]*. The behavior of name collisions is not defined. If you have two or more objects in the same component with the same name, the corresponding variable may reference either one.

Copyright © TIBCO Software Inc. All Rights Reserved. 168

Chapter 11 Class Inheritance and Introspection

This chapter describes General Interface extensions to the JavaScript class and inheritance model. With these extensions, General Interface provides a richer programming environment that is better suited to building complex object-oriented applications.

Classes and Inheritance in JavaScript 1.x jsx3.lang.Object and Classes in General Interface Declaring a Class Class-Like Constructs Introspection

Classes and Inheritance in JavaScript 1.x

JavaScript 1.x supports prototype inheritance. A class is defined by any function:

function Plant(latinName, englishName) { this.latinName = latinName; this.englishName = englishName; }

The prototype field of the class function represents the prototypical instance of the class. A new instance of the class will be a copy of the prototype, including any fields and methods placed in the prototype.

Plant.prototype.relatedSpecies = new Array();

Plant.prototype.getLatinName = function() { return this.latinName; };

Inheritance is supported by setting the prototype of a class function to a new instance of the superclass:

function Tree(latinName, englishName, flowering) { this.latinName = latinName; this.englishName = englishName; this.flowering = flowering; }; Tree.prototype = new Plant();

Tree.prototype.isFlowering = function() { return this.flowering; };

JavaScript supports an inheritance-aware instanceof operator. The following statements are true:

(var aPlant = new Plant()) instanceof Plant; (var aTree = new Tree()) instanceof Plant; (var aTree = new Tree()) instanceof Tree;

Copyright © TIBCO Software Inc. All Rights Reserved. 169

Because all classes implicitly extend the Object class, the following statement is also true: (var aPlant = new Plant()) instanceof Object;

jsx3.lang.Object and Classes in General Interface

General Interface defines its own base class, jsx3.lang.Object, which adds the following capabilities to the JavaScript 1.x model:

Obtaining the class that defines an instance with the getClass() method Calling an overridden method in a superclass with the jsxsuper() and jsxsupermix() methods A better toString() method that overrides Object.toString() and includes the name of the class from which the object was instantiated Introspection of class and interface membership using the instanceOf() method

The jsx3.lang.Object class works in conjunction with the other classes in the jsx3.lang package — Class, Exception, Method, and Package —to provide these further advantages over JavaScript 1.x:

A rich exception model with intelligible stack traces Full introspection of classes and methods Mixin style interfaces Introspectable packages Simple declaration of classes and members using standard JavaScript 1.x syntax that frees the developer from the details of prototype inheritance

All classes in General Interface descend from jsx3.lang.Object. Developers are encouraged to extend the General Interface base class in application code in order to fully incorporate the features enumerated above.

Declaring a Class

Classes are defined with the static method jsx3.lang.Class.defineClass() :

static method defineClass(strName, objExtends, arrImplements, fctBody)

The first parameter, strName, is a string that is the fully-qualified name of the class to define, such as "com.tibco.Widget". The defineClass() method ensures that the namespace object, com.tibco, exists before creating the Widget constructor.

The second parameter, objExtends, is the superclass of the class to define. If null is passed, jsx3.lang.Object is assumed. This parameter is usually provided as the constructor function of the superclass, the fully-qualified class name without quotes.

The third parameter, arrImplements, is an array of the interfaces that the class implements. This array can be empty or null.

The fourth parameter, fctBody, is a function that defines the contents of the class. The

defineClass() method executes this function exactly once after it has handled the details of the Copyright © TIBCO Software Inc. All Rights Reserved. 170 defineClass() method executes this function exactly once after it has handled the details of the JavaScript 1.x prototype inheritance implementation. The defineClass() method passes two parameters to fctBody. The first parameter is the constructor function of the newly defined class. The second parameter is the prototype object of the class. This is simply a syntactical shortcut that allows for the following concise idiom: jsx3.lang.Class.defineClass( "com.tibco.Widget", jsx3.lang.Object, // Object is implicit so this parameter could be null //in this case [jsx3.util.EventDispatcher],

function(Widget, Widget_prototype) { // define class members in Widget // define instance members in Widget_prototype } );

There are four types of members that can be included in the class definition: static fields, static methods, instance fields, and instance methods. Each of these types is introspectable with methods of the jsx3.lang.Class class. Static members are declared by defining fields of the class constructor. Continuing the preceding code example:

// define two static fields Widget.SERIAL = 1; Widget.ALL_WIDGETS = new Array();

// define a static method Widget.getWidgetBySerial = function(serial) { return Widget.ALL_WIDGETS[serial]; };

Static members are globally available using the fully-qualified name of the member, such as com.tibco.Widget.getWidgetBySerial(). The same member can be referenced with Widget.getWidgetBySerial() within the class declaration function, because com.tibco.Widget is aliased as Widget inside the function. Unlike in Java, static members are not accessible through instances of a class (that is, aWidget.SERIAL is undefined).

Instance members are declared by defining fields in the prototype field of the class constructor:

// define two instance fields Widget_prototype.serial = null; Widget_prototype.name = "?";

// define an instance method Widget_prototype.getSerial = function() { return this.serial; };

All classes must define a special instance method called init(). The defineClass() method throws an exception if the init() method isn't declared in the class declaration function. The init() method is effectively the constructor function. However, the defineClass() method

actually creates the class constructor so the developer has no way of customizing it. Instead, the Copyright © TIBCO Software Inc. All Rights Reserved. 171

actually creates the class constructor so the developer has no way of customizing it. Instead, the generated class constructor simply calls the init() method passing all the parameters that were passed to the constructor. Here is the init() method for the Widget class:

Widget_prototype.init = function(name) { this.name = name; this.serial = Widget.SERIAL++; };

The following code instantiates a Widget :

var widget = new com.tibco.Widget("myFirstWidget");

Class-Like Constructs

The jsx3.lang package defines three class-like constructs— Class, Interface, and Package. These constructs are not exactly equivalent to their Java/C++ namesakes.

Classes Classes have the following characteristics:

Are defined with the jsx3.lang.Class.defineClass() method Define static fields, static methods, instance fields, instance methods, and abstract instance methods Are instantiated Can be the superclass of another class Descend from jsx3.lang.Object

Interfaces Interfaces have the following characteristics:

Are defined with the jsx3.lang.Class.defineInterface() method Define static fields, static methods, instance methods and abstract instance methods Are not instantiated Can be the superclass of another interface Can be implemented by a class

Packages Packages have the following characteristics:

Are defined with the jsx3.lang.Package.definePackage() method Define static fields and static methods Contain classes and interfaces defined with jsx3.lang.Class

Unlike in Java, General Interface interfaces may contain concrete instance methods. When a class implements an interface, the instance methods of the interface are mixed into the class. A

mixed in method overrides a method of the same name inherited from the superclass but Copyright © TIBCO Software Inc. All Rights Reserved. 172

mixed in method overrides a method of the same name inherited from the superclass but doesn't override a method defined in the implementing class or mixed in from an interface coming earlier in the arrImplements parameter to the Class.defineClass() method.

Packages must be explicitly defined with the jsx3.lang.Package.definePackage() method in order to be introspectable. Simply defining the class com.tibco.Widget will not define the package com.tibco. Defining a package isn't required for the class to work. It simply allows the package to be introspected.

Classes, interfaces, and packages can "contain" classes/interfaces. Consider the following code assuming that the class com.tibco.Widget.Encoding is defined:

// returns [com.tibco.Widget, com.tibco.Widget.Encoding] jsx3.lang.Package.forName("com.tibco").getClasses();

// returns [com.tibco.Widget.Encoding] jsx3.lang.Class.forName("com.tibco.Widget").getClasses();

Introspection

Once a class, interface, or package has been defined as described above, it's introspectable. There are a few ways to get a handle to an instance of jsx3.lang.Class or jsx3.lang.Package :

var aClass = anObject.getClass(); // returns an instance of jsx3.lang.Class var aPackage = aClass.getPackage(); // returns an instance of jsx3.lang.Package

com.tibco.Widget.jsxclass; // instance of jsx3.lang.Class com.tibco.jsxpackage; // instance of jsx3.lang.Package

// the following returns null if any part of the namespace is undefined: jsx3.lang.Class.forName("com.tibco.Widget"); jsx3.lang.Package.forName("com.tibco");

Consult the API Documentation for all the methods of these classes that can be used to introspect their contents.

Copyright © TIBCO Software Inc. All Rights Reserved. 173

Chapter 12 Extensions to JavaScript Exception Handling

This chapter describes General Interface extensions to JavaScript exception handling and how to leverage these extensions to write code that is more robust and easier to maintain.

Exceptions in JavaScript Exceptions in General Interface Exceptions and the Call Stack When to Use Exceptions

Exceptions in JavaScript

Like many other programming languages, JavaScript provides for throwing and catching exceptions. JavaScript supports the standard try...catch...finally statement:

try { doSomething(); } catch (e) { window.alert(e.description); } finally { cleanUp(); }

JavaScript also supports the throw statement. Any type of object can be thrown:

throw "error!"; throw {name:"anError", description:"an error occurred"};

The browser creates and throws errors under certain circumstances. For example, trying to access a field on a variable that is undefined will raise an error. Trying to call a function that does not exist also raises an error. These types of exceptions can also be caught with the try...catch statement.

When an exception is raised and isn't caught, the current call stack is unwound and the browser receives an error event. Execution of JavaScript code continues when the next stack is created by a timeout event or by user interaction.

Exceptions in General Interface

General Interface extends the native JavaScript exception facilities in several ways that make it easier to build and debug large applications.

General Interface defines the jsx3.lang.Exception class, which extends jsx3.lang.Object and is the superclass of all General Interface exceptions. This base class is stack aware, which means that it stores the call stack at the point where it was created. By using and/or extending jsx3.lang.Exception, you can take advantage of some features of exceptions that exist in more advanced languages such as Java.

Several methods in the General Interface Framework throw exceptions to communicate to the

caller that an error has occurred. Note that some classes, such as jsx3.xml.Document, fail silently Copyright © TIBCO Software Inc. All Rights Reserved. 174

caller that an error has occurred. Note that some classes, such as jsx3.xml.Document, fail silently by storing error information in instance fields rather than throwing exceptions. General Interface Framework methods that throw a General Interface exception are documented in the API Documentation (Help>API Documentation). Such methods should be surrounded by a try...catch block to prevent the exception from reaching the top of the call stack. Because exceptions in JavaScript aren't checked as they are in Java, if a method that throws an exception isn't surrounded with a try...catch block, it's not a compilation error.

General Interface also defines jsx3.lang.NativeError, a subclass of jsx3.lang.Exception, which wraps the native browser exception object. NativeError is a cross-platform interface onto the exceptions that the browser may raise. Since NativeError extends Exception, application code can treat all exceptions caught in a try...catch block as instances of the Exception class. This is accomplished with the following code:

try { doSomething(); } catch (e) { // e may be a native browser Error object or an instance of // jsx3.lang.Exception thrown by application or framework code var ex = jsx3.lang.NativeError.wrap(e); window.alert(ex.printStackTrace()); }

Finally, in General Interface Builder and when error trapping is enabled in running General Interface applications, any error that reaches the top of the stack and the browser is routed to the General Interface logging system. The exception will be sent to the global logger, jsx3.util.Logger.GLOBAL, with severity ERROR.

Exceptions and the Call Stack

Any time an instance of jsx3.lang.Exception is created, it stores the current call stack. This can be accessed with either the getStack() or printStackTrace() methods of the class. This feature can be very helpful when diagnosing a problem in an application.

Unfortunately, in Internet Explorer, the native exception class does not store stack information. Therefore, an instance of jsx3.lang.NativeError only contains the stack up to the point when it was created, not up to the point where the error it wraps was raised.

The one exception to this is when a native error reaches the top of the call stack. In that particular case, the General Interface logging system does have access to the entire stack up to the function where the error was raised. This is problematic from the point of view of a developer, however, because the choice is between maintaining the stack by catching an error but losing information about how that error was created and seeing the full stack trace of the error but not being able to recover from the error.

One possible development practice to deal with this shortcoming of Internet Explorer is to include fewer try...catch statements in the early stages of developing an application and including more as the quality of the code improves.

Copyright © TIBCO Software Inc. All Rights Reserved. 175

When to Use Exceptions

Exceptions are a way of communicating an exception or error condition from a method to the caller of the method. Exceptions are favored over the older technique of returning a status code from a method, such as 0 for success and 1 for error, because exceptions can't be ignored by the calling code. Without exceptions, it's easy to write code that assumes every operation is successful. When an operation doesn't end in success, the error can show up in subsequent operations, and therefore be harder to diagnose.

In most implementations, throwing exceptions is a relatively expensive operation. Therefore, exceptions should be used to communicate truly exceptional conditions rather than conditions that may occur under the normal execution of a program.

The benefit of using exceptions usually increases with the size of the application. Exceptions require the developer to define the success and error conditions of methods and require the calling code to handle both possibilities. Code therefore can have fewer bugs and be clearer and more robust than code that uses another error reporting mechanism or ignores error conditions altogether. Additionally, exceptions help with the principle of failing early. In general, it's better to fail (raise an exception) at the first sign of trouble when the cause of the failure is well-known. Otherwise errors might cascade to other parts of a program where they are harder to diagnose.

Copyright © TIBCO Software Inc. All Rights Reserved. 176

Chapter 13 General Interface JavaScript Documentation Compiler

This chapter describes how to use the General Interface JavaScript Documentation Compiler (JSXDOC).

Overview Running JSXDOC

Overview

JSXDOC is a program that creates API documentation from JavaScript source files. JSXDOC parses JavaScript syntax and a comment metadata syntax to produce the structured documentation. JavaScript source files that are run through the compiler must conform to the JSXDOC syntax. JSXDOC can export documentation as XML or HTML files.

Syntax The supported documentation syntax is similar to javadoc syntax. Relevant comment blocks are range comments that begin with /** and are placed immediately before the member that they describe. You can document packages, classes, interfaces, methods, and fields. Methods and fields are defined in the class, interface, or package whose definition most closely precedes it. (It is an error to define a method or field in a location where there is no such class context).

The documentation compiler parses JavaScript to determine what type of member a comment block documents. The member declaration that follows the comment block (or that is specified with the @jsxdoc-definition tag) must match one of the following patterns.

jsx3.[lang.]Package.definePackage("NAME", ...) Defines a package. The package name is determined from the declaration. jsx3.[lang.]Class.defineClass("NAME", SUPER, [IMP1, IMP2, ...], ... ) Defines a class. The class name, superclass, and implemented interfaces are determined from the declaration. jsx3.[lang.]Class.defineInterface("NAME", SUPER, ...) Defines an interface. The interface name and super interface are determined from the declaration. prototype.NAME = jsx3.[lang.]Method.newAbstract("P1", "P2", ...) ; Defines an abstract method. The method name and parameter order are determined from the declaration. prototype.NAME = jsx3.Y(function(...)) Defines an asynchronous method. The method name is determined from the declaration. The method parameters are taken from the @param tags. prototype.NAME = function(P1, P2, ...) ... Defines an instance method. The method name and parameter order are determined from the declaration. NAME: function(P1, P2, ...) ... Defines an instance method (as in the previous declaration). The method name and parameter order are determined from the declaration. x.NAME = function(P1, P2, ...) ... Defines a static method. The method name and parameter order are determined from the declaration.

Copyright © TIBCO Software Inc. All Rights Reserved. 177

prototype.NAME = x; Defines an instance field. The field name is determined from the declaration. NAME: x - Defines an instance field (as in the previous declaration). The field name is determined from the declaration. x.NAME = x; Defines a static field. The field name is determined from the declaration.

Documentation Blocks Documentation blocks can begin with a free-form paragraph that describes the member. HTML tags are allowed in this and most other text blocks. HTML entities must be escaped in order to be interpreted as plain text. The type declaration of a field, if documented, must precede its description.

The param, return, and throws tags, and the field description, support optional type information. Types are always documented between curly braces, {}. A type can be any valid JavaScript identifier or package+identifier. A type whose class is included in a compilation will be linked automatically to the definition of that class. The following constructs are also supported, both alone and in most combinations.

type1 | type2 | ... type1 or type2 or ... type1... Variable number of method arguments which should be determined from the JavaScript arguments array. pType Parameterized type such as an Array that contains objects of another type. pType Multi-dimensional parameterized type such as a map that contains multiple sets of objects of other types.

Tags Tags begin on a new line and begin with the @ character. The following tags are supported.

@public, @package, @protected, @private Sets the access level of the documented member. If a documentation comment exists the default is public, otherwise the default is private. @version STRING Documents the version of the member. @since STRING Documents the version when the member was introduced. @deprecated [STRING] Documents that the member is deprecated and adds an optional description of the deprecation. @author STRING Documents the author of the member. Any number of author tags may be documented. @param NAME [{TYPE}] STRING Documents a method parameter. Any parameters that are not explicitely documented with this tag are parsed from the definition and included (without type or description) in the compiled documentation. @param {TYPE} NAME STRING This is an alternative supported syntax of a method parameter. @param-package and @param-private You can use these to set the access level of a particular parameter so that it does not show up in the compiled documentation. @return [{TYPE}] STRING Documents the return type of a method and adds a description to the returned object. The type is optional. Method that have no non-empty return statements should not include this tag. @throws [{TYPE}] STRING Documents an exception type that a method may throw and the conditions under which it is thrown.

@final Documents that a method should not be overridden or a class should not be Copyright © TIBCO Software Inc. All Rights Reserved. 178

@final Documents that a method should not be overridden or a class should not be extended. The JavaScript language does not enforce this documentation construct. @static Documents a field or member as static even when the member declaration is not understood by the parser to be a static declaration. @protected Documents that a method or field should only be used from within the class that defined it or one of that class's subclasses. The JavaScript language does not enforce this documentation construct. @abstract Documents that a class is abstract. Methods defined with j sx3.lang.Method.newAbstract() are automatically recognized as abstract. Any class or interface with an abstract member is also automatically recognized as abstract. @native Documents that this member is defined by the JavaScript engine or host browser. @see STRING Adds a See section to the documentation of this member. There are several supported formats for the STRING argument: "TEXT" Inserts a text label. TEXT Inserts an HTML link to URL. #LOCAL_FIELD [LABEL] References a field in the same class with optional label LABEL. #LOCAL_METHOD() [LABEL] References a method in the same class with optional label LABEL. pkg.Class#FIELD [LABEL] References a field in another class, pkg.Class, with optional label LABEL. pkg.Class#METHOD() [LABEL] References a method in another class, pkg.Class, with optional label LABEL. @jsxdoc-definition JS_DEFINITION In the case that a documentation block cannot appear immediately before the member definition, this tag can be used to specify the member definition. This tag can also be used to tell the compiler what member the comment block describes in the case that members are not defined according to the JavaScript syntax that the compiler expects. @jsxdoc-category CLASS In the case that the members of a package, class, or interface are defined across multiple files or sections of files, this tag can be used to indicate that tags following it belong to CLASS but without redefining CLASS in the process.

Example The following code example declares a JavaScript class, jsx3.util.list, and includes many of the JSXDOC tags.

/** * Adapted from jsx3.util.List. *

* An object-oriented version of the built-in JavaScript Array class. *

* Note that methods such as indexOf and remove compare objects * with the strict equality operators (=h1. and !\). Therefore, for the purposes of this * class 1 and "1" are not equal. * * @since 3.2 */ jsx3.Class.defineClass('jsx3.util.List', null, null, function(List, List_prototype) {

Copyright © TIBCO Software Inc. All Rights Reserved. 179

/** * {int} A final static field. * @final */ List.STATIC_FIELD = 5;

/** * If a is already an instance of this class, this method returns a. * If a is an array, this method returns a new List instance backed by a. * @param a {Array|jsx3.util.List} * @return {jsx3.util.List} * @throws {jsx3.IllegalArgumentException} if a is not a list or array. */ List.staticMethod = function(a) { if (a instanceof List) { return a; } else if (a instanceof Array) { return new List(a, true); } else { throw new jsx3.IllegalArgumentException("a", a); } };

/** * The instance initializer. Creates a new list. * @param a {Array} * @param-private bLive {boolean} */ List_prototype.init = function(a, bLive) { if (a instanceof Array) { this._src = bLive ? a : a.concat(); } else { this._src = ; } };

/** * @return {int} */ List_prototype.size = function() { return this._src.length; };

/** * Varargs example. * @param o {Object...} */ List_prototype.add = function(o) { this._src = this._src.concat(arguments); };

/**

Copyright © TIBCO Software Inc. All Rights Reserved. 180

* Parameterized type example. * @return {jsx3.util.List} this list converted to a list of strings. */ List_prototype.toStringList = function() { return this.filter(function(e) { return e.toString(); }); };

/** @private */ List._privateMethod = function(a) { return a;

Copyright © TIBCO Software Inc. All Rights Reserved. 181

};

});

Running JSXDOC

JSXDOC is distributed with the source distribution of General Interface as a Java class with an Ant task interface. The easiest way to run JSXDOC is via the Ant interface.

To get started:

1. Make sure that Java 1.5+ and Ant 1.7+ are installed. Downloads are available at http://java.sun.com and http://ant.apache.org. 2. Download the GI source distribution from at http://www.generalinterface.org. Unzip it to GI_SRC. 3. Run the command ant package in the directory GI_SRC/build/tools. This creates a jsx-tools.jar file in same directory. The JAR file contains the JSXDOC program and Ant task. 4. Copy jsx-tools.jar and the following files into a new directory, JSX_RUN.

GI_SRC/build/tools/lib/javacc/bin/lib/javacc.jar GI_SRC/build/tools/lib/jaxen/jaxen-1.1.jar GI_SRC/build/tools/lib/dojo/jsl.jar GI_SRC/build/tools/lib/xml/xalan-serializer-2.7.jar GI_SRC/build/tools/lib/saxon/saxon8.jar GI_SRC/build/tools/lib/saxon/saxon8-dom.jar GI_SRC/build/apidoc/

5. Now create an Ant build.xml file in JSX_RUN. 6. Copy the following example as a starting point.

Copyright © TIBCO Software Inc. All Rights Reserved. 6.

182

Copyright © TIBCO Software Inc. All Rights Reserved. 6.

183

7. In the same directory, create the Ant build.properties file from the following template. The build.properties file allows you to configure the Ant build process without modifying the build.xml file.

# The title of the compiled API documentation gi.apidocs.title = My Library® # The title of the compiled API documentation, XML-escaped gi.apidocs.title.esc = My Library&reg; # The copyright of the compiled API documentation, XML-escaped gi.apidocs.copyright = Copyright &copy; My Company

# The minimum access level of documented members: public, protected, private jsxdoc.access = protected jsxdoc.encoding = UTF-8

xsl.dir = apidoc js.dir = src tmp.dir = tmp doc.dir.xml = doc/xml doc.dir.html = doc/html

8. Place all JavaScript source files in the directory JSX_RUN/src. 9. Run the ant command from JSX_RUN. The build process is configured to export XML documentation to JSX_RUN/doc/xml/ and HTML documentation to JSX_RUN/doc/html/. 10. Open JSXRUN/doc/html/index.html in a web browser to view the new documentation.

Copyright © TIBCO Software Inc. All Rights Reserved. 184

Chapter 14 Protecting Namespaces in Multiple Application Environments

This chapter describes how to design General Interface applications to work properly in multiple application environments, such as portal deployments.

How Namespaces Affect Deployed Applications Protecting Application Code with Packages

How Namespaces Affect Deployed Applications

Multiple General Interface applications running in a single web page share a common JavaScript memory space. Consequently, one application can have intended and unintended effects on another General Interface application running in the same web page. There is no way of designing an application such that it's completely protected from other applications. This chapter describes how to design an application so that unintended effects between it and from other applications are greatly reduced.

The namespace of a General Interface application is the name of the global JavaScript variable that is set to the instance of jsx3.app.Server representing the application. Custom application JavaScript code usually references this variable extensively since the server provides access to the General Interface DOM and local data cache, among other things.

The namespace of a General Interface application must be unique for each application deployed in a single web page. If a namespace collision occurs, the code of only one of the applications has access to its jsx3.app.Server instance. The other applications will likely break. Namespaces should always be checked for uniqueness before creating a deployment page with multiple General Interface applications.

A good way to ensure namespace uniqueness is to use the reverse domain naming convention Copyright © TIBCO Software Inc. All Rights Reserved. 185

A good way to ensure namespace uniqueness is to use the reverse domain naming convention when choosing your application namespace. For example, you could use com.tibco.gi.App1 and com.tibco.gi.App2. This ensures that your applications won't conflict with General Interface applications from other organizations.

Setting the Application Namespace in General Interface Builder By default, the server namespace is the same as the project name, with any illegal characters removed. The value is displayed in the Namespace field on the Deployment panel of the Project Settings dialog (Project > Project Settings) and can be modified to any valid JavaScript variable name.

Using the Namespace in Application Code The jsx3.app.Server instance, the name of which is specified by the application namespace, provides access to the General Interface DOM and local data cache.

Access to the DOM is provided by the methods getDOM(), getJSX(), getJSXByName(), getJSXById(), and getBodyBlock() of the jsx3.app.Server class. All DOM nodes, which are instances of jsx3.app.Model, are indexed by both ID and name. The following code retrieves the DOM node of name "textbox" in the application of namespace com.tibco.gi.App1:

com.tibco.gi.App1.getJSXByName("textbox");

The DOM index on name tracks only one node per name. Therefore, the getJSXByName() method only returns a predictable value for names that are unique over the entire application.

The jsx3.GO() method is a shortcut for fetching a DOM node by name or ID. The jsx3.GO() method has access to all loaded General Interface applications and searches all of them for a DOM node of the given name. The jsx3.GO() method is therefore slower than getJSXByName() Copyright © TIBCO Software Inc. All Rights Reserved. 186

DOM node of the given name. The jsx3.GO() method is therefore slower than getJSXByName() and allows one application to affect another application. Only use jsx3.GO() in the General Interface Builder JavaScript Console where brevity is more important than accuracy. Application code should not use jsx3.GO.

jsx3.GO("textbox");

Access to the application local data cache is provided by the getCache() method in the jsx3.app.Server class. The following code fetches a cache document from the App1 application:

com.tibco.gi.App1.getCache().getDocument("docId");

Protecting Application Code with Packages

The application namespace isn't the only namespace that needs to be protected from other General Interface applications. Project JavaScript code should also be placed in a unique namespace to avoid affecting and being affected by other applications. A JavaScript namespace is known in General Interface as a package.

In general, applications should not declare global JavaScript functions. The following code defines a global JavaScript function:

function doTest() { return 1; }

This is equivalent to declaring the function as a member of the global window object:

window.doTest = function() { return 1; };

Since all General Interface applications deployed in the same web page share the same global window object, any code placed in it isn't private to a particular application. If two different applications define a global doTest() method, one version is overridden by the other and one application will probably break.

To avoid any naming collisions in function and variable names, all code should be placed in packages. Using the reverse domain naming convention is a good choice for avoiding collisions. A package is essentially a nested data structure descending from the window object. The following code creates the com.tibco.gi package and defines the doTest() function in it.

window["com"] = new Object(); com.tibco = new Object(); com.tibco.gi = new Object(); com.tibco.gi.doTest = function() { return 1; };

However, this code has a bug in it, because it will destroy any previously defined package descending from window.com, such as com.tibco.porta l. With this technique for creating a package, the nested objects should only be created if they do not already exist.

The jsx3.lang.Package class simplifies the task of creating a package greatly with the Copyright © TIBCO Software Inc. All Rights Reserved. 187

The jsx3.lang.Package class simplifies the task of creating a package greatly with the definePackage() method. The following code also defines the doTest() function in the com.tibco.gi package but without the bug in the previous code sample:

jsx3.lang.Package.definePackage("com.tibco.gi", function(gi) { gi.doTest = function() { return 1; }; });

Since JavaScript packages can be named using the reverse domain naming convention, they are very safe from naming collisions.

For more information, see the jsx3.lang. Package in General Interface API Reference.

Copyright © TIBCO Software Inc. All Rights Reserved. 188

Chapter 15 Implementing Context-Sensitive Help

This chapter describes how to implement context-sensitive help in a General Interface application.

About Context-Sensitive Help Basic Steps for Implementing Help

About Context-Sensitive Help

Context-sensitive help is a type of online help specific to a user interface topic or software feature. For example, context-sensitive help for a dialog would explain the options and settings of the dialog. The end user typically accesses context-sensitive help by clicking a button or pressing hot keys.

General Interface Framework, the General Interface runtime, provides a jsxhelpid property for implementation of context-sensitive help in your General Interface applications. The jsxhelpid property is a unique string identifier that can be set in the Properties Editor palette (Help ID) in General Interface Builder or set programmatically using the jsx3.app.Model.setHelpId() method.

When a help ID is specified for a component, the user can launch context-sensitive help by pressing hot keys, which are system- and locale-dependent. The application automatically listens for the key event and determines the closest ancestor of the object receiving the key event that has a help ID. If an ancestor exists, the key event is canceled and the application, which is the Server object, publishes an event of subject jsx3.app.Server.HELP.

Application code can register for the HELP event from the application's Server object and perform custom code appropriate for the application, such as launching an external web page or opening a custom-built General Interface help viewer.

Help Hot Keys The hot keys that invoke the help system are system- and locale-dependent. Hot keys are externalized in the locale.xml properties bundle in the JSX/locale/ directory. The default hot keys in locale.xml are Alt+F1 for Windows and Command+/ for Mac.

Help APIs The help APIs include the following:

jsx3.app.Model.getHelpId() returns the help ID of a component. jsx3.app.Model.setHelpId() sets the help ID of a component. jsx3.app.Server.HELP is the subject on an event that instances of this class publish when a context-help hot key is pressed in the context of a General Interface DOM node that has a help ID. The HELP event has the following properties: subject jsx3.app.Server.HELP target the serve helpid the value of the jsxhelpid property Copyright © TIBCO Software Inc. All Rights Reserved. 189

helpid the value of the jsxhelpid property model the General Interface DOM node that receives the key event jsx3.app.Server.invokeHelp(objJSX) invokes context-sensitive help as though the user had pressed the help hot key in the context of the DOM node.

For more information, see General Interface API Reference.

Basic Steps for Implementing Help

Implementing context-sensitive includes the following steps:

1. Set help IDs for areas of the user interface, such as palettes and dialogs: Set the Help ID property in the Properties Editor palette of General Interface Builder. Set the help ID programmatically using the jsx3.app.Model.setHelpId() method. 2. Subscribe to the HELP event using jsx3.app.Server.HELP ("event subject_").

For example, the next example demonstrates how to send a message to an alert when a server publishes a HELP event. The JavaScript package is eg.app and the server is eg.app.APP, as shown in the following example.

eg.app.APP.subscribe(jsx3.app.Server.HELP, eg.app.onHelp);

eg.app.onHelp = function(objEvent) { objEvent.target.alert("Help", " ") };

Copyright © TIBCO Software Inc. All Rights Reserved. 190

Chapter 16 Logging and Application Monitors

This chapter describes how to use the logging system to send and view logging messages. It also discusses how to use application monitors to view logging messages from running applications.

About Logging and Application Monitors Understanding the Logging System Configuration File Sending Logging Messages Viewing Logging Messages Creating a Custom Handler Creating a Custom Logging System Configuration File

About Logging and Application Monitors

General Interface provides an advanced logging system which is defined in the jsx3.util.Logger class. The logging system is designed to be an integral part of the development process. It can be used in General Interface Builder and in a running General Interface application to trace activity and diagnose errors. Logging messages can be sent to a variety of destinations using custom logging handlers — on-screen, memory, web service, local file, and so on. Which messages are displayed, where, and how they're displayed can be configured declaratively in an XML logging system configuration file without modifying source code.

Loggers and Handlers Two important classes of objects in the logging system are:

Loggers Handlers

A logger is used to log messages about a particular component of an application. After receiving the log message, the logger forwards the message to registered handlers. A logger may have one or more handlers associated with it.

A handler, which receives log messages from the loggers it's registered with, defines what to do with a logging message. A handler can output messages in a specified format to various destinations, such as to memory, system log, console, files, and so on. In some cases, a handler might ignore messages.

A logger is identified by its unique name. All logger instances exist in an inheritance tree and are descendants of the global logger. Inheritance is organized by name with the dot (".") character defining levels of the tree. For example, a logger named com.tibco inherits from com, which inherits from the root logger, global. Loggers are typically given names based on the package or class name of the component. Handlers must also have unique names. Because handlers don't inherit from other handlers, names can be much simpler and do not need to be based on inheritance.

Copyright © TIBCO Software Inc. All Rights Reserved. 191

Log Levels Each logger has a log level associated with it. Log levels control which messages pass through the logger. A logging message also has a level associated with it. Only a message with a level equal to or more severe than the level specified for the logger passes through the logger. The levels defined in the system are, in order of decreasing severity, — FATAL, ERROR, WARN, INFO, DEBUG, and TRACE.

In the following example, mylogger is assigned a level of DEBUG. This logger only forwards messages of level FATAL, ERROR, WARN, INFO, and DEBUG to the appropriate handlers. All TRACE messages are ignored.

If a log level isn't specified, the logger inherits the log level of its parent logger, such as the global logger. In this example, mylogger2 inherits log level INFO from its parent logger, global. Only FATAL, ERROR, WARN, and INFO messages are forwarded by mylogger2 to the registered handlers.

Handlers, like loggers, can also define a minimum level of message that they handle. In the following example from the logging system configuration file (logger.xml), appMonitor1 has been assigned a level of ERROR. This handler only outputs messages of a level equal to and more severe than ERROR, even though the logger it is registered with, global, forwards all messages of level INFO and more severe.

. . .

Understanding the Logging System Configuration File

The logging system configuration file, GI_HOME/logger.xml, specifies which logging messages are displayed, how they are displayed, and where they are sent.

You can also edit logger.xml, as well as create a custom logging system configuration file. See Creating a Custom Logging System Configuration File.

Memory Handler The memory handler stores a rotating cache of logging messages in memory. Note that some features of the General Interface Builder IDE require this handler. If it's not available, they won't function properly.

Copyright © TIBCO Software Inc. All Rights Reserved. 192

Memory Handler Attributes See Handler Attributes.

Memory Handler Properties The memory handler has the following property:

bufferSize : The size of the buffer and the number of records the buffer holds until it begins discarding old ones.

System Log Handler The system log handler prints logging messages to the General Interface Builder System Log palette in the IDE. For logging to work in the IDE, there must be only one system log handler.

System Log Handler Attributes See Handler Attributes.

System Log Handler Properties The system log handler has the following properties:

bufferSize : The size of the buffer and the number of records the buffer holds until it begins discarding old ones. format : The format of the delivered message. For definitions of formatting tokens, see jsx3.util.Logger.FormatHandler in General Interface API Reference. beepLevel : The message level that triggers a sound when printed to the System Log palette in the IDE. For more information, see Enabling Sound for Messages.

For sound to work properly, Firefox requires a plug-in that can play .wav files.

JavaScript Alert Handler The alert handler sends formatted messages to a JavaScript alert. The fatal handler, as configured in the default logger.xml file, ensures that fatal errors are displayed in a JavaScript alert. Fatal messages usually relate to failure to initialize the system or load an application and so may indicate that the output of other handlers isn't visible.

Copyright © TIBCO Software Inc. All Rights Reserved. 193

JavaScript Alert Handler Attributes See Handler Attributes.

JavaScript Alert Handler Properties The AlertHandler class has the following property:

format: The format of the delivered message. For definitions of formatting tokens, see jsx3.util.Logger.FormatHandler in General Interface API Reference.

The alert handler is registered with the jsx3.util.Logger logger to capture any errors not handled correctly by the other handlers.

Application Monitor Handler When an application monitor handler is registered for an application running outside of General Interface Builder, logging messages are sent to a separate browser window. This is useful for testing and debugging a deployed application.

The logging system configuration file provides a template for creating an application monitor handler. By default, the application monitor is disabled. For more information, see Creating an Application Monitor Handler.

Application Monitor Handler Attributes See Handler Attributes.

Application Monitor Handler Properties The application monitor handler has the following properties:

serverNamespace: The value must match the application namespace to associate the application monitor with the application. The namespace is specified in the Namespace field on the Deployment panel of the Project Settings dialog. Copyright © TIBCO Software Inc. All Rights Reserved. 194

field on the Deployment panel of the Project Settings dialog. If the serverNamespace property value is omitted, the application monitor is associated with the entire General Interface runtime rather than to a particular server instance. If this attribute is omitted, the disableInIDE and activateOnHotKey attributes have no meaning. disableInIDE: If set to true, the application monitor is disabled when the application is running in the IDE. If set to false, the application monitor is enabled in the IDE. The default setting is true. activateOnHotKey: If false, this monitor appears when the application is loaded and when the monitor is closed and a logging message is received. If true, this monitor is only launched when pressing the keyboard shortcut, Ctrl+Alt+m, in the running application. The default setting is false. format : The format of the delivered message. For definitions of formatting tokens, see jsx3.util.Logger.FormatHandler in General Interface API Reference.

Global Logger The global logger is the ancestor of all other loggers. Custom handlers and application monitor handlers can be registered with the global logger.

Alternately, handlers can be registered with a descendant logger.

Any logger can have the following attributes and nested entities:

Logger attributes: name : The unique name of the logger. level : Controls which messages pass through the logger. If this attribute is omitted, all log levels pass through the logger. See Log Levels. Nested entities — handler-ref: name : The name of the handler registered with the global logger. Custom handlers and application monitor handlers can be registered here.

Handler Attributes Handlers can include the following attributes:

name : The unique name of the handler. class : The name of the handler class. lazy : If true, the logging system waits for the class to load on its own. Use the lazy or require attribute but not both. require : If tru e, the class is loaded immediately after all statically loaded classes load using the dynamic class loading mechanism. If the specified handler class isn't statically loaded, use require="true", so the class is loaded and available when it's needed. For a list of statically loaded classes, see General Interface Framework Classes. Use the lazy or Copyright © TIBCO Software Inc. All Rights Reserved. 195

list of statically loaded classes, see General Interface Framework Classes. Use the lazy or require attribute but not both. level : Controls which messages the handler outputs. See Log Levels.

Sending Logging Messages

The simplest way to send a message to the logging system is with the jsx3.log() method. The jsx3.log() method is simply a shortcut for sending a logging message of level INFO to the global logger (jsx3.util.Logger.GLOBAL.info()).

In General Interface Builder, inserting this method in your JavaScript code:

jsx3.log("a logging message");

prints the following line to the System Log palette if the default logging file is used:

15:26:35.138 global (INFO) - a logging message

When a message is sent to the logging system, it is sent through a logger instance, which has a unique name and can also have a specified log level. A logging message also has a level associated with it. If the message's log level matches or exceeds the logger log level, the logger forwards it to the registered handler. For more information, see Log Levels.

For more precise control of the logger and level of a logging message, the Logger class can be used. The static Logger.getLogger() method returns a logger instance of the given name. Note that loggers are instantiated dynamically and the getLogger() method always returns a logger instance, even if it's not specified in the logging system configuration file.

For example,

var log = jsx3.util.Logger.getLogger("com.tibco");

The Logger class defines an instance method named for each level:

log.error("a terrible error occurred"); log.debug("x was equal to " + x);

There are several other methods of the Logger class that are useful for logging. For more information, see General Interface API Reference.

It is best programming practice to design logging messages as a permanent part of the source code. It's useful to partition the logging messages that an application or library creates by category. Each category corresponds to a unique logger instance. One practice is to define a logger for each class in a system with a name equal to the fully qualified class name. Another common practice is to divide the system into a set of subsystems, each with its own logger.

Logging messages can be stripped from code before the code is deployed. This is necessary under logging systems that use standard out, (in JavaScript) window.alert(), or some other mechanism that is highly visible to both the developer and the user of an application.

In General Interface applications, there's no need to remove the logging messages from the source code, because the logging system is configured through a declarative XML file. The advantage to leaving logging messages in your code is that you can diagnose errors after

deployment. Simply modify the logging system configuration file, run the deployed Copyright © TIBCO Software Inc. All Rights Reserved. 196

deployment. Simply modify the logging system configuration file, run the deployed application, and determine what the errors are by viewing the logging messages.

The logging system is designed to impact the performance of General Interface applications as little as possible. The following code is a good example of how to send a logging message efficiently when constructing the message is expensive. The code simply checks the logger to see whether the logging message passes the logger's level before creating and sending the message.

var Logger = jsx3.util.Logger; var log = Logger.getLogger("com.tibco"); if (log.isLoggable(Logger.INFO)) log.info(xmlDoc.toString()); // serializing XML may be // expensive

Viewing Logging Messages

There are two ways to view logging messages:

View in General Interface Builder

View at runtime

Viewing Logging Messages in General Interface Builder To show logging messages during development, General Interface Builder defines a handler class, jsx3.ide.SystemLogHandler. This class handles logging messages by printing them in the System Log palette located in the bottom panel of the user interface. This handler class is configured in the logging system configuration file just like any other handler.

The logging system configuration file, logger.xml, is located in the GI_HOME directory. The default configuration file includes the following lines that declare the General Interface Builder ide handler:

lazy="true">

value="jsx3.util.Logger.ERROR"/>

The following lines register the ide handler with the global logger:

Copyright © TIBCO Software Inc. All Rights Reserved. 197

By default, the ide handler is defined without a log level, so messages aren't filtered by level. Because the global logger is configured with level INFO, all messages of INFO and higher are forwarded to the ide handler and output to the System Log palette. TRACE and DEBUG messages aren't forwarded to the handler, regardless of the handler's level.

If you add level =" WARN" as an attribute of the handler element, the System Log palette would only display messages of severity WARN and higher, instead of INFO and higher. For example,

lazy="true" level ="WARN">

Viewing Logging Messages at Runtime Runtime access to the logging system is provided by the jsx3.app.Monitor handler class. This class handles logging messages by printing them in a separate browser window along side a running application.

An application monitor has three running modes that correspond to four stages of application development:

Off The monitor isn't configured in the logging system configuration file. This is the default setting. This is appropriate at the beginning of application development when all development occurs in General Interface Builder or at the end of development when the application is stable and error-free.

On The monitor is configured in the logging system configuration file with the activateOnHotKey property equal to false. This is appropriate when only developers are using a deployed application, because logging messages are always visible.

Hot Key Activated The monitor is configured in the logging system configuration file with the activateOnHotKey property equal to true. This is appropriate when a mix of developers and users have access to an application or when an error needs to be diagnosed in a live, deployed application.

To enable and use the application monitor,

1. Modify the logger system configuration file: Create a handler for each application you want to monitor. See Creating an Application Monitor Handler. Register the handler with a logger. See Registering an Application Monitor Handler with a Logger. 2. Run the application and see the log messages in the application monitor, which opens in a new browser window. If the activateOnHotKey property is set to true, press Ctrl+Alt+m to launch the monitor.

Copyright © TIBCO Software Inc. All Rights Reserved. 198

Creating an Application Monitor Handler A jsx3.app.Monitor handler must be configured for each monitored application. Add as many monitors as you'd like, each with a unique handler name, such as appMonitor1, appMonitor2, and so on. Monitors are matched up to applications by the serverNamespace property. The value for this property should be identical to the server namespace of the application, which is set in the deployment options (Project > Project Settings > Deployment).

Alternatively, if the serverNamespace property is omitted, the application monitor is associated with the entire General Interface runtime rather than to a particular server.

If you prefer, you can use logger.xml in the workspace/settings directory as a template and create a separate logger file for each deployment page. See Creating a Custom Logging System Configuration File.

In the following XML snippet of the logging system configuration file (logger.xml), two monitor handlers are created, one for each application.

require="true">

require="true">

If the specified handler class is not a statically loaded class, use require="true", so the class is dynamically loaded and available when it's needed. For a list of statically loaded classes, see General Interface Framework Classes.

Copyright © TIBCO Software Inc. All Rights Reserved. 199

Registering an Application Monitor Handler with a Logger Next, you need to register each monitor with a logger in the logging system configuration file. In the following XML snippet, two application monitor handlers are registered with the global logger.

Popup blockers may interfere with application monitors, since they exist in separate browser windows. If the monitor window does not appear as expected, verify that popup windows aren't blocked.

Creating a Custom Handler

A custom logging handler is another way to present logging messages. A custom handler could be used to send logging messages to a web service, write them to disk, send them to window.alert(), or show messages to the users of an application.

A custom logging handler, which must implement the abstract Handler.handle() method, is created by extending the jsx3.util.Logger.Handler class or one of its subclasses. This method defines how a logging message is handled. The following implementation, which simply stores a rotating cache of messages in memory, is from the MemoryHandler class:

MemoryHandler.prototype.handle = function(objRecord) { this._buffer.push(objRecord);

if (this._buffer.length > this._bufferSize) this._buffer.shift(); };

Custom handlers are configured in the logging system configuration file just like other handlers. Since custom handlers load after the logging system has been configured, they must be configured with the attribute lazy="true", so that the logging system won't throw an error on initialization if the handler class isn't loaded. Another option is to use the attribute require="true", so the class is loaded immediately using the dynamic class loading mechanism.

After calling the jsx3.lang.Class.defineClass() method to define a custom handler class, if using lazy="true", the jsx3.util.Logger.Handler.registerHandlerClass() method must be called to tell the logging system that the handler class has been defined. For example,

jsx3.util.Logger.Handler.registerHandlerClass( com.tibco.LogHandler.jsxclass);

Copyright © TIBCO Software Inc. All Rights Reserved. 200

Handlers may also define bean-style properties that can be configured in the logging system configuration file. Any property element nested within a handler element defines a name-value pair of a property of the handler. The handler class must have a bean-style setter method for any configurable property. For example, the handler class, FormatHandler, defines the property format, because it defines getFormat() and setFormat() methods. Therefore, any handler of a class that is a descendant of FormatHandler can be configured with the format property.

For more information, see jsx3.util.Logger.FormatHandler in General Interface API Reference.

Creating a Custom Logging System Configuration File

If you prefer, you can create a custom logging system configuration file and pass it to the deployed application as a deployment parameter at runtime. Custom logging system configuration files provide more flexibility. Development team members can use their own customized files as they develop applications instead of using one file shared by all. Also, you can create a configuration file for each application you deploy with only one application monitor enabled per file. This makes the file less cluttered and more readable.

For your convenience, a logger.xml template is provided for you in the workspace/settings directory. Open this template, add your custom loggers and handlers, and save it to any location with any name. When deploying the application, remember to copy this file to the web server with the other project files.

To pass the custom logging system configuration file as a deployment parameter, add the jsx_logger_config attribute to the script element on the page that launches the application. The value of the attribute should be an absolute URI or the relative path from the HTML launch page to the logging system configuration file.

For more information, see Deployment Parameters.

Copyright © TIBCO Software Inc. All Rights Reserved. 201

Chapter 17 Internationalizing and Localizing Applications

This chapter discusses how to internationalize and localize General Interface applications for an international audience.

About Internationalization and Localization API Classes for Localization Internationalized GUI Classes Localizing an Application

About Internationalization and Localization

Internationalization (i18n) and localization (l10n) of applications is the process of preparing an application for international audiences. This process involves separating locale-dependent resources from the program code. These resources can then be localized (translated) for other regions of the world (locales). The appropriate resource is then loaded at runtime according to the user's locale.

Definitions and Terms The following terms are some of the terms used in discussing internationalization and localization:

Internationalization is the process of preparing an application and its user interface so it can be used in more than one locale. An internationalized application is translation-ready. Internationalization is often abbreviated as 'i18n', where 18 represents the number of letters between 'i' and 'n.' Localization is the customization of application resources for a particular locale or region of the world. While internationalization generalizes an application for any locale, localization specializes the application for a single locale. Localization is often abbreviated as 'l10n', where 10 represents the number of letters between 'l' and 'n.' A locale defines a set of language and cultural conventions for the display and formatting of data in the user interface, such as labels, dates, , and messages. A locale is defined by a locale identifier which consists of a language identifier and/or a region identifier. Resourcing is the process of separating the locale-specific elements from the source code, so they can be externalized from the application. Resource bundles are used for resourcing strings and objects. Resource bundles are specialized files that contain a collection of translatable strings. A unique resource key identifies each string in the resource bundle. The hard-coded string in your application is replaced by a reference to the resource bundle and the resource key. These separate resource files are then sent to translators for translation into other languages. Unicode is a universal character encoding that provides a unique number for every character. Unicode is used in internationalizing applications, because it is independent of language, computer platform, and programming language. Examples of Unicode encoding include UTF-8 and UTF-16. For more information, see http://www.unicode.org/ .

Copyright © TIBCO Software Inc. All Rights Reserved. 202

API Classes for Localization

General Interface provides the following classes for localizing applications:

jsx3.util.Locale jsx3.util.DateFormat jsx3.util.MessageFormat jsx3.util.NumberFormat jsx3.app.PropsBundle

For more information on these classes, see General Interface API Reference (Help > API Documentation). jsx3.util.Locale General Interface 3.2 introduced a new class, jsx3.util.Locale, which represents a locale. A locale is a region of the world that shares a common language, writing, calendar, and so on. A locale is represented with a locale key, such as es_ES for Spanish in Spain. See Locale Keys.

The General Interface system, jsx3.lang.System, has a locale which determines the language and formatting of system messages. By default, the system locale is set automatically to the locale of the host web browser. However, the locale can be changed by calling the System.setLocale() method.

Each General Interface application, which is an instance of jsx3.app.Server, also has a locale. The server locale determines the locale of localized GUI controls that it contains. The application locale also determines which locale-sensitive resources are loaded into the application.

Locale Keys The locale key is the string representation of a locale, which includes a language or a language and a country in one of the following formats:

ll ll_CC

where ll is a lowercase, two letter, ISO 639 language code and CC is the optional, uppercase, two letter, ISO 3166 country code.

For a list of codes, visit these web sites:

International Organization for Standardization (ISO) - http://www.iso.ch/iso/en/ISOOnline.frontpage Language codes - http://www.loc.gov/standards/iso639-2/langhome.html Country codes - http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html

Copyright © TIBCO Software Inc. All Rights Reserved. 203

DateFormat, NumberFormat, and MessageFormat Three classes in the jsx3.util package form the foundation of the internationalization and localization services of General Interface: DateFormat, MessageFormat, and NumberFormat. These classes are internationalized, because they have a constructor that takes an arbitrary locale object as a parameter. The behavior of an instance of each class is dependent on the specified locale.

General Interface leverages data from the Common Locale Data Repository to localize these classes. The following locales from the CLDR are included with General Interface.

General Interface Locales Language ISO 639-1 Code ISO 639-1 Code + ISO 3166 Code

Arabic ar

Chinese zh zh_CN, zh_HK, zh_TW

Danish da da_DK

Dutch nl nl_BE, nl_NL

English en en_AU, en_CA, en_GB, en_NZ, en_US, en_ZA

French fr fr_FR, fr_CA, fr_BE

Finnish fi fi_FI

German de de_DE

Greek el el_GR

Hebrew he he_IL

Indonesian id id_ID

Italian it it_IT

Japanese ja ja_JP

Korean ko ko_KR

Norwegian nn nn_NO

Polish pl pl_PL

Portuguese pt pt_BR, pt_PT

Russian ru ru_RU

Spanish es es_MX, es_ES, es_US

Swedish sv sv_SE

Thai th th_TH

Turkish tr tr_TR

Vietnamese vi vi_VN

Copyright © TIBCO Software Inc. All Rights Reserved. 204

DateFormat The DateFormat class formats and parses dates in a localized manner. Months and days of the week are localized. Additionally, factory methods are available for creating formats that are appropriate for a particular locale.

NumberFormat The NumberFormat class formats numbers in a localized manner. Number symbols, such as the negative sign, decimal symbol, and percent symbol, are also localized. In addition, factory methods are available for creating formats that are appropriate for a particular locale.

MessageFormat The MessageFormat class constructs messages from a format and various inputs. It's localized, because it can format inputs according to both DateFormat and NumberFormat. jsx3.app.PropsBundle The jsx3.app.PropsBundle class handles localized loading of resources. A localized resource is a collection of dynamic properties files that define a set of properties localized for one or more locales. For an example of a properties bundle file, see GI_HOME/JSX/locale/locale.xml.

The directory structure of a properties bundle is as follows:

bundle_name.xml - the file containing the properties of the default locale and metadata describing the locales that are available in other files. For example, locale.xml. bundle_name.locale_key1_.xml - the file containing properties localized for locale locale_key1. For example, locale.fr.xml. bundle_name.locale_key2_.xml - the file containing properties localized for locale locale_key2. For example, locale.es.xml.

The default locale file in the properties bundle should be formatted as follows:

...

... ...

Any other file in the same properties bundle should be formatted as follows:

Copyright © TIBCO Software Inc. All Rights Reserved. 205

... ... ... ...

PropsBundle.getProps() An instance of the PropsBundle class is obtained programmatically with the static factory method, PropsBundle.getProps(). The first argument for this method is the base path of the localized resource. In this example, it would be bundle_name.xml preceded by the path to the directory containing the bundle. For example, path_to_bundle/locale.xml. The second argument is an instance of jsx3.util.Locale. The factory method loads the files appropriate for the requested locale based on the metadata contained in the default locale. For more information, see General Interface API Reference.

Key Fall-through The PropsBundle class provides for key fall-through. If a key isn't found in the properties file of a particular locale, the value from the next less-specific locale is used. For example, if an instance of PropsBundle with a locale of en_GB is queried for a key, it checks the properties of locale en_GB. If the key isn't found, it checks en, and finally, the properties of the default locale until a key is found.

Internationalized GUI Classes

Five GUI controls are internationalized in General Interface:

DatePicker TimePicker Select Menu Matrix

DatePicker and TimePicker The DatePicker and TimePicker classes use localized properties related to date format to display information appropriate for the locale of the application. DatePicker and TimePicker are localized for the locales listed in API Classes for Localization.

Copyright © TIBCO Software Inc. All Rights Reserved. 206

Select, Menu, and Matrix The Select, Menu, and Matrix classes display messages in the user interface. For example, when a Menu that doesn't have a CDF data source is selected, a message displays: - No Data -. The messages for these classes are externalized in the system properties bundle ( JSX/locale/locale.xml) and are therefore translation-ready (i18n). General Interface provides translations for the following locales.

Translations for GUI classes and system progress loader Language ISO 639-1 Code

Chinese h_CN, zh_TW

English en

French fr

German de

Japanese ja

Korean ko

Portuguese pt

Russian ru

Spanish es

Localizing an Application

Localizing an application involves the following steps:

Externalize locale-dependent messages and settings in a properties bundle Load the properties Set the application locale Set and use properties Localize CDF GUI controls

Externalizing Messages and Settings The first step towards internationalizing an application is to externalize all messages and settings that are locale-dependent. These are externalized as properties in a properties bundle. A properties bundle is a resource bundle where the type of resource is dynamic property. Properties bundle files contain locale-specific objects, such as menu and button labels in the application user interface.

Creating Properties Bundle Files To create a new single-file formatted, properties bundle in the Properties Bundle editor in General Interface Builder, complete these steps:

1. Choose File > New > Properties Bundle to open the editor.

2. Right-click the table header in the editor and choose Add New Locale. Copyright © TIBCO Software Inc. All Rights Reserved. 207

2. Right-click the table header in the editor and choose Add New Locale. 3. Type the key for the locale in the Add Locale dialog, such as en_US for US English or es for Spanish. For information on keys, see Locale Keys. Click OK.

4. Click each Default cell and type the value for the default language. For example, for menu_new, type New. 5. Click each cell of the new locale column and type the value for the new locale. For example, for menu_new, type Cree for the Spanish locale. If a value is specified, the cell background is white. Otherwise, the inherited value from the next less-specific locale is shown in a gray cell.

When authoring dynamic properties and properties bundle files using non-ASCII characters and non-western languages, save the file in a format that supports such characters, such as UTF-8 or UTF-16. See Character Encoding.

6. Save the file with the .xml extension in the jss folder of your project.

Properties bundles can be authored in General Interface Builder in single-file format only. However, the multiple-file format may be more efficient for large collections of properties.

Loading Properties Bundle Files Automatically To set the properties bundle file to automatically load when the application loads, complete the following steps in General Interface Builder:

1. Right-click the properties bundle file in the Project Files palette. 2. Choose Auto Load. The file now displays in a bold font in the Project Files palette.

Using Properties Any property contained in a dynamic properties file or properties bundle and loaded by an application is available to the application in the following ways:

Programmatically through the jsx3.app.Server.getProperties() method and the

jsx3.app.Properties API. For example, the following statement: Copyright © TIBCO Software Inc. All Rights Reserved. 208

jsx3.app.Properties API. For example, the following statement: myApp.getProperties().get("prop_key1"); evaluates to the value of the property, prop_key1, appropriate for the current locale of myApp. As dynamic properties of classes extending jsx3.gui.Painted. When a dynamic property of an instance of Painted is set, that property is expanded to the current value of the property stored in the server's properties object before the instance is painted. A dynamic property of an instance of Painted can be set with the jsx3.gui.Painted.setDynamicProperty() method. The Properties Editor palette in General Interface Builder allows you to assign dynamic properties to object properties. Right-click the Value cell of a property and select a dynamic property from the context menu or type the property key (ID) in the Value cell.

The Properties Editor palette also allows you to assign properties from a properties bundle file. To enter a property from a properties bundle file, type the property key (ID) in a Value cell of the Properties Editor palette.

Setting the Application Locale The locale of an application is determined in the following order, with the first one taking precedence over the others:

1. The last value passed to Server.setLocale(). 2. The default locale value specified in the Project Settings dialog and stored in the application configuration file (config.xml), if specified. See Deployment Panel. 3. The current system locale, which is specified by: a. The last value passed to System.setLocale() b. The locale as determined from the host browser c. en_US if the locale could not be determined from the browser

Default Locale The locale as determined by the browser may not be the most appropriate locale for an application. If an application must always display in one locale, regardless of the user, use the Default Locale setting in the Project Settings dialog. See Deployment Panel.

Server.setLocale() Method In some situations, specifying a default local isn't the best solution. In the following cases, use Server.setLocale() to set the locale:

The user can choose a locale. The locale that the user wants is stored on a server.

Note that after the Server.setLocale() method is called, the state of the application may be out of synchronization with the new locale. Call the Server.reloadLocalizedResources() method to reload any localized properties that have already been loaded by the application. Additionally, the view of the application may have to be repainted.

The following sample code demonstrates how to use the Server.setLocale() method.

Copyright © TIBCO Software Inc. All Rights Reserved. 209

/** * Function is executed when user selects the language on the Tools menu. * @param objMenu {jsx3.gui.Menu} * @param strID {String} the CDF record ID of the execute menu record. */

localization.doLoadLocalizeResource = function(objMenu, strID) { var objServer = localization.APP;

var locale = strID != "-1" ? Locale.valueOf(strID) : null;

LOG.info("Setting application locale to " + locale + ".");

// Set the locale of the server to the selected locale objServer.setLocale(locale);

// We need to tell the server to reload any localized properties objServer.reloadLocalizedResources();

// Reset the CDF cache of the menu since dynamic properties are used // in the source XML file.

objMenu.resetXmlCacheData();

// Menus cache their drop-down HTML content, so clear this. objMenu.repaint();

// Repaint the smallest region of the application that is localized. // Non-CDF control Stack with localized label text objServer.getJSXByName('blkApp').repaint();

}

Localizing CDF GUI Controls Some CDF attributes may have values that represent dynamic properties. These attributes must be of the form {key} where key is the key of a dynamic property of the control's server. If the dynamic property exists, the value of the attribute is changed to the value of the dynamic property when the XML source document is first loaded. Otherwise, the attribute is left unchanged.

For example, if you want to localize a menu using the properties bundle file, you would enter keys from the properties bundle file as the values for the jsxtext attributes, such as jsxtext="{menu_new}".

Then, if the locale is Spanish, the following keys are replaced with the appropriate values in the properties bundle file:

menu_new is replaced with Cree

menu_open is replaced with Abra Copyright © TIBCO Software Inc. All Rights Reserved. 210

menu_open is replaced with Abra menu_save is replaced with Salve

The replacement of key attributes with the property value occurs only once per XML document. The CDF attributes that are converted automatically include: jsxtext, jsxtip, jsximg, jsxstyle, jsxclass, and jsxkeycode. After the conversion, which occurs before the control is painted, the original value of any key that has been converted is lost. Therefore, changing the value of a dynamic property after the conversion doesn't change the CDF attribute value. Do not set CDF attributes programmatically to a property key. Instead, set CDF attributes to the property value programmatically. You can also use the CDF.convertProperties() method to perform the conversion.

Custom Localized Logic Applications may incorporate even more advanced localized functionality with custom localized code. Localized code would typically query the application server instance for its current locale and then modify its behavior based on the locale. This is a good strategy when localized behavior cannot be represented only as externalized string values.

In the following example, an alert displays on July 4 if the locale is US English.

var today = new Date(); if (myApp.getLocale.equals(jsx3.util.Locale.US) && today.getMonth()h1. 7 && today.getDate()4) { myApp.alert("Holiday","Today is Independence Day"); }

Copyright © TIBCO Software Inc. All Rights Reserved. 211

Chapter 18 Deploying Applications

This chapter describes how to deploy General Interface applications.

About Application Deployment Deploying as a Full Console Application Deploying as a Non-Console Application Overriding the Application Base Directory Posting Application Files Accessing Deployed Applications Deployment Parameters Using Cross-Domain GI

About Application Deployment

Deploying a General Interface application is simpler than deploying conventional web-based applications. The process consists of creating an HTML or XHTML page or link for launching the application and copying required files and folders to the web server. It isn't necessary to package the files into an archive.

Deployment consists of configuring the application for one of the following access models:

Full console application The application runs in a dedicated browser window. The application is launched when an end user opens an HTML or XHTML file or clicks an application hyperlink in an existing web page. Non-console application The application is inserted into an existing web page as a div element and only uses a portion of the page. A web page can contain multiple General Interface applications.

General Interface Builder provides the Deployment Utility for generating the HTML or XHTML code for launching applications. This chapter describes how to use the Deployment Utility and configure your application.

Copyright © TIBCO Software Inc. All Rights Reserved. 212

Deploying as a Full Console Application

Full console applications occupy the entire browser window, and run independently of other deployed applications.

To launch a full console application, a launch page is required. A launch page is an HTML or XHTML file that loads the application in a browser window. This file initializes the General Interface environment, loads your application into the browser, and renders it to the entire web page. You can create a new launch page or use the provided parameterized launch pages, shell.html or shell.xhtml.

There are two ways to launch a full console application:

Create a separate launch page Create a launch hyperlink and insert it into an existing web page

Creating a Launch Page You can use the HTML Page panel of the Deployment Utility to create an HTML or XHTML launch page that launches the application as a full console application.

To create a page for launching a full console application, complete these steps:

1. Select Project > Deployment Utility from the General Interface Builder menu. Copyright © TIBCO Software Inc. All Rights Reserved. 213

1. Select Project > Deployment Utility from the General Interface Builder menu.

2. Click the Browse button , to navigate to a directory, and type the launch file name, for example launch.html or launch.xhtml. If you're creating an XHTML launch page, check the XHTML checkbox and use the .xhtml extension. Click Save.

XHTML launch pages are used to verify the behavior of an application that runs as XHTML, such as a launch DIV on an XHTML portal page.

3. On the HTML Page panel, click the Create button to create the launch file. A new file is created in the selected directory. 4. Close the Deployment Utility. 5. Open the launch page in a web browser. The General Interface software initializes and your application displays. Before proceeding, you can view the source of the HTML page that was automatically generated. 6. Select View > Source from the browser menu to view the source of this page. The Deployment Utility generated the following lines of HTML markup: For XHTML files only, a DOCTYPE declaration is required before the html root element. An XHTML namespace attribute is also required for the .

The body element, which defines general window properties.

The div element, which provides the HTML container for your General Interface application. You can change the style of this element by modifying its CSS Copyright © TIBCO Software Inc. All Rights Reserved. 6.

214

application. You can change the style of this element by modifying its CSS properties.

. ... script element ... .

The script element, which loads the General Interface runtime, passes the project path to it, and specifies how classes are loaded.

The script element contains the following:

src="JSX/js/JSX30.js" The relative path from the web page to the General Interface runtime file. jsxapppath The relative path from the web page to the project directory. 7. Modify the HTML markup as needed to customize the page.

Creating a Launch Hyperlink To create a launch hyperlink for you application, use the Launch Hyperlink page of the Deployment Utility. Copy and paste the generated HTML markup into an existing web page. When you click this hyperlink on the web page, a parameterized launch page (shell.html) is called and the application is launched as a full console application.

To create a launch hyperlink to insert into an existing web page,

1. Select Project > Deployment Utility from the General Interface Builder menu to open the Deployment Utility. 2. Click the Launch Link tab.

Copyright © TIBCO Software Inc. All Rights Reserved. 2.

215

3. Copy the text in the lower pane of the tab and paste it into an HTML page. The following template is used for launch link HTML markup:

Launch Application

The href attribute of the element a contains the following:

shell.html The relative path from the web page to the parameterized application launch page. shell.html is located in the GI_HOME directory. jsxapppath The relative path from shell.html to your project directory. Launch Application The text of the hyperlink for launching the application. 4. Close the Deployment Utility. 5. Modify the HTML markup as needed to customize the hyperlink. For example, change the hyperlink text to the name of the application.

Deploying as a Non-Console Application

A non-console application is a deployed General Interface application that occupies a portion of a web page. Multiple General Interface applications can be deployed in a single web page. This is useful if you have multiple applications that interact with each other.

Non-console applications can be inserted into an existing web page using div elements. When the web page is loaded, the General Interface Framework initializes. Then the General Interface applications are loaded.

Using a DIV Element Use the Inline DIV tab of the Deployment Utility to automatically generate the HTML markup for the div element. Simply copy and paste this generated markup into the existing web page.

To generate the HTML markup for a div element,

1. Select Project > Deployment Utility from the General Interface Builder menu. 2. Click the Inline DIV tab.

Copyright © TIBCO Software Inc. All Rights Reserved. 2.

216

3. Copy the text in the lower pane of the tab and paste into an HTML page. The following template is used for creating a div element:

The script element contains src=" JSX/js/JSX30.js", which is the relative path from the web page to the General Interface runtime file, and jsxapppath, which is the relative path from the web page to the project directory.

4. Close the Deployment Utility. 5. Modify the HTML markup as needed to customize the page.

To insert multiple applications in one web page, the src attribute must be identical and the path to the JSXAPPS directory must be the same. For a parameterized src URI, only the attribute before the "?" needs to be identical. The query can be different. For example, these are considered identical even though the parameters are different. Note that the path to the JSXAPPS directory is the same, as required. src=" JSX/js/JSX30.js?jsxapppath=../workspace_/JSXAPPS/project1_path_"and src=" JSX/js/JSX30.js?jsxapppath=../workspace_/JSXAPPS/project2_path_". For more information on parameters, see Deployment Parameters.

Example General Interface Builder generates the following div elements for two of the General Interface Builder sample applications:

Copyright © TIBCO Software Inc. All Rights Reserved. 217

When this HTML markup is inserted in an HTML page, the applications are loaded in the same HTML page.

Deployed Applications and the Progress Bar To prevent General Interface progress bars from overlapping when deploying multiple applications in the same page, add position:relative in the div element of both deployed applications. For example,

The following figure shows an example.

Copyright © TIBCO Software Inc. All Rights Reserved. 218

Overriding the Application Base Directory

In some situations, you might need to override the application base directory. Overriding the application base directory is useful if other aspects of your development process, such as source control or access rights, restrict where files can reside on the disk. The General Interface jsxappbase parameter provides this flexibility.

To override the application base directory (jsxappbase), do the following:

Copyright © TIBCO Software Inc. All Rights Reserved. 219

1. Add this record to the project configuration file (config.xml):

path_to_content_folder/

2. Then save the config.xml file to the project folder in the JSXAPPS directory.

If the directory structure looks similar to the following figure, you would add this record to config.xml :

content/

Once the application directory is overridden, all URIs used in the application resolve relative to the base directory rather than to the config.xml file.

For more information on how URIs are resolved, see URI Resolution.

Posting Application Files

The final deployment step is to post General Interface software and your applications on an HTTP or HTTPS web server. Unlike most web applications, General Interface does not run in the application server. Instead, all browser-compatible files, such as .js, .xml, .xsl, .css, and .gif, are served to the browser and executed on the client.

General Interface is compatible with all HTTP/S web servers and requires no additional executables to be installed, either on the server or the client.

To finish deploying the General Interface application,

1. Copy the following files and folders to a directory accessible to the web server. The files can be in any location on the server. JSX folder

Copyright © TIBCO Software Inc. All Rights Reserved. 1.

220

=If you're developing your applications using the General Interface debug build (tib-gi-version-pro-debug), be sure to deploy the standard JSX folder from a deploy build (tib-gi-version-pro or tib-gi-version-pro-max). The debug JSX folder has additional debugging code and therefore runs slower. For more information on these release builds, visit Developer Network at http://www.generalinterface.org.

JSXAPPS folder which contains the project to be deployed Any other files in your workspace directory required by the application, including add-ins and prototypes

The addins and prototypes folders must be at the same level as the JSXAPPS folder to be available at runtime.

All launch pages for the applications shell.html or shell.xhtml is required if you deployed your application as a launch hyperlink. Also, shell.html must be located at the same level as the JSX folder. These files are located in the GI_HOME. See Creating a Launch Hyperlink. logger.xml, located in the GI_HOME directory, can be used to monitor logging messages from the deployed application. Modify this file as needed. See Logging and Application Monitors. jxs3.gui.window.html/.xhtml if you're using the jsx3.gui.Window class. Copy the file(s) from the GI_HOME directory. 2. Modify the relative URLs in the HTML markup generated by the Deployment Utility if your directory structure on the web server is different from the directory structure during development. For example, you might need to modify the application path, src path, path to shell.html, and so on. 3. Set access rights on the web server in the same manner as any standard HTTP/S accessible resource.

For dynamic properties files, be sure to use the .xml extension as some servers won't recognize the .jss extension. By default, General Interface, version 3.2 and higher, supports the .xml extension, which is the recommended file extension. See Dynamic Properties Files. If you continue to use the .jss extension, you might need to add a new Mime Type to the server.

Copyright © TIBCO Software Inc. All Rights Reserved. 221

Deployment Examples Because General Interface deployment is extremely flexible, there are few restrictions on where your files are located on the web server. Folders and files can be nested and in different locations. Due to the relative URI functionality introduced in General Interface 3.2, projects can be easily renamed and moved to new locations. For more information, see URI Resolution.

In some cases, the General Interface runtime is deployed in one location by the system administrator and developers deploy their applications to another location on the same web server. The following example demonstrates this scenario on a UNIX machine:

The system administrator installs General Interface on the web server at this location — /var/www/htdocs/gi/ version_number/ This directory contains: shell.html (launch page) JSX folder Other appropriate files The developer deploys the application here: /home/username/htdocs/JSXAPPS/app1 And also installs a web page containing the application here: /home/username/htdocs/app1/index.html

In another example, as shown in the following figure, the application launch pages, General Interface runtime, and application are deployed to a folder called gideploy. However, each of these is in a different folder. The launch pages are in an apps folder, General Interface is in a gi/3.2 folder, and the deployed application is in a gihome folder.

The script element on the app1.html launch page shown in the previous figure would look like this:

Copyright © TIBCO Software Inc. All Rights Reserved. 222

Accessing Deployed Applications

This section describes how end users can access General Interface applications.

To access an application in a browser on the client machine, navigate to the URL where the application files are deployed.

For example, if the application is deployed to the URL http://www.myserver.com, the user accesses the application by navigating to:

http://www.myserver.com/project_launch_file_path

where project_launch_file_path is the path to the HTML file for launching your application, relative to the HTML doc root directory of the HTTP server.

Deployment Parameters

This section describes how to configure deployment for individual General Interface Builder applications and the JSX system, which is the General Interface runtime.

There are two areas to consider when deploying GI applications:

Configuring Deployed Applications Configuring the Runtime

Configuring Deployed Applications There are two possible ways to configure the deployment of a General Interface application:

For each deployment, modify the HTML script element(s) on the web page that launches the application(s). For each application, modify the application configuration file (config.xml).

When the deployed application is launched, deployment parameters are passed to the General Interface runtime in the following order, with the first one taking precedence over the others:

1. Attributes of the HTML script element. 2. Query parameters of the src attribute of the script element. 3. Configuration parameters stored in the application configuration file, config.xml.

Copyright © TIBCO Software Inc. All Rights Reserved. 223

HTML Script Element One mechanism for configuring an application is to modify the script element of the HTML launch page where the application is deployed. Deployment parameters can be included as attributes of the script element or as query parameters in the src attribute of the script element.

General Interface provides several built-in parameters, such as jsxappns, jsxapploader, and jsxapppath. Custom attributes or parameters can also be added to the script element. For example, this mechanism can be used to communicate session information from a web server to a General Interface application. However, all attributes beginning with jsx are reserved for General Interface.

All attributes of the script element are deployment parameters used to configure the application except these reserved HTML attributes — id, space, type, charset, defer, src, and language.

The following parameters are significant in the General Interface runtime:

jsxappns. Application namespace. For example, jsxappns="myAPP". Because every application deployed on a single page must have a unique namespace, overriding the namespace can be useful when an application is multi-instantiated on the same page. However, the application must be written to never reference its namespace directly. jsxapploader. Specifies what type of progress bar to load when the application launches. For example, jsxapploader="0". 0 = standard progress bar 1 = portlet, subordinate progress bar

To prevent General Interface progress bars from overlapping when deploying multiple applications in the same page, see Deployed Applications and the Progress Bar.

jsxapppath. The path to the application. For example, jsxapppath="../workspace/JSXAPPS/samples/chart".

For examples of how to use these deployment parameters in the script element, see the following examples.

In this example, the jsxapppath attribute contains the application path.

In this example, the application path, jsxapppath, is passed as a parameter to the General Interface runtime file, JSX/js/JSX30.js.

Copyright © TIBCO Software Inc. All Rights Reserved. 224

To pass multiple parameters, use an ampersand (&). This example passes the application path and the progress bar loading as parameters.

Including the following log statement in a JavaScript file:

jsx3.log("The value of jsxprop1 is " + jsx3.getEnv("jsxprop1"));

would print the following output to the system log: The value of jsxprop1 is value1.

Using Cross-Domain GI

The cross-domain loading feature allows you to load the General Interface runtime and your application from different security domains, increasing deployment flexibility and allowing you to do the following:

Host the GI runtime on a content delivery network (CDN) for improved load times. Use a single runtime installation for several General Interface applications, including applications that are hosted on different domains. This can improve load time since the GI runtime may already be in the browser cache. Include General Interface applications in blogs and other management systems where hosting files is not permitted. Allow a system administrator to install a single instance of the General Interface runtime to be shared across an organization to simplify application deployment for users.

In a build of GI that supports cross-domain loading all XML and XSL data file have been converted into a JSONP-like format, which supports loading across domains.

For example, the file JSX/locale/messages.xml,

...

becomes JSX/locale/messages.xml.js,

Copyright © TIBCO Software Inc. All Rights Reserved. 227

jsx3.net.Request.xdr( "jsx:/locale/messages.xml", "\n\n \n \n \n \n \n ... ");

This conversion is completely automated by the build process, which uses the new JsEncodeTask task to compile the XML/XSL resources. The task is turned off by default to avoid some code and data bloat. To enable it you must set the build.gi.xd build property to true, either in build/user.properties or on the command line:

$> ant -Dbuild.gi.xd=true

A pre-built cross-domain ready distribution of GI is available for download as well.

If you want to host your application on a separate domain as well, you must process the XML and XSL resources in your application in a similar manner. You can do so using the same Ant task that General Interface uses. There is also a command line interface for the encoder that comes with the General Interface source distribution:

$> cd WORKSPACE/JSXAPPS/myApp $> find . -name "*.xml" -or -name "*.xsl" \| xargs \ sh GISRC/build/tools/bin/jsencode.sh -user ../

Deployment When deploying an application cross-domain you must modify the GI launch page to indicate the domains from which resources should be loaded in the cross-domain manner. Consider the following example:

The GI launch page is http://www.example.com/myApp.html The GI application is http://apps.example.com/JSXAPPS/myApp The GI runtime is http://cdn.host.com/gi/3.9.0

Then the launch page should include the following:

Launch Application

Copyright © TIBCO Software Inc. All Rights Reserved. 234

4. Use the application launch page to run the deployed application and test the performance.

For example, to launch your application using shell.html as the launch page, enter a URL similar to the following in the browser: http://web_server/deploy_dir/shell.html?jsxapppath=../JSXAPPS/MyProjectDir where web_server is the address of the web server, such as localhost:8080 or mywebserver.com, deploy_dir is the deployment directory on the web server, and MyProjectDir is the application project directory.

Copyright © TIBCO Software Inc. All Rights Reserved. 235

Chapter 20 Asynchronous Modular Platform

This chapter describes the Asynchronous Module Platform (AMP) and its features.

About AMP Extension Point Contract and Processing AMP Applications and Built-In Extension Points Plug-ins with Extensions and Extension Points Application Techniques and Utilities

About AMP

The Asynchronous Modular Platform (AMP) is a General Interface framework for building modular and high-performing enterprise-sized General Interface applications. AMP is an optional part of General Interface and is packaged as an add-in. AMP provides the libraries and templates that allow you to easily create extensible and loosely-coupled application components and combine them into a working whole. The design of AMP is inspired by the plug-in architecture.

AMP Capabilities This section describes common pitfalls of General Interface application development and how AMP helps overcome them to improve code quality and manageability.

Component Files Component files that are unnecessarily large often contain many objects that are initially invisible and may only become visible during uncommon use cases.

AMP helps manage component files so that they do not burden the overall code base. From the beginning of application development, AMP encourages decomposition of applications into constituent parts.

Asynchronous Resource Loading Dynamic class loading and synchronous resource loading are convenient for developers, but may cause major performance bottlenecks in a deployed application.

AMP makes working with asynchronously loaded resources as easy as working with synchronously loaded ones. By using asynchronous resource loading, developers can avoid the performance problems associated with dynamic class loading and synchronous resource loading. AMP also enforces asynchronous behavior by providing only asynchronous APIs.

Code Components Large, successful applications generally use a publish-subscribe pattern to notify application components of a change in application state. Unfortunately, this paradigm typically requires a great deal of boilerplate code, plus careful attention to components as they are added or removed from the application.

AMP allows you to define these types of dependencies declaratively in XML, thereby significantly reducing the amount of required boilerplate code. Copyright © TIBCO Software Inc. All Rights Reserved. 236

significantly reducing the amount of required boilerplate code.

Application Extensibility It is common for large applications to lack extensibility features. Extending this type of application typically involves both coding the extension and modifying the application. If such an application is extensible, it is because the developer has spent considerable effort to design an extensible framework.

AMP provides a modular framework that is engineered around the needs of extensible General Interface applications. The AMP infrastructure encourages and when appropriate, enforces, the design of application components according to well-defined interfaces that you can extend in the future without modifying the application.

Scaling and Complexity Adding new components can increase design complexity. In a poorly designed system, complexity can increase very rapidly (polynomially) as components are added, because each existing component must be modified to take into account interactions with every new component.

AMP reduces this complexity by encouraging application components to communicate with each other through well-defined interfaces, even for internal system components.

Testing In most application development environments, special care is required to build applications that can be easily tested. Because developers are usually pressed to complete development quickly, they may employ large, monolithic components, and create ad-hoc frameworks that are not designed with testing in mind.

AMP addresses testing concerns by encouraging developers to create modular components and by offering an application framework with generous log coverage and benchmark statistics.

Extension Point Contract and Processing

This section describes how extension points and contracts are processed.

Extension Points and Contracts Each extension point defines a contract that all of its extensions must adhere to. The extension point is the controller of the relationship with its extensions. The extension point processes its extensions (it is not processed by its extensions). Therefore, all extensions must meet the expectations of the extension point contract in order for the extension point to be able to process them.

Because extension points and extensions are declared in XML, the basic form of the contract must be defined in XML. Significant flexibility is permitted when augmenting the basic pattern. The most common way of processing extensions is to use the processExts() method of the jsx3.amp.ExtPoint class. The following example uses the onLoad() method of a subclass of jsx3.amp.PlugIn.

Copyright © TIBCO Software Inc. All Rights Reserved. 237

CustomPlugIn.prototype.onLoad = function() {

var log = this.getLog(); this.getExtPoint("xp1").processExts(function(ext, xml) { log.info("Processed XML " + xml + " from extension " + ext + "."); }; };

The processExts() method implements a visitor pattern. The parameter to the method is a function that is called once for every child element of the XML declarations of every extension to the extension point.

The following extension declaration

logs the following messages when the com.tibco.example.p1 is loaded.

[INFO] Processed XML from extension com.tibco.example.p1.x1. [INFO] Processed XML from extension com.tibco.example.p1.x1.

It is a good practice to document the contract of the extension point with its declaration using an XML comment, as shown above, or with arbitrary nested XML. Any nested XML is allowed, provided that it is not in the AMP XML namespace.

AMP recognizes a processor child element of the extension-point element. This allows the extension point to define the processing visitor declaratively rather than in code. If the processor is declared in the extension point definition, the parameter to the processExts() method is optional. When no parameter is passed, a processor is created via the getProcessor() method of the jsx3.amp.ExtProc class. See the General Interface API Guide for more information.

Processor Types This section describes the built-in processor types that cover the most common extension point contracts.

Type eval The inner text content of every extension child element is taken as a script and evaluated in the context of the extension object. The extension elements may define the attribute load="true". In this case, the plug-in that defines the extension is loaded before the script is evaluated. Therefore, the script can be evaluated synchronously (load="false") or asynchronously ( load="true"). Example (Descriptor file):

Copyright © TIBCO Software Inc. All Rights Reserved. 238

this.getPlugIn().doSomething();

Example (Processing code):

this.getExtPoint("xp").processExts();

Type return The inner text content of every extension child element is taken as a script and evaluated in the context of the extension object. The value of the evaluated script is returned by the extension processor. Example (Descriptor file):

this.getPlugIn()

Example (Processing code):

this.getExtPoint("xp").processExts().each(function(rv) { jsx3.log("Script returned: " + rv); });

In this case, the extension point contract does not specify whether or not the extending plug-in is loaded before the script is evaluated. Either the extending plug-in must be able to evaluate the code without being loaded or the processing plug-in must load the extending plug-in before evaluating the script.

Type return-async This type is the same as the return type, except that the extension elements may declare load="true". In this case, the plug-in that declares the extension is loaded before the script is evaluated. The processor object returns an object of type jsx3.$AsyncRV instead of the actual value of the script, because the script may be evaluated asynchronously. Example (Descriptor file):

this.getPlugIn()

Example (Processing code):

Copyright © TIBCO Software Inc. All Rights Reserved. 239

this.getExtPoint("xp").processExts().each(function(rv) { rv.when(function(v) { jsx3.log("Script asynchronously returned: " + v); }); });

Type instantiator The instantiator type instantiates an object of a custom class for every child element of every extension declaration. The instance-class attribute should be the fully qualified name of a General Interface class. The class must define a constructor with the following signature:

function init(ext : jsx3.amp.Ext, xml : jsx3.amp.XML);

Example (Descriptor file):

Example (Processing code):

this.getExtPoint("xp").processExts().each(function(o) { jsx3.log("Instantiated: " + o); });

Custom Processor Types In addition to the built-in types, you can register your own custom extension processor types to use with declarative extension processing.

To register a custom type, call the static method jsx3.amp.ExtProc.addProcessorFactory. The first parameter is the type key. Any processor elements whose type attribute matches this parameter will be handled by this custom type. The second parameter is the processor factory function. This function is called once for each processor element with a matching type attribute. The function is passed the processor element and should return an object that implements a process() function.

jsx3.amp.ExtProc.addProcessorFactory("customType", function(procXML) { return {process: function(ext, xml) { return procXML.attr("prefix") + "-" + xml.attr("id"); }}; } );

Registering this custom processor type allows the following processor definition in the plug-in descriptor file:

Copyright © TIBCO Software Inc. All Rights Reserved. 240

When a processor is defined declaratively for an extension point in the plug-in descriptor file, the argument to the processExts method is optional:

this.getExtPoint("xp").processExts().each(function(e) { jsx3.log("Extension: " + e); });

The processExts method returns the list of values returned by the process method of the processor, which was returned by the processor factory. The following extension definition

would log the following when the extension processing code included above executes

Extension: p-001 Extension: p-002

Extending PlugIn, ExtPoint, and Ext You can extend the AMP classes PlugIn, ExtPoint, and Ext and use them in the AMP metadata. The following example shows how to use a custom plug-in class.

The class attribute is the fully-qualified name of the class constructor function. The class must be defined before the plug-in is registered, because the plug-in cannot be instantiated if the class is not loaded. Therefore, define the class inline in the plugin.xml descriptor file (in a script element) or in an early load resource of a required plug-in. This also holds for custom extension point and extension classes.

You can use custom extension point and extension classes by declaring the class attribute of their declarations.

Extending one of these classes allows you to define custom logic on instances of plug-ins, extension points, and extensions. You can use either of the following techniques; the appropriate technique depends on how you like to organize code and whether you want to define the same methods on a single instance or on multiple instances. Use the first technique when you want to define members on a single instance.

Use the script, method, and field elements, and JavaScript resource with eval ="true" to define fields and methods on these objects. Extend a class if you want to define the same methods on multiple instances of a plug-in, extension point, or extension.

Copyright © TIBCO Software Inc. All Rights Reserved. 241

AMP Applications and Built-In Extension Points

This section describes the AMP applications, extension points, and plug-ins.

Applications and Extension Points Writing an AMP application is slightly different from writing a typical General Interface application because AMP takes over certain parts of the application life cycle. AMP itself defines the extension points that AMP applications use to perform actions at life cycle events.

An AMP application must enable the AMP add-in. Use the Project Settings dialog in General Interface Builder.

A non-AMP General Interface application defines a default component file that the runtime loads when the application loads. This setting is managed in the Project Settings dialog or with the objectseturl deployment parameter saved in the config.xml file. AMP applications do not define a default component file. Rather, they extend the jsx3.amp.main.layout extension point to provide a layout. The declaration of this extension point documents its contract.

The following example shows a possible implementation of this extension point.

[function (parent) { var b = new jsx3.gui.Block(); b.setText("Hello World"); parent.setChild(b); }][0]

The array literal syntax ([function(){}][0]) is included to make sure that the script evaluates to the function reference rather than just declaring a function in the global scope.

A non-AMP application defines an onLoad script that is executed as soon as the application paints for the first time. Instead of defining such a script in the Project Settings dialog, an AMP application extends the jsx3.amp.main.init extension point. The processor on this extension point is the simple eval type.

Copyright © TIBCO Software Inc. All Rights Reserved. 242

this.getPlugIn().onAppInit();

Standard Extension Points and Plug-Ins AMP defines other standard extension points and plug-ins for several useful application-level GUI controls. AMP also defines a plug-in for each optional class in the General Interface standard library. The names of these plug-ins are equal to the fully-qualified names of the classes that they load. Using these plug-ins, an AMP application can completely bypass lazy class loading, which is implemented with a synchronous (lower performing) load.

See the General Interface AMP API documentation for more information.

Extension Point: jsx3.amp.main.progress This extension point allows application code to be notified of AMP loading progress. For example, an application may implement a custom load progress indicator when it first loads. An application may also provide feedback to the user when AMP is loading resources over the course of running the application.

Plug-In: jsx3.amp.util.menumgr This plug-in allows a menu bar to be composed of AMP extensions. This plug-in is helpful if an application requires an extensible menu bars or context menus.

Plug-In: jsx3.amp.util.prefspanel This plug-in implements an extensible preferences panel. Panes may be added to the panel via AMP extensions.

Plug-In: jsx3.amp.util.wizard This plug-in implements a wizard control. Wizard panes may be added to the wizard via AMP extensions.

Plug-In: jsx3.amp.util.toolbarmgr This plug-in allows a toolbar to be composed of AMP extensions.

Optional Classes of the General Interface Standard Library The General Interface standard library contains the following optional classes; an AMP plug-in is defined for each of these classes:

Copyright © TIBCO Software Inc. All Rights Reserved. 243

jsx3.app.UserSettings jsx3.gui.Alerts jsx3.gui.Block jsx3.gui.BlockX jsx3.gui.Button jsx3.gui.CheckBox jsx3.gui.ColorPicker jsx3.gui.DatePicker jsx3.gui.Dialog jsx3.gui.Form jsx3.gui.Image jsx3.gui.ImageButton jsx3.gui.LayoutGrid jsx3.gui.Matrix jsx3.gui.Matrix.Column jsx3.gui.Menu jsx3.gui.Painted jsx3.gui.RadioButton jsx3.gui.Select jsx3.gui.Slider jsx3.gui.Sound jsx3.gui.Splitter jsx3.gui.Stack jsx3.gui.StackGroup jsx3.gui.Tab jsx3.gui.TabbedPane jsx3.gui.Table jsx3.gui.TextBox jsx3.gui.TimePicker jsx3.gui.ToolbarButton jsx3.gui.Tree jsx3.gui.Window jsx3.gui.WindowBar jsx3.net.Form jsx3.net.Service jsx3.xml.Cacheable

Plug-ins with Extensions and Extension Points

This section describes the AMP plug-ins, extensions, and extension points.

Plug-Ins Each AMP application comprises a set of AMP plug-ins, the functional units of an AMP application. As a developer, you decide how to decompose the application into its constituent plug-ins. Consider plug-ins to be application components that are either present (loaded) or absent (unloaded). In other words, design cohesive plug-ins that contain the parts of the application that function together, and tie plug-ins loosely to each other.

When decomposing an application, keep in mind that an AMP application loads at the granularity of plug-ins; by default, all parts of a plug-in are loaded together.

Plug-ins are defined with a plugin.xml descriptor file. Each plug-in has a unique identifier that is also the name of the directory in which the plugin.xml file is placed.

In the following example, the plug-in identifier is com.tibco.example.p1. Copyright © TIBCO Software Inc. All Rights Reserved. 244

In the following example, the plug-in identifier is com.tibco.example.p1.

...

To register plug-ins, refer to them in the plugins.xml file, and place the file in the plugins directory at the root of the General Interface application that uses AMP. Alternatively, you can use the AMP API to register plug-ins programmatically. For each plug-in registered in the plugins.xml file, there should be a directory in the plugins directory with a name equal to the ID of the registered plug-in. Each of these directories should contain a plugin.xml file.

...

The following figure shows the plugins directory structure.

You can locate the directory of a plug-in outside of the application's plugins directory. In this case, the path attribute of the plugin element should be the relative path from the plugins directory to the directory that contains the plugin directory.

path="../../otherApp/plugins/"> ...

Copyright © TIBCO Software Inc. All Rights Reserved. 245

Extension Points and Extensions A plug-in defines extension points and extensions. An extension point is an interface or contract between the plug-in that defines it and any extension that extends it. The form of this contract is loosely defined in AMP itself. It is a developer decision whether the contract takes the form of an XML schema, a JavaScript interface, or both.

An extension point is often designed to accept any number of extensions (one-to-many) but can also be designed to accept only one extension (one-to-one) or a specified number of extensions. The cardinality is not specified declaratively; it is enforced by the JavaScript code that processes the extensions.

An extension point is declared in a plug-in descriptor file.

An extension is a concrete implementation of the extension point contract. You can define an extension in the same plug-in that defines its extension point or in another plug-in. In both cases, the point attribute of the extension element is the fully-qualified identifier of the extension point. The fully-qualified identifier is the id attribute of the extension-point element appended to the identifier of its plug-in and separated with a period (".").

...

The extension point-extension relationship is loosely coupled and controlled by the extension point. It is possible for an extension to extend an extension point that is not registered. Similarly, it is usually acceptable for an extension point to have no extensions.

Plug-in Resources and the Plug-in Life Cycle Plug-ins comprise the plugin.xml descriptor file and a collection of resources, which can be JavaScript, CSS, XML, XSL, or JSS properties, or properties bundles. These reside in the plug-in's directory and are referenced within the descriptor file, as in the following example.

Copyright © TIBCO Software Inc. All Rights Reserved. 246

XML, XSL and dynamic properties resources are defined inline as a document fragment. When defining these resources inline, make sure that you define the correct XML namespace for the content. If the xmlns attribute is not specified, the document fragment will inherit the AMP XML namespace. Copyright © TIBCO Software Inc. All Rights Reserved. 247

XML namespace.

Prerequisites and Load Order Plug-ins and resources can define dependencies that enforce a load order. You must declare dependencies in order for the load order of application resources to be well-defined.

A plug-in can depend on another plug-in by declaring that it requires it in its descriptor file. When a plug-in requires another plug-in, then the required plug-in will load (step 5, above) before the requiring plug-in. In addition, the required plug-in is instantiated before the requiring plug-in. This means that all early load resources of the required plug-in are loaded before the early load resources of the requiring plug-in.

...

Similarly, a resource may require that another resource be loaded before it is loaded. A resource can also declare that a plug-in loads before the resource. This second option is useful for manual load resources for which the plug-in does not declare the dependency. In the following example, the com.tibco.example.lib plug-in loads before logic.js and logic.js loads before SampleClass.js.

...

Application Techniques and Utilities

This section describes techniques and utilities that AMP supports.

Copyright © TIBCO Software Inc. All Rights Reserved. 248

Declarative Event Subscriptions The AMP plug-in metadata allows plug-ins to declare information about events that they publish. It also allows plug-ins to declaratively subscribe to these events. The following example shows how to declare that a plug-in publishes an event.

The nested param elements are for documentation purposes only and are not validated at runtime.

An event is published with the publish() method of the jsx3.util.EventDispatcher interface, which is implemented by jsx3.amp.PlugIn. It is up the developer to publish the event programmatically in JavaScript.

CustomPlugIn.prototype.save = function(strValue) { // Perform the save this.publish({subject:"saved", value:strValue}); };

Event registration can be performed declaratively as in the following example. The inner text of the subscribe element is taken as a script to be evaluated in the context of the plug-in that declares it. The variable evt is defined in this context and is equal to the event object that was published.

this.getLog().info("The saved event was published with value: " + evt.value);

Instead of declaring the event subscription as a block of JavaScript code in the content of the subscribe element, you can use the handler attribute to reference a method on the plug-in object that will handle the event.

this.getLog().info("The saved event was published with value: " + evt.value);

Copyright © TIBCO Software Inc. All Rights Reserved. 249

AMP Events and the OpenAjax Hub The OpenAjax Alliance (www.openajax.org) is an open source initiative with the goal of increasing interoperability among JavaScript libraries. One part of the specification is the OpenAjax hub, which is an event publishing bus. When the OpenAjax hub is loaded in a web page containing and AMP application, AMP automatically publishes events to the bus. All events that are declared in the plug-in descriptor files are published to the OpenAjax hub.

Asynchronous Execution AMP is built from the ground up around asynchronous execution. All plug-ins and their resources are loaded asynchronously, and no synchronous APIs are provided.

Asynchronous loading performs much better than synchronous loading, especially over a high-latency HTTP connection. Asynchronous loads do not block the browser's UI , whereas synchronous loads do block the UI thread. However, asynchronous JavaScript code is usually harder to develop than synchronous code. The result has often been an unfortunate trade-off between developer productivity and application performance.

By contrast with other development environments, AMP effectively supports asynchronous programming through its declarative structure. Because AMP handles the asynchronous loading of all resources and their dependencies are defined declaratively, it is not necessary to write significant amounts of boilerplate code to load resources.

AMP also takes advantage of the powerful asynchronous idioms in General Interface. The centerpiece of these idioms is the jsx3.Y() function, which declares an asynchronous method.

Asynchronous methods defined using Y have a strict contract that helps promote uniformity across all asynchronous code. An example of these idioms is in the load() method of jsx3.amp.Resource. The following example shows how an action is performed when both rsrc1 and rsrc2 have loaded asynchronously.

this.getResource("rsrc1").load().and( this.getResource("rsrc2").load()).when(function() { // Perform an action });

See the General Interface API documentation for a detailed description of the jsx3.Y() method and its related objects.

Packaging Resources Decomposition into components is a powerful tool for decreasing coupling between logical components and managing application complexity. AMP makes it easy to package resources into a cohesive plug-in. These resources can refer to other resources within the same plug-in without much boiler plate code and without reference to a global namespace.

Plug-ins, extension points, and extensions can define fields and methods and execute arbitrary code inside the plugin.xml descriptor file. The elements script, method, and field can be children of the plugin, extension-point, or extension elements. In the following example, the script element this refers to the parent object.

Copyright © TIBCO Software Inc. All Rights Reserved. 250

return a + b;

"value"

By convention, this is defined to be the parent object (plug-in, extension point, or extension) containing an XML text block that is interpreted as a script field. This convention is evident in the script element above, the declarative event subscription mechanism and the standard extension point processors, eval, return, and return-async. We recommend that you follow the AMP convention when you define how your own extension points interpret their extensions.

Another useful feature is the eval attribute of a script resource. When this attribute is set to true , it causes the contents of the JavaScript file to be evaluated in the context of the plug-in instance. The following example shows how this is used in an external JavaScript file.

(function(plugIn) { plugIn.doSomething = function() { // do something here }; })(this);

Plug-Ins and GUI Components AMP also makes it easy to refer to a plug-in from a loaded GUI component. When a component file is loaded with the loadRsrcComponent() method of a plug-in, the following occur:

1. A getPlugIn() method is defined on the root object of the component file that returns the plug-in on which loadRsrcComponent() was called. 2. The component file is loaded with the plug-in as the URI resolver. This means that all relative paths are resolved relative to the directory of the plug-in.

The first item above makes it easy for all the code, whether defined in a JavaScript file or in the onAfterDeserialize block of a component file, to refer to the plug-in that contains the code. The second means that all paths contained in plug-in resources are defined relative to the plug-in itself. The following example shows a component file that takes advantage of these features.

Copyright © TIBCO Software Inc. All Rights Reserved. 251

objJSX._onBtnClick = function() { this.getPlugIn().performAction(); };

]]>

Build Tools The source distribution of General Interface 3.8 includes build tools that specifically aid in the deployment of high performing AMP applications.

One obvious downside of AMP applications is that application decomposition results in a large number of resource files. Loading a large number of files is usually much slower than loading fewer files, even when the sum size of the files is the same. This is especially true over an HTTP connection.

The new tools are delivered as Ant tasks:

AmpResourceMergeTask. This tool merges the resources of a plug-in into the plugin.xml descriptor file. This process takes advantage of the fact that most types of resources can be included inline in the descriptor file directly beneath the resource element. AmpPluginMergeTask. This tool merges plug-ins into the plugins.xml file. Just as resources can be included inline in plugin.xml, plug-ins may be included inline in the plugins.xml file.

By using these tools, you can deliver an AMP application with as few as two files, by contrast with the large number of files that would otherwise be required.

The files are:

config.xml, the General Interface application descriptor plugins/plugins.xml, the AMP plugins file

There are potential disadvantages in loading all resources in one file, because many resources may be used only in rare application use cases. For this reason, the build tools include options to merge a subset of the application plug-ins and resources.

Copyright © TIBCO Software Inc. All Rights Reserved. 252

AMP Localization This section describes how to localize an AMP application using localization features in AMP and in the General Interface Framework.

Resources A plug-in can localize one of its resources by registering multiple versions of the resource, one for each locale. The locales attribute registers these versions and is supported for all resource types. It is a whitespace-separated list of locale keys, as in the following example.

This resource declaration implies that the following files exist in the plug-in's directory.

data.xml data.en.xml data.fr.xml data.de.xml

The locale of the AMP application (jsx3.app.Server.getLocale()) determines which of the available files is loaded. In this example, the locales en_US and en would load data.en.xml. When no localized version of the resource is available for the locale, the default resource is loaded. In the example, the locale ja would load data.xml.

Plug-in Metadata You can localize the plug-in descriptor file using a technique similar to that used for resources. With this technique, you can localize the metadata that is part of the extension point and extension declarations.

Localized versions of plugin.xml are registered with the locales attribute of the plugin element in the main plugin.xml file. This attribute is a whitespace-separated list of locale keys for which

the file is localized. For example, the following plugin declaration: Copyright © TIBCO Software Inc. All Rights Reserved. 253

the file is localized. For example, the following plugin declaration:

implies that the following files are in the plug-ins directory in addition to plugin.xml, the contents of which are shown above:

plugin.es.xml plugin.de.xml

By contrast with localized resources, where the entire resource is replaced with the localized version of the resource, the contents of the localized version of the plug-in descriptor file are merged into the main descriptor file. This is handy because usually most of the plugin.xml content does not need to be localized (such as JavaScript functions).

The following algorithm is used when merging the localized plug-in descriptor file into the main descriptor file:

1. Copy all attributes of the localized document element plug-in into the base file. 2. For each extension-point element in the localized document, search for an extension-point element in the base file with the same value for the id attribute. If that element exists, do the following: a. Copy all attributes from the localized element into the base element. b. If the localized element has one or more child elements, replace all the children of the base element with the children of the localized element. Elements script, method, field, and processor are not removed from the base element. 3. For each extension element in the localized document, search for an extension element in the base file with the same value for the id attribute. If that element exists, do the following: a. Copy all attributes from the localized element into the base element. b. If the localized element has one or more child elements, replace all the children of the base element with the children of the localized element. Elements script, method, and field are not removed from the base element.

There is no locale "fall through" for localized plug-in descriptor files. For example, if plugin.xml is localized for locales en and en_US, and the application locale is en_US, the merged file is the combination of just plugin.en_US.xml and plugin.xml. In this case, plugin.en.xml is not used in the merge. However, if plugin.xml is localized only for the locale en and the application locale is en_US, then the merged file is the combination of plugin.en.xml and plugin.xml.

Property Bundles For fine grained localization using string replacement and message formats, AMP offers a properties bundle resource type.

The format of messages.xml is specified by the jsx3.app.PropsBundle class from the General Interface core library. Copyright © TIBCO Software Inc. All Rights Reserved. 254

Interface core library.

After this resource is loaded, the localized strings that it contains are available in the following ways:

Via the AMP API

plugIn.getResource("messages").getData().get("key")

Via the application

plugIn.getServer().getDynamicProperty("key")

Via CDF attribute conversion

One possible application of this functionality is in a extension point contract, as in the following extension point declaration:

It is then up to the extension processing logic to interpret the id attribute as a property key:

var bundle = this.getResource("messages").getData(); this.getExtPoint("keys").processExt(function(ext, xml) { jsx3.log("Got key:" + xml.attr("id") + " and value:" + bundle.get(xml.attr("id"))); });

For more information, see the "Internationalizing and Localizing Applications" chapter in the General Interface Developer Guide.

Using the AMPsample Application

General Interface (GI) includes an optional add-in module called the Asynchronous Modular Platform (AMP) to address some of the inherent difficulties encountered during the development of a large application. AMP provides a modular framework for GI developers to create application units called plug-ins which contain design components and other resources.

The intent of this guide is to examine the AMPsample application and each of its plug-in examples and look at how they individually contribute to the overall application.

MenuManager

ToolbarManager

Wizard (via "Help :: Red Help...")

Copyright © TIBCO Software Inc. All Rights Reserved. 255

PrefsController (via "File :: Settings...")

jsx3.amp.main.progress extension point

AMP metadata localization

and support in MenuManager and ToolbarManager

Event publishing/subscribing

jsx3.amp.persist plug-in

The running application has a series of menus and buttons that change the color of the background screen. In addition, there are two dialog examples to demonstrate a multi-screen "wizard" technique of gathering information and another to set a property.

There are a set of menus and buttons on the main layout screen that are populated during the initialization of each plug-in module. The selection of either the menu item or the button will change the application background to a different color.

Additionally, there is a plug-in with an associated menu called "Locale" that creates the text of each menu item by iterating through a list of language locales to convert them to their longer name. For example, the code "en" is transformed to "English".

Copyright © TIBCO Software Inc. All Rights Reserved. 256

In total, there are eight plug-in modules in seven directories that constitute the overall functionality of the application and each plug-in handles its own set of capabilities. The next section will begin investigating the structure of the AMPsample application.

Structure

A GI AMP project contains a directory named "plugins" and within it a descriptor file called "plugins.xml" is used to register each plug-in. An AMP engine is instantiated for every AMP application at runtime.

Each plug-in can be contained in its own directory structure. The name and path of the directory is part of the reference given in the plugins.xml file. The AMP engine processes plug-ins in the order that they are listed in the plugins.xml registry file.

As part of the registry entry, a path can be provided to reference the containing directory. For instance, you can use a relative path to another project with the following:

As the AMP engine processes each of the plug-in entries, it will assume the default path is relative to the "plugins" directory and will look for a directory with the same name as the plug-in "id" attribute. The plug-in directory will contain a file that describes the plug-in components and uses a default name of "plugin.xml". Note: it is also valid to bypass the referenced file and enter the same information entirely within the plugin element. However, keeping the plugin.xml file with the rest of its resources seems like a better practice.

The format of the plugins.xml file adheres to the plugins.xsd schema located at http://gi.tibco.com/xsd/plugins.xsd and http://www.generalinterface.org/xsd/plugins.xsd.

The AMPsample plugins.xml file contains the following XML:

Copyright © TIBCO Software Inc. All Rights Reserved. 257

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.tibco.com/gi/amp http://gi.tibco.com/xsd/plugins.xsd">

var uri = jsx3.app.Browser.getLocation();

var localeId = uri.getQueryParam("locale");

if (localeId)

this.getEngine().getServer().setLocale(jsx3.util.Locale.valueOf(localeId));

The first plug-in is identified by "init" and has a method available named "onRegister". The method's JavaScript will execute automatically after the plug-in is registered by the engine.

Each plug-in is loaded in the order that it appears in the list; therefore the second plug-in is "main". Let's take a look at the plugin.xml file associated with main.

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.tibco.com/gi/amp http://gi.tibco.com/xsd/plugin.xsd"

id="main"

name="UI Plug-In"

version="0.1">

The plugin.xml descriptor file starts out with the "plugin" element name and the schema names associated to namespaces. The attribute "id" matches the registered plug-in entry in the

plugins.xml file and must be unique. The version attribute is arbitrary and could be used to Copyright © TIBCO Software Inc. All Rights Reserved. 258 plugins.xml file and must be unique. The version attribute is arbitrary and could be used to check if the version of the plug-in supports certain capabilities for example. The id, name and version attributes can be read programmatically using the jsx3.amp.PlugIn class API.

The next section of the plugin.xml file describes which GI classes will be required in order for the plug-in to run properly.

In this case, the "main" plug-in will depend on the three declared classes. The engine manages the loading of the classes. All required plug-ins will be registered and instantiated before the plug-in is registered.

The next section of the plugin.xml file defines the resources used by the plug-in. Six resource types are allowed inside the resource tags:

script – JavaScript files;

xml – XML such as CDF and WSDL files;

xsl – XSL transformation files;

css – Cascading Style Sheet;

jss – GI dynamic properties file;

propsbundle – GI language properties.