User Interfaces

Business Space

Business Space is a UI framework designed for end users to interact with BPM functions. Business Space is a specialization of the IBM Lotus Mashups technologies. Business Space is built from a set of one or more "spaces". Each space contains one or more pages. Each page contains one or more widgets that are laid out on the page.

Each BPM product installed adds one or more Business Space widgets to the catalog of available widgets.

Events

Widgets can communicate with each other through the publish/subscribe of events between them. When a widget is registered with Business Space, its registration describes which events it can publish to and which events it can subscribe upon. When a widget is added to a page, it can then be wired to other widgets. One widget will act as the publisher of the event, and the other act as the subscriber. Two widgets can only be wired together if they support the same type of event.

See Also – Business Space

Flex Custom Widgets in Business Space - Using Flex within Business Space

References – Business Space


Custom Widgets

The widgets provided by IBM for business space are not the only widgets possible. You can create and use your own widgets to augment the existing functions. There are a number of steps and piece-parts required to build a new widget.

A widget is configured to Business Space by providing an XML configuration file that corresponds to the iWidget specification. Contained within this file are a number of properties that are used by the Business Space runtime to control how the widget behaves and is displayed.

In addition to the visual characteristics of the widget, we should realize that a widget can send events to other widgets as well as received events from other widgets. This is a form of publish and subscribe. The XML document also holds the information on what a widget can send to other widgets and can receive from other widgets.

An example iWidget XML control file may look as follows:

<?xml version="1.0" encoding="UTF-8" ?> <iw:iwidget id="iWidgetEditorTests1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" supportedModes="view" mode="view" lang="en" name="Hello"> <iw:content mode="view"> <![CDATA[ <div>Hello World</div> ]]> </iw:content> </iw:iwidget>

A deep understanding is recommend of the structure and semantics of this control file. IBM provides a rich function GUI editor that hides the majority of the details allowing values to be entered in a much more pleasing manner. See iWidget editor.

In addition to the iWidget XML control file, there is a second file which is a Business Space specific Catalog XML file. The purpose of this file is to tell Business Space about the nature of the widget so that Business Space can present this widget in its catalogs of available widgets.

Finally there is one more XML file of importance to us when building custom Business Space widgets. This file is the Endpoint Registration XML file. The purpose of this file is to provide information to the widget about where it should connect to at runtime in order to communicate with a WPS server instance. Business Space widgets typically make REST style communication calls to the WPS server.

iWidget Mode

One of the core concepts of an iWidget is its mode. Think of the mode of a widget as being a "state" that the widget as a whole may be in. Depending on the value of the mode, the widget can render itself in different ways. For example, if a widget is in view mode, then it might be displaying business data. If the same widget is in configuration mode, it might be displaying configuration data for itself such as which database to read data from.

A widget can be told its mode ... which is another way of saying how the widget is to represent itself for a particular task. As an example, setting its mode to:


Business space defines these three modes of operation.

iWidget Structure

The iWidgets supplied for Process Server can be found in the directory <ProcessServer>/BusinessSpace/widgets. These serve as a useful source of reference and should be examined to see how IBM has built its own widgets.

What follows next is a breakdown on the logical content of the iWidget XML documents. Note that these conform to the iWidget specification v2.0 which is very different from the previous version that was used in previous product releases.

The XML control file begins with an


iwidget

The <iw:iwidget> element is the root container in the document used to describe the iWidget. It has many possible attributes for its configuration.

Attributes:


Example

<iw:iwidget xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" iScope="com.kolban.AppStarter" id="appStarter" name="appStarter" supportedModes="view">

resource

<iw:resource id="{resourceName}" src="{uri}" version="{version}" mimeType="{mimeType}" callback=""/>

Attributes:


Example

<iw:resource src="appStarter.js" />

eventDescription

Attributes:


event


content

This tag contains the content that will be displayed/loaded in the Widget. This is usually HTML. The <iw:content> element is a child of the <iw:iwidget> element.

Attributes:

iWidget Modules/Data Structures


Managed Item Set

The ManagedItemSet is part of the iWidget specification. It defines data that is managed by the widget itself. This includes saving the data for later retrieval. This can be used for setting the configuration/properties of the widget so that later it can be restored.

The ManagedItemSet for an iWidget can be retrieved from the widget's iContext using the getiWidgetAttributes() function.

ManagedItemSet getiWidgetAttributes();

For example,

var myAttributes = this.iContext.getiWidgetAttributes();

Although the iWidget spec shows that the setItemValue function can take an object to save, reality is that there is a limitation of the iWidget container. To help with this, we should encode the object that we want to save as a string and save the string value as the attribute. In JavaScript, we can employ the JSON encoding and leverage the dojo.toJson function to encode a JavaScript object. When we retrieve the value, we can use the dojo.fromJson function to get the JavaScript object back again.

For example:

var x = new Object(); x.a = "Hello"; x.b = "World"; var myAttributes = this.iContext.getiWidgetAttributes(); myAttributes.setItemValue("test", dojo.toJson(x), false); myAttributes.save(); // Retrieve … var y = dojo.fromJson(myAttributes.getItemValue("test"));

Also note that saving attributes is recommended when the widget is in 'edit' mode. The actual persisting of these attributes back to the server only occurs when the widget goes from the edit mode back to view mode.

Functions on ManagedItemSet

ManagedItemSet setItemValue(in String itemName, in Object value, in boolean readOnly /*optional*/); Object getItemValue(in String itemName); ManagedItemSet removeItem(in String itemName); String[] getAllNames(); boolean isReadOnly(in String itemName); null save(in Function callbackFn /*optional*/); boolean addListener(in Function listener); boolean removeListener(in Function listener); ManagedItemSet clone();


function(in String managedItemSetName, in boolean success);

addListener This method returns a boolean indicating whether or not the request to add a listener to changes in iWidget v1.0 Specification the ItemSet was successful. Note that the signature for such a listener is:

module { null listener(in iEvent ev); }

removeListener This method returns a boolean indicating whether or not the request to remove a listener was successful.

clone This method returns a new ManagedItemSet that is a duplicate of the current ManagedItemSet. While this method does provide for cloning all the values within the ManagedItemSet, in general this will only clone the data fields for complex Objects, both type information and any embedded logic will most likely be lost.

iWidget iContext

ManagedItemSet getiWidgetAttributes(); ManagedItemSet getUserProfile(); ManagedItemSet getiDescriptor(); ItemSet getItemSet(in String name, in Boolean private); Object iScope(); String processMarkup(in String markup);

null processiWidgets(in DOMNode node); Element getElementById(in String id); Element[] getElementByClass(in String className); Element getRootElement(); null requires(in String requiredItem, in String version /*optional*/, in String uri, in Function callbackFn /*optional*/); iEvents iEvents; IO io; xml xml; String widgetId;


getiDescriptor This method returns the ManagedItemSet that provides access to attributes that both the iContext and the iWidget need to understand. If there is no ManagedItemSet related to the iWidget's descriptive items, this method MUST create an empty set and return it.

getItemSet This method returns an ItemSet corresponding to the requested name. If it does not already exist, an ItemSet will be created and associated with the supplied name. If a new ItemSet is created, the "private" parameter controls whether or not the ItemSet can be exposed to other components. If the ItemSet already exists, the "private" parameter is ignored. If access to the desired ItemSet is denied or the ItemSet cannot be created, null is returned.


function(requiredItem, uri, resourceHandle /* when appropriate */)

The following names refer to optional functionality defined here:

io

xml

iEvents This field contains an object that provides access to event services in a manner allowing the iWidgets on the page to interact in a loosely coupled manner while also providing control to whomever is defining the overall page/application. Types related to eventing are defined in a separate section below.

io This optional field contains an object that provides access to io services in a manner allowing the page as a whole to remain consistent, particularly in the face of server-side coordination between related application components. See also: iWidget IO.

xml This optional field is a placeholder for future definitions providing explicit support for XML-oriented processing. This version of the specification provides no such definitions, but they are expected in future versions. Extensions supported by more advanced iContexts SHOULD follow the pattern used for the iEvents and IO portions of these definitions. This allows iWidgets to determine the support for a "foo" extension defined by a group named "bar" using a construct of the form:

var fooSupported = (iContext._bar & iContext._bar.foo);

widgetId This field appears to be the Dojo Dijit ID for the Dijit Widget

Constants

iContext.constants.mode.VIEW = "view" iContext.constants.mode.EDIT = "edit" iContext.constants.mode.HELP = "help" iContext.constants.ATTRIBUTES = "attributes" iContext.constants.IDESCRIPTOR = "idescriptor" iContext.constants.USERPROFILE = "userprofile" iContext.constants.keys.SHIFT = 1 iContext.constants.keys.ALT = 2 iContext.constants.keys.CTRL = 4 iContext.constants.keys.META = 8 iContext.constants.keys.CAPSLOCK = 16


iEvents

module iEvents { null publishedEvents(in iEventDescription eventDesc[]); null handledEvents(in iEventDescription eventDesc[]); null fireEvent( in String name, /* event name, preferrably a serialized QName */ in String type, /* optional reference to type, preferrably a serialized QName */ in Object payload /* optional ... the event's data */); }


io

XMLHttpRequest XMLHttpRequest(); URI rewriteURI(in URI uri); XMLHttpRequest request(in requestVerb, in URI uri, in Function callbackFn, in String message /*optional*/, in [{headerName, value}] requestHeader /*optional*/);


Notes

Getting the URL for the widget

The URL for the widget can be obtained using:

var rootString = io.rewriteURL("");

Misc

After changing the Business Space Registry, much of the documentation says to execute an expensive restart of the server. Experience so far seems to be showing that simply stopping and then restarting the application called IBM_BSPACE_WIDGETS appears to be sufficient.

iWidget editor

In the latest versions of ID and RAD, there is a an iWidget editor built into the development tooling. The iWidget editor is documented in the RAD InfoCenter. This editor visualizes the iWidget XML description file in a custom editor that is designed to show the values of an iWidget. In addition, an iWidget control file can be created as a new artifact. To create a new iWidget, select New from a Web project. You must be in the Web Perspective. In the list of available artifacts, the iWidget entry can be found:

If the entry does not show up in the list, choose it from the New artifact list. It can be found in the Web folder.

This launches a wizard in which details of the new iWidget can be entered:

In the editor, the iWidget has a drop-down selection for the type of iWidget. The selections available are:


Once created, a new XML artifact appears in the project. To open this file in the iWidget editor, select Open With → Other and select iWidget Editor

Here is an example of an iWidget file opened in the editor with some data entered:

BSpaceWidgetRegistry

getWidgetRegistry() Returns the business space registry for the widget that contains the instance of this class.

getWidgetRegistryServiceURI() Returns the service URI that returns all the widget registries.

getWidgetRootURI() Returns the URI to the location of the widget definition XML.

getWidgetInfoByWidgetId(widgetId) Undocumented.

getServiceEndpoint(key) Returns the endpoint that matches the given key.

getServiceURLRoot() Returns the service URI root of the business space.

isInBSpace() Returns true if this widget is hosted in business space. False otherwise.

getDefinitionXMLPath() Returns the path to this widget's definition XML.

BSpaceGeneralHelper


Registering Widgets

In WPS 7.0, a new wsadmin task was introduced that performs the installation actions more elegantly than previous releases. The command is called AdminTask.installBusinessSpaceWidgets.

The syntax for the new WSAdmin task is as follows:

AdminTask.installBusinessSpaceWidgets('[ -nodeName *nodeName *-serverName *serverName *-widgets pathToWidgetZipFile]')

The input to this file is a manually created ZIP file. To create the ZIP file, first create a new folder. In that folder, create the following sub-folders:

ear Contains the EAR file for the Widget Web Project. This EAR contains the iWidget XML file and the JavaScript amongst possible others.

catalog Contains the catalog_nameOfWidget.xml file. The structure and content of this file is described at The Catalog File.

endpoints Contains the endpoint XML file

help (optional)

Once done, ZIP up the data so that these folders are the immediate children in the ZIP. This is the ZIP file to be passed to the installBusinessSpaceWidgets script in the -widgets parameter.

The effect of running this command will be to install the EAR contained within the ZIP as well as register the new Business Space widget. Experience shows that although the EAR application is installed, it is not automatically started. It must be started before the widget can be used in Business Space.

An almost identical command is available to remove (un-install) a previously installed widget. Like the install script, the un-install script takes the ZIP file as input.

AdminTask.uninstallBusinessSpaceWidgets('[ -nodeName *nodeName *-serverName *serverName *-widgets pathToWidgetZipFile]')

Updating the information about the widget in WPS can also be achieved through scripting:

AdminTask.updateBusinessSpaceWidgets('[ -nodeName *nodeName *-serverName *serverName *-catalogs pathToCatalogXMLFile]')

The same command can be used to update the endpoints XML file:

AdminTask.updateBusinessSpaceWidgets('[ -nodeName *nodeName *-serverName *serverName *-endpoints pathToEndpointsXMLFile]')

After installing or updating a widget (at least in test), restart the server.

When installing a widget, the catalog file is copied into:

<Profile>/BusinessSpace/Node/Server/mm.runtime.prof/config

Deleting the file from this location will also delete the widget. The file called catalog_default.xml should also be edited to remove the associated includes.

Similarly, a directory called:

<Profile>/BusinessSpace/Node/Server/mm.runtime.prof/endpoints

contains the endpoint files.

The Catalog File

The XML Catalog file that is used to register a widget does not appear to be any known industry standard. It appears to be IBM specific and very technical in nature at that. No publicly understood documentation is known to exist that describes this mysterious content. By examination (and guesswork), the Catalog XML file seems to contain the following information.

In WPS v7.0, a new catalog structure was designed that differs from that of previous releases. The name of the XML file should be:

catalog_nameOfWidget.xml

Documentation on this is currently poor. Its general structure appears to be:

<catalog id="???"> <resource-type>Catalog</resource-type> <category name="???"> <title>Text</title> <description>Text</description> <entry id="{namespace}name" unique-name="{namespace}name"> <title>Text</title> <description>Text</description> <definition>Path???</definition> <preview>Path???</preview> <icon>Path???</icon> <previewThumbnail>Path???</previewThumbnail> <shortDescription>Text</shortDescription> <metadata name="com.ibm.bspace.version">1.0.0.0</metadata> <metadata name="com.ibm.bspace.owner">IBM</metadata> <metadata name="com.ibm.bspace.serviceEndpointRefs"> [{ "name": "serviceUrlRoot", "required": "false", "refId": "endpoint://{namespace}name", "refVersion": "1.0.0.0" }] </metadata> </entry> <category> </catalog>

The text entries in the XML Catalog can be NLS encoded using the following format:

<nls-string lang="en">Human Readable Text</nls-string>

The fields in the Catalog structure are as follows:



It is also used in the category selection in a couple of places: and

catalog/category/entry/description The description shows up in the category selection

catalog/category/entry/definition This entry points to the path of the iWidget XML file available from a URL. This links together the Catalog data and the iWidget XML description data. It is from here that the runtime can obtain the iWidget XML description document.



Registry Endpoints XML

The endpoint registry XML example looks as follows:

<?xml version="1.0" encoding="UTF-8"?> <BusinessSpaceRegistry xmlns="http://com.ibm.bspace/BusinessSpaceRegistry" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://com.ibm.bspace/BusinessSpaceRegistry BusinessSpaceRegistry.xsd "> <Endpoint> <id>{namespace}name</id> <type>{namespace}name</type> <version>1.0.0.0</version> <url>/WebPath/</url> <description>Description</description> </Endpoint> </BusinessSpaceRegistry>

BusinessSpaceRegistry/Endpoint/id The ID of this endpoint information. This is what is references in the Registry Widget XML in the tag serviceEndpointRef/refId.


JavaScript for a new widget

When a widget is loaded by Business Space, that widget usually supplies some JavaScript code to be executed. As the Business Space widget is loaded and used, callbacks are executed into this code. It is this code that controls the user interactions and makes REST calls to back-end servers and updates the HTML of the page to display or change content. JavaScript does not natively have similar concepts to Java of package names and class names. Dojo provides a similar mapping using the two Dojo methods called dojo.provide and dojo.declare. Using these methods provides the ability to declare the Java equivalent of a Class type in a package. This is used with custom Widgets in the iWidget specification. In the iWidget definition, there is an attribute called iScope. This takes the name of the declared JavaScript class. When an instance of a Business Space widget is created on the page, a corresponding instance of the JavaScript class object is also created.

dojo.provide("com.kolban.SampleWidget"); dojo.declare("com.kolban.SampleWidget", [dijit._Widget], { "onLoad": function() { dojo.mixin(this, new com.ibm.bspace.common.util.widget.BSpaceCommonUtilityLoader()); this.require("com.ibm.bspace.common.util.widget.BSpaceGeneralHelper"); }, "onUnload": function() {}, "onReload": function() {}, "onRefreshNeeded": function() {}, "onSizeChanged": function() {} });

Functions

The JavaScript written to implement the widget contains callback functions that are called by the Business Space framework. The names of these functions are architected. What follows is a brief description of the different callbacks available.


In addition, for each of the modes, a callback function is available for when the mode is selected:

onview

onedit

Modes

A widget can be in any one of a number of modes. The common modes are view and edit. To switch mode, the iContext event called onModeChanged can be invoked.

this.iContext.iEvents.fireEvent("onModeChanged", null, "{newMode: 'view'}");

HTML rewriting

It is possible that there is HTML re-writing going on in the environment. I seem to see that the widget.xml contains:

_IWID_

is being replaced with a UUID which I believe to be the iWidget ID (what ever that means). This same widgetID can be obtained from iContext.widgetId.

Debugging iWidget JavaScript

Assuming you are running the iWidget in FireFox with FireBug installed, adding the JavaScript code statement:

debugger;

causes a breakpoint to be reached which stops the execution and throws you into the FireBug JavaScript debugger.

Adding the JavaScript:

console.log("Text");

caused the text to be logged to the FireBug console.

Event handling

A widget can send (publish) and receive (handle) events from other widgets. IBM's supplied Business Space widgets both publish and handle events. This means that custom widgets can be wired together with the IBM widgets to react or cause reaction. In order for two widgets to be wired together, one needs to publish an event interface and the other needs to handle the exact same event interface. The configuration that describes published and handled events is performed in the iWidget XML document. There are two tags of interest. These are:

eventDescription

event

The eventDescription contains:

<iw:eventDescription id="{eventDescName}" payloadType="{payloadType}" description="{description}" lang="{locale}" title="{title}"> <!-- one per locale --> <iw:alt description="{description}" title="{title}" lang="{locale}" /> </iw:eventDescription>

id This appears to be a unique ID for the eventDescription. It must match the value used in the eventDescName in the event tag.

payLoadType This describes the type of data that can be incoming.

lang A locale (eg. "en")

description A textual description of the event

title Unknown. Although this shows up in the spec, it does not show up in the iWidget editor.

The event contains

<iw:event id="{eventName}" eventDescName="{eventDescName}" published="{boolean}" handled="{boolean}" handlerItemName="{attributeValue}" onEvent="{handlerName}" />

id The identity of the event. This must match between event sender and receiver.

To send an event one uses the method called:

iContext.iEvents.fireEvent()

The function defined in the onEvent attribute of the event tag accepts a single parameter defined as follows:

module iEvent { String name; String type; Object payload; String source; }


When the JavaScript function named in the <iw:event onEvent=...> entry is called, it is passed a JavaScript Object as a parameter. This object contains at least the following:

The iWidget specification provides a set of predefined events that callback into the JavaScript code without event specifications in the XML file having to be coded. These are:


{ "newMode": value }

Called when the mode of the widget has changed

{ "newWidth": value, "newHeight": *value *}


Dojo Level Workarounds

The level of Dojo distributed with Business Space is back-level compared to the latest possible Dojo release. At the time of writing, the level of Dojo supplied is 1.4.3. Many of the expected Dojo functions simply aren't there. Here are some of them (but by no means all) and some suggested workaround:

None at this time.

Debugging and Problem determination

If after building a custom widget, things are not working as expected, here are some tips to follow to see what might be going wrong:

In the catalog file, there is an entry called <definition>. This defines a WEB path to the iWidget xml file. Open a browser and attempt to access this file. For example:

http://localhost:9080/PathToWidgetXMLFile

After making changes to the definitions, consider restarting the Business Space server. When changes actually take effect is not completely known.

When logging JavaScript objects, consider using the FireBug command:

console.debug(object)

This will log the object to the console in an expanded form that allows one to interrogate the object's contents very easily.

While developing Custom Widgets, changes are frequently made to the code files. If a browser caches code, then re-testing can be a challenge. In FireFox 3, the Function Key 5 (F5) causes a re-load of the current page bypassing any cached files.

Assuming you are running the iWidget in FireFox with FireBug installed, adding the JavaScript code statement:

debugger;

causes a breakpoint to be fired when reached which stops the execution and throws you into the FireBug JavaScript debugger.

If the widget appears but there is no flex content, check that the expected SWF file is the one named.

See Also:


Custom Widget Walk through

In this section we will walk through the creation of a trivial custom widget from beginning to end to demonstrate the creation of such an entity. It assumes familiarity with the previous topics

We create a new Dynamic Web based project to hold our new widget. We call the project MyTestWidget and have it associated with a deployable EAR called MyTestWidgetEAR. This project will host the JavaScript and iWidget XML file.

Now we need to create the JavaScript file that will be called to handle events.

dojo.provide("com.sample.MyTestWidget"); dojo.declare("com.sample.MyTestWidget", null, { onLoad: function () { console.log("onLoad called"); }, onUnload: function() { console.log("onUnload called!"); }, onview: function() { console.log("onview"); }, onedit: function() { console.log("onEdit called!"); }, onReload: function() { console.log("onReload called"); }, onRefreshNeeded: function() { console.log("onRefreshNeeded called!"); console.log("Root: " + this.getWidgetRootURI()); console.log("here: " + this.iContext.io.rewriteURI("")); }, onSizeChanged: function(event){ console.log("onSizeChanged called"); console.log("New sizes: width=" + event.payload.newWidth + " height=" + event.payload.newHeight); }, /** * Sample Event handler … */ handleEvent: function(event) { console.log("handleEvent called! : " + event.payload); } });

Create the iWidget XML file. Right click in the Web Content folder of the new project and select create New > Other. From the Web folder of the New dialog, find and select iWidget.

The name of the new iWidget should be MyTestWidget.

Open the newly created iWidget XML file with the iWidget editor. This may have to be done with the Open > Other and then select the editor explicitly.

Give values to some of the iWidget attributes such as name and iScope. The iScope parameter MUST has the Dijit name of the widget. Save the result and close the editor.

Here is the data contained in the iWidget XML file:

<?xml version="1.0" encoding="UTF-8" ?> <iw:iwidget id="MyTestWidget" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" supportedModes="view" lang="en" iScope="com.sample.MyTestWidget"> <iw:content mode="view"> <![CDATA[ <div>Hello World</div> ]]> </iw:content> <iw:resource src="MyTestWidget.js"/> </iw:iwidget>

Create a General Project called MyTestWidgetPackage. This project will be used to hold Business Space widget installation and packaging artifacts.

In the new project, create three simple folders called:

catalog

ear

endpoints

The result should look as follows:

In the catalog folder, create a file called catalog_MyTestWidget.xml and in the folder called endpoints create a file called endpoints.xml. These should be created as simple files.

Copy the following XML fragment into the content of the file catalog_MyTestWidget.xml. This fragment is a template for what we need and will be further edited.

<?xml version="1.0" encoding="UTF-8"?> <catalog id="myWidget"> <resource-type>Catalog</resource-type> <category name="myWidget"> <title> <nls-string lang="en">My Widget</nls-string> </title> <description> <nls-string lang="en">My Widget description.</nls-string> </description> <entry id="{mynamespace}myWidget" unique-name="{mynamespace}myWidget"> <title> <nls-string lang="en">My Widget Title 2</nls-string> </title> <description> <nls-string lang="en">My Widget Description 2</nls-string> </description> <definition>/WebRoot/myWidget.xml</definition> <preview>/WebRoot/images/preview_myWidget.gif</preview> <icon>/WebRoot/images/icon_myWidget.gif</icon> <previewThumbnail>/WebRoot/images/thumb_myWidget.gif</previewThumbnail> <shortDescription> <nls-string lang="en">My Short Description</nls-string> </shortDescription> <metadata name="com.ibm.bspace.version">1.0.0.0</metadata> <metadata name="com.ibm.bspace.owner">IBM</metadata> <metadata name="com.ibm.bspace.serviceEndpointRefs"> [{ "name": "serviceUrlRoot", "required": "false", "refId": "endpoint://{mynamespace}myWidget", "refVersion":"1.0.0.0" }] </metadata> </entry> </category> </catalog>

Change the following:

All references to myWidget to be MyTestWidget

All references to WebRoot to be MyTestWidget

The result will be:

<?xml version="1.0" encoding="UTF-8"?> <catalog id="MyTestWidget"> <resource-type>Catalog</resource-type> <category name="MyTestWidget"> <title> <nls-string lang="en">My Test Widget</nls-string> </title> <description> <nls-string lang="en">My Test Widget description.</nls-string> </description> <entry id="{mynamespace}MyTestWidget" unique-name="{mynamespace}MyTestWidget"> <title> <nls-string lang="en">My Test Widget Title 2</nls-string> </title> <description> <nls-string lang="en">My Test Widget Description 2</nls-string> </description> <definition>/MyTestWidget/MyTestWidget.xml</definition> <preview>/MyTestWidget/images/preview_myWidget.gif</preview> <icon>/MyTestWidget/images/icon_myWidget.gif</icon> <previewThumbnail>/MyTestWidget/images/thumb_myWidget.gif</previewThumbnail> <shortDescription> <nls-string lang="en">My MyTestWidget Short Description</nls-string> </shortDescription> <metadata name="com.ibm.bspace.version">1.0.0.0</metadata> <metadata name="com.ibm.bspace.owner">IBM</metadata> <metadata name="com.ibm.bspace.serviceEndpointRefs"> [{ "name": "serviceUrlRoot", "required": "false", "refId": "endpoint://{mynamespace}MyTestWidget", "refVersion":"1.0.0.0" }] </metadata> </entry> </category> </catalog>

Copy the following XML fragment into the endpoints.xml file:

<?xml version="1.0" encoding="UTF-8"?> <BusinessSpaceRegistry xmlns="http://com.ibm.bspace/BusinessSpaceRegistry" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://com.ibm.bspace/BusinessSpaceRegistry BusinessSpaceRegistry.xsd "> <Endpoint> <id>{mynamespace}myWidget</id> <type>{mynamespace}myWidget</type> <version>1.0.0.0</version> <url>/WebRoot/</url> <description>Location of MyWidget</description> </Endpoint> </BusinessSpaceRegistry>

Change all occurrences of myWidget to MyTestWidget and the WebRoot to also be MyTestWidget. The result will be:

<?xml version="1.0" encoding="UTF-8"?> <BusinessSpaceRegistry xmlns="http://com.ibm.bspace/BusinessSpaceRegistry" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://com.ibm.bspace/BusinessSpaceRegistry BusinessSpaceRegistry.xsd "> <Endpoint> <id>{mynamespace}MyTestWidget</id> <type>{mynamespace}MyTestWidget</type> <version>1.0.0.0</version> <url>/MyTestWidget/</url> <description>Location of MyWidget</description> </Endpoint> </BusinessSpaceRegistry>

Now we want to generate the EAR file for the MyTestWidget Web project and save the result in the file system underneath the ear folder in the packaging project.

Refreshing the packaging project now shows that the EAR is contained in the ear folder:

Generate a ZIP file containing just these folders and their contents. This can be done through the ID Export option. Remember to select "Create only selected directories" to ensure that no extra directories are created that we do not want.

If examined in a ZIP tool, the following would be shown:

Once the ZIP file has been created, the Widget is ready to be installed. Use the wsadmin script to install the widget. Make sure that the script is pointing to the ZIP file that was just created. See Registering Widgets. After installation has been completed, restart the WPS server to ensure that all changes have taken effect. Once the server has been restarted, Business Space can be launched. In the page editing section, we will now see a new widget that can be added to a page:

Once added, we can see it in place within the Business Space environment:

It isn't a very exciting widget … but it is indeed a custom widget.

Using RAD 8.0.3 to create an iWidget

Mashup Center

See also:

Multiple Browser instances and BPM

When developing or working with BPM solutions, it is not uncommon to want to work with multiple browsers open on your desktop to a variety of BPM applications. Such applications can include:


In a secure WAS environment, each of these applications requires you to authenticate with the target WAS server before the application can be used. Unfortunately, this can cause a problem. To understand this, let us examine how WAS authentication through a browser works.

When you login to WAS and provide a user name and password, that data is sent to WAS only once. WAS validates that the user name and password match and generates a security token. This token is probably no more than a long sequence of characters. When the browser subsequently interacts with WAS, the token is passed back from the browser back to WAS. On seeing this token, WAS now knows who you are and trusts the previous authentication. This means that the userid and password only ever flowed to WAS once. All transmissions between the browser and WAS occur over the encrypted HTTPS (SSL) transport and hence the content of the token is never exposed on the network and can't be sniffed and replayed by other users.

When the token is originally generated by WAS and sent back to the browser, the token is saved locally by the browser in the form of a cookie. This cookie containing the token is what is sent back to WAS when the browser makes subsequent calls back to WAS.

So far ... no problems.

Now imagine bringing up two browser windows or tabs running in the same browser. If we sign-on to a WAS based application on one window, a token is created and saved in the local cookie store. If we sign-on to WAS in the second window, again a token is created and saved in the local cookie store. The problem is ... is that there is only one cookie store shared by all browser windows/instances. So if you sign-in as user "A" in one browser instance and then sign-in as user "B" in a second browser instance, the token/cookie for user "A" is replaced with the token/cookie for user "B".

From a users perspective, this manifests itself as either getting unexpected results when working with WAS applications in different browser windows or else we get additional requests to authenticate as the cookies are constantly being expired and refreshed.

Fortunately, there is a solution.

When we use the FireFox browser, each instance of the browser can have its own private profile. Think of this as a complete set of configurations including the storage area where cookies are saved. If we want to have multiple browsers up and running then we can launch multiple instances of FireFox, each with its own profile.

The FireFox program has two command line flags that should be supplied:

-ProfileManager

-no-remote

The first parameter causes FireFox to display the ProfileManager dialog which allows us to create and select the profile to be used.

The second parameter forces FireFox to use a second profile even if an existing instance of FireFox is already running. Without this flag, a second profile will be ignored and FireFox will use the profile in effect for the first instance started.

The ProfileManager dialog is shown next:

Use the Create Profile button to create as many profiles as desired. To start FireFox with a specific profile, select it and click the Start Firefox button.

Note that multiple tabs in a single instance of FireFox will always share the same profile so utilize multiple profiles and hence multiple browser instances to keep them separate.

Business Space Supplied Widgets

Business Space comes with a variety of Widgets. As other BPM products are installed, so too are additional sets of Widgets.

Business Configuration

Business Rules

Human Task Management

The Human Task Management category of Business Space contains the following widgets:


Escalations List

Human Workflow Diagram

A BPEL process can contain a set of Human Tasks. The Human Workflow Diagram widget allows us to visualize the human tasks within instances of BPEL processes and see where we are within the process with respect to the human tasks being executed. It dynamically examines the process associated with a selected task and draws a picture of where that task is within the process relative to other tasks.

The following illustrates an example of the Human Workflow Diagram.

The widget responds to the following events:


An example wiring of this widget would be to a Tasks List widget with:

Tasks List (Item Selected) → Human Workflow Diagram (Open)

My Team's Tasks

My Work Organizer

Process Definitions List

Processes List

Task Definitions List

Task Information

Tasks List

|| |Action Requested|| |Focus Changed|| |Items Selected|| |Task Released|| |Task Delegated|| |Task Terminated|| |Task Deleted|| |Task Claimed|| |Escalation Started||

Problem Determination

Solution Administration

Solution Operation

User Management

Viewers

Web Viewer

The Web Site viewer widget displays the contents of a web site. The web site displayed can be configured in the settings for the widget or can be passed in via an event definition.

Script Adapter

The Script Adapter widget can be wired to receive events published by any other widget. When it receives an event, it can then forward that event onwards to any other wired widget. The value of this is two-fold. First, it can be used during widget development for debugging. When one widget publishes an event, the fact that the event was published and its payload can be logged by the Script Adapter. Secondly, JavaScript source code can be supplied as a configuration parameter to the Script Adapter widget. This JavaScript can operate against the payload data and potentially massage or transform its content. The passed in data is available in a variable called payload. Payload will be a String. If it contains JSON encoded data, then the data will have to be expanded. An example of this is:

var myObject = eval('(' + payload + ')');

Visual Step

JSPs

See Also:

WebSphere Portal

See also:

Liferay

Liferay is an Open Source Portal environment.

Installing Liferay on WAS

Liferay can be installed on WAS v8 environment. Since we are working with IBM BPM, chances are good that our familiarity with WAS v8 will be higher than other Java EE platforms.

We start our installation by creating a new WAS profile. I'll assume you know how to do that. Create the profile with no special augmentations.

Download the Liferay package without a bundled Java EE environment. This can be found in the Additional Files page at the Liferay web site: