Top Banner
Lotus® Expeditor Developing Applications for Lotus Expeditor
410

Lotus Expeditor: Developing Applications for Lotus Expeditor

Feb 03, 2022

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Lotus Expeditor: Developing Applications for Lotus Expeditor

Lotus® Expeditor

Developing Applications for Lotus Expeditor

���

Page 2: Lotus Expeditor: Developing Applications for Lotus Expeditor
Page 3: Lotus Expeditor: Developing Applications for Lotus Expeditor

Lotus® Expeditor

Developing Applications for Lotus Expeditor

���

Page 4: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note

Before using this information and the product it supports, read the information in “Notices,” on page 395.

Third Edition (November 2006)

This edition applies to Version 6, Release 1 of IBM Lotus Expeditor and to all subsequent releases and modifications

until otherwise indicated in new editions.

© Copyright International Business Machines Corporation 2004, 2006. All rights reserved.

US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contract

with IBM Corp.

Page 5: Lotus Expeditor: Developing Applications for Lotus Expeditor

Contents

Product overview . . . . . . . . . . . 1

What’s new in Lotus Expeditor, version 6.1 . . . . 2

Lotus Expeditor Client for Desktop . . . . . . 2

Runtime and tooling environment . . . . . 2

Application types . . . . . . . . . . . 3

Security . . . . . . . . . . . . . . 3

User interface . . . . . . . . . . . . 3

Document services . . . . . . . . . . 4

Communication . . . . . . . . . . . 4

Data . . . . . . . . . . . . . . . 5

Lotus Expeditor Client for Devices . . . . . . 5

Runtime and tooling environment . . . . . 6

Application types . . . . . . . . . . . 6

User interface . . . . . . . . . . . . 6

Communication . . . . . . . . . . . 6

Overview of the managed client platform . . . . . 6

Managed client services . . . . . . . . . . 7

Access services . . . . . . . . . . . . 8

Interaction services . . . . . . . . . . . 9

Lotus Expeditor Client for Desktop . . . . . 9

Lotus Expeditor Client for Devices . . . . 10

Platform management . . . . . . . . . . 10

Lotus Expeditor Toolkit . . . . . . . . . . 11

Getting started with the Lotus Expeditor Toolkit 11

Lotus Expeditor Toolkit overview . . . . . 11

Supported platforms and prerequisite software 12

Understanding the development platforms . . 12

Setting up the Lotus Expeditor Toolkit . . . 12

Setup for Desktop development . . . . 12

Setup for Device development . . . . . 13

Creating a sample Client Services project . . 13

Running your project on development

runtimes . . . . . . . . . . . . 13

Setting Toolkit preferences . . . . . . . 14

Turning on build automatically . . . . . . 14

Concepts . . . . . . . . . . . . . 15

Client Services Project . . . . . . . . 15

Managing Client Services project

dependencies . . . . . . . . . . . . 15

Target Definition . . . . . . . . . 15

Target features . . . . . . . . . . 17

Secondary Dependencies . . . . . . . 17

Automatic management of manifest

package dependencies . . . . . . . . 17

Configuring the Client Services launcher . . 18

Configuring the Lotus Expeditor Toolkit

environment for Sametime . . . . . . . . 18

Creating and using Client Services applications 19

Creating a Client Services project . . . . . 19

Creating a Client Services fragment project . . 20

Converting a Java project into a Client

Services project . . . . . . . . . . . 21

Updating the buildpath and classpath for

converted Client Services projects . . . . . 21

Setting Client Services project properties . . . 21

Launching Client Services launch

configurations from the manifest editor . . . 22

Using the samples . . . . . . . . . . . . 22

Installing samples using the Rational Software

Development Platform . . . . . . . . . . 22

Installing samples using Eclipse (without RSDP) 23

Cloudscape sample . . . . . . . . . . 24

Setup instructions . . . . . . . . . 24

Troubleshooting . . . . . . . . . . 25

DB2 Everyplace sample . . . . . . . . 25

Setup instructions . . . . . . . . . 26

Troubleshooting . . . . . . . . . . 26

Echo sample . . . . . . . . . . . . 27

Setup instructions . . . . . . . . . 27

Echo Secure sample . . . . . . . . . 30

Setup instructions . . . . . . . . . 30

Eclipse Preferences sample . . . . . . . 31

Setup instructions . . . . . . . . . 31

Running the sample . . . . . . . . 32

Embedded Transaction Container sample . . 32

Setup instructions . . . . . . . . . 33

ISync sample . . . . . . . . . . . . 34

Setup instructions . . . . . . . . . 34

Troubleshooting . . . . . . . . . . 38

JMS with Lotus Expeditor micro broker

provider sample . . . . . . . . . . . 39

Setup instructions . . . . . . . . . 39

Option A: Using the in-memory-based

micro broker instance . . . . . . . . 40

Option B: Using the file-persistence-based

micro broker instance . . . . . . . . 41

JMS with MQe provider sample . . . . . 42

Setup instructions . . . . . . . . . 42

Troubleshooting . . . . . . . . . . 43

JNDI sample . . . . . . . . . . . . 44

Setup instructions . . . . . . . . . 45

Troubleshooting . . . . . . . . . . 45

Log and Log Reader sample . . . . . . . 46

Setup instructions . . . . . . . . . 46

Troubleshooting . . . . . . . . . . 47

MQ Everyplace sample . . . . . . . . 48

Setup instructions . . . . . . . . . 48

Troubleshooting . . . . . . . . . . 49

Order Entry sample . . . . . . . . . 50

Setup instructions . . . . . . . . . 50

Order Entry Rich Client sample . . . . 51

Order Entry Web Application sample . . . 52

OSGi Preferences Service sample . . . . . 53

Setup instructions . . . . . . . . . 53

Pizza JSP sample . . . . . . . . . . 54

Setup instructions . . . . . . . . . 55

Portlet Communication sample . . . . . . 55

Setup instructions . . . . . . . . . 56

Rich Application sample . . . . . . . . 57

Setup instructions . . . . . . . . . 57

Troubleshooting . . . . . . . . . . 58

© Copyright IBM Corp. 2004, 2006 iii

Page 6: Lotus Expeditor: Developing Applications for Lotus Expeditor

Rich Text Editor sample . . . . . . . . 58

Setup instructions . . . . . . . . . 58

Secured Web application sample . . . . . 59

Setup instructions . . . . . . . . . 59

Running the sample . . . . . . . . 59

Service Tracker sample . . . . . . . . 60

Setup instructions . . . . . . . . . 60

Simple Portlet sample . . . . . . . . . 63

Setup instructions . . . . . . . . . 63

Simple Portlet Viewer sample . . . . . . 64

Setup instructions . . . . . . . . . 64

Web Page Aggregation of Portlets sample . . 65

Setup instructions . . . . . . . . . 65

Troubleshooting . . . . . . . . . . 66

Web Application sample . . . . . . . . 66

Setup instructions . . . . . . . . . 66

Web Application Log sample . . . . . . 67

Setup instructions . . . . . . . . . 67

XML Parser sample . . . . . . . . . . 68

Setup instructions . . . . . . . . . 68

Developing applications . . . . . . . 71

Application models . . . . . . . . . . . . 71

Application design considerations . . . . . . . 71

End-to-End applications . . . . . . . . . 71

Topology . . . . . . . . . . . . . . 73

Business logic . . . . . . . . . . . . 73

Persistence . . . . . . . . . . . . . 74

Messaging . . . . . . . . . . . . . . 74

Management . . . . . . . . . . . . . 75

Serviceability . . . . . . . . . . . . . 75

Interaction . . . . . . . . . . . . . . 75

Cross platform APIs . . . . . . . . . . 75

Packaging . . . . . . . . . . . . . . 76

Components . . . . . . . . . . . . 76

Fragments . . . . . . . . . . . . . 77

Features . . . . . . . . . . . . . 77

Class loading . . . . . . . . . . . . . 78

Developing the application user interface . . . . 81

Understanding the user interface . . . . . . 81

Eclipse . . . . . . . . . . . . . . 81

UI toolkits . . . . . . . . . . . . . 82

Visual Editor for Java . . . . . . . . . 82

User interaction in the Lotus Expeditor . . . 82

User interface organization . . . . . . . 83

Title bar . . . . . . . . . . . . 83

Menu bar . . . . . . . . . . . . 83

Banner bar . . . . . . . . . . . 84

Data area . . . . . . . . . . . . 84

Coolbar/Toolbar . . . . . . . . . . 84

Status bar . . . . . . . . . . . . 84

Application Launcher . . . . . . . . 84

Using widgets on devices . . . . . . . . 84

Functional partitioning . . . . . . . 84

Device normalization . . . . . . . . 84

Mobile extensions widgets . . . . . . 85

eSWT programming tips . . . . . . . 87

Using the Restricted Workbench . . . . . . 87

Applicability and benefits . . . . . . . 88

Using ILockdownService . . . . . . . . 88

Acquiring the ILockdownService . . . . 88

Using the ILockdownService to remove the

window title trim . . . . . . . . . 89

Using the ILockdownService to lock the

window . . . . . . . . . . . . 89

Using the ILockdownService to exit the

Restricted Workbench and logoff the OS . . 89

Using personalities . . . . . . . . . . . 89

Creating a personality . . . . . . . . . 89

Lifecycle events . . . . . . . . . . . 91

Creating a global toolbar . . . . . . . . 91

Developing composite applications . . . . . . 91

Understanding composite applications . . . . 91

Creating composite application projects . . . . 92

Creating an SWT view component . . . . . 93

Creating a portlet component . . . . . . 96

Developing composite application logic . . . . 97

Developing data access applications . . . . . . 98

Understanding embedded database development 98

Databases . . . . . . . . . . . . . 98

Embedded databases . . . . . . . . 99

DB2 Everyplace and Cloudscape

comparison . . . . . . . . . . . 99

Deployment and synchronization . . . . . 100

Security considerations . . . . . . . 101

Database lifecycle management . . . . . 102

Enabling projects for data access application

development . . . . . . . . . . . . 102

Client Services target profile features . . . 102

Developing database logic . . . . . . . . 103

Data access application development best

practices . . . . . . . . . . . . . 103

Database Lifecycle Management . . . . . 104

Accessing a defined managed datasource 104

Monitoring operations on a managed

datasource . . . . . . . . . . . 104

Accessing the default managed datasource 104

Developing Embedded Transaction applications 105

Understanding the Embedded Transaction

Container . . . . . . . . . . . . . . 105

Concepts . . . . . . . . . . . . . 106

EJB Container . . . . . . . . . . 106

Home Interfaces . . . . . . . . . 106

Finder Methods . . . . . . . . . 107

Component interfaces . . . . . . . 107

Transaction management . . . . . . 107

Container managed transactions . . . . 107

Programmatic transaction management 107

DataSource/TxnDataSource . . . . . 107

Creating Embedded Transaction projects . . . 108

Using a Client Services Embedded

Transaction project versus an EJB project . . 108

Creating a Client Services Embedded

Transaction project . . . . . . . . . 108

Converting an EJB project to a Client Services

Embedded Transaction project . . . . . . 109

Embedded Transaction Container preferences 109

Developing Embedded Transaction Container

logic . . . . . . . . . . . . . . . 110

Implementing finder methods . . . . . . 110

Configuring and using data sources . . . . 112

iv Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 7: Lotus Expeditor: Developing Applications for Lotus Expeditor

Creating and binding DataSource

instances . . . . . . . . . . . . 112

Locating and connecting to a DataSource 112

Locating EJBs . . . . . . . . . . . 113

Finding EJB homes . . . . . . . . 113

Conserving JDBC resources . . . . . . . 113

Working with user managed transactions . . 113

Advanced topics . . . . . . . . . 114

Providing custom bundle activation . . . . 114

Advanced topics . . . . . . . . . 114

Creating Session and Entity Beans . . . . 114

Creating a Container Managed Persistence

(CMP) bean . . . . . . . . . . . 115

Creating EJB CMP 1.1 beans . . . . . 116

Creating a stateless session bean . . . . 116

Creating a Bean Managed Persistence

(BMP) bean . . . . . . . . . . . 117

Customizing for target data base (DB2e and

Derby) . . . . . . . . . . . . . . 118

Packaging and deploying Embedded

Transaction applications . . . . . . . . . 119

Invoking deployment . . . . . . . . . 119

Embedded Transaction Deployment

Descriptor . . . . . . . . . . . . 119

Embedded Transaction Deployment Editor 120

Debugging and testing Embedded Transaction

applications . . . . . . . . . . . . . 120

Enabling logging and tracing with the

Embedded Transaction Container . . . . . 120

Run or debug Client Services Embedded

Transaction Container projects using the

Client Services launcher . . . . . . . . 121

Run or debug a Client Services Embedded

Transaction Container project on the Lotus

Expeditor runtime . . . . . . . . . . 121

Run or debug a non-Client Services EJB

project on the Lotus Expeditor runtime . . . 121

Run or debug a Client Services Embedded

Transaction Container project on a non-Lotus

Expeditor runtime . . . . . . . . . . 122

Setting breakpoints on generated code . . . 122

Developing management applications . . . . . 122

Developing applications to drive the Enterprise

Management Agent . . . . . . . . . . 122

Accessing the OSGiAgentService object . . . 123

Developing Enterprise Management Agent

SyncML tree extensions . . . . . . . . . 123

SyncML tree extensions overview . . . . 123

Creating an Extension to the SyncML Tree 123

Creating an Extension to register the

command for Exec Leaf . . . . . . . . 124

Developing update manager applications . . . 125

Developing messaging applications . . . . . . 125

Understanding messaging applications . . . . 125

Publish and subscribe messaging . . . . . 126

Topics and hierarchical topic names . . . 128

Publication and subscription messages 130

Point-to-point – queues and queue managers 132

Java Message Service . . . . . . . . . 132

WebSphere MQ Everyplace . . . . . . . 133

Lotus Expeditor micro broker . . . . . . 133

Scenarios and applications . . . . . . 134

Understanding the micro broker

components . . . . . . . . . . . 135

Micro broker topologies . . . . . . . 137

MQTT . . . . . . . . . . . . . . 139

Quality of Service . . . . . . . . . 140

Clean session . . . . . . . . . . 140

WebSphere MQ Everyplace and micro broker

comparison . . . . . . . . . . . . 141

Enabling projects for messaging . . . . . . 141

Client Services target profile features . . . 141

Developing messaging application logic . . . 142

MQ Telemetry Transport . . . . . . . 142

Developing network aware applications . . . . 142

Understanding network aware applications . . 142

Enabling network aware applications . . . . 143

Developing network aware application logic . . 143

Component registration . . . . . . . . 143

Creating and configuring handlers . . . . 145

Adding and configuring customized handlers 146

Using the NetStatus API to detect the real

network status . . . . . . . . . . . 147

Using enhanced HttpClient . . . . . . . 147

Monitoring remote resources . . . . . . 148

Using the notification and check models . . 149

Notification model . . . . . . . . 149

Check model . . . . . . . . . . 150

Developing portlet applications . . . . . . . 150

Understanding Portlet applications . . . . . 150

URL Addressability . . . . . . . . . 151

Client Services Portlet projects . . . . . . 152

Portlet API and Type support . . . . . . 152

Unsupported features . . . . . . . . 153

Using the Portlet Aggregation Tag Library 153

Creating Portlet projects . . . . . . . . . 154

Creating a Client Services Portlet project . . 154

Converting a J2EE portlet project to a Client

Services Portlet project . . . . . . . . 154

Importing Client Services portlet projects . . 155

Adding a portlet to a Client Services Portlet

project . . . . . . . . . . . . . . 155

Developing Portlet application logic . . . . . 155

Aggregating portlets to JSPs . . . . . . 155

Securing Portlet application resources . . . 156

Transport level security (HTTPS) . . . . 156

Programmatic security . . . . . . . 157

Debugging and testing Client Services Portlet

applications . . . . . . . . . . . . . 157

Debugging and testing Client Services Portlet

projects on a test environment . . . . . . 157

Debugging and testing Client Services Portlet

projects on non-Lotus Expeditor runtimes . . 157

Developing Rich Client applications . . . . . . 157

Creating a simple Rich Client Platform

application . . . . . . . . . . . . . 158

Creating a simple Rich Client Application for

devices . . . . . . . . . . . . . . 160

Creating a Rich GUI application for devices 160

Setup . . . . . . . . . . . . . 160

Creating the basic parts of a Rich GUI

application . . . . . . . . . . . 160

Contents v

Page 8: Lotus Expeditor: Developing Applications for Lotus Expeditor

Running your application on the

development runtime . . . . . . . . 162

Creating an eRCP workbench application

from an existing project . . . . . . . . 162

Deploying an eRCP workbench application 163

Installing an eRCP workbench application 164

Running an eRCP eWorkbench application 165

Managing an eRCP eWorkbench application 165

Extending the capabilities of your application 165

Customizing the user interface . . . . . 165

Using themes . . . . . . . . . . 165

Custom widgets . . . . . . . . . 167

Using SWidgets . . . . . . . . . . 197

Managing contributions to the user interface 197

Accessing SWidgets and JFaceEX objects . . 198

Adding and contributing menus . . . . . 198

Menu contributions . . . . . . . . 199

Creating a top-level menu . . . . . . 200

Creating views . . . . . . . . . . . 201

Applying Capitalization and punctuation

guidelines . . . . . . . . . . . . 201

Creating helpful messages . . . . . . . 202

Critical . . . . . . . . . . . . 202

Warning . . . . . . . . . . . . 202

Customizing existing applications . . . . . 202

Activities . . . . . . . . . . . . . 203

Using activities . . . . . . . . . . 203

Integrating existing RCP applications into Lotus

Expeditor . . . . . . . . . . . . . . 204

Developing with user interface widgets . . . 204

Adding spell checking to applications . . . 204

Using dictionaries supported by a given

locale . . . . . . . . . . . . . 204

Using dictionaries supported by the

platform default locale . . . . . . . 205

Using given dictionaries . . . . . . . 205

Using given dictionaries and a customized

user dictionary . . . . . . . . . . 205

Using the getSuggestions string . . . . 205

User dictionary manager . . . . . . 206

Contributing custom spell checking

services . . . . . . . . . . . . 208

Implementing an embedded Web browser 216

Creating an embedded browser . . . . 217

Enhancing an embedded browser view 217

Setting browser preferences . . . . . . 219

Using the Rich Text Editor . . . . . . . 225

Creating a custom Rich Text Editor . . . 225

Using and controlling the custom Rich

Text Editor . . . . . . . . . . . 225

Accessing a Web address with the integrated

browser application . . . . . . . . . 227

Customizing the integrated browser

application with Eclipse preferences . . . 228

Using the Portlet Viewer . . . . . . . 228

Portlet Viewer extension examples . . . 229

Using the Portlet Viewer with WSRP

portlets . . . . . . . . . . . . 229

Widgets for devices . . . . . . . . . 230

Creating help for the application . . . . . . 230

Developing synchronization applications . . . . 230

SyncML . . . . . . . . . . . . . . 230

Understanding SyncML development . . . 230

Technology overview . . . . . . . . 231

SyncML4J common . . . . . . . . 231

SyncML4J data synchronization . . . . 231

SyncML4J device management . . . . 232

Enabling projects for SyncML development 232

Client Services target definition

components . . . . . . . . . . . 232

SyncManager . . . . . . . . . . . . 232

Understanding the SyncManager . . . . . 232

Enabling projects for the SyncManager . . . 233

SyncService extension point . . . . . 233

TypeService extension point . . . . . 233

SchedulerService extension point . . . . 235

Developing SyncManager application logic 235

Developing Web applications . . . . . . . . 238

Understanding Web Applications . . . . . . 239

Creating Web Application projects . . . . . 239

Using a Client Services Web project versus a

Dynamic Web project . . . . . . . . . 240

Creating a Client Services Web project . . . 240

Converting a Dynamic Web project to a

Client Services Web project . . . . . . . 242

Developing Web Application logic . . . . . 242

Accessing resources . . . . . . . . . 242

Using JSP Standard Tag Libraries . . . . . 243

Java Server Faces (JSF) development . . . . 243

Using the Sun JSF Reference

Implementation . . . . . . . . . 243

Struts development . . . . . . . . . 243

Securing Web Application resources . . . . 244

Configuring a Web Application . . . . 244

Supported authentication mechanisms . . 245

Using the User Admin Service to create

users and roles . . . . . . . . . . 245

Using the Admin Utility for OSGi to

create users and roles . . . . . . . . 246

Exporting Web Application bundles . . . . 247

WAB Utility . . . . . . . . . . . . 247

WAB Utility installation . . . . . . . 247

WAB Utility usage and parameters . . . 247

Using Lotus Expeditor servers . . . . . . 249

Servicing Web Applications . . . . . . . . 249

Web Container Logging . . . . . . . . 249

Configuring the Web Container Logging 250

Debugging and testing Web Applications . . . 250

Running and debugging using Client

Services launcher . . . . . . . . . . 250

Running and debugging using ″Run on

Server″ style . . . . . . . . . . . . 250

Running or debugging Client Services

Web Projects on the Client Services

runtime . . . . . . . . . . . . 250

Run or debug a non-Client Services Web

Project on the Client Services runtime . . 250

Running or debugging a Client Services

Web Project on a non-Client Services

runtime . . . . . . . . . . . . 251

Developing Web Services . . . . . . . . . 251

Understanding Web Services . . . . . . . 251

vi Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 9: Lotus Expeditor: Developing Applications for Lotus Expeditor

Technologies . . . . . . . . . . . . 251

Web Services Description Language

(WSDL) . . . . . . . . . . . . 251

Simple Object Access Protocol (SOAP) . . 252

JAX-RPC . . . . . . . . . . . . 252

The Web Services Client Programming

Model . . . . . . . . . . . . . 252

Tools . . . . . . . . . . . . . . 253

Tools for Mobile Web Services

development . . . . . . . . . . 253

Web Services Resource Framework . . . . . 253

Understanding WSRF applications . . . . 253

Technologies . . . . . . . . . . . 253

WS-Resource . . . . . . . . . . 254

WSRF Runtime . . . . . . . . . . 254

WSRF tools . . . . . . . . . . . 255

Creating WS-Resource projects . . . . . 255

Developing WS-Resource providers . . . 256

Creating a WS-Resource client . . . . . 258

Supported data types . . . . . . . . 259

Developing WSRF application logic . . . . 260

WS-Resource provider application . . . 260

WS-Resource client applications . . . . 264

WS-Resource creation operations . . . . 264

WS-Resource LifeTime operations . . . 265

WS-Resource properties operations . . . 266

WS-Resource service method operations 270

Packaging and deploying WS-Resource

bundles . . . . . . . . . . . . . 271

Deploying a WS-Resource provider . . . 271

Deploying a WS-Resource client . . . . 272

Accessing a WS-Resource from Java

applications . . . . . . . . . . . 272

Securing a WS-Resource . . . . . . . . 273

Enabling security for WS-Resource

providers . . . . . . . . . . . . 273

Enabling security for WS-Resource clients 274

Developing custom authenticators . . . 274

Mobile Web Services . . . . . . . . . . 275

Creating Mobile Web Services . . . . . . 275

Creating Mobile Web Services providers 275

Creating Mobile Web Services clients . . 277

Developing Mobile Web Services logic . . . 283

Custom serialization (marshalling) . . . 283

Securing Mobile Web Services . . . . . . 289

Creating secure Mobile Web Services

providers . . . . . . . . . . . . 289

Securing pre-existing Mobile Web Services

providers . . . . . . . . . . . . 290

Creating secure Mobile Web services

clients . . . . . . . . . . . . . 290

Securing pre-existing Mobile Web Services

clients . . . . . . . . . . . . . 292

Editing the Mobile Web Services security

configuration . . . . . . . . . . 293

Deploying Mobile Web Services . . . . . 299

Deploying Mobile Web Services providers 299

Deploying Mobile Web Services clients 300

Axis Web Services . . . . . . . . . . . 301

Creating Axis Web Services . . . . . . . 301

Creating an Apache Axis based Web

Services client . . . . . . . . . . 301

Directly obtaining an instance of the

interface stub . . . . . . . . . . 302

Obtaining an instance of the interface stub

using the JNDI mechanism . . . . . . 302

Defining the extensions to register the

Service Interface to JNDI provider . . . 303

Programmatically creating accounts for

Apache Axis Web Services clients . . . . 304

Developing wired applications . . . . . . . 305

Portlet communication . . . . . . . . . 305

Defining actions and properties . . . . . 305

Wiring portlets . . . . . . . . . . . 306

Wire extension examples . . . . . . . 306

Using the portlet wiring tool . . . . . . 307

Creating Cooperative Components with the

Lotus Expeditor Property Broker . . . . . . 307

Creating your components . . . . . . . 308

Registering your definitions with the broker 309

Working with the Property Broker WSDL file 309

Using the Composite Application

Infrastructure . . . . . . . . . . . 311

Declarative wiring with the Portal Admin

tool . . . . . . . . . . . . . . . 311

Specifying a custom owner for your SWT

action . . . . . . . . . . . . . . 311

Developing for serviceability . . . . . . . . 312

Understanding serviceability . . . . . . . 312

Enabling projects for serviceability . . . . . 312

Developing serviceability logic . . . . . . 313

JSR47 Logging (java.util.logging) . . . . . 313

JSR47 Tracing (java.util.logging) . . . . . 314

OSGi Logging . . . . . . . . . . . 314

OSGi Tracing . . . . . . . . . . . 314

Eclipse Logging . . . . . . . . . . 314

Eclipse Tracing . . . . . . . . . . . 315

Apache Commons Logging . . . . . . . 315

Java.util.logging best practices . . . . . . 315

Migrating applications . . . . . . . . . . 319

Automated migration . . . . . . . . . 319

Manual migration . . . . . . . . . . . 319

Migrating component logic . . . . . . . . 320

Compatibility plug-ins provided . . . . . 320

Plug-ins removed in this release . . . . . 320

Metatype Service changes . . . . . . . 322

Changes to plug-in startup . . . . . . . 322

Migrating OSGi services . . . . . . . . . 322

Debugging and testing applications 323

Local debugging and testing . . . . . . . . 323

Client Services Launcher . . . . . . . . 323

Client Services Server . . . . . . . . . 324

Creating a server . . . . . . . . . . 324

Editing a server . . . . . . . . . . 324

Adding projects to a server . . . . . . . 324

Starting a server . . . . . . . . . . 325

Remote debugging and testing . . . . . . . 325

Packaging and deploying applications 327

Contents vii

Page 10: Lotus Expeditor: Developing Applications for Lotus Expeditor

Packaging applications for distribution . . . . . 327

Understanding application lifecycle . . . . . 327

Understanding methods of installation . . . . 328

Local installation . . . . . . . . . . 328

Enterprise installation . . . . . . . . 328

Understanding the types of install artifacts . . 328

Installer/Uninstaller . . . . . . . . . 329

Update site . . . . . . . . . . . . 329

Features . . . . . . . . . . . . . 329

Plug-ins . . . . . . . . . . . . . 330

Native libraries . . . . . . . . . . . 330

Configuration file updates . . . . . . . 331

Installation instructions . . . . . . . . 331

Enterprise distribution instructions . . . . 331

Using Ant tasks to build a deployable bundle 331

Deploying projects for local testing . . . . . . 331

Exporting plug-ins using the PDE . . . . . 332

Globalizing your application . . . . . 333

Support for multiple locales . . . . . . . . 333

IBM language groups . . . . . . . . . . . 333

Supporting preferred fonts and bidirectional

layouts . . . . . . . . . . . . . . . 335

Creating translatable plug-ins . . . . . . . . 335

Securing applications and data . . . . 337

Accounts framework . . . . . . . . . . . 337

Adding accounts . . . . . . . . . . . 338

Retrieving accounts . . . . . . . . . . 339

Updating accounts . . . . . . . . . . 339

Listening for account changes . . . . . . . 340

Implementing a custom account type . . . . 340

Managing secure passwords . . . . . . . 340

SSL and accounts . . . . . . . . . . . 341

Login configurations . . . . . . . . . . . 341

Logging into the platform . . . . . . . . 342

Logging into remote servers . . . . . . . 342

Using HTTP basic authentication . . . . . 343

Using form-based authentication . . . . . 343

Using platform single sign-on . . . . . . . 345

Implementing single sign-on with remote

servers . . . . . . . . . . . . . . 345

Contributing a login configuration . . . . . 346

Enabling applications for

configuration . . . . . . . . . . . 349

Using preferences . . . . . . . . . . . . 349

Creating preference pages . . . . . . . . 349

Using the Managed Settings framework . . 349

Creating a managed settings-aware

application . . . . . . . . . . . 350

Using the Portal Policy API on the client 351

Creating Eclipse Preference Sets with the

Policy Type Editor . . . . . . . . . 351

Understanding preference options . . . . . 358

Eclipse preferences . . . . . . . . . 358

Configuration admin . . . . . . . . . 358

OSGi preference service . . . . . . . . 359

Using the XML parser services . . . . . . . 359

Locating the Web Container ports using the

HttpSettingListener Service . . . . . . . . . 361

Using the Meta Type Service . . . . . . . . 362

Reference information . . . . . . . 365

Lotus Expeditor top level menus . . . . . . . 365

File menu . . . . . . . . . . . . . 365

View menu . . . . . . . . . . . . . 365

Help menu . . . . . . . . . . . . . 366

OSGi . . . . . . . . . . . . . . . . 366

OSGi specification . . . . . . . . . . . 366

Working with OSGi bundles . . . . . . . 366

Creating OSGi bundles . . . . . . . . 366

Bundles . . . . . . . . . . . . 366

Conventions for creating bundles . . . . 367

Creating manifest files . . . . . . . 367

Packages . . . . . . . . . . . . 368

Understanding services . . . . . . . . 369

Registering and unregistering a service

with the OSGi Framework . . . . . . 369

Getting and un-getting services from the

OSGi Framework . . . . . . . . . 370

Lotus Expeditor Toolkit . . . . . . . . . . 372

Wizards . . . . . . . . . . . . . . 372

New Client Services Project Wizard . . . . 372

New Client Services Fragment Project Wizard 373

Convert Project to Client Services Project

Wizard . . . . . . . . . . . . . 375

Client Services Project Properties page . . . 376

Dialogs . . . . . . . . . . . . . . 376

Client Services Launch Configuration dialog 376

Debugging a remote Client Services

runtime . . . . . . . . . . . . 377

Lotus Expeditor Toolkit Preference Dialog 377

Tag library . . . . . . . . . . . . . . 378

Aggregation tag library . . . . . . . . . 378

Message reference . . . . . . . . . . . . 380

Web Container messages . . . . . . . . 380

Appendix. Notices . . . . . . . . . 395

Trademarks . . . . . . . . . . . . . . 397

viii Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 11: Lotus Expeditor: Developing Applications for Lotus Expeditor

Product overview

Developing Applications for Lotus® Expeditor is your tool for developing powerful managed client

applications that run on desktops, laptops, tablets, and handheld devices. If you are experienced in

developing Java™ Enterprise Edition (JEE) applications, portlet applications, Web Services, or Eclipse

applications, then you are ready to develop applications for Lotus Expeditor.

With the Lotus Expeditor, you can move key components of your applications from the server to desktop,

laptop, tablet, and handheld clients by using standard APIs and services. Moving application components

to run on a client can have dramatic results for business. End-users benefit from improved application

response time because applications perform business operations locally on the client. As a result, there is

a reduction in network traffic between clients and servers, and in server workload. Furthermore, mobile

end-users can continue to productively use their applications from their clients even when they are at a

location that does not have network connectivity, such as a customer site. You can also utilize the local

graphical user interface (GUI) capabilities of the client devices to deliver a richer user experience than can

be supported by a Web browser.

The Lotus Expeditor Toolkit provides a complete, integrated set of tools that allows you to develop,

debug, test, package and deploy client applications that use the Client Services. This toolkit is built on

Eclipse technology and extends the powerful Rational® suite of development tools so you can leverage

your existing skills and software components. Eclipse is an award-winning, open source platform for the

construction of powerful software development tools and rich desktop applications. Leveraging the

Eclipse plug-in framework to integrate technology on the desktop saves technology providers time and

money by enabling them to focus their efforts on delivering differentiation and value for their offerings.

Full details on Eclipse are available at http://www.eclipse.org.

The toolkit also provides Ant tasks so you can create Ant scripts to automate the building of your

applications. In addition, the toolkit provides program samples to help jump start your application

development projects.

The combination of the Lotus Expeditor Client and the Lotus Expeditor Server provide the client and

server middleware ″connectors″ necessary to deliver and manage end-to-end applications (see the below

figure). System Administrators use the Lotus Expeditor server to install and configure the server

middleware, so client applications can securely perform assured transactions and database

synchronization with Enterprise applications and data. For more information on the server platform,

please refer to the Lotus Expeditor Server documentation.

New for Lotus Expeditor Client for Desktop, Portal administrators can now use WebSphere® Portal Server

to control managed client applications available to end-users based on access rights defined by the

administrator. For more information, please refer to the Assembling and Deploying Lotus Expeditor

Applications.

Lotus Expeditor Toolkit End-to-end Tools

End-to-end Applications

End-to-end Services

Enterprise and Portal Applications(Extended)

Lotus Expeditor Client

Desktop: jclDesktopDevice: jclDevice

Eclipse, AST, Rational SoftwareDevelopment Platform

Enterprise and Portal Applications

Lotus Expeditor Server

Websphere ApplicationServer / JEE

© Copyright IBM Corp. 2004, 2006 1

Page 12: Lotus Expeditor: Developing Applications for Lotus Expeditor

With Lotus Expeditor Client for Desktop, you can develop managed client applications that run on the

following operating systems:

v Microsoft® Windows® XP Professional Service Pack 1 and 2

v Microsoft Windows XP Home Edition Service Pack 1 and 2

v Microsoft Windows XP Tablet PC Edition 2005

v RedHat EL 4.0 WS with GTK support – Update 3

v Novell Linux® Desktop 9 (NLD9) Service Pack 3

v Microsoft Windows 2000 Service Pack 4

With Lotus Expeditor Client for Devices, you can develop managed client applications that run on the

following operating systems:

v Windows Mobile 5.0 (PocketPC and Phone)

v Windows Mobile 2003 SE (PocketPC and Phone)

In summary, the powerful client platforms, toolkit, and server platform enable you to develop compelling

managed client applications that run on a variety of clients and securely access e-business on demand™

applications, services, and data. You can use programming skills you have already acquired to develop

these applications. This guide provides the information you need to deliver these applications to your

customers.

What’s new in Lotus Expeditor, version 6.1

This section describes what’s new in Lotus Expeditor, version 6.1

Lotus Expeditor Client for Desktop

The Lotus Expeditor Client for desktop, version 6.1 provides many new application functions over the

previous release, the WebSphere Everyplace® Deployment for Windows and Linux client, version 6.0.

Here are the highlights of the new application features:

Runtime and tooling environment

jclDesktop

J9 2.3 with jclDesktop is a custom configuration that provides a reduced-footprint runtime

environment for the client platform. jclDesktop is the default configuration for desktops.

Eclipse Rich Client Platform (RCP) 3.2.1

The client platform includes the Eclipse Rich Client Platform, version 3.2.1, which implements the

OSGi Release 4 specification.

Eclipse Integrated Development Environment (IDE) 3.2.1

The Lotus Expeditor Toolkit extends the tooling provided by the Eclipse Plug-in Development

Environment (PDE) and works with the Eclipse Visual Editor provided by the Eclipse Integrated

Development Environment (IDE), version 3.2.1.

Eclipse Web Tools Project (WTP) 1.5.1

The Lotus Expeditor Toolkit extends the Web tooling in WTP so you can use the existing Web

tooling provided by WTP to develop Web applications. This environment does not support

development of Java Server Faces (JSF) applications.

WebSphere Application Server Toolkit (AST) 6.1.1

The Lotus Expeditor Toolkit extends the Web, EJB, and portlet tooling in AST so you can continue

to use existing tools to develop Web, Embedded Transaction, and portlet client applications

respectively. This environment does not support development of JSF applications.

Rational Software Development Platform 7.0

The Lotus Expeditor Toolkit extends the Web, EJB, and portlet tooling provided by Rational

2 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 13: Lotus Expeditor: Developing Applications for Lotus Expeditor

Application Developer 7.0 and Rational Software Architect 7.0 so you can continue to use existing

tools to develop Web, Embedded Transaction, and portlet client applications respectively.

Application types

Portlets (JSR 168)

The portlet container runs portlets that comply with the JSR 168 specification. The portlet

container also supports “wiring” (i.e. communications among portlets) using wire definitions

defined on the portal server with the existing portal wiring tool. The wiring information is

included in the markup sent to the client for the portal-defined perspective represented by that

page.

Composite Applications

Composite applications enable the integration of information from multiple applications,

providing end users with the content they need based on their role and task. Lotus Expeditor

enables you to integrate portlets and Eclipse applications through the use of the Property Broker.

Compatibility

Lotus Expeditor Client for Desktop continues to support Web, Embedded Transaction, Eclipse,

messaging, database, and Web Services applications.

Security

Key Store

The key store provides an encrypted local repository for user ids, passwords, certificates, and

other credentials. Applications can store their credentials in the key store to reduce the number of

times a user is prompted for credentials (e.g. the user is prompted once to unlock the key store).

The implementation is based on standard JSE key stores and the Java Authentication and

Authorization Service (JAAS).

Single Sign-on

The single sign-on service uses operating specific key stores for the key. User authentication with

the operating system allows the managed client to access the key and unlock the platform. Users

can also log into the key store without being prompted for a password.

Accounts

Accounts provide an interface for accessing account information, regardless of account type and

data store. Accounts contain information for accessing a given service, such as server, user name,

password, protocol, port, SSL details, and other preferences.

User interface

Eclipse Rich Client Platform (RCP) 3.2.1

RCP 3.2.1 supports the Standard Widget Toolkit (SWT), which provides a cross-platform API that

tightly integrates with the native widgets of the operating system; JFace, which provides

convenience features such as dialogs; and the Workbench, which enables you to add your

applications to the application desktop.

Personality

A personality extends the concept of a WorkbenchAdvisor to allow for different

WorkbenchWindow configurations to run within one running Virtual Machine (VM). Lotus

Expeditor provides a personality, which is a standalone personality that supports Eclipse and

composite application-driven perspectives.

Workbench Personality with Application Launcher

The application switcher is enhanced to support application hierarchies. Applications may be

placed in folders (i.e. cascading submenus). For portal-defined perspectives, the application

hierarchy maps to the page group hierarchy defined on the portal server. “Native” applications

may also be added to the launcher and accessed from the workbench. Native applications

launched from the workbench will appear in their own windows as they do when launched from

Product overview 3

Page 14: Lotus Expeditor: Developing Applications for Lotus Expeditor

the operating system. Windows for applications launched from the workbench will appear in the

application switcher. The launcher also supports the following functionality:

v Supports multiple user workspaces via command line –data option

v Supports launching multiple personalities

v Supports bring-to-front of application instead of launch of multiple instances

The workbench can also launch eRCP applications.

Access to “native” applications and selected system services from the workbench

The workbench and application launcher are enhanced to (optionally) provide access to the

following features. In the portal-managed client environment, access to these functions is

restricted based on portal access control and configured using the “Launcher administration

portlets”.

v Launch an application installed on the client (e.g. Notes®, Office, etc...)

v Shutdown the operating system

v Log off the operating system

v Change the keyboard layout

v Change the current operating system locale

v Lock the screen (using screen lock program included in the operating system)

User Interface Widgets

The user interface widgets provide a common look and feel for all user interfaces that use the

managed client platform. These widgets provide the following features:

v Renders the toolbar skin, which means it formats the toolbar to make its style consistent with

the style defined for the application it displays in

v Manages drag and drop of items within the toolbar

v Saves and loads the last state of toolbar items using the Eclipse memento pattern, which uses

the saveState and restoreState methods to remember the position of each toolbar item when

the user shuts down the client so that the same toolbar items display when the user restarts it

Embedded Browser

The Embedded Browser extends an application’s functions, such as browser launch, handles

events, and preference user interface, etc. The Embedded Browser is based on SWT browser

widget in Eclipse, which can support Internet Explorer on Windows and Mozilla on Linux.

Document services

Rich Text Editor

Rich Text Editor is a DOM-based Editor, which provides HTML and plain text editing. It is a very

thin layer on top of the DOM browser, and the editing operation is achieved primarily by using

DOM calls.

Text Analyzer

The Text Analyzer framework can be extended to provide Spell Checker functionality. Spell

Checker functionality is used to check misspelled words in a document and supports 26

languages. The Spell Checker functionality can be used by many editors, by implementing the

document interfaces.

Communication

Axis Web Services

The managed client platform also supports JAX-RPC compliant clients by bundling the Apache

Axis runtime components. The Apache Axis 1.3 tools available in the Rational Application

Developer (RAD) should be used to generate the code needed to consume Web services via

JAX-RPC. You can use Axis Web Services when a JSR 172 implementation cannot meet your

application requirements. For example, use Axis Web Services when your application requires

automatic two-way conversions between Java Collections and SOAP Arrays. The Axis Web

4 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 15: Lotus Expeditor: Developing Applications for Lotus Expeditor

Services support SSL and Basic Authentication. Lotus Expeditor Client for Desktop continues to

support Web Services client applications that conform to the JSR 172 specification.

Network Layer

The Network Layer includes a main framework for handling network faults. This service

provides a handler extension point for applications to extend and includes the following

functionality:

v Failures can be handled at the HTTP protocol level - provides a service for querying the state

of the client

v Manages multiple server states and provides a service to query the state of the servers

v Detects the network adapter status

v Detects the operating system power events (standby or hibernate) and provides an interface

layer on top of os.events to be used by other plug-ins to query the system power status

Micro broker

The micro broker is a very small footprint, 100% Java message broker, capable of running in

resource-constrained environments. It is suitable for embedding in applications and solutions that

have a need for messaging, notification and event services. Micro broker supports publish and

subscribe messaging paradigm. It provides a messaging infrastructure, which enables lightweight

messaging clients to communicate with each other, on one host or across a network, as well as

with enterprise brokers through its bridging capabilities. Micro broker uses the MQ Telemetry

Transport (MQTT) protocol over TCP/IP. Micro broker allows for the bridging of messages to

WebSphere MQ servers.

Property Broker

Property Broker wires are created via calls to the property broker APIs. Wires are tied to

navigation elements and are enabled or disabled when a perspective is activated or deactivated

respectively. Wires enable different components to communicate with each other while remaining

completely decoupled. Currently, the client only supports PROPERTY-TO-ACTION wires.

Although Property Broker supports multiple wire types, the portal projection model supports

only this type.

OSGi Event Admin

Nearly all the bundles in an OSGi framework must deal with events, either as an event publisher

or as an event handler. The Event Admin service provides an inter-bundle communication

mechanism. It is based on an event publish and subscribe model, popular in many message based

systems.

Data

Database Lifecycle Management

Database Lifecycle Management provides interoperability with a relational database in a uniform

and transparent manner, while providing the platform administrators and developers a

declarative way of specifying the required database structure and the ability to initially populate

that database prior to client access, as well as supporting migration from one database structure

to another.

Sync Manager

Synchronization Manager allows users and applications to initiate, control and monitor

synchronization of local data stores using one or more synchronization services. Synchronization

Manager integrates multiple synchronization services under the same framework. Lotus

Expeditor provides synchronization services for DB2e, ISync, SyncML, and composite application

integration.

Lotus Expeditor Client for Devices

The Lotus Expeditor Client for Devices provides many new application functions over the previous

release, the Workplace Client Technology™ Micro Edition 5.7.2. These enhancements focus on updating

Product overview 5

Page 16: Lotus Expeditor: Developing Applications for Lotus Expeditor

the capabilities of the managed client platform to support Windows Mobile 5.0 and Windows Mobile

2003 SE devices with the most current technologies. Here are the highlights of the new application

features:

Runtime and tooling environment

jclDevice

J9 2.3 with jclDevice is a custom configuration that provides an optimal reduced-footprint

runtime environment for the client platform that supports Java Micro Environment (JME)

Foundation Profile 1.1.

Eclipse Embedded Rich Client Platform (eRCP) 1.0

The client platform includes the Eclipse Embedded Rich Client Platform, version 1.0 for handheld

devices, such as PDA’s and smart phones. eRCP implements the OSGi Release 4 specification.

Tooling

You can use the Lotus Expeditor Toolkit to develop device applications by using any of the same

tooling environments supported for the desktop client.

Application types

Eclipse Embedded Rich Client Platform (eRCP) applications

Lotus Expeditor Client for Devices now enables you to run eRCP applications.

Embedded Transaction Applications

Lotus Expeditor Client for Devices now enables you to run business logic that conforms to a

subset of the EJB 2.0 specification.

Compatibility

Lotus Expeditor Client for Devices continues to support Web, messaging, database, and Web

Services applications.

User interface

Eclipse Embedded Rich Client Platform (eRCP) 1.0

eRCP supports a subset of APIs and capabilities available in the RCP with the benefit of smaller

resource requirements. eRCP includes the embedded SWT (eSWT), embedded JFace (eJFace) and

Mobile Extensions.

Communication

Lotus Expeditor Client for Devices supports the Micro Broker and OSGi Event Admin. Lotus Expeditor

Client for Devices continues to support Web Services client applications that conform to the JSR 172

specification.

Overview of the managed client platform

The managed client platform provides the following set of standards-based Client Services for the

development of your managed client applications:

v Managed Client Services including a selection of runtime environments, a robust component

framework, and additional component services, all of which enable Java applications to run on

multiple operating systems and clients.

v Platform Management including the Eclipse Update Manager and an Enterprise management agent to

install and update applications and services on the client platform.

v Access Services including data and synchronization services, transactional messaging, Web Services, a

Web container to run local Web applications, an embedded transaction container to run local embedded

Enterprise Java Beans (EJB’s), a portlet container to run local portlets, and more.

v Interaction Services including integrated browser controls to launch Web applications, Eclipse

technology to support GUI applications, a portlet viewer to launch portlets, and a Workbench that

enables end-users to install and launch one or more applications.

6 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 17: Lotus Expeditor: Developing Applications for Lotus Expeditor

The client platform provides a set of standards-based APIs that you use to invoke these services.

Managed Client Applications

ClientServices Interaction Services

Access Services

Platform Management

Managed Client Services

Windows, Linux, Windows Mobile

Managed client services

The client platform provides a choice of runtime environments that enable Java applications to run across

multiple operating systems. For Lotus Expeditor Client for Desktop, the runtime environment is

jclDesktop, which is a custom runtime environment with reduced footprint (i.e. jclDesktop does not

include AWT). For Lotus Expeditor Client for Device, the runtime environment is jclDevice, which is a

custom runtime environment that runs applications written to the JME Foundation Profile 1.1

specification.

The client platform provides a Service Framework that implements the OSGi R4 framework specification

and provides a service-oriented architecture on top of the runtime environments. The OSGi framework

specification is provided by the OSGi Alliance. The OSGi Alliance’s mission is to specify, create, advance,

and promote wide industry adoption of an open service delivery and management platform.

Incorporating the OSGi standard into the client platform provides four very important capabilities:

v It enables multiple applications and components to share a single Virtual Machine (VM) that

implements the Java specifications. This saves valuable resources on the client when running multiple

applications because only one instance of the VM is launched rather than multiple instances of the VM.

v It enables applications to share services and packages, which further reduces resource requirements on

devices.

v It separates service interface from service implementation and provides publish, find, and bind

operations in support of a service-oriented architecture. This capability enables integration of business

applications on the same device.

v It enables dynamic life-cycle management without a VM restart so components can be updated without

impacting other unrelated components that are running at the same time.

The Eclipse framework is built on the Service Framework, which provides Eclipse with powerful

capabilities, such as the ability to dynamically load and unload components without restarting the Eclipse

framework and robust life cycle management of components.

The client platform also provides optional OSGi services, such as UserAdmin, LogService, Configuration

Management, and more.

Product overview 7

Page 18: Lotus Expeditor: Developing Applications for Lotus Expeditor

Access services

Access Services provide a familiar programming model for JEE developers so they can reuse their skills

and software components to develop applications that run on managed clients. Additionally, Access

Services enable managed client applications to support offline operations. Access Services also enable you

to move key components of your application to the client platform through the use of standard APIs.

For desktops, the client platform provides an embedded Web container to run JEE Web applications that

support the Servlet 2.3/2.4, JSP 1.2/2.0, JSF 1.1, JSTL, and Struts specifications. For devices, the Web

container supports Servlet 2.3 and JSP 1.2 to conserve resources. The Web container enables you to move

your Web applications from the server to clients to preserve the existing browser user interface, leverage

your existing Web components, and provide a richer user experience through support of local and offline

operations.

The client platform also provides an embedded Transaction Container to run JEE Enterprise Java Beans

(EJB’s) that conform to any of the following specifications: 1.1 and 2.0 Stateless Session Beans, Container

Managed Persistence (CMP) Entity Beans, and Bean Managed Persistence (BMP) Entity Beans. This

container enables you to move your business logic from the server to clients so you can leverage your

existing beans to make business logic available to client applications, including Web applications, and

support local and offline operations. These business logic components are referred to as Embedded

Transaction applications.

In addition, the desktop client provides a portlet container to run portlets that support the JSR 168

specification.

There are four key services that support local and offline operations.

First, you can use the JDBC API with DB2® Everyplace or IBM® Cloudscape™ as a local SQL database

when more advanced data manipulations are required than can be supported by placing data in a local

file store. These databases can periodically synchronize with Enterprise databases to capture data on the

client for use by the client application when the user is offline. These databases can also protect local data

through data encryption.

DB2 Everyplace is an extremely small footprint relational database (200-300 KB). It is especially suitable

for embedded devices, where large databases and sophisticated queries are not normally required, but

can also be used on larger devices. DB2 Everyplace provides transaction support covering updates to

multiple tables within a single transaction, encrypted tables, and zero client administration.

IBM Cloudscape is a 100% pure Java relational database, providing SQL-92, partial SQL-99, and SQLJ

support, indexes, triggers, transactions, encryption, and the standard features that one expects of a

relational database. Because IBM Cloudscape contains a larger number of features, it is approximately 2

MB in size. Therefore, IBM Cloudscape might not be suitable for smaller, resource-constrained devices.

Second, you can also use the Java Message Service (JMS) API with WebSphere MQ Everyplace (MQe) to

send and receive messages. MQe provides once-only, assured messaging and supports offline operations

with local message queues that hold messages when the device is offline and then sends these queued

messages to Enterprise applications when the device is back online. Similarly, messages destined for

client applications are held in server-side message queues and then sent to the client applications when

the device is back online. MQe encrypts messages to protect content over the network. As a result, the

client platform enables your users to conduct secure e-business on demand transactions.

Third, you can use the JMS API with the micro broker, which is suitable for applications that require

messaging, notification and event services. The micro broker supports publish and subscribe messaging

in which publishers generate messages containing information about a particular subject, subscribers

express interest in messages containing information on a particular subject, and a broker receives

8 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 19: Lotus Expeditor: Developing Applications for Lotus Expeditor

messages from publishers and delivers messages on a particular subject to the subscribers registered for

that subject. You can support offline operations through defined quality-of-service levels and durable

subscriptions.

Fourth, for the desktop client, you can use the Network Layer API to determine the status of the network

and remote resources when running your applications. You can then execute your application logic

accordingly.

For online operations, the client platform supports Web Services so client applications can consume and

provide Web Services in a secure manner. As a result, your users have access to a broad range of business

data and consumer information. The client platform implements Web Services similar to those defined in

JSR 172 and provides support for document literal encoded streams that exchange well-typed data objects

so client applications can consume Web Services. You can also develop an OSGi service and, during

registration of the service, indicate that it is also available as a Web Service. For the desktop client, you

can also use Axis Web Services so client applications can consume Web Services, with full support for

JAX-RPC (JSR 101).

The SyncML4J (SyncML for Java) toolkit enables you to develop data synchronization and device

management client applications based on the Open Mobile Alliance (OMA) Data Synchronization (DS)

and Device Management (DM) standard protocols. As a framework, SyncML4J supports user-defined

data sources. Data sources can range from simple resources, such as memos and images, to complex

schema-aware data types, such as relational databases or PIM databases.

For the desktop client, security services support: a key store, which provides an encrypted local

repository for user security information; accounts, which allows access to user account information (e.g.

user id and password); and single sign-on, which minimizes logon prompts. Additional services include:

database lifecycle management, which provides uniform interoperability with different relational

databases; and synchronization manager, which allows users and applications to initiate, control and

monitor synchronization of local data stores using one or more synchronization services.

Interaction services

This section provides information on interaction services.

Lotus Expeditor Client for Desktop

The Lotus Expeditor Client for Desktop is built on the Eclipse Rich Client Platform (RCP) so you can

deliver applications that provide a rich user experience across multiple platforms. The client platform

provides the Workbench, Standard Widget Toolkit (SWT), JFace, Help and Preferences interaction services.

The Workbench provides an integrated application desktop window so end-users can install, manage and

launch one or more applications within a single window. The Workbench presents each application

individually in its own perspective, only one of which is visible at any given time. When an end-user

selects an application from the Workbench, the Workbench launches the perspective for that application.

You specify an extension point for each of your applications so the Workbench can correctly launch the

perspective for your application.

The desktop client supports Web technology so users can interact with local Web Applications through a

Web browser. Each Web application installed onto the Workbench runs in a browser perspective. When

an end-user selects a Web application from the Workbench, the Workbench launches a browser

perspective which in turn launches a local Web browser to run the Web application within the

Workbench window. When you specify the extension point for Web applications, the Workbench

automatically handles launching your Web applications in the browser perspective. You can also use this

extension point to enable the Workbench to launch a Web application on a remote server.

The desktop client also supports rich client applications, which interact with end-users through a

graphical user interface (GUI). Each rich client application installed onto the Workbench runs in an

application perspective. In this case, each application must contribute its own perspective to the

Product overview 9

Page 20: Lotus Expeditor: Developing Applications for Lotus Expeditor

Workbench. In each perspective, an application provides the collection of views, layout of views, and

actions appropriate for the tasks that end-users will perform with the application. You use SWT and the

JFace toolkit to develop the GUI for rich client applications. SWT provides a cross-platform API that

tightly integrates with the native widgets of the operating system and, therefore, gives your applications

a look and feel that makes them virtually indistinguishable from native applications. The JFace toolkit

provides a set of components and helper utilities that simplify many of the common tasks in developing

SWT user interfaces. When an end-user selects a rich client application from the Workbench, the

Workbench launches the appropriate perspective to run the application within the Workbench window.

When you specify the extension point for rich client applications, the Workbench automatically handles

launching the perspectives for your rich client applications.

The desktop client also provides services that enable you to contribute Helps and Preferences for your

applications so end-users can understand and configure your applications respectively within the

Workbench.

A personality extends the concept of a WorkbenchAdvisor to allow for different WorkbenchWindow

configurations to run within one running VM. The desktop client provides a personality. However, you

can also provide your own personalities.

The user interface widgets provide a common look and feel for all user interfaces that run on the desktop

client platform. These widgets provide the following features:

v Renders the toolbar skin, which means it formats the toolbar to make its style consistent with the style

defined for the application it displays in

v Manages drag and drop of items within the toolbar

v Saves and loads the last state of toolbar items using the Eclipse memento pattern, which uses the

saveState and restoreState methods to remember the position of each toolbar item when the user

shuts down the client so that the same toolbar items display when the user restarts it

The Embedded Browser extends an application’s functions, such as browser launch, handles events, and

preference user interface, etc. The Embedded Browser is based on SWT browser widget in Eclipse, which

can support Internet Explorer on Windows and Mozilla on Linux.

Lotus Expeditor Client for Devices

The Lotus Expeditor Client for Devices is built on the Eclipse embedded Rich Client Platform (eRCP) so

you can deliver applications that provide a rich user experience across multiple handheld devices. The

device client provides the embedded Workbench (eWorkbench), embedded Standard Widget Toolkit

(eSWT), embedded JFace (eJFace) interaction services. These services support a subset of the Eclipse RCP

APIs.

The device client provides a customized eRCP eWorkbench. When running in the development

environment, this workbench displays just like the normal eRCP eWorkbench. However, when running

on a device, the customized eWorkbench is invisible to the user. It runs in the background and does not

provide user interface. Instead, it allows eRCP applications to seamlessly integrate with the native GUI

and shows running eRCP applications in the Windows task list. The user clicks the link for an

application, and it displays like a normal application on the device.

The device client also supports Web technology so users can interact with local Web applications through

a Web browser.

Platform management

Platform Management installs, maintains, and configures applications and services on the client. There

are two platform management services.

The Update Manager enables end-users to directly install applications and components from standard

Eclipse update sites onto managed clients.

10 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 21: Lotus Expeditor: Developing Applications for Lotus Expeditor

The Enterprise Management Agent works cooperatively with the Device Management Server provided by

the Lotus Expeditor Server to perform management operations. The agent and server use the

SyncML/DM protocol defined by the Open Mobile Alliance to communicate management requests. An

administrator can schedule management jobs for devices that include software installation, update, and

configuration. When installing and updating software components, the management system determines

which components are already on the device and then installs only the missing components.

Lotus Expeditor Toolkit

The Lotus Expeditor Toolkit provides a complete, integrated set of tools that allows you to develop,

debug, test, package and deploy client applications that use Client Services. You can use the toolkit to

develop the following types of client applications:

v Eclipse Rich Client Platform applications (desktop client only)

v Eclipse embedded Rich Client Platform applications

v Web applications

v Embedded Transaction applications

v Portlet applications (desktop client only)

v Database applications

v Messaging applications

v Web Services applications

The toolkit provides wizards that enable you to create Client Services projects to develop client

applications. The toolkit uses Target Definitions to provide a convenient method for you to specify the

runtime environment, the build-time environment, and the set of components that can run on the

platform. For example, when you create a Client Services project, you select a Target Definition and set of

Features from a list of available targets and the toolkit automatically sets up the Java Build Path and

runtime for your project. You can then edit, compile, and debug your project. The toolkit provides a

default list of Target Definitions; however, you can create your own definitions.

You can also use the toolkit to build custom client platforms for your devices. However, custom

platforms require an OEM license from IBM.

The toolkit is built on Eclipse 3.2.1 and extends the familiar application development tools so you can

leverage your existing skills and software components.

Getting started with the Lotus Expeditor Toolkit

The information in this section guides you through the process of setting up the Lotus Expeditor Toolkit

and creating a sample plug-in with Lotus Expeditor Toolkit.

Lotus Expeditor Toolkit overview

The Lotus Expeditor Toolkit provides the tools necessary to create and test OSGi plug-ins, Web

Applications, Embedded Transaction Applications, Web Services client and providers, and Portlet

applications for use on the Lotus Expeditor platform. Lotus Expeditor is built on Eclipse 3.2.1, which is

built on top of OSGi. For this release, Eclipse 3.2.1 plug-ins run as OSGi plug-ins. The Plug-in Developer

Environment (PDE) provided with Eclipse 3.2.1 provides many features that are useful in the

development of OSGi plug-ins. The Lotus Expeditor Toolkit is built upon the solid base provided by the

Eclipse PDE.

Lotus Expeditor Toolkit allows developers to focus on the creation of plug-ins, without requiring them to

become OSGi plug-in internals experts. In its simplest form, the toolkit is designed for the developer who

wants to develop and store ten or twenty plug-ins with automated assistance purely within the Eclipse

environment.

Product overview 11

Page 22: Lotus Expeditor: Developing Applications for Lotus Expeditor

Using the Lotus Expeditor Toolkit, developers build applications and services as ″plug-ins″ that run on

Lotus Expeditor runtime. A plug-in may be packaged as a JAR file with information in the manifest file

that relates information to Lotus Expeditor Toolkit about the plug-in, such as the services and packages

the plug-in imports and/or exports. A plug-in may also be packaged in a plug-in structure. For more

information, see “Packaging and deploying applications” on page 327.

Supported platforms and prerequisite software

The Lotus Expeditor Toolkit runs on the following platforms and supports application development for

the Lotus Expeditor runtime on these same platforms:

v Windows XP

v RedHat EL 4.0 WS with GTK support Update 3

The toolkit supports application development for the Lotus Expeditor runtime on these same platforms

plus Windows Mobile 2003 SE and Windows Mobile 5 PPC and Phone Editions.

In addition, Lotus Expeditor Toolkit can be installed into any of the following development tools:

v Rational Application Developer (RAD) 7.0

v Rational Software Architect (RSA) 7.0

v Eclipse 3.2.1 + Web Tools Project (WTP) 1.5.1

v WebSphere Application Server Toolkit (AST) 6.1.1

Understanding the development platforms

Developing Applications for Lotus Expeditor makes several references to the Rational Software

Development Platform. The Rational Software Development Platform is a powerful set of integrated

development tools that supports open standards. The Platform is based on the Eclipse open source

platform and runs across multiple platforms including Linux. The tools Rational Application Developer

(RAD) and Rational Software Architect (RSA) are used as base tools for the Lotus Expeditor Toolkit. You

can install the Lotus Expeditor Toolkit on top of RAD or RSA. When this documentation mentions the

Rational Software Development Platform, it means specifically the RAD and RSA tools.

For a list of supported development tools, refer to “Supported platforms and prerequisite software.”

Setting up the Lotus Expeditor Toolkit

This section provides Desktop and Device installation instructions for the Lotus Expeditor Toolkit.

Setup for Desktop development: Before you use the Lotus Expeditor Toolkit, verify that you have done

the following:

Note: Upon the first startup of a workspace, you will see a dialog that prompts you to automatically set

the preferences for the Lotus Expeditor Toolkit. Selecting yes in this dialog, causes steps 1 and 2

below to be done automatically. You may also skip them when performing a manual set up.

1. Set the plug-in development target platform location to the Lotus Expeditor development runtime.

a. Select Window > Preferences > Plug-in Development > Target Platform.

b. Set the Location field for the target platform to <toolkit_install_location>/eclipse/plugins/com.ibm.pvc.wct.runtimes_ 6.1.0.0-<date>/eclipse.

c. Select OK.2. Set the default workbench JRE to be the Lotus Expeditor JRE. Lotus Expeditor runtime ships with

jclDesktop.

a. Select Window > Preferences > Java > Installed JREs.

b. Click the check box next to jclDesktop to select it as the default workbench JRE.

c. Click OK.

12 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 23: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: The PDE Target Platform page provides a method of selecting ″Pre-defined Targets″ and applying

those targets to the environment. In general, this option should not be used when building

applications with the Lotus Expeditor Toolkit. This may reset the target platform to point to the

IDE environment in which you are developing.

Setup for Device development: When installing the Lotus Expeditor Toolkit, install both the desktop

and device features. Upon the first startup of a workspace, you will see a dialog that prompts you to

automatically set the preferences for the Lotus Expeditor Toolkit. Select yes in this dialog. Next, prepare

the IDE to build applications for devices:

1. Select Window > Preferences > Client Services.

2. Change Default Target Selection to Default Device Target.

3. Expand Java and click Installed JREs.

4. Check jclDevice Win32 x86.

5. Expand Plug-in Development and click Target Platform.

6. Select Default Device Target under Pre-defined Targets and click Load Target. Alternately, Browse to

eclipse_home\plugins\com.ibm\pvc.wct.device.runtimes_6.1.0.0-date\rcp\eclipse and click

Reload.

7. Click OK to exit.

Creating a sample Client Services project

Refer to the following instructions to create a sample Client Services project that includes the Client

Services Pizza JSP Web Application Sample project:

1. Select Window > Open Perspective > Other > Plug-in Development from the menu bar.

2. Select Help > Samples Gallery.

3. Select Application Samples >Lotus Expeditor samples > Pizza JSP Web Application.

4. Select Import.

Running your project on development runtimes: This section contains information on running projects

on both desktop and device runtimes.

Running on the Desktop runtime: To run your project on development runtimes, perform the following

procedure:

1. Select Finish on the Pizza JSP Web Application Sample project naming dialog.

The Pizza JSP Web Application Sample project appears in the Package Explorer view.

2. Launch the Lotus Expeditor runtime.

a. Select either Run > Run... or Debug > Debug...

b. In the Launch Configuration Dialog that comes up, select Client Services. Click New Launch

Configuration.

c. Select the Target tab and ensure that Default Target is selected.

d. Click Run.

Note you did not have to explicitly install the Pizza JSP Web Application into Lotus Expeditor

runtime. This is because, as part of standard Eclipse behavior, the Lotus Expeditor runtime launches

all plug-ins in the user’s workspace (plus any enabled external plug-ins found in the Target Platform

folder).This behavior is controlled by the Plug-ins tab of your Lotus Expeditor.

3. Now, with the Pizza JSP Web Application already running on the Lotus Expeditor runtime, verify its

behavior by launching the application in the runtime’s browser. Click Open to display Pizza JSP Web

Application as a selectable application to launch from the Lotus Expeditor runtime.

Running on the Device runtime: You can run your application on the Lotus Expeditor for Devices runtime

by launching the workbench. The workbench will detect your application and list it as an application you

can start. To run the workbench:

Product overview 13

Page 24: Lotus Expeditor: Developing Applications for Lotus Expeditor

1. Select Run > Run...

2. Double-click Client Services.

3. Change the new configuration’s name.

4. Switch to the Profile tab, and select Default Device Target.

5. For Runtime JRE, select jclDevice Win32 x86.

6. Switch to the Plug-ins tab and click Select All.

7. Switch to the Configuration tab and select Use an existing config.ini file as a template, then click

Variables.... Select rcp_devicebase and then click OK. ${rcp_devicebase}/config.ini should appear

in the path field.

8. Click Run.

Setting Toolkit preferences

After the Lotus Expeditor Toolkit installation, users may change the Client Services default values by

selecting Window > Preferences... > ClientServices. The following Client Services preferences can be

modified:

Auto-Management Preference

v Search for dependencies automatically upon resource changes

Select this option to enable the tools to search for package dependencies whenever the user modifies

source files. When this option is deselected, the tooling will not search for any unresolved or unused

dependencies in your project.

v Attempt to automatically resolve Manifest dependencies

Select this option to enable the tools to automatically manage the package dependency information in

the manifest file. Package dependencies in your project’s Java code will automatically be reflected

through proper updates to the manifest file. When this option is deselected, package dependencies that

are not properly reflected in the manifest are flagged with problem markers, along with quick fixes to

resolve the problems.

v Give preference to Required-Bundle

Require-Bundle will be used to automatically resolve a package dependency in cases where either

Require-Bundle or Import-Package can be used.

v Give preference to Import-Package

Import-Package will be used to automatically resolve a package dependency in cases where either

Require-Bundle or Import-Package can be used.

Default Target Selection

Use the drop-down list to choose the default Target Definition. This means that when creating a new

Client Services project or a new Client Services launch configuration, the default Target Definition

selection will be obtained from this setting.

Show plug-in objects in editors and dialogs using...

v Identifiers

This selection displays the plug-ins and features objects using their given ID attribute. A plug-in or

feature will always have an ID value associated with them. This is not the case with the NAME.

v Presentation names

This selection displays the plug-ins and features objects using their given NAME attribute.

Turning on build automatically

For optimum launch performance, the ’build automatically’ preference should be enabled. To enable

’build automatically’, select Project from the main menu bar. If Build Automatically is checked, the

preference is already enabled. If it is not checked, select the option to enable it.

14 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 25: Lotus Expeditor: Developing Applications for Lotus Expeditor

Concepts

The Lotus Expeditor Toolkit extends the Eclipse and Rational integrated development environment to

support the development, testing, and deployment of Eclipse plug-ins and OSGi plug-ins. The Lotus

Expeditor Toolkit adds wizards and editors that collectively provide a developer with the tools needed to

create, build, test, and package applications for the Lotus Expeditor runtime.

Client Services Project: A Client Services project contains a set of plug-ins and an associated Target

Definition. All or some of the Target Definition’s features may be selected. In addition, Client Services

projects can:

v Automatically update the Java Build Path.

Lotus Expeditor Toolkit can automatically update the project’s Java Build Path to reflect the project’s

Target Definition and Features settings. Refer to “Target Definition” and “Target features” on page 17

for more information.

v Provide a default plug-in activator.

The toolkit can create a default bundle activator class. You can tailor the default plug-in activator class

by editing the source file for the class folder.

v Automatically update the Manifest file.

The toolkit can automatically update the Manifest file in the Client Services project to contain

appropriate OSGi metadata for the project. Client Services manages or provides initial default values

for the metadata fields by:

– Setting Bundle-Name to the project name on project creation

– Setting Bundle-Version to 1.0.0 on project creation

– Setting Bundle-Activator to the default bundle activator if one was created

– Updating Import-Packages and Require-Bundle to reflect the packages imported by the project’s

classes. Refer to “Automatic management of manifest package dependencies” on page 17 for more

information

Managing Client Services project dependencies

The following describes how to best use the tooling provided by the Lotus Expeditor Toolkit to manage

the dependencies in a Client Services project. These dependencies include the Java Build Path and the

manifest file. When developing Eclipse plug-ins or OSGi plug-ins, the Java Build Path, the packages used

by the plug-in’s code, and the manifest are all related.

v The Java Build Path must contain the necessary libraries and plug-ins that contribute the packages and

classes used by the project’s plug-in code during the compilation process. If this is not the case, the

tools will tag the code with problem markers indicating that a referenced package or class cannot be

found.

v The manifest must contain references to the packages and plug-ins that the plug-in code is using. This

is how the OSGi framework manages the class path of the plug-in at runtime. A reference to a

particular plug-in implementation is done through a Require-Bundle manifest entry. A reference to a

required package is done through an Import-Package manifest entry. Failure to properly resolve these

dependencies in the manifest can cause the plug-in to fail at runtime with a “class not found” error

(NoClassDefFoundError).

The following mechanisms are available to help manage both the Java Build Path and the manifest file:

Target Definition: A target definition specifies all aspects of a target - including its location, constituent

plug-ins and environment. Please refer to the Eclipse Documentation for more information on Target

Definitions. The Client Services project wizard provides a method for defining the Target’s features and

each feature’s plug-ins to be used at runtime. Note that each Target’s feature is composed with a set of

one or more plug-ins.

Product overview 15

Page 26: Lotus Expeditor: Developing Applications for Lotus Expeditor

A Target Definition defines a set of Target features. Target features enable you to focus on the logical

service requirements of the service instead of the requirements of the actual underlying Client Services

plug-ins.

When you create a Client Services project, you select a Target Definition and a set of Target features for

the project. The Lotus Expeditor Toolkit updates the Java Build Path for the project to reflect the Java

Runtime Environment (JRE) of the platform, based on the Target Definition and Target features you

selected. The Target Features you selected are automatically added to the Java Build Path of the project.

The Lotus Expeditor Toolkit provides Target Definitions that represent the bundles available in the Lotus

Expeditor runtime.

Creating a Target Definition: The Lotus Expeditor Toolkit has extended the functionality of a regular PDE

target definition. To support this new functionality, Lotus Expeditor Toolkit has additional elements and

attributes not found in a traditional PDE target definition. The PDE contains a graphical target definition

editor. Since the editor is not aware of these additional elements and attributes, it will remove them when

you use it to modify the target definition. Therefore, you should use the graphical editor to create the

initial content of the target definition, and then add additional content with the text editor.

The additional attributes and elements created by the Lotus Expeditor Toolkit are used to modify the

behavior of the Client Services Launcher. A target can contain a list of feature and plug-in elements.

These elements are displayed on the Profile tab of the Client Services Launcher. By default, all listed

elements are required and cannot be deselected. If a feature or plug-in is not required for launching but

can add optional functionality, add the attribute optional="true". For example:

<feature id="com.ibm.db2e.feature" optional="true"/>

A target definition may also specify the config.ini location to be used during launch. You can do this by

adding a config element with a location attribute. The location can be absolute or contain variables. The

value of the location will set the location of the config.ini template to be used for launching. A default

personality can also be specified with a personality element with an id attribute. The value of the id

attribute should be the personality ID to be specified during launch. For example:

<config location="${rcp_base}/config.ini"/>

Additional launcher settings include specifying environment variables. To do this, create an envVariables

element. If you prefer the variables values to replace the existing environment variables, add the attribute

replace=“true”. Under the envVariables element, create a separate child element called variable. Each

variable element has a value attribute and optionally, an os attribute if it is specific to a particular

operating system. For example:

<envVariables>

<variable name="PATH" value= "${isynch_win32}/os/win32/x86;${db2e_win32}/os/win32/x86"

os="win32"/>

<variable name="LD_LIBRARY_PATH" value=

"${isynch_linux}/os/linux/x86:${db2e_linux}/os/linux/x86"

os="linux"/>

</envVariables>

Lastly, a target definition can define the default product and application for launching. This is specified in

a program element. To specify a product, create a prodId attribute and set the value to the product ID. To

specify an application, create an appId attribute and set the value to the application ID. If both are

specified, a useProd attribute should also be included. The value should be set to true if the product

takes precedence, otherwise it should be set to false. For example:

<program prodId="com.ibm.rcp.platform.personality.branding.DefaultProduct"

appId="com.ibm.rcp.personality.framework.RCPApplication" useProd="true"/>

You can replace the default Lotus Expeditor branding with a custom branding, by replacing the Default

Branding feature (com.ibm.rcp. personality default..branding.feature) with your own feature.

16 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 27: Lotus Expeditor: Developing Applications for Lotus Expeditor

Branding is the look and feel of the product - it includes splash screens and window decorations. For

details on creating your own branding feature, refer to the documentation Assembling and Deploying

Lotus Expeditor Applications.

To launch with your custom branding, you must create a custom target definition:

1. Create a general project (File > New > Project > General Project).

2. Create a target definition within your general project (File > New > Target Definition).

a. Select the general project as the parent folder.

b. Specify a name for the target.

c. Use an existing target definition, and select Default.

d. Select Finish. The target definition editor appears with your new target definition.3. Customize your new target definition:

a. On the Overview page, select the Features tab

b. Search for com.ibm.rcp.personality.personality.default.branding.feature and select Remove.

c. Select Add and select your custom branding feature.

d. Save your target definition.4. To launch your new target definition, select Run > Run... The run wizard appears.

a. Double click Client Services.

b. On the Main tab, locate the Program to Run box. Select your custom product from the drop down

list.

c. On the Profile tab, Browse to find and select your custom target definition.

d. Review the features that are selected. You can only deselect features that are not required.

e. Select Run.

Lotus Expeditor launches with your custom branding.

Target features: A Target feature represents a logical service, such as an XML parser or logging service

that consists of one or more plug-ins. Target features enable you to focus on the logical requirements of

the service instead of the requirements of the actual underlying plug-ins.

Secondary Dependencies: Secondary Dependencies allow users to include plug-ins in the build path

without adding references to the Manifest. By using this mechanism to include these plug-ins in the build

path, users can compile and develop their code with the convenient features of Eclipse JDT. Once the

user references one of the packages in a plug-in in the Secondary Dependency list, Lotus Expeditor

Toolkit can display a warning to inform the user the project is compiling against classes which are not

available during runtime (For information on how to change the severity of this notification, see “Setting

Toolkit preferences” on page 14). The Lotus Expeditor Toolkit also provides “quick fixes” to resolve this

problem by adding corresponding references to the Manifest. The user may also configure the Lotus

Expeditor Toolkit to automatically add dependencies to the Manifest, whenever they are found. Please see

“Automatic management of manifest package dependencies.”

The Target features and plug-ins selected from a project’s Target Definition are added to the Secondary

Dependencies for dependency management.

Note: For the Lotus Expeditor Toolkit to find possible dependencies in your project’s code, you must use

the Automated Management of Dependencies table on the Dependencies page of the Plug-in

Manifest Editor or select features and/or plug-ins from the project’s Target definition.

Automatic management of manifest package dependencies: Manifest package dependencies are

automatically managed for Client Services projects by default. This capability can be disabled through the

new project wizard when creating a Client Services project and through the Client Services properties tab

of an existing project. When enabled, this option automatically updates the Require-Bundle or

Product overview 17

Page 28: Lotus Expeditor: Developing Applications for Lotus Expeditor

Import-Package entries in the project’s manifest file based on changes in the project’s Java code. The

header to which the dependencies are added is specified by a per project preference. You can change this

preference on the Dependencies Page of the Plug-in Manifest Editor, the project’s Client Services property

page under the options tab, or the first page of the Client Services Project creation wizard.

When new package dependencies are added to the project’s Java code, the manifest file is automatically

updated with the proper entries. It is important to note that this mechanism requires the developer to use

the Target Definition or secondary dependencies to represent the project’s plug-in dependencies. Plug-ins

that are placed on the Java Build Path through the project’s Java properties page will not be handled by

this mechanism.

If this option is disabled, the tools will flag the manifest file with error markers if packages are used in

the Java code without being referenced in the manifest file. These errors can then be selectively fixed

through the quick fix mechanism.

Lotus Expeditor Toolkit will search for manifest package dependencies by default. This capability can be

disabled through the new project wizard when creating a Client Services project and through the Client

Services properties tab of an existing project. If this option is disabled, the user can still manually search

the project for manifest dependencies by using the Add dependencies link in the Automated

Management of Dependencies panel on the Dependencies page of the Plug-in Manifest Editor.

Configuring the Client Services launcher

To configure the Client Services launcher, perform the following procedure:

1. 1. From the Java perspective, select Run > Run... to invoke the Launch Configuration Dialog wizard

2. Create a new Client Services launch configuration.

At this point, you can run this configuration with default values or proceed to configure it farther.

3. In the Main tab of this new Client Services launch configuration, select the Workspace Data,

Personality, Program to Run, Java Runtime Environment and National Language Support groups for

this launch.

4. The Argument tab will contain default values for the Program and VM argument data of this Target

Definition.

5. In the Profile tab, select any necessary pre-defined Target Definitions for this launch.

6. In the Plug-ins tab, individual plug-ins may be selected in addition to the list already defined in the

Profile tab.

7. The Configuration tab contains default configuration data for the location and format of this

configuration file.

8. The Tracing tab displays a list of plug-ins that support tracing.

9. Use the Environment tab to define environment variables for the configuration.

10. Use the Source tab to add any additional sources or archives to the configuration.

11. The Common tab contains default configuration data for the OSGi console.

12. Click Run to launch the new Client Services launch configuration.

Configuring the Lotus Expeditor Toolkit environment for Sametime

These instructions assume sametime is installed c:\sametime.

1. Set the target platform:

a. From within the Eclipse IDE, select Window > Preferences.

b. Expand Plug-in Development.

c. Select Target Platform.

d. In the Location edit control, type C:\sametime.

e. Click the Reload button.

f. Click OK.

18 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 29: Lotus Expeditor: Developing Applications for Lotus Expeditor

2. Set the JRE:

a. From within the Eclipse IDE, select Window > Preferences.

b. Expand Java.

c. Select Installed JREs.

d. Check the box next to jclDesktop.

e. Click OK.3. Set the Compliance Compiler level:

a. From within the Eclipse IDE, select Window > Preferences.

b. Expand Java.

c. Select Compiler.

d. Set the Compiler Compliance Level to 1.4.

e. Click OK.4. Set the default platform:

a. From within the Eclipse IDE, select Window > Preferences.

b. Select Client Services.

c. Change the Default Target Selection to Sametime Target.

d. Click OK.5. Create a new runtime configuration:

a. From within the Eclipse IDE, select Run > Run...

b. Select Client Services.

c. Click New.

d. Enter a name (for example, sametime).

e. Select Clear workspace data before launching.

f. Click Run.

The Sametime® target sets all VM arguments. The tabs on the client services launcher function similar to

the Eclipse PDE launcher, with a few additions. If you want to add or remove plug-ins from the launch

configuration at a feature level, change to the profile tab and select the features to add and remove.

Creating and using Client Services applications

This section describes the tasks for creating and using Client Services projects.

Creating a Client Services project

Complete the following steps to create a new Client Services project:

1. Select File >New >Project.

The Select a wizard page displays.

2. Select Client Services > Client Services Project.

3. Click Next.

The Client Services Plug-in Project panel displays.

4. Specify a project name in the Project name field.

5. Click Next.

The Client Services Content page displays.

6. Modify the Plug-in Properties as necessary .

7. Modify the Plug-in Options as necessary.

8. Modify the Auto-Management Preference as necessary. Click Next.

9. The Target Profile page displays. The selected Target Definition is the target specified in the

Preference page. You may select another Target via the Combo list.

Product overview 19

Page 30: Lotus Expeditor: Developing Applications for Lotus Expeditor

A description of the Target Definition you selected displays in the Description field.

10. Select the features and plug-ins to be included for this project by checking the check boxes beside

the features names or IDs. You may select Finish here, or click Next to view the Template page.

11. Create a Client Services project using one of the three templates – Preference page Basic Application,

Rich Basic Application or Text-Editor Sample Application:

a. Perform steps 1 through.10 above, but do not select Finish. Rather, select Next to view the

Template’s page

b. Select one of three templates and click Finish or select Next to change the default Application

name, Package name, and so on for this project.

Note: If the Target Definition that you selected in step 9 on page 19 requires specific services, the

services are automatically selected in the Target features field. You can select any additional

services that the application uses.

12. Click Next. The Templates panel is displayed. You may select a Template for this application.

Note: In some cases, a Client Services Project cannot automatically determine the correct Manifest

dependency settings. For example, if your code uses the java.lang.Class.forName(...) API,

the tool cannot correctly calculate the required Manifest dependency settings at compile time.

In this case you should disable the Attempt to automatically resolve Manifest dependencies

option and configure the dependency section of the Manifest manually by using the Manifest

Editor.

13. Click Finish.

Lotus Expeditor Toolkit creates a Client Services project.

Creating a Client Services fragment project

1. Select File > New > Project.

The Select a wizard page displays.

2. Expad Client Services and select Client Services Fragment Project.

3. Click Next.

The Client Services Fragment Project page displays.

4. Specify a project name in the Project name field. Click Next.

5. The Fragment Content page displays. Modify the Fragment Properties as necessary.

6. Modify the Host Plug-in.

Note: A host plug-in ID must be selected.

Modify the Auto-Management Preference as necessary.

7. Click Next.

Note: In some cases, a Client Services project cannot automatically determine the correct Manifest

dependency settings. For example, if your code uses the java.lang.Class.forName(...) API,

the tool cannot correctly calculate the required Manifest dependency settings at compile time.

In this case, you should disable the Attempt to automatically resolve Manifest dependencies

option and configure the dependency section of the Manifest manually by using the Manifest

Editor.

8. The Target Profile page displays. The selected Target Definition is the target specified in the

Preference page. You may select another Target via the Combo list.

9. Select the features and plug-ins to be included for this project by checking the check boxes besides

the features names or IDs.

20 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 31: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: If the Target Definition that you selected above requires specific services, the services are

automatically selected in the Target Features field. You can select any additional services that

the application uses.

10. Click Finish.

The Lotus Expeditor Toolkit creates a Client Services Fragment project.

Converting a Java project into a Client Services project

Complete the following steps to convert a Java project into a Client Services project:

1. Select File->New->Other....

The Select a wizard page displays.

2. Expand Client Services and select Convert Project to Client Services Project.

3. Select Next.

The Convert Existing Project page displays.

4. Select the project that you want to convert from the list of Available projects.

Note: You may check the Copy project before conversion checkbox to make a copy of the selected

project and convert the copy.

5. Click Next.

The Target Profile page displays. The selected Target Definition is the target specified in the Preference

page. You may select another Target Definition via the Combo list.

6. Select the features and plug-ins to be included for this project by checking the check boxes besides the

Features names or IDs.

7. Click Finish.

The Lotus Expeditor Toolkit converts the Java project into a Client Services project.

Note: Any project of a Java, WEB, Plug-in, or EJB nature can be converted to a Client Services project.

For more information about natures, please refer to the Eclipse documentation.

Updating the buildpath and classpath for converted Client Services projects

To update the buildpath and classpath for projects that have been converted into Client Services projects,

perform the following procedure:

1. Import the external jar into the Client Services Project, using File > Import > File System wizard.

2. Add the external jar to the Bundle-ClassPath of the manifest.mf file.

3. Open the manifest.mf file with the Manifest Editor.

4. Click on the Runtime tab, and add the external jar file to the Classpath section.

5. Add the Export-Package Statement to the manifest.mf file. To add the Export-Package statement, from

the Bundle Manifest Editor select the Runtime tab, and add the packages in the Exported Packages

section for any other projects that must reference this external jar.

6. Add a Require-Bundle/Import-Package to Manifest to reference the dependent project. To add the

Require-Bundle statement, from the Manifest Editor select the Dependencies tab, and add the

referenced bundle to the Required Plug-ins section. To add the Import-Package statement, from the

Manifest Editor open the Dependencies tab, and add the packages to the Import Packages section.

Setting Client Services project properties

Client Services projects have some project-specific properties. To modify the project properties, complete

the following steps:

1. Right-click on your Client Services project and select Properties.

2. Select Client Services.

The Target Profile tab allows you to modify the previously selected Target Definition, Target features,

plug-ins and Feature plug-ins.

Product overview 21

Page 32: Lotus Expeditor: Developing Applications for Lotus Expeditor

The Options tab allows you to modify the Auto-Management preferences - Require-Bundle or

Import-package.

See the table, Client Services Project Options in “New Client Services Project Wizard” on page 372 for

additional information.

3. Make the changes you desire and click OK to commit your changes.

Launching Client Services launch configurations from the manifest editor

To launch a Client Services launch configuration from the Client Services project’s manifest editor,

perform the following procedure:

1. Navigate to the Overview tab of the Client Services project’s manifest editor, and select Launch Client

Services application.

2. A list of Client Services launch configurations displays if more than one Client Services launch

configurations are currently defined.

If there is only one launch configuration, it will be the one launched. If there is no configuration, one

is created and launched for the project.

3. From the list of Client Services launch configurations, select a configuration.

4. Click OK. The selected configuration is launched.

Using the samples

To get started using the client platform or specific features of the client platform, review the collection of

client platform samples. The pre-built samples are provided by the Lotus Expeditor Toolkit.

Installing samples using the Rational Software Development Platform

The Samples Gallery is a facility that is available in the Rational product set. It acts as a centralized

location or repository for samples. The gallery is accessible from both the Welcome page and from the

Help menu. The samples in the gallery are split into three categories:

Showcase samples

Demonstrate end-to-end applications that follow best practices for application development.

Application samples

Demonstrate more than one tool or API.

Technology samples

Demonstrate a single tool or API.

When you open a sample, you see a short description of the sample, setup instructions, and a link to

import the sample into your tooling workspace. Samples are located in the Lotus Expeditor section of

each category. Additional samples are also available on the IBM developerWorks® Web site

at:http://www.ibm.com/developerworks

To import one or more samples from the Samples Gallery, follow these steps:

1. Select Help > Samples Gallery.

2. Select a category (Showcase, Application, or Technology samples).

3. Select the [+] next to the Lotus Expeditor samples. This displays a list of the samples, and some

additional categories, that are available.

4. Select one of the samples. The overview page is displayed, providing a short description of the

sample.

5. Do one of the following:

v If you are new to the sample, select the Setup instructions link. This page provides detailed

instructions on prerequisites and information on how to run the sample. You can also import the

sample from the Setup instructions page.

22 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 33: Lotus Expeditor: Developing Applications for Lotus Expeditor

v If you are familiar with the sample and it’s prerequisites, select the Import the sample link. This

displays a dialog to prompt you to install the sample.

Installing samples using Eclipse (without RSDP)

The sample projects are provided by the Lotus Expeditor Toolkit. The samples are provided as archive

files containing pre-built projects. Prior to beginning the steps to import the projects, you must know the

install location of the com.ibm.rcp.tools.samplegallery plug-in provided by the Lotus Expeditor Toolkit.

If you are unsure of the location, go to Help > Software Updates > Manage Configuration. The dialog

shows the Eclipse SDK, followed by a set of directories. Locate the Lotus Expeditor Toolkit, and note the

directory. The com.ibm.rcp.tools.samplegallery plug-in resides in the directory + /plugins.

Important: Samples that contain portlets, or that use the embedded transaction container, require the use

of a Rational Software Development Platform (RSDP) with the Lotus Expeditor Toolkit

installed. These projects might import successfully on an Eclipse with the WTP environment,

but full function, including Run on Server launch capabilities, are not available.

To import one or more samples, follow these steps:

1. Select File > Import ...

2. On the Import Wizard, select General, then Existing Projects into Workspace, then Next.

3. Select the radio button for Archive file.

4. Enter the name of a specific jar, or browse to the com.ibm.rcp.tools.samplegallery plug-in directory,

then the archive directory, and select one of the archive files.

Table 1. Sample file names

File name Sample

cloudscape.jar “Cloudscape sample” on page 24

db2e.jar “DB2 Everyplace sample” on page 25

echo.jar “Echo sample” on page 27

echosecure.jar “Echo Secure sample” on page 30

eclipseprefs.jar “Eclipse Preferences sample” on page 31

ejbtestdriver.jar “Embedded Transaction Container sample” on page 32

isync.jar “ISync sample” on page 34

jmsmb.jar “JMS with Lotus Expeditor micro broker provider

sample” on page 39

jms.jar “JMS with MQe provider sample” on page 42

jndi.jar “JNDI sample” on page 44

log.jar “Log and Log Reader sample” on page 46

mqe.jar “MQ Everyplace sample” on page 48

orderentry.jar “Order Entry sample” on page 50

osgiprefs.jar “OSGi Preferences Service sample” on page 53

pizzajsp.jar “Pizza JSP sample” on page 54

portletcomm.jar “Portlet Communication sample” on page 55

richapp.jar “Rich Application sample” on page 57

rte.jar “Rich Text Editor sample” on page 58

secwebapp.jar “Secured Web application sample” on page 59

servicetracker.jar “Service Tracker sample” on page 60

calcportlet.jar “Simple Portlet sample” on page 63

Product overview 23

Page 34: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 1. Sample file names (continued)

File name Sample

portletviewer.jar “Simple Portlet Viewer sample” on page 64

simpleaggr.jar “Web Page Aggregation of Portlets sample” on page 65

webapplication.jar “Web Application sample” on page 66

weblog.jar “Web Application Log sample” on page 67

xmlparser.jar “XML Parser sample” on page 68

5. The dialog shows the projects present in the archive jar. Select Finish to install the projects into your

workspace.

Specific instructions for each of the samples is provided in the following sections.

Cloudscape sample

This sample illustrates the use of the local Cloudscape database.

You can use this sample only on the desktop runtime.

Time requested: 2 minutes

This sample consists of a single Client Services project, com.ibm.rcp.samples.cloudscape. Key concepts

demonstrated in this sample are as follows:

v Creation of a Cloudscape DataSource object

v Creation of a database within the current workspace

v Creation of a database using SQL specified in the Java code

v Use of PreparedStatement objects to execute SQL statements

For additional information about this sample, refer to the Cloudscape.java class in the

com.ibm.rcp.samples.cloudscape package.

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, cloudscape.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Cloudscape.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.cloudscape plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.

24 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 35: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. To start the sample, enter start com.ibm.rcp.samples.cloudscape in the Console view.

osgi> start com.ibm.rcp.samples.cloudscape

osgi> ***Created table: dish

***Inserted three records into table: dish

***Selected records from table: dish

Dish NO.=1111, Dish Name=Noodle, Dish Price=12.25

Dish NO.=2222, Dish Name=Fish, Dish Price=32.24

Dish NO.=3333, Dish Name=Pizza, Dish Price=25.32

***Deleted table: dish

Troubleshooting:

Problem:

When attempting to run the start com.ibm.rcp.samples.cloudscape command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.cloudscape

Cause:

The com.ibm.rcp.samples.cloudscape bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that the com.ibm.rcp.tools.samples.cloudscape bundle is

selected.

Problem:

When attempting to run the start com.ibm.rcp.samples.cloudscape command in the console, the

following message is displayed:

org.osgi.framework.BundleException: The bundle could not be resolved.

Reason: Missing Constraint: Require-Bundle: org.apache.derby.core; bundle-version="0.0.0"

Cause:

The org.apache.derby.core bundle is not available in the runtime.

Action:

Edit your launch configuration and verify that the org.apache.derby.core bundle is selected. Related samples:

See DB2e sample on using an alternative databaseThis sample illustrates a use of the local DB2 Everyplace database.

See ISync sample to synchronize content from a relational database on the server to a local

Cloudscape or DB2e databaseThis sample demonstrates how to use the ISync APIs to synchronize relational data from a DB2

Everyplace Sync Server to a local DB2 Everyplace or Cloudscape database.

See JNDI sample to declaratively define (bind) a DataSource objectThis sample demonstrates the use of JNDI APIs and declarative JNDI.

DB2 Everyplace sample

This sample illustrates a use of the local DB2 Everyplace database.

Time required: 2 minutes

This sample consists of a single Client Service project, com.ibm.rcp.samples.db2e. Key concepts

demonstrated in this sample are as follows:

v Creation of a DB2 Everyplace DataSource object

v Creation of a database within the current workspace

v Creation of a database using SQL specified in the Java code

Product overview 25

Page 36: Lotus Expeditor: Developing Applications for Lotus Expeditor

For additional information about this sample, refer to the DB2e.java class in the

com.ibm.rcp.samples.db2e package.

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, db2e.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as DB2e.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.db2e plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.db2e in the Console view.

Note: To stop the sample, use the stop com.ibm.rcp.samples.db2e command.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.db2e

osgi> ***Created table: employee

***Inserted three records into table: employee

***Selected all records from table: employee

Employee NO.=112233, FirstName=John, AGE=22

Employee NO.=445566, FirstName=Mary, AGE=33

Employee NO.=778899, FirstName=Lily, AGE=44

***Deleted table: employee

Troubleshooting:

Problem:

When attempting to perform the start com.ibm.rcp.samples.db2e command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.db2e

Cause:

The com.ibm.rcp.samples.db2e bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that the com.ibm.rcp.tools.samples.db2e bundle is

selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.db2e command in the console, the

following message is displayed:

26 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 37: Lotus Expeditor: Developing Applications for Lotus Expeditor

org.osgi.framework.BundleException: The bundle could not be resolved.

Reason: Missing Constraint: Require-Bundle: com.ibm.db2e;

bundle-version="0.0.0"

Cause:

The com.ibm.db2e bundle is not available in the runtime.

Action:

Edit your launch configuration and verify that the com.ibm.db2e bundle is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.db2e command in the console, the

following message is displayed:

java.lang.UnsatisfiedLinkError: Can’t find library db2ejdbc (db2ejdbc.dll) in

sun.boot.library.path or java.library.path

Cause:

The operating system specific fragment for com.ibm.db2e bundle is not available in the runtime.

Action:

Edit your launch configuration and verify that the com.ibm.db2e.win32.x86 or com.ibm.db2e.linux.x86

fragment is selected. Related samples:

See the Cloudscape sample for an alternative database included with the platformThis sample illustrates the use of the local Cloudscape database.

See ISync sample to synchronize content from a relational database on the server to a local

Cloudscape or DB2e databaseThis sample demonstrates how to use the ISync APIs to synchronize relational data from a DB2

Everyplace Sync Server to a local DB2 Everyplace or Cloudscape database.

See the JNDI sample to declaratively define (bind) a DataSource objectThis sample demonstrates the use of JNDI APIs and declarative JNDI.

Echo sample

This sample demonstrates the Mobile Web Services capabilities.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

This sample contains three projects: com.ibm.rcp.samples.ws.echo.client,

com.ibm.rcp.samples.ws.echo.marshal, and com.ibm.rcp.samples.ws.echo.server.

Key concepts demonstrated in this sample are as follows:

v Expose an OSGi service as a Web Service

v Use custom serialization and deserialization (also referred to as custom marshalling)

v Access a Web Service using a dynamic client

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

Product overview 27

Page 38: Lotus Expeditor: Developing Applications for Lotus Expeditor

d. Enter the name of the sample jar file, echo.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Echo.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.ws.echo.server,

com.ibm.rcp.samples.ws.echo.marshal, and com.ibm.rcp.samples.ws.echo.client plug-ins are

selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter a start bundle_name command for each plug-in in the Console view. Bundle

names are as follows:

v com.ibm.rcp.samples.ws.echo.marshal – Starts the marshal plug-in to register the custom serializer

implementations.

v com.ibm.rcp.samples.ws.echo.server – Starts the Web service provider bundle.

v com.ibm.rcp.samples.ws.echo.client – Starts the Web service client bundle.

Attention: You must start these bundles in the order shown and stop bundles in the reverse order.

To stop a bundle, use the stop bundle_name command.

Output is similar to the following:

28 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 39: Lotus Expeditor: Developing Applications for Lotus Expeditor

osgi> start com.ibm.rcp.samples.ws.echo.marshal

osgi> start com.ibm.rcp.samples.ws.echo.server

osgi> start com.ibm.rcp.samples.ws.echo.client

osgi> refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={ws.location=http://localhost:3760/ws/pid/echoSvc, serv

ice.id=107}

SERVER_SIDE=null

Bundle ws:http://localhost:3760/ws/pid/echoSvc?wsdl says:

{req1=Counter = 1}

{req1=Counter = 1}@java.util.GregorianCalendar[time=1150078860000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zo

ne=sun.util.calendar.ZoneInfo[id="America/Chicago",offset=-21600000,dstSavings=3600000,useDaylight=true,transitions=235,

lastRule=java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,st

artMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endD

ayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2006,MONTH=5,WEEK_OF_YEA

R=24,WEEK_OF_MONTH=3,DAY_OF_MONTH=11,DAY_OF_YEAR=162,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,

MINUTE=21,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-21600000,DST_OFFSET=3600000]

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={service.pid=echoSvc, SERVER_SIDE=true, service.id=106}

SERVER_SIDE=true

This is the server side bundle, skipping...

------------

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={ws.location=http://localhost:3760/ws/pid/echoSvc, service.id

=107}

SERVER_SIDE=null

Bundle ws:http://localhost:3760/ws/pid/echoSvc?wsdl says:

{req2=Counter = 2, req1=Counter = 1}

{req2=Counter = 2, req1=Counter = 1}@java.util.GregorianCalendar[time=1150078860000,areFieldsSet=true,areAllFieldsSet=tr

ue,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Chicago",offset=-21600000,dstSavings=3600000,useDaylight=tru

e,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=t

rue,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMont

h=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2006,M

ONTH=5,WEEK_OF_YEAR=24,WEEK_OF_MONTH=3,DAY_OF_MONTH=11,DAY_OF_YEAR=162,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR

=9,HOUR_OF_DAY=21,MINUTE=21,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-21600000,DST_OFFSET=3600000]

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={service.pid=echoSvc, SERVER_SIDE=true, service.id=106}

SERVER_SIDE=true

This is the server side bundle, skipping...

------------

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={ws.location=http://localhost:3760/ws/pid/echoSvc, service.id

=107}

SERVER_SIDE=null

Bundle ws:http://localhost:3760/ws/pid/echoSvc?wsdl says:

{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1}

{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1}@java.util.GregorianCalendar[time=1150078860000,areFieldsSet=true,

areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Chicago",offset=-21600000,dstSavings=36000

00,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=360

0000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0

,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1

,ERA=1,YEAR=2006,MONTH=5,WEEK_OF_YEAR=24,WEEK_OF_MONTH=3,DAY_OF_MONTH=11,DAY_OF_YEAR=162,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MO

NTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=21,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-21600000,DST_OFFSET=3600000]

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={service.pid=echoSvc, SERVER_SIDE=true, service.id=106}

SERVER_SIDE=true

This is the server side bundle, skipping...

------------

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={ws.location=http://localhost:3760/ws/pid/echoSvc, service.id

=107}

SERVER_SIDE=null

Bundle ws:http://localhost:3760/ws/pid/echoSvc?wsdl says:

{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1, req4=Counter = 4}

{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1, req4=Counter = 4}@java.util.GregorianCalendar[time=1150078860000,

areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Chicago",offset=-2160000

0,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/Chicago,offset=-21600

000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=72000

00,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minima

lDaysInFirstWeek=1,ERA=1,YEAR=2006,MONTH=5,WEEK_OF_YEAR=24,WEEK_OF_MONTH=3,DAY_OF_MONTH=11,DAY_OF_YEAR=162,DAY_OF_WEEK=1

,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=21,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-21600000,DST_OFFSET=

3600000]

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={service.pid=echoSvc, SERVER_SIDE=true, service.id=106}

SERVER_SIDE=true

This is the server side bundle, skipping...

------------

refs[i]: {com.ibm.rcp.samples.ws.echo.service.EchoService}={ws.location=http://localhost:3760/ws/pid/echoSvc, service.id

=107}

SERVER_SIDE=null

Bundle ws:http://localhost:3760/ws/pid/echoSvc?wsdl says:

{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1, req5=Counter = 5, req4=Counter = 4}

{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1, req5=Counter = 5, req4=Counter = 4}@java.util.GregorianCalendar[t

ime=1150078860000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Chicag

o",offset=-21600000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/Chi

ff 21600000 d S i 3600000 D li h Y 0 M d 3 M h 2 D 8 D OfW k

Product overview 29

Page 40: Lotus Expeditor: Developing Applications for Lotus Expeditor

Related sample:

See the Echo Secure sample for Mobile Web Services security enablementThis sample demonstrates Mobile Web Services Security.

Echo Secure sample

This sample demonstrates Mobile Web Services Security.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

This sample contains three projects: com.ibm.rcp.samples.wssecurity.echo.client,

com.ibm.rcp.samples.wssecurity.server, and com.ibm.rcp.samples.wssecurity.registration.

Key concepts demonstrated in this sample are as follows:

v Expose an OSGi service as a Web Service

v Access a Web Service using a dynamic client

v Use of the OSGi UserAdmin service to define users that can access the service

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, echosecure.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Echo Secure.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.wssecurity.registration, ,

com.ibm.rcp.samples.wssecurity.echo.client, and com.ibm.rcp.samples.wssecurity.echo.server

plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter a start bundle_name command for each plug-in in the Console view. Bundle

names are as follows:

v com.ibm.rcp.samples.wssecurity.registration – Starts the registration plug-in to create user

definitions.

v com.ibm.rcp.samples.wssecurity.echo.client – Starts the Web service client bundle.

v com.ibm.rcp.samples.wssecurity.echo.server – Starts the Web service provider bundle.

Note: To stop a bundle, use the stop bundle_name command.

Output is similar to the following:

30 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 41: Lotus Expeditor: Developing Applications for Lotus Expeditor

osgi> start com.ibm.rcp.samples.wssecurity.registration

osgi> start com.ibm.rcp.samples.wssecurity.echo.server

osgi> start com.ibm.rcp.samples.wssecurity.echo.client

start SecureEchoClient bundle...

return = HelloWorld!

osgi> stop com.ibm.rcp.samples.wssecurity.echo.client

osgi> stop com.ibm.rcp.samples.wssecurity.echo.server

osgi> stop com.ibm.rcp.samples.wssecurity.registration

Related samples:

See the Echo sample for use of the Mobile Web Services custom marshallingThis sample demonstrates the Mobile Web Services capabilities.

Eclipse Preferences sample

This technology sample demonstrates usage of the Eclipse Preferences capabilities.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

Two projects are included in this sample: com.ibm.rcp.samples.preferences.eclipse and

com.ibm.rcp.samples.preferences.eclipse.ui.

Key concepts demonstrated in this sample:

v Use of the org.eclipse.core.runtime.Plugin.getPluginPreferences API

v Use of the org.eclipse.core.runtime.preferences extension point to initialize default preference values

v Use of the org.eclipse.ui.preferencePages extension point to define a preference page

v Use of the org.eclipse.ui.preferences.ScopedPreferenceStore class

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, eclipseprefs.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Eclipse Preferences.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.preferences.eclipse and

com.ibm.rcp.samples.preferences.eclipse.ui plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

Product overview 31

Page 42: Lotus Expeditor: Developing Applications for Lotus Expeditor

f. Click Apply and then Run.

Running the sample:

You will use both the console and the workbench to use this sample. First, a preferences page has been

contributed to the workbench. Select File > Preferences, then Sample Preference Page to view the

preference page. The location field shows the current default value. Change the value of the location field

to xxxxx. Select OK to save the updated preference value. (The Restore Defaults button causes the

default value to be redisplayed.) Now switch to the console window. Output similar to the following is

displayed:

osgi> Current storage location : file:/C:/Documents and Settings/fred/runtime-test/

Default storage location : file:/C:/Documents and Settings/fred/runtime-test/

This information show the current value of the preference and the default value. Since these statements

were output prior to changing the preference, they show the same value. Because you changed the

current value of the preference, you can display the updated values by first stopping and then restarting

the com.ibm.rcp.samples.preferences.eclipse plug-in. Perform the following steps using the console:

1. Enter stop com.ibm.rcp.samples.preferences.eclipse to stop the sample plug-in.

2. Enter start com.ibm.rcp.samples.preferences.eclipse to start the sample plug-in.

Note: There is a slight delay between the time that you enter the start command and the messages

appears. This is a condition of the sample code that enables the PreferenceInitializer and the

BundleActivator to run before attempting to display the information.

Output similar to the following is displayed:

osgi> Current storage location : file:/C:/Documents and Settings/fred/runtime-test/

Default storage location : file:/C:/Documents and Settings/fred/runtime-test/

osgi> stop com.ibm.rcp.samples.preferences.eclipse

osgi> start com.ibm.rcp.samples.preferences.eclipse

osgi> Current storage location : xxxxx

Default storage location : file:/C:/Documents and Settings/fred/runtime-test/

Related sample:

See the OSGi Preferences Services sample for the use of the OSGi Preferences Service to store

preferencesThis sample demonstrates the use of the OSGi Preferences Service to save and retrieve preference

information.

Embedded Transaction Container sample

This sample demonstrates capabilities of the Embedded Transaction Container.

Time required: 2 minutes

The sample contains three Client Services Embedded Transaction projects and one Client Services project.

com.ibm.rcp.samples.txncontainer.entitybean.cmp11

Sample Embedded Transaction project containing a bean conforming to Container Managed

Persistence (CMP) from the EJB 1.1 specification.

com.ibm.rcp.samples.txncontainer.entitybean.cmp20

Sample Embedded Transaction project containing a bean conforming to Container Managed

Persistence (CMP) from the EJB 2.0 specification.

com.ibm.rcp.samples.txncontainer.sessionbean

Sample Embedded Transaction project containing a Stateless Session Bean.

32 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 43: Lotus Expeditor: Developing Applications for Lotus Expeditor

com.ibm.rcp.samples.txncontainer.testdriver

Test bundle that calls each of the other beans.

Key concepts demonstrated in this sample are as follows:

v Implementation of Embedded Transaction Container Entity Beans

v Implementation of Embedded Transaction Container Session Beans

v Use of JNDI to locate beans

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, ejbtestdriver.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as TxnContainer.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.txncontainer.entitybean.cmp11,

com.ibm.rcp.samples.txncontainer.entitybean.cmp20,

com.ibm.rcp.samples.txncontainer.sessionbean, and com.ibm.rcp.samples.txncontainer.testdriver

plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.txncontainer.testdriver in the Console view.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.txncontainer.testdriver

* ************************************ *

* Testing sample Stateless Session EJB

* ************************************ *

Stateless Session EJB JNDI lookup successful

JNDI lookup returned: com.ibm.rcp.samples.txncontainer.sessionbean.IBMCustomerDatabaseHome

Stateless Session EJB Object created successfully

create() returned: com.ibm.rcp.samples.txncontainer.sessionbean.IBMCustomerDatabase

Executing Stateless Session EJB business methods

Attempting connection to CUSTOMER

Attempting connection to CUSTOMER

list() returned:

0) Smith, Sam

Stateless Session EJB business methods executed successfully

* ********************************* *

* Testing sample CMP 1.1 Entity EJB

* ********************************* *

Product overview 33

Page 44: Lotus Expeditor: Developing Applications for Lotus Expeditor

CMP 1.1 Entity EJB JNDI lookup successful

JNDI lookup returned: com.ibm.rcp.samples.txncontainer.entitybean.cmp11.PVCCustomerJDBCHome

CMP 1.1 Entity EJB Object created successfully

create() returned: com.ibm.rcp.samples.txncontainer.entitybean.cmp11.PVCCustomerJDBC

Executing CMP 1.1 Entity EJB business methods

getId() returned: 1157639752696

getLastName() returned: Holmes

getFirstName() returned: Hank

CMP 1.1 Entity EJB business methods executed successfully

* ********************************* *

* Testing sample CMP 2.0 Entity EJB

* ********************************* *

CMP 2.0 Entity EJB JNDI lookup successful

JNDI lookup returned: com.ibm.rcp.samples.txncontainer.entitybean.cmp20.PVCCustomer20JDBCHome

CMP 2.0 Entity EJB Object created successfully

create() returned: com.ibm.rcp.samples.txncontainer.entitybean.cmp20.PVCCustomer20JDBC

Executing CMP 2.0 Entity EJB business methods

getId() returned: 1157639752865

getLastName() returned: Baxter

getFirstName() returned: Beth

CMP 2.0 Entity EJB business methods executed successfully

Executing CMP 2.0 Entity EJB finder methods

findByFirstName() returned 1 EJB objects

1157639752865) Beth

findByLastName() returned: 1 EJB objects

1157639752865) Baxter

CMP 2.0 Entity EJB finder methods executed successfully

osgi> stop com.ibm.rcp.samples.txncontainer.testdriver

ISync sample

This sample demonstrates how to use the ISync APIs to synchronize relational data from a DB2

Everyplace Sync Server to a local DB2 Everyplace or Cloudscape database.

Time required: 2 minutes

You can use this sample on both desktop and device runtimes. However, only DB2 Everyplace can be

used as a client on the device runtimes. To run this sample, you must have access to an IBM DB2

Everyplace Sync Server installation.

A key concept demonstrated in this sample is the use of the ISync APIs.

Setup instructions:

Before importing and running this sample, you must have DB2 Everyplace Sync Server installed or have

access to one.

The DB2 Everyplace Sync Server can be installed as a standalone product, or as part of the Lotus

Expeditor Server installation. If installed as a standalone product, the demo applications must be installed

to properly configure the user IDs required by this sample.

To verify accessibility to the DB2 Everyplace Sync Server, use a Web browser to connect to the URL

http://server:port/db2e/db2erdb, where server and port are the correct server and port for your

installation. The server responds with the page content:

DB2e SyncServer (Thu Jan 26 18:56:25 CST 2006)

1. To import the sample:

34 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 45: Lotus Expeditor: Developing Applications for Lotus Expeditor

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, isync.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.Notes:

v If the server is not installed on the local machine on port 8080, then you must update the server.url

property value in the db2sync_db2e.properties or db2sync_db2j.properties file contained in the

com.ibm.rcp.samples.isync project. Set the value to http://xxxx:8080, where xxxx is the IP address

of the DB2 Everyplace Sync Server.

v By default the project is set up to use DB2 Everyplace as the local target for the synchronization

operation. If you prefer to use Cloudscape as the local target, edit the ISyncBundle.java file and

change the propertyUrl in the start method from String propertyUrl =

"com.ibm.rcp.samples.isync.db2sync_db2e" to String propertyUrl =

"com.ibm.rcp.samples.isync.db2sync_db2j"

2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as ISync.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.isync plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.isync in the Console view.

Note: To stop a bundle, use the stop com.ibm.rcp.samples.isync command.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.isync

osgi> *********************

SubsSet:

Subs:

SubsType: 0

Event Type: 1

Event Code: 1001

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs:

SubsType: 0

Event Type: 1

Event Code: 1007

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs: Configuration

SubsType: 100

Event Type: 1

Event Code: 1008

Product overview 35

Page 46: Lotus Expeditor: Developing Applications for Lotus Expeditor

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs: Configuration

SubsType: 100

Event Type: 1

Event Code: 1002

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs: Configuration

SubsType: 100

Event Type: 1

Event Code: 1003

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs: Configuration

SubsType: 100

Event Type: 1

Event Code: 1004

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs: Configuration

SubsType: 100

Event Type: 1

Event Code: 1005

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs: Configuration

SubsType: 100

Event Type: 1

Event Code: 1004

Progress: 0

**********************

*********************

SubsSet: Configuration

Subs:

SubsType: 0

Event Type: 1

Event Code: 1011

Progress: 0

**********************

*********************

SubsSet: SUBSCRIPTION_SET1

Subs:

SubsType: 0

Event Type: 1

Event Code: 1007

Progress: 0

**********************

*********************

36 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 47: Lotus Expeditor: Developing Applications for Lotus Expeditor

SubsSet: SUBSCRIPTION_SET1

Subs: JDBCSUB1

SubsType: 102

Event Type: 1

Event Code: 1008

Progress: 0

**********************

Sample set subs .

*********************

SubsSet: SUBSCRIPTION_SET1

Subs: JDBCSUB1

SubsType: 102

Event Type: 1

Event Code: 1002

Progress: 0

**********************

*********************

SubsSet: SUBSCRIPTION_SET1

Subs: JDBCSUB1

SubsType: 102

Event Type: 1

Event Code: 1003

Progress: 0

**********************

*********************

SubsSet: SUBSCRIPTION_SET1

Subs: JDBCSUB1

SubsType: 102

Event Type: 1

Event Code: 1004

Progress: 50

**********************

*********************

SubsSet: SUBSCRIPTION_SET1

Subs: JDBCSUB1

SubsType: 102

Event Type: 1

Event Code: 1005

Progress: 50

**********************

*********************

SubsSet: SUBSCRIPTION_SET1

Subs: JDBCSUB1

SubsType: 102

Event Type: 1

Event Code: 1004

Progress: 100

**********************

*********************

SubsSet: SUBSCRIPTION_SET1

Subs:

SubsType: 0

Event Type: 1

Event Code: 1011

Progress: 100

**********************

*********************

SubsSet:

Subs:

SubsType: 0

Product overview 37

Page 48: Lotus Expeditor: Developing Applications for Lotus Expeditor

Event Type: 1

Event Code: 1012

Progress: 100

**********************

Synchronization succeeded

Subscription Set: SUBSCRIPTION_SET1 Status: COMPLETED

osgi> stop com.ibm.rcp.samples.isync

Troubleshooting:

Problem:

When attempting to perform the start com.ibm.rcp.samples.isync command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.isync

Cause:

The com.ibm.rcp.samples.isync bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that the com.ibm.rcp.samples.isync bundle is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.db2e command in the console, the

following message is displayed:

org.osgi.framework.BundleException: The bundle could not be resolved.

Reason: Missing Constraint: Require-Bundle: com.ibm.db2e; bundle-version="0.0.0"

Cause:

The com.ibm.db2e bundle is not available in the runtime.

Action:

Edit your launch configuration and verify that the com.ibm.db2e bundle is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.db2e command in the console, the

following message is displayed:

java.lang.UnsatisfiedLinkError: Can’t find library db2ejdbc (db2ejdbc.dll)

in sun.boot.library.path or java.library.path

Cause:

The operating system specific fragment for com.ibm.db2e bundle is not available in the runtime.

Action:

Edit your launch configuration and verify that the com.ibm.db2e.win32.x86 or com.ibm.db2e.linux.x86

fragment is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.isync command in the console, the

following message is displayed:

java.lang.UnsatisfiedLinkError: Can’t find library isync4j (isync4j.dll)

in sun.boot.library.path or java.library.path

Cause:

The operating system specific fragment for com.ibm.mobileservices.isync bundle is not available in

the runtime.

Action:

Edit your launch configuration and verify that the com.ibm.mobileservices.isync.win32.x86 or

com.ibm.mobileservices.isync.linux.x86 fragment is selected.

38 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 49: Lotus Expeditor: Developing Applications for Lotus Expeditor

Problem:

The com.ibm.rcp.samples.isync bundle starts and output to the console begins. The last message

output to the console is as follows:

Exception code: 304 304 com.ibm.mobileservices.isync.ISyncException: 304

Cause:

The user ID and password combination used to access the server is not valid.

Action:

The default users, nurse1 and nurse2, are defined as part of the DB2e Everyplace Sync Server sample

installation. If the samples were not installed on the server, either install the samples now, or use

another ID that has been configured at the server. The user ID and password are specified in the

db2sync_db2e.properties or db2sync_db2j.properties files using the isync.user and isync.password

properties.

Problem:

The com.ibm.rcp.samples.isync bundle starts and output to the console begins. The last message reads

as follows:

Exception code: 315 315 com.ibm.mobileservices.isync.ISyncException: 315

Cause:

The user ID has previously synchronized the database to another system or location.

Action:

The user ID is not configured to synchronize to multiple devices. Edit the user ID to delete its current

devices, or modify the DB2 Everyplace Sync Server configuration to allow synchronization to

multiple devices. Related samples:

See the DB2e sample for use of the DB2 Everyplace database without ISync technologyThis sample illustrates a use of the local DB2 Everyplace database.

See the Cloudscape sample for an alternative database included with the platformThis sample illustrates the use of the local Cloudscape database.

JMS with Lotus Expeditor micro broker provider sample

This sample demonstrates the use of the Java Message Service (JMS) publish and subscribe messaging

interfaces with the micro broker JMS provider.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of micro broker APIs to create a micro broker instance

v Use of JMS APIs with micro broker provider

v Use of declarative JNDI to define connection factory and topic objects

Setup instructions:

There are two options for using this sample:

v “Option A: Using the in-memory-based micro broker instance” on page 40

v “Option B: Using the file-persistence-based micro broker instance” on page 41

In both options, the com.ibm.rcp.samples.microbroker.jmspubsub project contains code that publishes

messages to a topic and subscribes to a topic to receive messages.

Option A uses the com.ibm.rcp.samples.microbroker.setup project to create and start a

memory-only-based micro broker instance. When the com.ibm.rcp.samples.microbroker.setup bundle is

stopped, the micro broker instance is stopped and the definition deleted. If the

Product overview 39

Page 50: Lotus Expeditor: Developing Applications for Lotus Expeditor

com.ibm.rcp.samples.microbroker.setup is started and stopped after the com.ibm.micro.gettingstarted

bundle was used, the micro broker instance defined by com.ibm.micro.gettingstarted is stopped and the

definition removed.

Option B uses the evaluation bundle, com.ibm.micro.gettingstarted, to create and start a

file-persistence-based micro broker instance. When the com.ibm.micro.gettingstarted bundle is stopped,

the micro broker instance continues to run and the definition remains.

While many micro broker instances can be created and configured, only a single micro broker instance

can be started within a process. You cannot use this sample if another micro broker instance is in use,

with the exception of the FirstBroker instance defined by and started by the

com.ibm.micro.gettingstarted or the com.ibm.rcp.samples.microbroker.setup bundles.

Option A: Using the in-memory-based micro broker instance:

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, jmsmb.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as JMS Micro broker Memory.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.microbroker.setup and

com.ibm.rcp.samples.microbroker.jmspubsub plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter a start bundle_name command for each plug-in in the Console view. Bundle

names are as follows:

v com.ibm.rcp.samples.microbroker.setup

v com.ibm.rcp.samples.microbroker.jmspubsub

Note: When finished with the sample, enter stop com.ibm.rcp.samples.microbroker.jmspubsub

followed by stop com.ibm.rcp.samples.microbroker.jmspubsub.

This completes the sample and removes the micro broker instance that might conflict with

other samples.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.microbroker.setup

FirstBroker started.

osgi> start com.ibm.rcp.samples.microbroker.jmspubsub

osgi> PublisherThread: Starting

SubscriberThread: Starting

SubscriberThread: Received message This is message 0

SubscriberThread: Received message This is message 1

40 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 51: Lotus Expeditor: Developing Applications for Lotus Expeditor

SubscriberThread: Received message This is message 2

SubscriberThread: Received message This is message 3

SubscriberThread: Received message This is message 4

osgi> stop com.ibm.rcp.samples.microbroker.jmspubsub

osgi> stop com.ibm.rcp.samples.microbroker.setup

Option B: Using the file-persistence-based micro broker instance:

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, jmsmb.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as JMS Micro broker Persistence.

d. Select the Plug-ins tab and verify that the com.ibm.micro.gettingstarted and

com.ibm.rcp.samples.microbroker.jmspubsub plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter a start bundle_name command for each plug-in in the Console view. Bundle

names are as follows:

v com.ibm.micro.gettingstarted

v com.ibm.rcp.samples.microbroker.jmspubsub

Note: When finished with the sample, enter stop com.ibm.rcp.samples.jmspubsub followed by stop

com.ibm.micro.gettingstarted.

This completes the sample.

Output is similar to the following:

osgi> start com.ibm.micro.gettingstarted

osgi> start com.ibm.rcp.samples.microbroker.jmspubsub

PubisherThread: Starting

osgi> SubscriberThread: Starting

SubscriberThread: Received message This is message 0

SubscriberThread: Received message This is message 1

SubscriberThread: Received message This is message 2

SubscriberThread: Received message This is message 3

SubscriberThread: Received message This is message 4

osgi> stop com.ibm.rcp.samples.microbroker.jmspubsub

osgi> stop com.ibm.micro.gettingstarted

Product overview 41

Page 52: Lotus Expeditor: Developing Applications for Lotus Expeditor

Related sample:

See the JMS with MQe provider sample for use of the MQe provider using JMS APIsThis sample demonstrates the use of the Java Message Service (JMS) point-to-point messaging

interfaces with the MQ Everyplace provider.

JMS with MQe provider sample

This sample demonstrates the use of the Java Message Service (JMS) point-to-point messaging interfaces

with the MQ Everyplace provider.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of JMS APIs with MQ Everyplace provider

v Use of declarative JNDI to define MQ Everyplace Queue Manager and Queue factory objects

Setup instructions:

This sample relies on the ability to create its own MQ Everyplace Queue Manager. Only a single MQ

Everyplace Queue Manager is allowed to be active at any one time. You cannot use this sample at the

same time as the MQ Everyplace sample, the Order Entry sample, or any other application that might

have attempted to create a queue manager.

Before running this sample, you must make the following updates:

1. Update the mqe.ini configuration file. To do so, open the mqe.ini file, located in the jmsQM directory.

For the DirName property, replace c:\sample_workspace with the location of the current project

workspace.

2. Update the plugin.xml file. To do so, open the plugin.xml file for the project, and switch to the

Extensions tab in the editor. In the All Extensions list, expand the first

com.ibm.pvc.jndi.provider.java.genericobject extension point and continue expanding until

(method-parameter) is shown. Select (method-parameter) and in the Extension Details panel, update

the Value field, and replace c:\sample_workspace with the location of the current project workspace.

Note: Keep in mind that Linux users must reformat the workspace locations appropriately.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, jms.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as JMS.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.jms plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.jms in the Console view.

42 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 53: Lotus Expeditor: Developing Applications for Lotus Expeditor

4. When the sample has completed, enter stop com.ibm.rcp.samples.jms. This completes the sample and

removes the queue manager definitions that might conflict with other samples.

Output is similar to the following:

osgi> PTPSample - simple example of sending and receiving a message.

osgi> start com.ibm.rcp.samples.jms

Creating a ConnectionFactory

Retrieving a ConnectionFactory from JNDI

Creating a Connection

Starting the Connection

Creating a non-transactional Session

Retrieving a Destination from JNDI

Creating a MessageProducer

Creating a MessageConsumer

Creating a TextMessage

Adding Text

Sending the message to ExampleQM+SYSTEM.DEFAULT.LOCAL.QUEUE

Reading the message back again

Got message:

HEADER FIELDS

------------------------------------------------------------------

JMSType: jms_text

JMSDeliveryMode: 2

JMSExpiration: 0

JMSPriority: 4

JMSMessageID: ID:00007e5db5f52d3cfffffef6ebdd5f44

JMSTimestamp: 1138504147131

JMSCorrelationID: null

JMSDestination: ExampleQM:SYSTEM.DEFAULT.LOCAL.QUEUE

JMSReplyTo: null

JMSRedelivered: false

PROPERTY FIELDS (read only)

------------------------------------------------------------------

JMSXRcvTimestamp : 1138504147301

JMSXDeliveryCount : 1

MESSAGE BODY (read only)

------------------------------------------------------------------

A simple text message from PTPSample

Reply string equals original string

Closing Connection

finished

osgi> stop com.ibm.rcp.samples.jms

Troubleshooting:

Problem:

When attempting to perform the start com.ibm.rcp.samples.jms command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.jms

Cause:

The com.ibm.rcp.samples.jms bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that com.ibm.rcp.samples.jms is selected.

Problem:

When the com.ibm.rcp.samples.jms bundle starts, the following message is displayed:

javax.jms.JMSException: Cannot start a queue manager for JMS: .ini

file c:\workspaces\test\com.ibm.rcp.samples.jms\jmsQM\mqe.ini not found

Product overview 43

Page 54: Lotus Expeditor: Developing Applications for Lotus Expeditor

Cause:

The MQ Everyplace .ini file that contains the queue manager configuration is unable to be opened.

Action:

Edit the plugin.xml file residing in the project directory, and verify that the DirName parameter

correctly references the target workspace.

Problem:

When the com.ibm.rcp.samples.jms bundle starts, the following message is displayed:

javax.jms.JMSException: Cannot start a queue manager for JMS

Cause:

The directory containing the Queue Manager definition is not accessible.

Action:

Edit the mqe.ini file residing in the jmsQm directory, and verify that the DirName parameter correctly

references the target workspace.

Problem:

When the com.ibm.rcp.samples.jms bundle starts, the following message is displayed:

javax.jms.InvalidDestinationException: Cannot resolve ExampleQM/SYSTEM.DEFAULT.LOCAL.QUEUE

Cause:

A Queue Manager already exists in the platform that does not contain the Queue definition

Action:

This sample defines its own queue manager, so if another bundle or application (such as Order Entry

or OFN Teller) has already started, the expected queue manager cannot be defined.

Stop this sample using the stop com.ibm.rcp.samples.jms command. Stop all other samples that you

might have started to remove their queue manager definitions. Restart the sample.

Problem:

When the com.ibm.rcp.samples.jms bundle starts, the following message is displayed:

javax.jms.JMSException: Cannot create JNDI InitialContext!

Cause:

The JNDI Provider has not been started; therefore, JNDI lookups are not available.

Action:

Verify that the com.ibm.pvc.jndi.provider.java bundle is included in your runtime or launch

configuration. Related samples:

See the MQe sample for use of the MQe client using MQe-specific APIsThis technology sample demonstrates the use of IBM WebSphere MQ Everyplace (MQe).

See the JMS with Lotus Expeditor micro broker provider sample for use of the Java Message Service

(JMS) publish and subscribe messaging interfacesThis sample demonstrates the use of the Java Message Service (JMS) publish and subscribe messaging

interfaces with the micro broker JMS provider.

JNDI sample

This sample demonstrates the use of JNDI APIs and declarative JNDI.

Time required: 2 minutes

You can use this sample on both desktop and device runtimes. However, only the DB2 Everyplace

DataSource can be returned on the device runtimes.

Key concepts demonstrated in this sample are as follows:

v Use of the JNDI bind() and lookup() APIs for binding and locating a simple object

44 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 55: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Use of the JNDI extension points to define a data source object

v Use of the lookup() API to locate a resource defined via extension points

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, jndi.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as JNDI.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.jndi plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.jndi in the Console view.

Note: To stop the sample, enter stop com.ibm.rcp.samples.jndi.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.jndi

osgi> Object SampleSimpleObject bound with value: SimpleObject

Object retrieved from lookup: SimpleObject

Object SampleSimpleObject unbound.

The object lookup for SampleDataSourceDB2e returned com.ibm.db2e.jdbc.DB2eDataSource@69326932

The object lookup for SampleDataSourceDerby returned org.apache.derby.jdbc.EmbeddedDataSource@44024402

osgi> stop com.ibm.rcp.samples.jndi

Troubleshooting:

Problem:

When attempting to perform the start com.ibm.rcp.samples.jndi command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.jndi

Cause:

The com.ibm.rcp.samples.jndi bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that com.ibm.rcp.samples.jndi is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.jndi command in the console, the

following message is displayed:

Product overview 45

Page 56: Lotus Expeditor: Developing Applications for Lotus Expeditor

javax.naming.NoInitialContextException: Cannot instantiate

class: com.ibm.pvc.jndi.provider.java.InitialContextFactory. Root exception is

java.lang.ClassNotFoundException: com.ibm.pvc.jndi.provider.java.InitialContextFactory

Cause:

The com.ibm.pvc.jndi.provider.java plug-in is either not available in the runtime or has not been

started.

Action:

Edit your launch configuration and verify that com.ibm.pvc.jndi.provider.java bundle is selected. Related sample:

See the JMS sample for use of the JNDI extensions points for JMS and MQe objectsThis sample demonstrates the use of the Java Message Service (JMS) point-to-point messaging

interfaces with the MQ Everyplace provider.

Log and Log Reader sample

This sample demonstrates the use of the OSGi Log and LogReader services.

Time required: 2 minutes

This sample contains two projects: com.ibm.rcp.samples.log and com.ibm.rcp.samples.logreader.

The logreader project shows how to register a listener with the OSGi LogReader service to receive

notification of LogEvents.

The log project shows how to create OSGi Log messages. The resulting messages will be displayed by the

logreader.

Key concepts demonstrated in this sample are as follows:

v Use of Log Service APIs to log information to a common log service

v Use of the LogReader service APIs to receive notification of new log events

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, log.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Log Reader.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.log and

com.ibm.rcp.samples.logreader plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.

46 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 57: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. To start the sample, enter a start bundle_name command for each plug-in in the Console view. Bundle

names are as follows:

v com.ibm.rcp.samples.logreader – Starts the Log Reader sample plug-in.

v com.ibm.rcp.samples.log – Starts the Log sample plug-in.

Note: When finished with the sample, enter stop com.ibm.rcp.samples.logreader or all log messages

are repeated on the console.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.logreader

LogReader received LogEntry: BundleEvent STARTED

Time: 1138593859708

Source Bundle: com.ibm.rcp.samples.logreader

Level: INFO

osgi> start com.ibm.rcp.samples.log

LogReader received LogEntry: BundleEvent STARTED

Time: 1138593867550

Source Bundle: com.ibm.rcp.samples.log

Level: INFO

LogReader received LogEntry: This is a log message!

Time: 1138593867551

Source Bundle: com.ibm.rcp.samples.log

Level: WARNING

osgi> LogReader received LogEntry: This is a log message with exception

Time: 1138593867552

Source Bundle: com.ibm.rcp.samples.log

Level: ERROR

Exception:

java.lang.Exception: An Exception

at com.ibm.rcp.samples.log.Log.doLogMessage(Log.java:63)

at com.ibm.rcp.samples.log.Log.run(Log.java:35)

at java.lang.Thread.run(Thread.java:567)

LogReader received LogEntry: This is another log message!

Time: 1138593867553

Source Bundle: com.ibm.rcp.samples.log

Level: INFO

osgi> stop com.ibm.rcp.samples.logreader

Troubleshooting:

Problem:

When attempting to perform the start com.ibm.rcp.samples.logreader command in the console, the

following message is displayed: Cannot find bundle com.ibm.rcp.samples.logreader

Cause:

The com.ibm.rcp.samples.logreader bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that the com.ibm.rcp.samples.logreader is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.log command in the console, the

following message is displayed: Cannot find bundle com.ibm.rcp.samples.log

Cause:

The com.ibm.rcp.samples.log bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that the com.ibm.rcp.samples.log is selected.

Product overview 47

Page 58: Lotus Expeditor: Developing Applications for Lotus Expeditor

Related sample:

See the Echo Secure sample for Mobile Web Services security enablementThis sample demonstrates Mobile Web Services Security.

MQ Everyplace sample

This technology sample demonstrates the use of IBM WebSphere MQ Everyplace (MQe).

Time required: 2 minutes

This sample contains two Client Services projects: com.ibm.rcp.samples.mqeclient and

com.ibm.rcp.samples.mqeserver.

The mqeclient project sends MQ Everyplace messages to a queue.

The mqeserver project starts a Queue Manager and listens for messages sent by the mqeclient.

Key concepts demonstrated in this sample are as follows:

v Creation of a local MQe Queue Manager

v Creation of listeners to enable a local MQe Server

v Accessing an existing Queue Manager

v Sending messages

v Receiving messages

Setup instructions:

This sample relies on the ability to create its own MQ Everyplace Queue Manager. Only a single MQ

Everyplace Queue Manager is allowed to be active at any one time. You cannot use this sample at the

same time as the JMS with MQe Provider sample, the Order Entry sample, or any other application that

might have attempted to create a queue manager.

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, mqe.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as MQe.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.mqeserver and

com.ibm.rcp.samples.mqeclient plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter a start bundle_name command for each plug-in in the Console view. Bundle

names are as follows:

v start com.ibm.rcp.samples.mqeserver – Starts the MQe server plug-in.

48 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 59: Lotus Expeditor: Developing Applications for Lotus Expeditor

v start com.ibm.rcp.samples.mqeclient – Starts the MQe client plug-in.4. When the sample has completed, enter stop com.ibm.rcp.samples.mqeclient. Next, enter stop

com.ibm.rcp.samples.mqeserver. This completes the sample and removes the queue manager

definitions that might conflict with other samples.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.mqeserver

com.ibm.rcp.samples.mqeserver: MqeServer starting in 2 seconds...

osgi> com.ibm.rcp.samples.mqeserver: connection administration message created

com.ibm.rcp.samples.mqeserver: create administration message put to AdminQ

com.ibm.rcp.samples.mqeserver: listener created

com.ibm.rcp.samples.mqeserver: connection administration message created

com.ibm.rcp.samples.mqeserver: create administration message put to AdminQ

com.ibm.rcp.samples.mqeserver: listener started

com.ibm.rcp.samples.mqeserver: ..MQeServerBundle - registering message listener

com.ibm.rcp.samples.mqeserver: MqeServer has been started OK

osgi> start com.ibm.rcp.samples.mqeclient

com.ibm.rcp.samples.mqeclient: MqeClient - starting in 2 seconds...

com.ibm.rcp.samples.mqeclient: ..Create a message with id: 1 and data:This is a test message

com.ibm.rcp.samples.mqeclient: ..Put the message to QM/queue: MQeServer/SYSTEM.DEFAULT.LOCAL.QUEUE

osgi> com.ibm.rcp.samples.mqeserver: *****************************************************************

com.ibm.rcp.samples.mqeserver: A new message arrived on Queue SYSTEM.DEFAULT.LOCAL.QUEUE with ID = 1

com.ibm.rcp.samples.mqeserver: Message = This is a test message

com.ibm.rcp.samples.mqeserver: *****************************************************************

osgi> stop com.ibm.rcp.samples.mqeclient

com.ibm.rcp.samples.mqeclient: MqeClient has been stopped

osgi> stop com.ibm.rcp.samples.mqeserver

com.ibm.rcp.samples.mqeserver: stop listener administration message created

com.ibm.rcp.samples.mqeserver: stop listener administration message put to AdminQ

com.ibm.rcp.samples.mqeserver: listener stopped

com.ibm.rcp.samples.mqeserver: delete listener administration message created

com.ibm.rcp.samples.mqeserver: delete listener administration message put to AdminQ

com.ibm.rcp.samples.mqeserver: listener deleted

com.ibm.rcp.samples.mqeserver: Stopping QM

com.ibm.rcp.samples.mqeserver: Deleting QM

com.ibm.rcp.samples.mqeserver: MqeServer has been stopped.

Troubleshooting:

Problem:

When attempting to perform the start com.ibm.rcp.samples.mqeserver command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.mqeserver

Cause:

The com.ibm.rcp.samples.mqeserver bundle is not available in your runtime

Action:

Edit your launch configuration and verify that com.ibm.rcp.samples.mqeserver is selected.

Problem:

When attempting to perform the start com.ibm.rcp.samples.mqeclient command in the console, the

following message is displayed:

Cannot find bundle com.ibm.rcp.samples.mqeclient

Cause:

The com.ibm.rcp.samples.mqeclient bundle is not available in your runtime.

Product overview 49

Page 60: Lotus Expeditor: Developing Applications for Lotus Expeditor

Action:

Edit your launch configuration and verify that com.ibm.rcp.samples.mqeclient is selected.

Problem:

When the com.ibm.rcp.samples.mqeserver bundle starts, the following message is displayed:

com.ibm.rcp.samples.mqeserver: ERROR - java.lang.Exception: ERROR - QM Already Running

Cause:

A Queue Manager already exists in the platform that does not contain the Queue definition.

Action:

This sample defines its own queue manager, so if another bundle or application (such as Order Entry

or OFN Teller) has already started, the expected queue manager cannot be defined. Stop this sample

using the stop com.ibm.rcp.samples.mqeclient and stop com.ibm.rcp.samples.mqeserver commands.

Stop all other samples that you might have started to remove their queue manager definitions.

Restart the sample. Related sample:

See the JMS sample for use of the JMS APIs with MQeThis sample demonstrates the use of the Java Message Service (JMS) point-to-point messaging

interfaces with the MQ Everyplace provider.

Order Entry sample

Order Entry is a three-tier, sample application that demonstrates the following components and

capabilities: Web container, Java Servlet 2.3, OSGi Preferences, MQe, JDBC, DB2e, RCP views, and

preference pages.

Time required: 10 minutes

You can use both the Rich and Web Application views on the desktop runtime, but you can only use the

Web Application on the device runtime.

Order Entry illustrates the following scenario:

A delivery employee drives a soda truck to three different customers: SpeedyMarket, Marine Mart, and

Quick Stop. As he travels to each of these locations to offload his stock, he determines how many bottles

and cans of soda to order for the next week and enters that information into his device. The order is

stored in the local DB2 Everyplace database and queued for transmission to the server using MQ

Everyplace. The order is transmitted to the server only when a network connection exists and the server

is ready to receive; otherwise, it is held on the device. After the order is sent from the device to the

backend server, a confirmation message is displayed on the device.

In this scenario, the Order Entry client processes input from the user and generates requests to the Order

Entry server, which represents an inventory management system. A DB2 Everyplace database stores the

requests and sends the requests through MQ Everyplace to the Order Entry server. When the Order Entry

server receives a message, it confirms the order and sends a response to the client. When the response

message is received, Order Entry updates the status of the order in the client database.

Note: This sample provides both a rich client and a Web application, but uses a common service project

for accessing the server.

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and configure it.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

50 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 61: Lotus Expeditor: Developing Applications for Lotus Expeditor

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, orderentry.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. Follow steps for one of the following sample applications:

v “Order Entry Rich Client sample”

v “Order Entry Web Application sample” on page 52

Order Entry Rich Client sample:

The Order Entry Rich Client application consists of the following bundles:

v Client side bundle providing shared packages:

com.ibm.rcp.samples.orderentry.common

v Client side service implementation:

com.ibm.rcp.samples.orderentry.service

v Client side desktop application:

com.ibm.rcp.samples.orderentry.richapp

v Server side demo application:

com.ibm.rcp.samples.orderentry.server

To configure and run the Order Entry Rich Client application, follow these steps:

1. Select Run > Run from the main menu.

2. Select Client Services and click New.

3. Type a unique name for your configuration, such as Order Entry.

4. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.orderentry.common,

com.ibm.rcp.samples.orderentry.service, and com.ibm.rcp.samples.orderentry.richapp plug-ins are

selected.

5. Click Run. After the runtime starts, click Open > Order Entry Rich Client Sample to open the

application perspective. This new perspective contains two views: Submit Order, and Order Status.

a. In the Submit Order view, select a customer from the list.

b. Select a quantity for cans and bottles and click Submit.

Note: The Order Status view displays any existing orders for this customer. If orders are

displayed, the order status for those orders is also displayed.

In addition, if this application is connected to a server-side application, the order’s status

changes from Queued to Confirmed. Click Refresh to synchronize orders and update status.

6. Repeat this procedure to submit orders for any additional customers.

7. To close the application, right-click the Perspective tab and select Close.

To configure and run the server, follow these steps while the client runtime is running. The server

application causes the order status to be changed from Queued to Confirmed in the Order Status view.

1. Select Run > Run from the main menu.

2. Select Java Application and click New.

3. Type a name for your configuration, such as Order Entry Server.

Product overview 51

Page 62: Lotus Expeditor: Developing Applications for Lotus Expeditor

4. Click Browse to identify the project and then select com.ibm.rcp.samples.orderentry.server from the

list.

5. Click Search to identify the main class.

6. Select Server from the displayed list to select com.ibm.rcp.samples.orderentry.server.Server as the

class containing the main method.

7. Click Run to start the application. The Order Entry Server application takes a few seconds to start.

The server application is ready to begin handling messages when the following message is displayed:

DEBUG -- BaseMQeTransport: Transport thread started

If you have already created orders, the following message is displayed in the Server application

console:

DEBUG -- PROCESS ORDER

8. In the Order Status view, click Refresh to update the order status. As response messages are received

from the server application, the following message is displayed in the console:

DEBUG -- RESPONSE RECEIVED

Order Entry Web Application sample:

The Order Entry Web Application consists of the following bundles:

v Client side bundle providing shared packages:

com.ibm.rcp.samples.orderentry.common

v Client side service implementation:

com.ibm.rcp.samples.orderentry.service

v Client side Web application:

com.ibm.rcp.samples.orderentry.webapp

v Server side demo application:

com.ibm.rcp.samples.orderentry.server

To configure and run the Order Entry Web application, follow these steps:

1. Select Run > Run from the main menu.

2. Select Client Services and click New.

3. Type a unique name for your configuration, such as Order Entry.

4. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.orderentry.common,

com.ibm.rcp.samples.orderentry.service, and com.ibm.rcp.samples.orderentry.webapp plug-ins are

selected.

5. Click Run. After the runtime starts, click Open > Order Entry Web Sample to open the application. A

browser perspective opens and displays the first page of the application.

6. To use the application, follow these steps:

a. Click Start.

b. Select a customer from the list.

c. Select New Order.

d. Select a quantity for cans and bottles and click Submit.

Note: If this application is connected to a server-side application, the order’s status changes from

Queued to Confirmed. Click Refresh to synchronize orders and update status.

7. Repeat this procedure to submit orders for any additional customers.

8. To close the application, right-click the Perspective tab and select Close.

52 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 63: Lotus Expeditor: Developing Applications for Lotus Expeditor

To configure and run the server, follow these steps while the client platform is running. The server

application causes the order status to be changed from Queued to Confirmed in the Order Status view.

1. Select Run > Run from the main menu.

2. Select Java Application and click New.

3. Type a name for your configuration, such as Order Entry Server.

4. Click Browse to identify the project and then select com.ibm.rcp.samples.orderentry.server from the

list.

5. Click Search to identify the main class.

6. Select Server from the displayed list to select com.ibm.rcp.samples.orderentry.server.Server as the

class containing the main method.

7. Click Run to start the application. The Order Entry Server application takes a few seconds to start.

The server application is ready to begin handling messages when the following message is displayed:

DEBUG -- BaseMQeTransport: Transport thread started

If you have already created an order, the following message is displayed in the Server application

console:

DEBUG -- PROCESS ORDER

8. In the Order Status view, click Refresh to update the order status. As response messages are received

from the server application, the following message is displayed in the console:

DEBUG -- RESPONSE RECEIVED

Related sample:

See the Echo Secure sample for Mobile Web Services security enablementThis sample demonstrates Mobile Web Services Security.

OSGi Preferences Service sample

This sample demonstrates the use of the OSGi Preferences Service to save and retrieve preference

information.

Time required: 2 minutes

Three Client Services projects are included in this sample: com.ibm.rcp.samples.preferences.osgi.service,

com.ibm.rcp.samples.preferences.osgi.serviceimpl, and

com.ibm.rcp.samples.preferences.osgi.serviceconsumer.

The service project defines an interface for a service.

The serviceimpl project provides an implementation of the service, and the serviceconsumer project

requests and uses the service. The serviceimpl project contains a service that stores some preference or

configuration information using the OSGi Preferences service.

The serviceconsumer project calls the service, causing preference information to be retrieved and stored.

Key concepts demonstrated in this sample are as follows:

v Use of the OSGi Preferences Service

v Bundle componentization into service consumer, service implementer, and service interfaces,

decoupling consumer from implementer

v Registration of OSGi Services

v Use of the OSGi Service Tracker

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

Product overview 53

Page 64: Lotus Expeditor: Developing Applications for Lotus Expeditor

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, osgiprefs.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as OSGi Preferences.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.preferences.osgi.service, ,

com.ibm.rcp.samples.preferences.osgi.serviceimpl, and

com.ibm.rcp.samples.preferences.osgi.serviceconsumer plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To run the sample:

a. Enter start com.ibm.rcp.samples.preferences.osgi.serviceimpl to start the sample service

implementation.

b. Enter start com.ibm.rcp.samples.preferences.osgi.serviceconsumer to start the sample service

consumer. The service consumer calls the service implementation’s run() method, causing

messages to be printed to the console, and preference information to be updated.

c. Enter stop com.ibm.rcp.samples.preferences.osgi.serviceconsumer to stop the sample service

consumer.

d. Enter start com.ibm.rcp.samples.preferences.osgi.serviceconsumer to start the sample service

consumer again. Note the change to the value of the last execution time from the previous time

that you entered the start command.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.preferences.osgi.serviceimpl

osgi> start com.ibm.rcp.samples.preferences.osgi.serviceconsumer

SampleService data location: file:/C:/Documents and Settings/james/workspace/

This service has not been previously executed by james

osgi> stop com.ibm.rcp.samples.preferences.osgi.serviceconsumer

osgi> start com.ibm.rcp.samples.preferences.osgi.serviceconsumer

SampleService data location: file:/C:/Documents and Settings/james/workspace/

This service was last executed by james on 1138074724210

Related sample:

See the Eclipse Preferences sample for use of the Eclipse preferences API and extension pointsThis technology sample demonstrates usage of the Eclipse Preferences capabilities.

Pizza JSP sample

This sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the Web Container. The sample application is a pizza-ordering Web application.

Time required: 5 minutes

54 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 65: Lotus Expeditor: Developing Applications for Lotus Expeditor

Key concepts demonstrated in this sample are as follows:

v Use of the WctWebApplication extension point

v Use of JSP

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, pizzajsp.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Switch to the J2EE perspective.

b. Right-click com.ibm.rcp.samples.webapp.pizzajsp.

c. Select Run > Run on Server from the main menu.

d. Select a Client Services server from the list. If a Client Services server is not on the list, select

Manually define a server and choose it from the list of server types.

e. Click Finish.3. To run the sample, use the Web browser opened by the tools. The Web application URL is displayed.

You can also view the Web application in the client runtime. To do so, select Open > Sample Pizza

JSP Web Application. To end the runtime, select File > Exit from the menu.

Note that this sample does not require use of the console to run the sample.

Related samples:

See the Web Application sample for a simple non-secured Web applicationThis sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the local Web Container. The sample application is a Hello World application.

See the Web Application Log sample for a Web application that provides a user interface to log entriesThis sample demonstrates the usage of Java Server Pages (JSPs) within a web application intended for

deployment on the local Web Container. The sample application displays log contents obtained from

the OSGi LogReader service.

See the Secure Web Application sample for a Web application secured using form-based

authenticationThis sample demonstrates a local, secured Web application intended for deployment on the local Web

container.

Portlet Communication sample

This sample demonstrates two Java Specification Request (JSR) 168 portlets exchanging data.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

This sample contains two Client Services projects: com.ibm.rcp.samples.portletcommunication.portlets and

com.ibm.rcp.portletcommunications.views.

Product overview 55

Page 66: Lotus Expeditor: Developing Applications for Lotus Expeditor

The portlets project contains the two portlets that are used in this sample. The views project contains the

user interface objects required to display the two portlets using the portlet viewer capabilities.

Key concepts demonstrated in this sample are as follows:

v Use of the PortletViewer view

v Wiring of two portlets for data exchange

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, portletcomm.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.

Note: The WSDL files necessary to define the property broker bindings for the portlets use extensions

to the WS-I standard for WSDL. As a result, WSDL validation warnings are listed in the

Problems view on resources P2PSearchResult.wsdl and P2PQuickSearch.wsdl in the

com.ibm.rcp.samples.portletcommunication.portlets project. These warnings do not affect the

ability to run the sample successfully.

2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Portlet Communication.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.portletcommunication.portlets

and com.ibm.rcp.samples.portletcommunication.views plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample:

a. When the workbench displays, select Open > Portlet Communication Sample to open its

perspective.

b. Enter search text in the Search Portlet View, and select Search. The result is displayed in the Result

Portlet View.

c. To end the runtime, select File > Exit from the menu.

This sample does not require use of the console to run.

Related samples:

See the Simple Portlet sample to create a simple portletThis sample demonstrates a local JSR 168 portlet enabled for local portlet container.

See the Portlet Aggregation sample to lay out multiple portlets on a single Web pageThis sample demonstrates the use of a Web page aggregation of portlets.

56 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 67: Lotus Expeditor: Developing Applications for Lotus Expeditor

See the Portlet Viewer sample as an alternative mechanism for viewing local portletsThis sample demonstrates the use of the Portlet Viewer, a predefined view enabling display of Java

Specification Request (JSR) 168 and WSRP-compliant portlets. This sample demonstrates the viewing

of JSR 168 portlets only.

Rich Application sample

This sample creates a Client Services project to illustrate the basic elements of a rich application.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

Key concepts demonstrated in this sample are as follows:

v Use of the WctApplication extension point

v Assembly of an application with one perspective, two views, and three actions

v Use of view options to prevent closing or moving

v Use of global menu actions

v Use of application-specific (perspective) actions

v Use of view-specific actions

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, richapp.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Rich Application.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.richapp plug-ins is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. This sample makes several contributions to the client user interface and menu system. To view these

capabilities:

v After the workbench starts, select Sample Menu > Run Global Action to perform this action. The

action results in a dialog box containing the message Global Action. Global actions are available

even when no perspectives are open.

v Select Open > Sample Rich Application to open the application. The application demonstrates a

perspective containing two views. Primary View is a non-closable, non-movable view. Secondary

View can be closed or moved within the perspective. The sample application was contributed to the

launcher list by implementing the WctApplication extension point.

Product overview 57

Page 68: Lotus Expeditor: Developing Applications for Lotus Expeditor

v With the sample application opened, close the Secondary View. Then select Sample Menu > Open

Secondary View to reopen the view. This demonstrates actions (Open Secondary View) that are

specific to an application (perspective).

v Click Secondary View to highlight this view. Select Sample Menu > Run View Action to run a

view specific action. This results in a dialog box containing the message View Action. This

demonstrates an action that is specific to a view.

Troubleshooting:

Problem:

The sample application is not available in the Open menu.

Cause:

The com.ibm.rcp.samples.richapp plug-in is not present or does not resolve in the client platform.

Action:

Verify that the com.ibm.rcp.samples.richapp plug-in is contained in the runtime. If the plug-in is

present, check the status of the plug-in. Go to the console view, and enter the b

com.ibm.rcp.samples.richapp command. The second line of output indicates the plug-in status. If the

status is not RESOLVED or ACTIVE, then there is a problem with the plug-in and its dependencies.

Use the diag com.ibm.rcp.samples.richapp command to identify any unsatisfied dependencies.

Resolve any missing dependencies and restart the platform.

Rich Text Editor sample

This sample demonstrates how to include the Rich Text Editor within an Eclipse view.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

The key concept demonstrated in this sample is the use of Rich Text Editor APIs to create toolbar and

editor widgets.

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, rte.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory, then the archive directory, and select the archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To configure and run the sample:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Rich Text Editor.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.richtexteditor plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.

58 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 69: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. To start the sample, when the workbench displays, select Open > Rich Text Editor Sample to open its

perspective. Enter text within the editor view. You may use the coolbar icons within the Rich Text

Editor View to format the text.

This sample does not require use of the console to run.

Related sample:

See the Echo Secure sample for Mobile Web Services security enablementThis sample demonstrates Mobile Web Services Security.

Secured Web application sample

This sample demonstrates a local, secured Web application intended for deployment on the local Web

container.

Time required: 5 minutes

You can use this sample only on the desktop runtime.

This sample contains three projects: com.ibm.rcp.samples.ws.echo.client,

com.ibm.rcp.samples.ws.echo.marshal, and com.ibm.rcp.samples.ws.echo.server.

Key concepts demonstrated in this sample are as follows:

v Expose an OSGi service as a Web Service

v Use custom serialization and deserialization (also referred to as custom marshalling)

v Access a Web Service using a dynamic client

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, secwebapp.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Locate the project com.ibm.rcp.samples.webapp.secured.form in the Project Explorer under the

Dynamic Web Projects folder.

b. Right-click the project and select Run > Run on Server. The Server Selection dialog is displayed.

c. Select a Client Services server from the list. If a Client Services server is not on the list, select

Manually define a server and choose it from the list of server types.

d. Click Finish to launch the runtime.

Running the sample:

To run the sample, follow these steps:

1. View the Web browser opened by the tools. Select Create Users to create the necessary users for this

sample.

2. Select one of the available pages (admin.jsp, user.jsp, or guest.jsp). The login page is displayed.

Product overview 59

Page 70: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. Enter the Userid and Password for one of the users listed on the page. If the Userid is not enabled to

access a particular page, an error page is displayed.

4. Use the browser’s Back button to return to the Web application main page (/secured_form/index.jsp).

5. Click Logout to log out of the application, allowing another user to be selected.

The following table shows the accessibility of the pages within the application:

User index.jsp admin.jsp user.jsp guest.jsp

not logged in U

nancy (admin) U U U U

bob (user) U U U

fred (guest) U U

Before exiting the runtime, select Delete Users from /secured_form/index.jsp to clean up the users

added for this sample.

To end the runtime, select File > Exit from the menu.

Note: This sample does not require use of the console to run.

Related samples:

See the Web Application sample for a simple, non-secured Web applicationThis sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the local Web Container. The sample application is a Hello World application.

See the Web Application Log sample for another Web application that provides a user interface to log

entriesThis sample demonstrates the usage of Java Server Pages (JSPs) within a web application intended for

deployment on the local Web Container. The sample application displays log contents obtained from

the OSGi LogReader service.

See the Pizza JSP sample for a JSP-based Web applicationThis sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the Web Container. The sample application is a pizza-ordering Web application.

Service Tracker sample

This sample creates two Client Services project to demonstrate how to use OSGi service trackers.

Time required: 2 minutes

This sample creates the following projects: com.ibm.rcp.samples.servicetracker, and

com.ibm.rcp.samples.servicetracker.service.

The servicetracker project creates and starts two service trackers for the

com.ibm.pvc.webcontainer.listeners.HttpSettingListener service. One tracker is a simple implementation

that returns an instance of the service, if one is available. The second tracker is a more sophisticated

implementation that receives notifications of changes in service life cycle.

The service bundle registers an instance of the com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service. By starting and stopping this bundle during run time, you can view output to see how the events

are processed.

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

60 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 71: Lotus Expeditor: Developing Applications for Lotus Expeditor

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, servicetracker.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Service Tracker.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.servicetracker and

com.ibm.rcp.samples.servicetracker.service plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample:

a. In the Console view, enter ss to list the bundle IDs and locate the servicetracker ID.

b. Enter a start bundle_name command for each plug-in in the Console view. Bundle names are as

follows:

v com.ibm.rcp.samples.servicetracker – Starts the sample bundle. This causes the

CustomServiceTracker to identify all of the HttpSettingListener service implementations that are

registered. In addition, a message is displayed every 10 seconds showing the current set of

HttpSettingListener services that are currently registered.

v com.ibm.rcp.samples.servicetracker.service – Starts the sample service bundle. This registers

an additional instance of the HttpSettingListener service, causing output from the

CustomServiceTracker. After two seconds, the service will modify itself causing additional

output from the CustomServiceTracker.

Note: To stop a bundle, use the stop bundle_name command.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.servicetracker

CustomServiceTracker: Service added:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:39

CustomServiceTracker: Service added:

service.vendor:IBM

service.description:HttpSettingListener for the Web Http Service 1.0 IBM Implementation

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:46

CustomServiceTracker: Service added:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:65

CustomServiceTracker: Service added:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

Product overview 61

Page 72: Lotus Expeditor: Developing Applications for Lotus Expeditor

service.id:66

osgi> SimpleServiceTracker: Tracking service at 0 seconds.

ServiceTracker monitoring 4 service instances

Service instance returned if getService() called:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:39

SimpleServiceTracker: Tracking service at 10 seconds.

ServiceTracker monitoring 4 service instances

Service instance returned if getService() called:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:39

osgi> start com.ibm.rcp.samples.servicetracker.service

CustomServiceTracker: Service added:

service.vendor:IBM

service.ranking:-2147483648

service.description:Service part of com.ibm.rcp.samples.servicetracker

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:94

osgi> CustomServiceTracker: Service modified: service.update:1149994259253

service.vendor:IBM

service.ranking:-2147483648

service.description:Service part of com.ibm.rcp.samples.servicetracker

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:94

SimpleServiceTracker: Tracking service at 20 seconds.

ServiceTracker monitoring 5 service instances

Service instance returned if getService() called:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:39

osgi> stop com.ibm.rcp.samples.servicetracker.service

CustomServiceTracker: Service removed: service.update:1149994259253

service.vendor:IBM

service.ranking:-2147483648

service.description:Service part of com.ibm.rcp.samples.servicetracker

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:94

osgi> SimpleServiceTracker: Tracking service at 30 seconds.

ServiceTracker monitoring 4 service instances

Service instance returned if getService() called:

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:39

osgi> stop com.ibm.rcp.samples.servicetracker

CustomServiceTracker: Service removed: service.vendor:IBM

62 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 73: Lotus Expeditor: Developing Applications for Lotus Expeditor

service.description:HttpSettingListener for the Web Http Service 1.0 IBM Implementation

objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:46

CustomServiceTracker: Service removed: objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:65

CustomServiceTracker: Service removed: objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:39

CustomServiceTracker: Service removed: objectClass:

com.ibm.pvc.webcontainer.listeners.HttpSettingListener

service.id:66

Simple Portlet sample

This sample demonstrates a local JSR 168 portlet enabled for local portlet container.

Time required: 2 minutes

You can use this sample only on the desktop runtime.

Key concepts demonstrated in this sample are as follows:

v Definition of a JSR 168 portlet for use on the local portlet container

v Use of the WctWebApplication extension point to enable access to a single portlet

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, calcportlet.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Locate the project com.ibm.rcp.samples.portlets.calculatorportlet in the Project Explorer under the

Dynamic Web Projects folder.

b. Right-click the project and select Run > Run on Server. The Server Selection dialog is displayed.

c. Select a Client Services server from the list. If a Client Services server is not on the list, select

Manually define a server and choose it from the list of server types.

d. Click Finish to launch the runtime.

3. To run the sample, use the Web browser opened by the tools. The portlet URL is displayed. You can

also view this portlet in the client runtime. To do so, select Open > Sample Calculator Portlet. To end

the runtime, select File > Exit from the menu.

This sample does not require use of the console to run.

Related samples:

Product overview 63

Page 74: Lotus Expeditor: Developing Applications for Lotus Expeditor

See the Portlet Aggregation sample to lay out multiple portlets on a single Web pageThis sample demonstrates the use of a Web page aggregation of portlets.

See the Portlet Viewer sample as an alternative mechanism for viewing local portletsThis sample demonstrates the use of the Portlet Viewer, a predefined view enabling display of Java

Specification Request (JSR) 168 and WSRP-compliant portlets. This sample demonstrates the viewing

of JSR 168 portlets only.

See the Portlet Communication sample to wire two portlets together for action processingThis sample demonstrates two Java Specification Request (JSR) 168 portlets exchanging data.

Simple Portlet Viewer sample

This sample demonstrates the use of the Portlet Viewer, a predefined view enabling display of Java

Specification Request (JSR) 168 and WSRP-compliant portlets. This sample demonstrates the viewing of

JSR 168 portlets only.

Time required: 2 minutes

You can use this sample only on the desktop runtime. This sample requires the use of the “Simple Portlet

sample” on page 63.

Key concepts demonstrated in this sample are as follows:

v Use of the com.ibm.rcp.portletviewer.portlets extension point to define the portlet for viewing by the

viewer

v Use of compound view IDs for defining the layout of a simple perspective

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, portletviewer.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as Portlet Viewer.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.portletviewer and

com.ibm.rcp.samples.portlets.calculatorportlet plug-ins are selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample when the workbench displays, select Open > Sample PortletViewer to open its

perspective.

This sample does not require use of the console to run.

Related samples:

64 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 75: Lotus Expeditor: Developing Applications for Lotus Expeditor

See the Simple Portlet sample to create a simple portletThis sample demonstrates a local JSR 168 portlet enabled for local portlet container.

See the Portlet Aggregation sample to lay out multiple portlets on a single Web pageThis sample demonstrates the use of a Web page aggregation of portlets.

See the Portlet Communication sample to wire two portlets together for action processingThis sample demonstrates two Java Specification Request (JSR) 168 portlets exchanging data.

Web Page Aggregation of Portlets sample

This sample demonstrates the use of a Web page aggregation of portlets.

Time required: 2 minutes

You can use this sample only on the desktop runtime. This sample requires the use of the “Simple Portlet

sample” on page 63.

This sample contains two Client Services projects: com.ibm.rcp.samples.portlets.portletaggregator and

com.ibm.rcp.portlets.dateportlet.

The portletaggregator project is a Client Services Web project that contains a JavaServer Page that

aggregates the content of two portlets onto a single Web page.

Key concepts demonstrated within this sample are as follows:

v Definition of a JSR 168 portlet for use on the local portlet container

v Use of the WctWebApplication extension point to enable access to a single portlet

Setup instructions:

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, simpleaggr.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Locate the project com.ibm.rcp.samples.portlets.portletaggregator in the Project Explorer under

the Dynamic Web Projects folder.

b. Right-click the project and select Run > Run on Server. The Server Selection dialog is displayed.

c. Select a Client Services server from the list. If a Client Services server is not on the list, select

Manually define a server and choose it from the list of server types.

d. Use the Default Target to launch the sample and click Next.

e. On the Add and Remove Projects page, the Configured projects list must contain the

com.ibm.rcp.samples.portlets.portletaggregator, com.ibm.rcp.samples.portlets.calculatorportlet and

com.ibm.rcp.samples.portlets.dateportlet projects. If these projects are not listed, select each of

these projects in the Available projects list and then click Add.

f. Click Finish to launch the server.

Product overview 65

Page 76: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. To run the sample, use the Web browser opened by the tools. The Web application URL is displayed.

You can also view the Web application in the client runtime. To do so, select Open > Sample Portlet

Web Page Aggregation. To end the runtime, select File > Exit from the menu.

This sample does not require use of the console to run.

Troubleshooting:

Problem:

The Web page displays an error that the page cannot be displayed due to an HTTP 500 - Internal

Server error or the following message:

Error 500: Unable to get RequestDispatcher for Context:

[/.com.ibm.rcp.samples.portlets.dateportlet] and URL:

[/DatePortlet/default/ver=1.0]. Verify values and/or enable cross context access.

An error is also logged in the runtime and can be viewed in the console.

Cause:

The com.ibm.rcp.samples.portlets.dateportlet sample has been not added to the launch.

Action:

From the Servers view, right-click the Client Services server and then select Open. From the Server

Overview page, select Advanced to open the launch configuration. Select the Plug-ins tab and ensure

that the com.ibm.rcp.samples.portlets.dateportlet plug-in is selected.

Problem:

The Web page displays an error that the page cannot be displayed due to an HTTP 500 - Internal

Server error or the following message:

Error 500: Unable to get RequestDispatcher for Context: [/CalculatorPortlet]

and URL: [/CalculatorPortlet/default/ver=1.0]. Verify values and/or

enable cross context access.

An error is also logged in the runtime and can be viewed in the console.

Cause:

The com.ibm.rcp.samples.portlets.calculatorportlet sample has been not added to the launch.

Action:

From the Servers view, right-click the Client Services server and then select Open. From the Server

Overview page, select Advanced to open the launch configuration. Select the Plug-ins tab and ensure

that the com.ibm.rcp.samples.portlets.calculatorportlet plug-in is selected. Related samples:

See the Simple Portlet sample to create a simple portletThis sample demonstrates a local JSR 168 portlet enabled for local portlet container.

See the Portlet Communication sample to wire two portlets together for action processingThis sample demonstrates two Java Specification Request (JSR) 168 portlets exchanging data.

See the Simple Portlet Viewer sample for an alternative mechanism for viewing local portletsThis sample demonstrates the use of the Portlet Viewer, a predefined view enabling display of Java

Specification Request (JSR) 168 and WSRP-compliant portlets. This sample demonstrates the viewing

of JSR 168 portlets only.

Web Application sample

This sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the local Web Container. The sample application is a Hello World application.

Time required: 2 minutes

Setup instructions:

66 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 77: Lotus Expeditor: Developing Applications for Lotus Expeditor

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, webapplication.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Locate the project com.ibm.rcp.samples.webapp.hello in the Project Explorer under the Dynamic

Web Projects folder.

b. Right-click the project and select Run > Run on Server. The Server Selection dialog is displayed.

c. Select a Client Services server from the list. If a Client Services server is not on the list, select

Manually define a server and choose it from the list of server types.

d. Click Finish to launch the runtime.3. To run the sample, use the Web browser opened by the tools. The message Hello World is displayed

in the browser. You can also view this portlet in the client runtime. To do so, select Open > Sample

Hello JSP Web Application. To end the runtime, select File > Exit from the menu.

This sample does not require use of the console to run.

Related samples:

See the Secured Web Application sample for a Web application secured using form-based

authenticationThis sample demonstrates a local, secured Web application intended for deployment on the local Web

container.

See the Web Application Log sample for a Web application that provides a user interface to log entriesThis sample demonstrates the usage of Java Server Pages (JSPs) within a web application intended for

deployment on the local Web Container. The sample application displays log contents obtained from

the OSGi LogReader service.

See the Pizza JSP sample for a JSP-based Web applicationThis sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the Web Container. The sample application is a pizza-ordering Web application.

Web Application Log sample

This sample demonstrates the usage of Java Server Pages (JSPs) within a web application intended for

deployment on the local Web Container. The sample application displays log contents obtained from the

OSGi LogReader service.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of the WctWebApplication extension point

v Use of JSP

v Use of the OSGi LogReader service

Setup instructions:

Product overview 67

Page 78: Lotus Expeditor: Developing Applications for Lotus Expeditor

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, weblog.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Switch to the J2EE perspective.

b. Right-click com.ibm.rcp.samples.webapp.weblog.

c. Select Run > Run on Server from the main menu.

d. Select a Client Services server from the list. If a Client Services server is not on the list, select

Manually define a server and choose it from the list of server types.

e. Click Finish.3. To run the sample, use the Web browser opened by the tools. The Web application URL is displayed.

You can also view the Web application in the client runtime. To do so, select Open > Sample Web

Log Web Application. To end the runtime, select File > Exit from the menu.

This sample does not require use of the console to run the sample.

Related samples:

See the Web Application sample for a simple, non-secured Web applicationThis sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the local Web Container. The sample application is a Hello World application.

See the Secure Web Application sample for a Web application secured using form-based authenticationThis sample demonstrates a local, secured Web application intended for deployment on the local Web

container.

See the Pizza JSP sample for a JSP-based Web applicationThis sample demonstrates the usage of Java Server Pages (JSPs) within a Web application intended for

deployment on the Web Container. The sample application is a pizza-ordering Web application.

See the Log and Log Reader sample for use of the OSGi Log Service and LogReader ServiceThis sample demonstrates the use of the OSGi Log and LogReader services.

XML Parser sample

This sample creates a Client Services project to demonstrate how to use a Simple API for XML (SAX)

parser to get information stored in XML files.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Accessing a SAX Parser using the OSGi XML Parsing Service

v Loading resources from Bundle objects

v Preparing InputSource objects to enable DTD or Schema verification for resources contained in the

bundle

Setup instructions:

68 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 79: Lotus Expeditor: Developing Applications for Lotus Expeditor

Before you can run the sample, you must first import the sample into your workspace and launch the

test runtime.

1. To import the sample:

a. Select File > Import.

b. From the Import Wizard, select General and then select Existing Projects into Workspace. Click

Next.

c. Select the Archive file radio button.

d. Enter the name of the sample jar file, xmlparser.jar, or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory, then the archive directory, and select the

archive file.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.2. To launch the test runtime:

a. Select Run > Run from the main menu.

b. Select Client Services and click New.

c. Type a unique name for your configuration, such as XML Parser.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.xmlparser plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.xmlparser in the Console view.

Note: To stop the sample, enter stop com.ibm.rcp.samples.xmlparser.

Output is similar to the following:

osgi> start com.ibm.rcp.samples.xmlparser

osgi> ***Begin Document***

[bookshelf]

[TechnologyBooks]

[Book]

[Name]

JAVA 2 Programming

[/Name]

[Price]

$30.99

[/Price]

[TotalPages]

325

[/TotalPages]

[/Book]

[Book]

[Name]

J2EE Design and Development

[/Name]

[Price]

$52.49

[/Price]

[TotalPages]

583

[/TotalPages]

[/Book]

[/TechnologyBooks]

[/bookshelf]

***End Document***

Product overview 69

Page 80: Lotus Expeditor: Developing Applications for Lotus Expeditor

70 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 81: Lotus Expeditor: Developing Applications for Lotus Expeditor

Developing applications

This section provides comprehensive and detailed information on developing applications for Lotus

Expeditor.

Application models

There are several application patterns that are recommended for use in the managed client platform. One

pattern is the browser user interface pattern, which is supported by the Web Application Model. Web

applications present their user interface through the use of generated scripting language such as HTML,

which is rendered for display by a browser.

Another pattern is to build a graphical user interface using Eclipse, to aggregate display components into

views, and views into perspectives. Applications will be defined using extension points to define the

actions, views, and perspective that provide the user interface. This pattern is the rich client user interface

pattern, which is supported by the Rich Client Application Model.

For Lotus Expeditor Client for Desktop, there are additional application patterns. The portlet pattern is

supported by the Portlet Application Model. This pattern is based on JSR 168.

Another pattern is the Composite Application pattern, which is supported by the Composite Application

Model. In this model, multiple applications cooperate by using inter-component communications. For

example, you can use the Property Broker to communicate among portlets and/or Eclipse applications

running in the same client process. Or, you can use the micro broker to communicate among applications

running in the same or different processes.

Application design considerations

You can design client applications in much the same way that you design standard Enterprise

applications. However, there are unique considerations for designing client applications. The list of

considerations in this section is not necessarily comprehensive for all possible decision points; however,

this list provides key considerations for developing client applications.

End-to-End applications

The client and server platforms enable the development of end-to-end applications through an end-to-end

programming model (see figure below) that connects managed client applications to Enterprise

applications, services and data. An end-to-end application can be distributed between a client device and

a server in which case there are two nodes in the application. However, an end-to-end application might

be distributed across more nodes. The exact design of an end-to-end application depends on your specific

requirements; however, this section discusses considerations on how you might construct these

applications.

© Copyright IBM Corp. 2004, 2006 71

Page 82: Lotus Expeditor: Developing Applications for Lotus Expeditor

WebUI

RichUI

Local BusinessLogic Services

Web Services

SyncMLLibraries

MQe

DB2e orCloudscape

EnterpriseManagement

Agent

Update Manager

Portal Services(Desktop only)

WebServices

[SyncMLLibraries]

MQGateway

DB2eSync Server

DeviceManagement

Server

Update sites

Portal Server

Consume and publishWeb Services

Synchronize objects

Send and receivesecure transactions

Synchronizerelational data

Server-managed SWinstall & maintenance

User-initiated SWinstall & Maintenance

Aggregation, role-basedaccess control

Sync

ESB

Replicate

Data

MessagingApplications

RDB's

Lotus Expeditor "Connectors"

Lotus Expeditor - Client

Lotus Expeditor - Server

Managed client applications can use WebSphere MQ Everyplace (MQe) to exchange secure transactional

messages with Enterprise applications that support MQ messaging. MQ Everyplace operates in many

topologies, from peer-to-peer, to client, to server using the MQ Everyplace gateway technology. For

example, a JEE application can implement Message Driven Beans (MDB) to exchange messages with a

managed client application. This exchange can occur through an MQ Everyplace Gateway-MQ Server

configuration. However, managed client applications can also use MQe to exchange messages directly

with other MQe applications in the network.

DB2 Everyplace and Cloudscape are both capable of synchronizing with the DB2 Everyplace (DB2e) Sync

Server, using the IBM ISync technology provided by the client platform. A System Administrator

configures the DB2e Sync Server to synchronize data with Enterprise databases. The initial

synchronization activity creates the local database schema, and also populates the initial set of data in the

local database on a device. When a client application updates the local database, synchronization can

transfer that data to Enterprise databases that are configured to receive it. When Enterprise applications

update data in an Enterprise database, synchronization can transfer that data to local device databases

that are configured to receive it. Database administrators set up the DB2e Sync Server with the necessary

subscriptions for synchronization, and can set up filtering of data to limit the amount of data distributed

between nodes. The DB2e Sync Server supports synchronizing relational data on the client with relational

data on the following Enterprise databases: DB2 Universal Database™ Informix® Dynamic Server, IBM

Cloudscape, Lotus Domino® Server, Oracle, Microsoft SQL Server, and Sybase Adaptive Server Enterprise.

72 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 83: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: Administrators can use the Lotus Expeditor server to install and configure the DB2 Everyplace

Synchronization Server, WebSphere MQ Everyplace, including the function necessary for

WebSphere MQ Everyplace to act as a gateway server to the WebSphere MQ products, and the

Device Management Server.

Managed client applications can also consume and provide Web Services. This requires an active

connection between the Web services consumer and provider.

An optional capability, which some customers have chosen to implement, is another IBM product called

Lotus Mobile Connect. Lotus Mobile Connect enables client applications to operate over secure,

optimized, roaming network connections on wireless and wire-line networks. Lotus Mobile Connect

installs below TCP/IP APIs so TCP/IP applications can continue to run without change and benefit from

these capabilities.

Topology

When you build a client application, you should determine which types of clients your application will

support. For example, will your application run on high-powered clients, such as desktops and laptops,

or handheld devices, such as PDA’s, or all of the above?

After you select the client(s), you should consider the capabilities of these client(s). For example,

handheld devices typically have slower processors and less memory than desktop or laptop clients, so

applications that require intensive floating point calculations or substantial memory are not appropriate

for handheld devices, but are perfectly fine for desktops and laptops. DB2e and Cloudscape are both

embedded databases. However, DB2e is much smaller than Cloudscape, so you might choose DB2e for

handheld devices such as PDAs and choose Cloudscape, which has greater database capabilities, for more

powerful clients, such as desktops and laptops.

Device form factors - such as screen size, color, user input types - also present challenges. For example,

complex forms requiring a lot of specific data entry might not be appropriate for a device that doesn’t

have a keyboard and uses a stylus to point at a keyboard.

You should also consider the network connectivity of your clients. Is the client always connected to the

network, intermittently connected to the network, or never connected to the network? You should also

consider speed, reliability, and cost of the network connection. For example, client applications requiring

large data transfers might not be suitable for a cell phone connection that charges by the byte, so a good

design point might be to handle large transfers of data when the user is present in an office environment

with a high-speed, no-cost network connection.

Business logic

When you build an end-to-end application, you must decide how to distribute the business logic across

the nodes that comprise the application so your mobile users are productive when they are offline. The

amount of business logic in the client application must be sufficient to perform all necessary work.

However, you might consider moving business logic components that require frequent updating to a

server node to avoid network traffic and administration costs associated with managing these same

components on clients.

In addition, client applications can provide multiple levels of capability, reserving some capability for

when a reliable connection exists to an Enterprise server, and disabling that capability if the server is

unavailable.

Business logic can be packaged within a client application or made available as a separate component,

such as a plug-in, an Embedded Transaction, or local Web Service.

Developing applications 73

Page 84: Lotus Expeditor: Developing Applications for Lotus Expeditor

Persistence

Most applications manipulate data. This can take the form of read-only access of databases to retrieve

catalog items, or of database update for creation of orders that need to be processed. Data can take the

form of files distributed on disk, or relational database capability. When dealing with databases, you can

choose to use databases only as a local data repository, or as a repository that actively synchronizes with

an Enterprise database.

Consider the following design possibilities:

v Use a database as a local repository when your application requires more advanced data organization

and access capabilities than can be supported by a local file store – especially if a relatively large

amount of data is stored on the device.

v Use a local database to protect, or encrypt, data in case a device is lost or stolen .

v Use database synchronization to exchange the current state of data between local databases and an

Enterprise database, when transaction boundaries or the order of state changes is not important.

v Consider how much data needs to be distributed and when (once only at initialization, one-way from

one node to another only on an infrequent basis, frequent exchange between nodes). Balance these

considerations with the storage capabilities at each node, and the networking requirements that would

permit the exchange to take place.

v Consider database organization, filtering, and conflict resolution policies if you choose to use database

synchronization.

Messaging

Messaging links client applications to Enterprise applications, services, and data. Messaging can take

various forms, whether a plain socket-based application, Web Services, or a more sophisticated store and

forward transaction messaging capability that supports connected as well as disconnected usage. When

choosing a form of messaging, you should consider the following requirements in the design of your

end-to-end applications:

v Online vs. offline operation

v Security, including message confidentiality, non-repudiation, and authentication

v Synchronous vs. asynchronous messaging

v Once-only assured transactions

v Configuration of the messaging solution

Web Services support secure, online, synchronous access to information; however, an online connection

must be active between the Web Services consumer and provider to access information across the

network. Security features include message confidentiality, integrity, and authentication.

MQe provides transaction messaging that supports online and offline operation, security features

(message confidentiality, non-repudiation, authentication), synchronous and asynchronous messaging, and

once-only assured transactions. Transaction messaging provides a convenient mechanism for defining or

identifying transaction boundaries when performing such actions as creating or updating orders,

particularly if the transaction requires updates across multiple resources in the Enterprise such as

inventory management, shipping and billing systems.

Note: Certain nodes in the end-to-end system might not be able to manage or commit transactions

because these nodes might not have transaction coordination and, therefore, do not have the

master copy of all of the data.

The micro broker implements publish and subscribe messaging, which supports online and offline

operations, and synchronous and asynchronous messaging.

74 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 85: Lotus Expeditor: Developing Applications for Lotus Expeditor

Management

Management covers a wide range of activities, from initial device provisioning to application

management. When you design your application, you should consider the implications of your design in

regards to application management, specifically in two key areas: componentization and data formats.

First, if you design a monolithic application, then the management system must distribute and install a

complete new copy of the application to update nodes with the latest version of the application.

Depending on the size of the application and the frequency of updates, this design might adversely affect

network capacity and disrupt users. If you design and package the application as multiple installable

components, then the management system distributes and installs only those components that require an

update. You might also be able to reuse components in different applications that run on the same or

different nodes. There is a trade-off between the granularity of the components and the complexity of

administering the set of components that comprise an application.

Second, you must consider the effect on data when updating applications or components. If you design

your components and data format so that local data is upwardly compatible, then users can continue to

access their data after application and component updates. Otherwise, you must provide a mechanism to

update the existing data to match a new or revised format and ensure that all installed components that

consume this data can process this format.

Serviceability

Distributed applications pose additional issues of serviceability as compared to applications running on a

single node. Logging and problem resolution might be difficult if the application is running on one node,

and the node only occasionally connects to a central logging repository. In these situations, you must

consider how to transfer logging information from a node to the central logging repository, how to track

user usage, and help in problem resolution.

Interaction

You must first decide if your application will support user interactions and, if so, which interaction

model to use. You might choose the Web Application or Portlet Application model when moving a Web

application or portlet from the server to the client to reduce development and training costs. You might

choose the Rich Client Application model when you require more control over the user experience.

If your application requires a user interface, then you must consider the device characteristics in the

design of the user interface. For example, if you are developing a Web application for PDA’s and laptops,

then you can design the layout of the Web pages to fit within the constraints of the PDA screen size.

When you run the application on the PDA, the Web browser will render the markup for the PDA screen

size. When you run the same Web application on a laptop, the Web browser will render the same

markup, which should fit within the larger screen size. Of course, there might be cost vs. usability

tradeoffs in supporting a common user interface across multiple device types instead of tailoring the user

interface for each device type. For example, multiple Web pages might be required to perform a set of

related business operations on the smaller screen size of a PDA while a single Web page might suffice for

the larger screen of a laptop.

Cross platform APIs

This section shows you the common API functionality that is supported across the Lotus Expeditor Client

for Desktop and Lotus Expeditor Client for Devices, to assist you in the development of your managed

client applications. For common API functionality, Lotus Expeditor Client for Devices either supports the

same APIs or a proper subset of APIs available on Lotus Expeditor Client for Desktop. As a result, Lotus

Expeditor provides a programming model that scales across desktops, laptops, tablets, and handheld

devices.

Developing applications 75

Page 86: Lotus Expeditor: Developing Applications for Lotus Expeditor

API Lotus Expeditor Client for Desktop Lotus Expeditor Client for Devices

Java jclDesktop (default) jclDevice (supports JME Foundation

1.1)

OSGi OSGi R4 core plus optional services:

v User Admin Service

v Log Service

v Configuration Admin Service

v Metatype Service

v Preferences Service

v Event Admin Service

OSGi R4 core plus optional services:

v User Admin Service

v Log Service

v Configuration Admin Service

v Metatype Service

v Preferences Service

v Event Admin Service

Eclipse RCP 3.2.1 eRCP 1.0

Data Sync SyncML4J 2.6 SyncML4J 2.6

Database Access JDBC 3.0 with DB2e or Cloudscape JDBC JSR 169 with DB2e

Database Sync ISync with DB2e or Cloudscape ISync with DB2e or * Cloudscape

Messaging – Point-to-Point JMS 1.1 with MQe JMS 1.1 with MQe

Messaging – Pub-Sub JMS 1.1 with micro broker JMS 1.1 with micro broker

Web Services Client JSR 172, JSR 101 JSR 172

Web Applications Servlet 2.3/2.4

JSP 1.2/2.0

Servlet 2.3

JSP 1.2

Embedded Transaction Applications EJB 2.0 subset EJB 2.0 subset

Name Lookup JNDI JNDI

* Available via OEM licensing

Packaging

Client applications and Target Features are packaged as features, each of which consists of one or more

components. The client platform cannot directly run J2EE packaging artifacts such as EAR and WAR files.

Components

The Eclipse framework, and therefore the client platform, is organized around a plug-in and extension

point model. The framework provides a core set of components. Additional components are provided in

a directory or JAR file organized in a specific structure, and implement instantiations of the various

extension points. The framework reads the component declarative information, and incorporates the

components into the correct locations in the framework.

A plug-in is the level at which components are declared to the Eclipse framework. A plug-in is a JAR file

with a plug-in manifest file named plugin.xml. The plug-in manifest describes the plug-in to the

framework and enables a plug-in to consume and/or provide extensions from/to other plug-ins. For

example, a plug-in can provide user interface extensions, such as perspectives, views, editors, and

wizards. It can also provide business logic or core services to other plug-ins, but contribute no extensions

to the user interface.

A bundle is the level at which components are declared to the OSGi Service Framework. A bundle is a

JAR file with a bundle manifest file named MANIFEST.MF. The bundle manifest describes the bundle to the

service framework and enables a bundle to consume and/or provide packages and services from/to

other bundles. Bundles can also include a Bundle Activator class. The Bundle-Activator header in the

bundle manifest file identifies the class to the framework. At startup time, the framework creates an

instance of this class and calls its start() method. The Bundle Activator can then publish services, start

its own threads, and so on. When the bundle shuts down, the framework calls the activator’s stop()

76 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 87: Lotus Expeditor: Developing Applications for Lotus Expeditor

method. While the bundle shuts down, the Bundle Activator can release resources that are obtained since

the start method was called and revoke any services it has published.

Recall that the Eclipse framework is built on the OSGi Service Framework. Therefore, you can define each

component in your applications as a plug-in, a bundle, or both depending on your requirements.

Note: For a component to be recognized by the client platform, the toolkit and the Eclipse Plug-in

Development Environment (PDE), it must have a unique name and version. If you develop a

plug-in, specify a unique value for the name attribute and a version number for the version

attribute in the plug-in manifest. If you develop a bundle, specify a unique value for the

Bundle-SymbolicName attribute and a version number for the Bundle-Version attribute in the bundle

manifest.

A component can generally be organized in one of three ways:

v A directory containing at least a plugin.xml file. The directory may also contain a MANIFEST.MF file

located in the META-INF directory, additional files, as well as Java code contained within JAR files.

A plugin.xml file is required if the component defines extension points for use by other plug-ins or

implements extension points provided by other plug-ins.

v A directory containing at least a MANIFEST.MF file in the META-INF directory. The directory will also

contain Java code contained in JAR files. The MANIFEST.MF will refer to the JARs by referencing them

via the Bundle-Classpath attribute.

Components that provide only business logic or OSGi services and do not intend to provide or

implement any extension points can use this format. Components without plugin.xml files that need to

be available when building other components or when launching the client platform by using either

the toolkit or the PDE must be organized in this format.

v A single JAR file containing at least a META-INF\MANIFEST.MF or a plugin.xml file.

Components may be provided for use in the client platform by collecting all of the component artifacts

into a single JAR file. While this organization will run successfully, this organization is not compatible

with the toolkit and Eclipse PDE.

Fragments

A component may not always provide a complete implementation. In some cases, fragments may be used

to complete or extend a component.

For example, the primary component may provide an implementation that contains translatable text in a

default language. Fragments are then used to provide translations for additional languages.

A second case where fragments are often used is to provide platform (processor/operating system)

specific implementations.

Fragments contain either a fragment.xml (similar to a plugin.xml), or a MANIFEST.MF, or both. A fragment

is associated with, or dependent upon, a specific primary component, but still maintains a unique

identity. Querying a list of components will also return fragments, so that these fragments can be

individually started and stopped.

Fragments generally add classes or resources to the class path normally used by the primary component.

Fragments do not contain Bundle-Activator classes. Since fragments are only extensions to a component,

they cannot be required or imported by another component.

Features

On disk, an Eclipse-based product is structured as a collection of components and fragments. Each

component or fragment contains the code that provides some of the product’s functionality. The code and

other files for a component or fragment are installed on the local computer, and get activated

automatically as required. A product’s components are grouped together into features. A feature is the

smallest unit of separately downloadable and installable functionality

Developing applications 77

Page 88: Lotus Expeditor: Developing Applications for Lotus Expeditor

The fundamentally modular nature of the Eclipse platform makes it easy to install additional features and

components into an Eclipse-based product, and to update the product’s existing features and components.

You can do this either by using traditional native installers running separately from Eclipse, or by using

the Eclipse platform’s own Update Manager. The Eclipse Update Manager can be used to discover,

download, and install updated features and components from special web based Eclipse update sites.

The basic underlying mechanism of the Update Manager is simple: the files for a feature or component

are always stored in a sub-directory whose name includes a version identifier (e.g., ″2.0.0″). Different

versions of a feature or component are always given different version identifiers, thereby ensuring that

multiple versions of the same feature or component can co-exist on disk. This means that installing or

updating features and components requires adding more files, but never requires deleting or overwriting

existing files. Once the files are installed on the local computer, the new feature and component versions

are available to be configured. The same installed base of files is therefore capable of supporting many

different configurations simultaneously; installing and upgrading an existing product is reduced to

formulating a configuration that is incrementally newer than the current one. Important configurations

can be saved and restored to active service in the event of an unsuccessful upgrade.

Large Eclipse-based products can organize their features into trees starting from the root feature that

represents the entire product. This root feature then includes smaller units of functionality all the way

down to leaf features that list one or more plug-ins and fragments. The capability to group features

hierarchically allows products to be built on top of smaller products by including the smaller products

and adding more features.

Some included features may be useful add-ons but not vital to the proper functioning of the overall

product. Feature providers can elect to mark these features as optional. The Update Manager allows users

to choose whether or not to install optional features. If not installed right away, optional features can be

added at a later date.

Class loading

This section explains how classes are located and loaded by the client platform. A class loader is

responsible for loading classes. A class is loaded by a hierarchy of cooperating class loaders as shown in

the figure below.

FrameworkClass Loader

BundleClass Loader

Boot Class Loader(bootclasspath)

ExtensionClass Loader(java.ext.dirs)

ApplicationClass Loader(classpath)

SystemBundle

OtherBundles

Thread(Content

ClassLoader)

Public

Class

Space

(osgi.framework.systempackages)

default(change via osgi.parentClassloader)

Export-Package

Import-Package

Require-Bundle

Figure 1. Class loaders

78 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 89: Lotus Expeditor: Developing Applications for Lotus Expeditor

A typical Java application has a global name space that consists of the contents of the JARs in a single,

well-defined class path. A set of class loaders cooperates to locate and load classes based on this class

path. These class loaders include the Application Class Loader to load application classes (normally

found in the CLASSPATH), the Extension Class Loader to load standard extension classes (normally in the

jre/lib/ext directory, which is specified in the java.ext.dirs property), and the Boot Class Loader to

load system classes (normally from rt.jar in the jre/lib directory).

Class loading functions differently in the client platform because the client platform is built on the OSGi

Service Framework. Since the mechanics for supporting plug-ins are implemented by using the OSGi

Service Framework, a plug-in is the same as an OSGi bundle for the purpose of this explanation. The

bundle and its associated classes specify and implement the process for Java class loading, prerequisite

management, and the bundle’s life cycle.

Each bundle installed and resolved in the OSGi Service Framework must have a class loader created

when the first attempt is made to load a class from that bundle. This class loader, called the Bundle Class

Loader, provides each bundle with its own name space to avoid name conflicts and enables package

sharing with other bundles.

The Bundle Class Loader searches for classes and resources in the bundle’s class path as defined by the

Bundle-Classpath header in the bundle’s manifest. The Bundle Class Loader has a parent class loader as

specified in the osgi.parentClassloader property. By default, the parent class loader is the Extension

Class Loader for the client platform. However, the Extension Class Loader also has a parent class loader -

the Boot Class Loader. As a result, the parent of the Bundle Class Loader actually consists of the Boot

Class Loader and the Extension Class Loader.

A bundle can export the classes and resources in one or more of its packages by specifying each such

package name in the Export-Package header in its manifest. The classes and resources in each exported

package become part of the Public Class Space and are made available to other bundles with permission

to use the package A bundle can import one or more packages by specifying each package name in the

Import-Package header in its manifest. If the bundle has permission to import these packages, then the

bundle can use the classes and resources in these packages as defined in the Public Class Space. A

package can be shared based on its name and, optionally, its version. Multiple bundles can share (export)

a package with the same name. Each package in the Public Class Space is unique based on its package

name, exporting bundle’s symbolic name, and exporting bundle’s version. As a result, multiple versions

of the same package can exist in the Public Class Space.

A bundle may access a package from the Public Class Space by importing the package (using

Import-Package) or requiring the bundle which exports the package (using Require-Bundle). A bundle

that imports a package must know the name of the package it needs to import and may explicitly control

which bundle provides the package it actually uses by specifying additional matching attributes to select

a particular exporter of a package. A bundle can explicitly use all packages exported by another bundle

by specifying the required bundle in the Require-Bundle manifest in its header. The Require-Bundle

manifest header contains a list of bundle symbolic names that need to be searched after the imports are

searched but before the bundle’s class path is searched.

The figure below illustrates the search order used to locate classes and resources.

Developing applications 79

Page 90: Lotus Expeditor: Developing Applications for Lotus Expeditor

The OSGi Framework must adhere to the following rules for class or resource loading. When a bundle’s

class loader is requested to load a class or find a resource, the search must be performed in the following

order:

1. If the class or resource is in a java.* package, the request is delegated to the parent class loader;

otherwise, the search continues with the next step. If the request is delegated to the parent class

loader and the class or resource is not found, then the search terminates and the request fails.

2. If the class or resource is from a package included in the boot delegation list

(org.osgi.framework.bootdelegation), then the request is delegated to the parent class loader. If the

class or resource is found there, the search ends. The default for the platform is * which indicates that

all packages are delegated to the parent class loader.

yes

Failure

yes

Start

yes

yes

no

no

no

no

no

yes

yes

yes

yes

nono

no

yes

no

no

no

yes

yes

Success

java. ?*

bootdelegation?

imported?

Search Requiredbundles

Search bundleclass path

Search fragmentsbundle class path

packageexported?

found?

found?

found?

dynamicimport?

Delegate towire's exporter

Delegate towire's exporter

Delegate toparent class loader

Delegate toparent class loader

found?

found?

found?

found?1

2

3

4

5

6

7

8

9

Figure 2. Search order used to locate classes and resources

80 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 91: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. If the class or resource is in a package that is imported using Import-Package or was imported

dynamically in a previous load, then the request is delegated to the exporting bundle’s class loader;

otherwise the search continues with the next step. If the request is delegated to an exporting class

loader and the class or resource is not found, then the search terminates and the request fails.

4. If the class or resource is in a package that is imported from one or more other bundles using

Require-Bundle, the request is delegated to the class loaders of the other bundles, in the order in

which they are specified in this bundle’s manifest. If the class or resource is not found, then the

search continues with the next step.

5. The bundle’s own internal bundle class path is searched. If the class or resource is not found, then the

search continues with the next step.

6. Each attached fragment’s internal bundle class path is searched. The fragments are searched in

ascending bundle ID order. If the class or resource is not found, then the search continues with the

next step.

7. If the class or resource is in a package that is exported by the bundle or the package is imported by

the bundle (using Import-Package or Require-Bundle), then the search ends and the class or resource

is not found.

8. Otherwise, if the class or resource is in a package that is imported using DynamicImport-Package, then

a dynamic import of the package is now attempted. An exporter must conform to any implied

package constraints. If an appropriate exporter is found, a wire is established so that future loads of

the package are handled in Step 3. If a dynamic wire is not established, then the request fails.

9. If the dynamic import of the package is established, the request is delegated to the exporting bundle’s

class loader. If the request is delegated to an exporting class loader and the class or resource is not

found, then the search terminates and the request fails.

When delegating to another bundle class loader, the delegated request enters this algorithm at Step 3.

Developing the application user interface

This section provides information on application user interface development.

Understanding the user interface

This section provides introductory information for understanding the user interface.

Eclipse

The Eclipse 3.0 SDK provides an open framework to enhance functionality to the Integrated Development

Environment (IDE). These features (or plug-ins) are easily versioned and dynamically installed or

updated without restarting the IDE. Software developers using Eclipse have often wished for a similar

model for their desktop applications. With previous versions of Eclipse, this was possible but difficult,

especially when heavily customizing menus, layouts, and other user interface elements.

Eclipse Version 3 introduces the Rich Client Platform (RCP), a refactoring of the fundamental parts of the

UI, enabling RCP to be used as a general-purpose application platform. Its internals are the same OSGi

run time and GUI toolkit provided by the Eclipse IDE, but now these are easily used by application

developers to provide robust, customizable, and portable Java applications. Because of its Eclipse open

source license, you can use the technologies that went into Eclipse to create your own commercial-quality

programs. The GUI toolkits used by Eclipse RCP are the same used by the Eclipse IDE and enable

applications with optimal performance that have a native look and feel on any platform that they run on.

The client platform provides the default product and workbench. The workbench provides the default

look-and-feel that incorporates the base menus, images, and application launcher. Application developers

can create new applications that run within the confines of the platform. The workbench provides the

facilities that developers can use to enable applications to be launched.

Developing applications 81

Page 92: Lotus Expeditor: Developing Applications for Lotus Expeditor

There are two main application user interface types that can be hosted within the platform. Web

application based user interfaces are displayed within an embedded browser view that is part of a

predefined perspective provided by the platform. The web application can either be locally hosted within

the provided web container environment, or be running on a remote server. For more information on

creating web applications, refer to “Developing Web applications” on page 238.

The second main application user interface type is an application built using Java-based widgets. In order

to contribute to the workbench, applications must provide a perspective and declare the perspective to

the workbench using the WctApplication extension point. The perspective is a standard Eclipse

perspective and is composed of one or more views (or editors). Views (and editors) are constructed from

UI widgets such as tables, buttons, text fields and more. Wizards and dialogs can also be created by the

application to perform specific tasks. Wizards and dialogs can be launched by widgets (buttons) within a

view, or from various menu bars that are available within the platform.

UI toolkits

The following UI toolkits are used by the Eclipse IDE and plug-ins, and work equally well for RCP

applications.

The Standard Widget Toolkit (SWT) provides a completely platform-independent API that is tightly

integrated with the operating system’s native windowing environment. Java widgets actually map to the

platform’s native widgets. This gives Java applications a look and feel that makes them virtually

indistinguishable from native applications. In cases where native function is not provided, the SWT

emulates it in a manner in keeping with the platform’s normal look and feel. This toolkit overcomes

many of the design and implementation trade-offs that developers face when using the Java Abstract

Window Toolkit (AWT) or Java Foundation Classes (JFC). AWT gives the least common denominator

approach and is therefore functionally limited. JFC is more flexible, but because all widgets are painted

by the toolkit, JFC always seems to have trouble precisely emulating a native look and feel.

The JFace toolkit is a platform-independent user interface API that extends and interoperates with the

SWT. This library provides a set of components and helper utilities that simplify many of the common

tasks in developing SWT user interfaces. For example, it provides the dialogs, wizards, and rich text

editors used by the Eclipse IDE. JFace also has tables and trees that utilize a model view controller

(MVC) architecture to separate data access login from data display logic. JFace also provides the

mechanisms by which plug-ins programmatically contribute to the workbench, which is further discussed

in the next topic.

Lotus Expeditor for Devices provides subsets of the full SWT and JFace widgets sets. It also provides

Mobile Extensions which are particularly useful on devices.

Visual Editor for Java

The visual editor for Java is a code-centric Java editor that helps you design applications that have a

graphical user interface (GUI). The visual editor is based on the JavaBeans™ component model and

supports visual construction using the Standard Widget Toolkit (SWT), the Abstract Window Toolkit

(AWT), or Swing. A developer can use the visual editor for Java to create SWT composites. These SWT

composites can be used inside of Eclipse views and perspectives and used in Lotus Expeditor.

User interaction in the Lotus Expeditor

The default user interface provided for the Lotus Expeditor is similar in appearance and action to other

user interfaces, such as Microsoft Windows, Macintosh, and Motif. Users employ a ″selection/action″

model to interact with it.

In a selection/action model, selection pertains to each view and is independent of other selections in

other views. The view retains what is called selection memory. For example, when a user selects one or

more items in a list in one view, and goes to a different view (in a different plug-in or the same one), and

then returns to the list in the original view, the selected items are still selected. This selection model helps

users remember where they were and what they were doing in the view.

82 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 93: Lotus Expeditor: Developing Applications for Lotus Expeditor

Inactive selection refers to the display of a previous selection at the same time that the active selection is

displayed. All actions only take place on active selections, but continuing to display the inactive selection

helps users remember the choices they have made.

User interface organization

The following figure illustrates the organization of the user interface.

The following parts of the Lotus Expeditor user interface are displayed by default:

v Title bar

v Menu bar

v Status bar

The main data area contains only a default image when the client platform starts. Once applications have

been opened, then the views associated with the application will be displayed.

Title bar: The Title bar displays the program title and icon. The displayed information is part of the

branding elements that can be changed. .

Menu bar: The menu bar contains the set of actions that have been provided by either the default

workbench or by other applications.

Usability guidelines recommend that all features of an application be available from the menu items on

the menu bar. They also can be available from buttons or context menus. Context menus are displayed

when a user right-clicks the background of a user interface component, such as a view or document.

In general, menus should display all menu items that are applicable to the current view.

If Then

A menu item is not applicable to what is currently

selected, but the user can take an action while in the

same tab or window to enable the menu item

That menu item should appear dimmed

A menu item is not applicable to what is in the view That menu item should be hidden

Title Bar

Menu Bar

Main Data Area

Status Bar

Toolbar/Coolbar

View View ViewLauncher

Sidebar

Figure 3. User interface organization

Developing applications 83

Page 94: Lotus Expeditor: Developing Applications for Lotus Expeditor

Pull-right menus should always be enabled, even if none of the items in the pull-right menu are

available. Users should be able to view the contents of the pull-right menu, even if none of the actions

are available.

Banner bar: The banner bar can optionally display a graphic and the application name. The

configuration and graphical image used by the banner bar can be changed.

Data area: The primary data area of the user interface contains the perspectives and views associated

with an application.

Coolbar/Toolbar: The Coolbar/Toolbar area is used to display icons for actions that are available.

Usability guidelines suggest that all actions available on the Coolbar or toolbar are also available via

actions on the menu bars. The Coolbar/Toolbar area is optionally displayed and is configurable by the

administrator. Users can also elect to display or hide the Coolbar/Toolbar area.

Status bar: The status area can be used by applications to display information regarding the status of

their application. The components in the status area are associated with a particular perspective and view.

The status bar is optionally displayed and is configurable by the administrator.

Application Launcher: The Launcher is represented in the user interface as a button with a drop down

menu that contains the list of applications available to the user. The user selects a menu entry to open or

launch the application.

Using widgets on devices

The following sections contain information on Rich GUI programming for devices.

Functional partitioning: Embedded Rich GUI applications are composed of widgets and graphics

provided by eSWT which is a strict subset of the Standard Widget Toolkit (SWT) used for Rich GUI

desktop applications. The eSWT API is partitioned into two sets of function. The “Core” set contains the

minimal function required to run basic applications. The “Expanded” set contains additional function

which may be more appropriate for higher end devices with larger displays and more memory resources.

Since eSWT based applications are using subsets of SWT, these applications also function on any desktop

SWT implementation.

Mobile Extensions is a set of function primarily targeted for mobile devices, although some widgets it

provides may also be useful on desktop platforms. Lotus Expeditor Client for Desktops provides a

Mobile Extensions library for Win32 platforms.

Devices may potentially carry these functional sets in various configurations or packaging schemes. For

instance, low end devices may include a Core library and a Mobile library. Higher end devices may carry

a converged library that contains all three sets of function. For this reason, eRCP workbench applications

should always declare eSWT and Mobile Extensions dependencies by using “Import Packages” rather

than “Required Plug-ins” statements in their manifest which tie an application to a specific plug-in. Lotus

Expeditor Client for Devices includes a converged eSWT library.

Device normalization: Unlike desktop machines which all have large screens and pointer mechanisms,

mobile devices come in a wide range of shapes and sizes and have a variety of input mechanisms. As

much as possible, we would like to write applications that run well on any kind of mobile device. Note

that there is a big difference between simply running on a device and running well. Usability is a vital

concern for mobile devices where environments vary and expectations for ease of use are very high.

eSWT and Mobile Extensions attempts to normalize devices so that the application programmer does not

have to do a lot of work to handle the differences among devices. It does this in two ways: implicitly, by

providing a device’s native look and feel that a user is familiar with, and explicitly by providing

mechanisms that abstract input and output through the actual device hardware.

84 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 95: Lotus Expeditor: Developing Applications for Lotus Expeditor

Implicit normalization automatically provides some level of device adaptation by giving applications

indirect access to a device’s native widgets. Since eSWT widgets are implemented using a platform’s

native widgets, eSWT widgets appear and behave similarly to widgets in native applications. The

end-user can recognize and interact with these widgets as they’re use to. The programmer gains these

benefits simply by using eSWT widgets.

Explicit normalization is provided via specific mechanisms that a programmer is encouraged to use.

These generally fall into two categories: organizing output on a display and handling different input

mechanisms.

Display normalization:

1. Use of flow based layouts is strongly encouraged – Layouts like RowLayout and GridLayout

position widgets independently of screen size.

2. Use of absolute coordinates is highly discouraged – Display sizes and aspect ratios can vary

considerably. To guarantee that widgets are fully displayed, the programmer would have to calculate

proper coordinates for each different display size.

Even though layouts help considerably in adapting to different screen sizes, a program that runs well on

all devices should also perform the following:

1. Check if the computed layout is larger than the available screen size, and if so, add scroll bars to

allow scrolling the content.

2. Check for high aspect ratios which may restrict layout or allow for additional content. For example,

on a mobile device with a long, narrow landscape display, content may be better displayed in two

columns or in side by side panes.

Input normalization:

1. Use of the Mobile Extensions Command feature is highly encouraged – Commands are an

abstraction that the Mobile Extensions library maps to a specific mechanism depending upon the

device capabilities. This will usually be pointer driven menus or soft keys.

2. Use of buttons is discouraged – Many devices do not have pointer devices. Therefore, buttons on

these devices must be navigated to using jog controls or arrow keys and then selected. Jogging

through numerous widgets is more time consuming and may also be cumbersome depending on the

device controls. If buttons are highly desired, then the application can check via the MobileDevice

class to see if the screen is a touch screen. This allows use of buttons when they can be easily selected

and use of Commands or some other mechanism when they can not be.

3. Use of menus is discouraged – Of minor consideration is that the width of the menu bar may be

quite limited on some devices. It is difficult for your application to determine how many top level

menu items can be supported. Menus may also be somewhat difficult to navigate on non-pointer

devices. However, a more important reason not to use menus is that you may be bypassing the

device’s most natural or efficient input mechanism.

Mobile extensions widgets:

CaptionedControl

Determining which control has focus can be difficult on mobile devices where lighting conditions

are often less than optimal. (For instance, hairline width cursors in a text field can be very

difficult to see even under good conditions.) This widget “captions” a control with a label that

shows focus highlighting whenever the control has focus. With an entire label highlighted, it is

easy to see where focus is.

ContrainedText

A convenience widget which sets the initial input mode of a text field and also limits the

characters than can be entered within the field.

Developing applications 85

Page 96: Lotus Expeditor: Developing Applications for Lotus Expeditor

DateEditor

Allows the user to select a date, time, time offset or duration in a platform specific manner.

Constructor styles allow the program to choose FULL or COMPACT display modes, or rely on

the platform default.

HyperLink

Displays a label in a style which indicates it can be selected. Selecting the label (containing valid

link text) will cause an appropriate platform function to be launched. For instance, selecting an

e-mail address link will launch the platform’s e-mail program, selecting a URL will launch the

platform’s browser and selecting a phone number will cause the platform’s dialer to dial that

number. Note that not all platforms may have corresponding platform function. For instance,

PDAs may not have a built in phone.

ListBox

This is a Model-View-Controller (MVC) style widget which displays a list of items in the most

efficient/useful way for a given platform. The application may specify many hints as to how the

list should be presented, but the details of the actual presentation are device dependent.

ListView

This is an advanced List widget which allows inclusion of an image with each list item. The

ListView layout can also be changed at runtime in order to display more or fewer items

depending on the user’s preferences.

MobileDevice

This object allows the application to query information about the specific device the application is

running on and be informed about device state changes as they occur. For instance, an event is

sent when the device is closed, or a remote keyboard becomes available.

MobileShell

This widget allows applications to create a full screen window on a device, such as might be

desired for a slide show or game. The window created can also dynamically change its trim to

provide a window with more or less application area. MobileShell can also be used to poll for

key state as commonly done within game execution loops.

MultiPageDialog

This dialog allows the application to show multiple pages which are displayed one at a time. It

provides function similar to TabFolder in desktop SWT, but in a more platform dependent

fashion. The more restricted nature of this dialog over TabFolder allows it to map more readily to

native platform functionality.

QueryDialog

This dialog allows the application to query the user for a single piece of data and is provided as

a convenience class.

SortedList

This list widget automatically sorts its items in ascending or descending order. In addition, the

end user can filter the list. That is, by entering characters, items not containing that subset of

characters will not be displayed in the list. Such function is useful on devices where scrolling

through a list may not be as quick or easy to do as on a desktop.

TaskTip

This class provides an asynchronous indicator that a long running task is progressing. The

indication is similar in purpose to a mouse-over generated ToolTip which provides a bit of extra

information that is generally unobtrusive in nature. An application may open and close a TaskTip

as desired.

TextExtension

Basically, the Text widget with some mobile specific features. It allows a program to set the

semantic meaning of the text field so that platform specific features may be utilized to aid text

entry. For instance, if the field is intended to hold an e-mail address, the widget may access the

system e-mail application to retrieve possible e-mail address completions that the user may select

86 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 97: Lotus Expeditor: Developing Applications for Lotus Expeditor

from. The initial input mode may also be set to a particular character set. The user can change the

input mode as needed. Finally, the widget allows the setting of an initial casing mode, so that text

can be entered in all upper case or one of several other modes. Again, the user may change the

casing mode.

TimedMessageBox

This dialog shows one of several styles and audible patterns. It automatically closes after a short

period of time, thus reducing the need for user interaction to dismiss the dialog. For instance,

such a message may be useful to inform the user than someone wants to start a chat session.

eSWT programming tips:

v Disposal of Colors - You should dispose of the colors you create when there is no longer a need for

that color. You should not create the color, set it in the GC, dispose the color, then attempt to use the

GC. In this instance, you are disposing of the color before you are done using it.

v Layouts – Standard SWT practice is to either call layout() or pack() on a container with a layout

before opening the container. Otherwise, the layout calculation is not performed and elements may not

be visible.

v Commands – The Command constructor type parameter may only be used for mapping Commands to

softkeys, thus priority values should be used as well as type for appropriate ordering when

Commands are displayed within a menu.

v Command activation – Remember that Commands may not be the only (or best) interaction method

on all devices. Direct selection of items should also be supported. For example, a list widget may

support several Commands such as Open, Edit, and Delete. Direct selection (clicking) of a list item

should invoke the default Command action (Open). In some cases, a double click action may also be

supported (double clicking an item may invoke the Edit action).

v PaintListeners – Listeners should be added before a window is opened. Otherwise, the window will

not paint correctly when opened.

v Key Events - Do not assume there will be an elapse time between key pressed and key released events.

On a device with virtual keyboard these events may be sent back to back.

v Virtual Keyboard – On PPC, the virtual keyboard covers the bottom of display. Do not place text fields

requiring keyboard input in the bottom portion of a window, or if you do, ensure that the window is

scrollable so that the user may scroll the text field into view. Other platforms provide better

mechanisms such as providing an output field integrated with the virtual keyboard so the user can see

what is typed regardless of where the widget is positioned.

v Screen Size – Don’t assume that the screen will always be small. Some devices are capable of

connecting to large displays, where a few widgets, expanded to take up the entire screen will look very

odd. If going over a certain panel size would look odd, then limit your panel size, or adjust its content.

v Using images - When loading and using images, do not use the ImageData class unless you specifically

need to modify the image’s pixels. Image loading that does not involve ImageData employs an

optimized code path that is much faster than paths involving ImageData. Please note that many SWT

snippets show code like:

ImageData imageData = new ImageData("filename");

Image image = new Image(display, imageData);

Do not use code like this unless you intend to manipulate the image. Instead use:

Image image = new Image(display, "filename");

Using the Restricted Workbench

The Restricted Workbench provides an environment in which the user is restricted from accessing the

operating system and the Lotus Expeditor Workbench is used as the desktop shell.

The Lotus Expeditor Workbench alters its behavior, look, and feel when the Lockdown Feature is

installed on a Lotus Expeditor client machine. Once the Lockdown Feature is installed, the Lotus

Expeditor Workbench uses the Lockdown Service to achieve the restricted nature described below:

Developing applications 87

Page 98: Lotus Expeditor: Developing Applications for Lotus Expeditor

v No title bar

v No sizing borders

v Maximized to fill the screen

v Pinned down in the Z-order such that no other windows can be drawn beneath it

v Cannot be closed

v Cannot be resized

v Cannot be minimized

v File > Exit is removed from the Menu Bar

The above workbench environment is described as the Restricted Workbench.

Applicability and benefits

The Restricted Workbench allows system administrators to restrict the functionality of the user’s

workstation to a set of applications and OS services configured by the system administrator; in essence

creating a managed client. Target deployments include centrally managed clients such as bank branch

teller terminals and retail point of sales devices as well as customer facing kiosks such as ATMs.

The Restricted Workbench supports the following platforms:

v Windows XP SP1&2

v Red Hat Enterprise Linux Workstation 4

v NLD 9.0

The fundamental behavior of the Restricted Workbench is the same across platforms. Implementation

details differ between the Windows and Linux operating systems.

The key components to both implementations of the Restricted Workbench are:

v Code to pin down the workbench window by removing borders and isolating the window to the

bottom of the z-order

v Code that blocks keystrokes to prevent a user from circumventing the Restricted Workbench

v Installing scripts, registry updates, policy files and other install pieces that are executed by the

Lockdown Feature Install Handler and are also part of the Restricted Workbench

v The Restricted Workbench and the rcplauncher process work together to determine the nature of

workbench close events so that the user is not left with an empty desktop while the Lotus Expeditor

Workbench is restricted.

Using ILockdownService

To initiate a Restricted Workbench, the ILockdownService OSGi service is used.

The ILockdownService OSGi service is intended to be used by subclasses of WorkbenchWindowAdvisor in

order to lock down the initial workbench window. This service will lock one and only one window, and

it will effectively become the user’s desktop shell. The preWindowOpen method is intended to be called

during preWindowOpen of the WorkbenchWindowAdvisor and the postWindowOpen method is intended to be

called during postWindowOpen of the WorkbenchWindowAdvisor.

When using ILockdownService, take care not to do the following:

v Allow unrestricted access to the file system through applications running in the Workbench as there are

opportunities for circumventing lockdown by allowing users to have unrestricted file system access

v Allow applications to exit the workbench without using the exitLockDown method call

Acquiring the ILockdownService: The following code illustrate how to acquire the ILockdownService:

88 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 99: Lotus Expeditor: Developing Applications for Lotus Expeditor

public ILockdownService getLockdownService(BundleContext ctx){

ILockdownService rWorkbenchService = null;

ServiceReference ref = ctx.getServiceReference(ILockdownService.class.getName());

if(ref != null)

rWorkbenchService = (ILockdownService) ctx.getService(ref);return rWorkbenchService;

}

Using the ILockdownService to remove the window title trim: The following code sample illustrates

how to use the ILockdownService to remove the window title trim during preWindowOpen for a subclass of

WorkbenchWindowAdvisor:

ILockdownService rWorkbench = getLockdownService(bContext);

if(rWorkbench != null && !rWorkbench.isLockedDown())

rWorkbench.preWindowOpen(getWindowConfigurer());

Using the ILockdownService to lock the window: The following code sample illustrates how to use the

ILockdownService to lock a window during postWindowOpen for a subclass of WorkbenchWindowAdvisor:

if(rWorkbench != null && !rWorkbench.isLockedDown())

rWorkbench.postWindowOpen(getWindowConfigurer());

Using the ILockdownService to exit the Restricted Workbench and logoff the OS: The following code

sample illustrates how to use the ILockdownService to exit the Restricted Workbench and logoff the OS:

ILockdownService rWorkbench = getLockdownService(bContext);

if(rWorkbench != null){

rWorkbench.exitLockDown(ILockdownService.EXIT_DATA_LOGOFF);

PlatformUI.getWorkbench.close();

}

Using personalities

The personality of an application defines the framework the platform uses to determine what

perspectives or windows, menus, action bar items and status line controls are displayed when the

application starts. It can also determine what services are available, an event sequence, or what life cycle

should be applied to the objects associated with that application.

The layout of the window that contains the views and folders included in your application is defined by

a perspective, which is the Eclipse equivalent of a window. You set the desired perspective by specifying

a personality for your application.

A personality may be needed for one of two reasons. The first is that your application needs to provide a

different UI than other applications running on that platform. The other is to have fine control over the

application’s startup sequence.

Personalities are activated by specifying the personality ID on the command line. For example:

richclient -personality personality.id.

In addition, a default personality can be specified using the plugin_customization.ini file with the

following key:

com.ibm.rcp.personality.framework/DEFAULT_PERSONALITY_ID=

com.ibm.myexample.personality

Creating a personality

Personalities are contributed to the platform via the com.ibm.rcp.personalty.framework.personalities

extension point. Use the following procedure to create a personality:

1. Create an extension of the org.eclipse.ui.application.WorkbenchWindowAdvisor class. Refer to

Eclipse documentation for lifecycle events.

public class DefaultWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

public DefaultWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer) {

super(configurer);

Developing applications 89

Page 100: Lotus Expeditor: Developing Applications for Lotus Expeditor

}

public void createWindowContents(final Shell shell) {

// Create your layout and menus here. See Eclipse documentation

for details on WorkbenchWindowAdvisor.createWindowContents

}

public void postWindowOpen() {

// Do stuff like logging into the platform etc

try {

doLogin();

}

catch (LoginException e) {

// Do stuff

}

}

}

2. Create a class that implements com.ibm.rcp.personality.framework.IWorkbenchWindowAdvisorFactory.

The create(IWorkbenchWindowConfigurer) method should return an instance of your

WorkbenchWindowAdvisor subclass created in the first step.

import org.eclipse.ui.application.IWorkbenchWindowConfigurer;

import org.eclipse.ui.application.WorkbenchWindowAdvisor;

import com.ibm.rcp.personality.framework.IWorkbenchWindowAdvisorFactory;

public class WorkbenchWindowAdvisorFactory implements

IWorkbenchWindowAdvisorFactory {

public WorkbenchWindowAdvisorFactory() {

super();

}

public WorkbenchWindowAdvisor create(IWorkbenchWindowConfigurer configurer) {

return new DefaultWorkbenchWindowAdvisor(configurer);

}

}

3. Add an extension to the com.ibm.rcp.personality.framework.personalities extension point,

specifying your factory class created in the second step.

<extension point="com.ibm.rcp.personality.framework.personalities">

<personality

allowMultipleWindows="false"

icon="icons/icon_notes.gif"

class=""

factory="com.ibm.myexample.personality.

WorkbenchWindowAdvisorFactory"

name="%PlatformPersonalityName"

id="com.ibm.myexample.personality"/>

</extension>

4. Launch Lotus Expeditor and specify the new personality by personality ID.

The extension point startBundles enables defining a set of bundles that should be associated with a

Personality.

90 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 101: Lotus Expeditor: Developing Applications for Lotus Expeditor

The following example would associate the org.eclipse.equinox.event bundle to the Personality

identified by the extension point com.ibm.myexample.personality.

<extension point="com.ibm.rcp.lifecycle.personality.startBundles">

<personality id="com.ibm.myexample.personality">

<bundle id="org.eclipse.equinox.event"/>

</personality>

</extension>

Note: You can invoke additional personalities which will join the currently running Lotus Expeditor

Client environment rather than creating another full instance.

For information on contributing a personality to a menubar, refer to “Lotus Expeditor top level menus”

on page 365.

Lifecycle events

The events in the startup lifecycle in a personality are:

v preWindowOpen

v fillActionBars

v createWindowContents

v postWindowCreate

v preWindowOpen

v postWindowOpen

v Contributed personality startup tasks are executed

The events in the shutdown lifecycle of a window that are used in a personality are:

v preWindowShellClose

v postWindowClose

Creating a global toolbar

When a global toolbar is created in a Lotus Expeditor personality, the following steps occur:

DefaultWorkbenchWindowAdvisorFactory implements IWorkbenchWindowAdvisorFactory. In its create

method, DefaultWorkbenchWindowAdvisor is instantiated. DefaultWorkbenchWindowAdvisor overrides the

CreateActionBarAdvisor method, and instantiates DefaultActionBarAdvisor. DefaultActionBarAdvisor

overrides the fillActionBars method, and calls the actionBuilder.fillCoolBar and

ControlSetHelper.getInstance().fillCoolBar methods in it.

Developing composite applications

This section provides information on composite application development.

Understanding composite applications

Composite applications are applications that enable independently-developed components which provide

specific business functions to run together in a single application.

They are considered Portal-managed applications in that they are described and deployed on WebSphere

Portal and can be centrally managed from WebSphere Portal. They are supported on the Lotus Expeditor

client by the composite application infrastructure, which provides the following services:

v APIs that are common between Lotus Expeditor and WebSphere Portal, such as:

– Property broker – In WebSphere Portal, the property broker allows two portlets to communicate

with each other through the use of a Property and Action registry and a wiring mechanism. This

functionality has been ported to the client to support Property to Action model communication. The

architecture built into the client supports additional action-based communication systems, such as

Developing applications 91

Page 102: Lotus Expeditor: Developing Applications for Lotus Expeditor

Standard Widget Toolkit (SWT), Abstract Window Toolkit (AWT), and OSGI events. You can extend

the property broker API to support different Action-based targets through the Action Handler

Extension Point.

– Synchronization – Composite applications whose components implement the Synchronizable

interface are able to synchronize their data so that the application can be available for use while the

client is offline or when a connection to the WebSphere Portal server is not available. When an

application’s components implement this interface, users of the application have the ability to

register the application for synchronization. After an application is registered, when a

synchronization job runs on the client, the synchronization code for the application is called. The

code that synchronizes the data must be provided by the application components, using SyncML or

another synchronization service registered with the Synchronization Manager.

– Managed settings – A framework that retrieves policy and preference settings, or any other name

and value pairs defined by you on a back-end system, and stores them in the Eclipse preference

store implemented on the client. For composite applications, which are managed by WebSphere

Portal, this means that the framework manages portal policies on the client. A portal policy is a

collection of settings that influences the behavior of a portal resource and the experience that users

have when working with it. Using policy, you can limit or extend the functionality provided by a

resource based on the role and associated permissions defined for a given user. The portal policy

settings you define for a resource in WebSphere Portal are likewise applied to that resource on the

client. Policies are kept up-to-date through scheduled synchronization jobs. The client implements a

federated policy architecture in which policy providers identify a precedence order for policy

retrieval.v Serialization service – On Websphere Portal, components that contain custom code call the Serialization

SPI to serialize their data and generate a custom application definition in the form of an XML

fragment. The server exposes Web Services and Representational State Transfer (REST)-based services

that provide application-specific information to the XML-based application definition. When the

application is provisioned to the client, WebSphere Portal passes the XML fragment to the client. The

client reads the XML fragment and calls the components that implement the Deserializable SPI to

create instances of the custom domain objects defined by the components.

v Application definition - The client uses a standard composite XML document structure referred to as

the composite application instance to define the application. You can use the application instance to

specify application-specific information to create an importable CAI XML file for the client. The basic

construction of this XML package is a high level container hosting embedded XML fragments called

domain objects. These domain objects are the definitions for the various components within a

composite application and can be reconstructed on the client using the Deserializable interface.

Creating composite application projects

This topic provides a list of steps that you must complete to create a composite application project which

is made up of a SWT view component and a portlet component.

The sample application that is described in this section is one of the many types of composite

applications you can build. This section does not attempt to provide details for the steps required to

build every type of composite application supported on the client.

One step that you must complete to create both application components is to create a portlet. You can use

development tools to create a fully functioning portlet, or, to create a portlet that represents an SWT view

on the client and is not a fully functioning portlet, you can create a dummy portlet and edit it. The

dummy portlet serves as a container to which you can add custom preferences, such as

com.ibm.rcp.viewId or com.ibm.rcp.folder, using the rich client layout portlet. Views that implement

technologies such as Property Broker (for inter-portlet communication), WSRP, or Managed Browser APIs

require fully-functioning portlets, no dummy portlets. To create the SWT view component, we will start

with a dummy portlet and enhance it to enable it to register actions and properties using a WSDL file.

92 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 103: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: Some of the steps in these procedures ask you to use an Eclipse-based development tool. You can

use any of the following tools, among others:

v Rational Application Developer

v IBM Workplace™ Designer

v Eclipse

v Eclipse Web Tools Platform (WTP) project, which extends the Eclipse platform with tools for

developing J2EE Web applications.

To build a simple composite application made up of a SWT view component and a portlet component,

perform the following steps:

1. Create the SWT view component. See Creating a SWT view component.

2. Create the portlet component. See Creating a portlet component.

3. On the client machine, from the Preferences window, select Home Portal Account and provide the

Portal account connection information.

Creating an SWT view component

The SWT view component consists of an Eclipse plug-in containing one or more views and

corresponding portlets to represent each of the views that are built using the dummy portlet. In this

example, we are creating just one view and one corresponding portlet.

To create an SWT view component, complete the following steps:

1. In an Eclipse-based development tool, create a dummy portlet by using the portlet wizard. Leave the

resulting portlet as is.

2. Create a WSDL file to define the actions that you want to make available. See Defining actions and

properties . The IBM Workplace Designer tool provides a graphical wizard for creating WSDL files.

The following sample WSDL content defines the following items:

v An action – produceURL

v An input parameter:

name – URL

type – tns:BaseURL

v Output parameters:

name – URL From Tree

type – tns:BaseURL

name – Progress

type – tns:Progress<definitions name="LoadURLInBrowser_Service"

targetNamespace="http://www.ibm.com/wps/c2a"

xmlns="http://schemas.xmlsoap.org/wsdl/"

xmlns:portlet="http://www.ibm.com/wps/c2a"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns:tns="http://www.ibm.com/wps/c2a"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<types>

<xsd:schema targetNamespace="http://www.ibm.com/wps/c2a">

<xsd:simpleType name="BaseURL">

<xsd:restriction base="xsd:string">

</xsd:restriction>

</xsd:simpleType>

<xsd:simpleType name="Progress">

<xsd:restriction base="xsd:string">

</xsd:restriction>

</xsd:simpleType>

Developing applications 93

Page 104: Lotus Expeditor: Developing Applications for Lotus Expeditor

</xsd:schema>

</types>

<message name="LoadURLRequest">

<part name="urlFromTree" type="tns:BaseURL"/>

</message>

<message name="OurResponse">

<part name="loadedURL" type="tns:BaseURL"/>

<part name="progress" type="tns:Progress"/>

</message>

<portType name="LoadURL_Service">

<operation name="loadURL_Operation">

<input message="tns:LoadURLRequest"/>

<output message="tns:OurResponse"/>

</operation>

</portType>

<binding name="ManyOutParamsBinding" type="tns:LoadURL_Service">

<portlet:binding/>

<operation name="loadURL_Operation">

<portlet:action name="produceURL"

type="standard"

caption="Load the new URL"

description="Load.a.new.url.in.the.main.window"

actionNameParameter="ACTION_NAME"/>

<input>

<portlet:param name="URL" partname="urlFromTree" caption="url.loader"/>

</input>

<output>

<portlet:param name="URL From Tree" partname="loadedURL" caption=

"Browser URL"/>

<portlet:param name="Progress" partname="progress" caption=

"Browser Progress"/>

</output>

</operation>

</binding>

</definitions>

3. Reference the WSDL file in the portlet preferences by updating the deployment descriptor

(portlet.xml) file of the portlet. For example:

<portlet>

<portlet-preferences>

...

<preference>

<name>com.ibm.portal.propertybroker.wsdllocation</name>

<value>/wsdl/ManagedBrowser.wsdl</value>

</preference>

</portlet-preferences>

</portlet>

4. Using an Eclipse-based development tool, create the SWT view plug-in for which the portlet serves

as a placeholder.

5. Code the view to publish properties and code the action to update the view on property changes.

The property broker framework supports the following handler interfaces:

v Core Eclipse commands that implement the IHandler (org.eclipse.core.commands.IHandler)

interface. Use this interface if your application can not depend on any features that require user

interface packages. For example, use this implementation if your product runs in a device that

does not have SWT or AWT available. Implement the execute() method. The PropertyChangeEvent

94 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 105: Lotus Expeditor: Developing Applications for Lotus Expeditor

is set as the event trigger and can be accessed by calling ExecutionEvent.getTrigger(). The

following sample code processes a property broker change event in an Eclipse IHandler action:

public Object execute(ExecutionEvent event) throws ExecutionException

{

if (event.getTrigger() instanceof PropertyChangeEvent){

final Display display = Display.getDefault();

final PropertyChangeEvent pce = PropertyChangeEvent)event.getTrigger();

...

}

}

v SWT based handlers that implement the IHandler (org.eclipse.core.commands.IHandler)

interface. Use this interface if you are writing visual components with SWT. Implement the

execute() method in your handler. The event passed into this method is of type Event

(org.eclipse.swt.widgets.Event) and implements the PropertyChangeEvent

(com.ibm.rcp.propertybroker.event.PropertyChangeEvent) interface. Unlike the IHandler

implementation the SWT event passed in can simply be typecast to the PropertyChangeEvent

interface. The following sample code gets the broker’s event interface from an SWT IAction:

public void runWithEvent(Event event) {

//Make sure the Event is from the Property Broker

if (event instanceof PropertyChangeEvent){

final Display display = Display.getDefault();

final PropertyChangeEvent finalEvent = (PropertyChangeEvent)event;

...

}

}

The SWT component should use the SWTHelper (com.ibm.rcp.propertybroker.swt.api.SWTHelper)

class to publish its properties. This helper class removes the complexity of identifying the SWT

View instance the property came from by having the caller simply pass in a ″this″ pointer to the

view. The following sample code publishes a URL on the broker from an SWT based view:

PropertyValue value = PropertyFactory.createPropertyValue(prop, selection);

SWTHelper.changedProperties(new PropertyValue[]{value}, this);

The core broker also has a version of the changedProperties() method that enables the property

broker to resolve the specific instance property change to a specific instances action at runtime. A

Java String is passed into the changedProperties() method as the owner context of the property

change. The string should match the EntityID of the source in the wire.

Use the SWTHelper methods to help in retrieving the correct ViewPart. For example:

public void runWithEvent(Event event) {

//Make sure the Event is from the Property Broker

if (event instanceof PropertyChangeEvent){

final Display display = Display.getDefault();

final PropertyChangeEvent finalEvent = (PropertyChangeEvent)event;

display.asyncExec(new Runnable() {

public void run( ) {

//Get the wire definition from the event

Wire def = finalEvent.getWireDefinition();

//Our view object type

PreviewView pView = null;

//view for this action.

PreviewView pView =

Developing applications 95

Page 106: Lotus Expeditor: Developing Applications for Lotus Expeditor

(PreviewView)SWTHelper.locateView(def.getTargetEntityId());

...

}

v AWT components that implement the Component (java.awt.Component) class. 6. To enable view-to-view communication, register your action with the broker by extending the

com.ibm.rcp.propertybroker.PropertyBrokerAction extension point. In the class attribute, reference

the Java class that will be instantiated by the broker and that you created in the previous Step. In the

file attribute, specify the name of the WSDL file you created previously.

7. Create an Eclipse Feature project that contains the view plug-in you created. Your plug-in can be

bundled into an existing feature. If you do add it to an existing feature, update the version number

of the feature to ensure that the plug-in is installed with the next client update.

8. Create an Eclipse Update Site project and import your feature, and then deploy your Eclipse Update

site to the WebSphere Portal server or another HTTP server. The supporting files required for the

client to run the SWT view are now available.

9. Return to the SWT view portlet and, using Rational Application Developer or J2EE Web application

tools provided by the Eclipse Web Tools Platform (WTP) project, bundle the portlet into a Web

Application Archive (WAR) file. Adding the portlet to a WAR file makes it easier to deploy, and

subsequently update.

10. From the Administration page, navigate to the WebSphere Portal → Portlet Management → Web

Modules page, and then click Install to install your WAR file as a Web module.

11. Verify the portlet was installed by searching for it on the Portlet Management → Portlets page.

12. In the Templates → Application page, create a new application and make the following edits:

a. In the Content tab, define the layout for the application and add the portlet to the page.

b. In the Rich Client tab, select This portlet represents an SWT view on the rich client, and then

type the ID of the SWT view plug-in into the Eclipse view id field.

c. In the Wires tab, create wires between your portlets by specifying the source portlet, the output

property, the target page, which defaults to current, the target portlet, the target property, and

whether or not the wire is public or private. If you want to implement cross-page wires, which

are wires that open an event in a second page, you must designate them as global actions. To do

so, click Manage Actions and then select the Global check box.

Creating a portlet component

This topic explains how to develop a portlet that will run locally and communicate with an SWT based

component after both have been projected to the client from a WebSphere Portal server.

You must complete the steps in Creating a SWT view component before you can perform the steps below.

To create a portlet component, complete the following steps:

1. Using an Eclipse-based development tool, create a fully functioning portlet, not a dummy portlet. It

must use the IBM Portal property broker functionality to publish properties to the SWT component.

2. Reference the same WSDL file that you created in the previous procedure in the portlet preferences

in the portlet.xml deployment descriptor file.

3. Using Rational Application Developer or the J2EE Web application tools provided by the Eclipse

Web Tools Platform (WTP) project, bundle the portlet into a Web Application Archive (WAR) file.

4. From the Administration page, navigate to the WebSphere Portal → Portlet Management → Web

Modules page, and then click Install to install your WAR file as a Web module.

5. Verify the portlet was installed by searching for it on the Portlet Management → Portlets page.

6. In the Templates → Application page, create a new application and make the following edits:

a. In the Content tab, define the layout for the application and add the portlet to the page.

96 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 107: Lotus Expeditor: Developing Applications for Lotus Expeditor

b. In the Rich Client tab, select This portlet runs locally on the rich client (requires client

bundle), and then type the directory of the Web module for the portlet into the Portlet context

root field to configure your portlet to be exposed in the client through the local JSR-168 container.

c. In the Wires tab, create wires between this portlet and the portlet representing the SWT view by

specifying the source portlet, the output property, the target page, which defaults to current, the

target portlet, the target property, and whether or not the wire is public or private. If you want to

implement cross-page wires, which are wires that open an event in a second page, you must

designate them as global actions. To do so, click Manage Actions and then select the Global

check box. 7. You must add the portlet to the feature for the SWT view plug-in. Use the Lotus Expeditor

command line tool (WAB Tool) to compile the portlet WAR file into an Eclipse-based plug-in. The

WAB tool is provided in the Lotus Expeditor Development kit. Go to the plugins directory, and look

in the com.ibm.pvc.tools.web.translator plug-in for the wab.exe file. See WAB Utility for information

on using this tool.

8. Add the resulting plug-in to the feature plug-in you created for the SWT view.

9. From the Portlet Management → Portlets page, find the portlet you just created, and click the

Configure icon to open it, and then add the feature ID to the portlet properties to ensure that the

feature is installed when the application is installed from the portal catalog.

10. Redeploy the update site with the newly added plug-in to the HTTP server. If you already deployed

the feature and are adding this plug-in to an existing feature, be sure to increment the version

number so that the client can pick up your changes with its next update.

Developing composite application logic

This section provides an overview of the steps you must complete to create a basic composite application.

The types of components that can comprise a composite applications, the tools you can use to build

them, and the technologies that they can employ are wide-ranging. For example, you can build a

contributing component of a composite application that employs views based on any of the following

technologies:

v Standard Widget Toolkit (SWT)

v JSR 168 Viewer

v WSRP Viewer

v WEB container, JSP

v Embedded Browser

v Abstract Window Toolkit (AWT)

In addition, the client implementation of the property broker API enables the following subsection of

components to communicate with one another:

v Standard Widget Toolkit (SWT)

v JSR 168 Viewer

v Abstract Window Toolkit (AWT)

This section provides instructions that are based on steps that were used to create the sample application,

Managed Browser, which you can find in the samples gallery.

The sample composite application employs the following two supported composite application

technologies and enables them to communicate with one another:

v SWT view-based components – Built as a standard widget toolkit view designed in RAD or Eclipse

that is installed on a deployed Eclipse Update Site. You create a portlet to represent the view and

define values for a set of custom portlet properties that identify it as an SWT-based view. You can use

the administrative tools provided by WebSphere Portal or the Lotus Expeditor Rich Client Layout tool

to organize the layout of this and other portlets into a page design that is customized for the users of

Developing applications 97

Page 108: Lotus Expeditor: Developing Applications for Lotus Expeditor

your application. When the component is downloaded to the client, the client infrastructure constructs

the user interface for your component based on the customizations you defined in WebSphere Portal.

v Portlet-based components – Built as a portlet in RAD or Eclipse. The portlet component is bundled into

an Eclipse-style plug-in to be downloaded to the client using either the Lotus Expeditor WAB tool or

the Lotus Expeditor Client Services Toolkit. When the component is downloaded, the client uses the

JSR 168 portlet viewer, which reconstructs the portlet as an SWT view, to display it.

The sample application uses WebSphere Portal to represent an SWT-based view in a portal based

application, and then projects it to the client. It also uses WebSphere Portal to project a portlet to the

client. In both cases, what ultimately runs on the client are standard Eclipse-based SWT views.

By projecting the views through WebSphere Portal, you can:

v Leverage portal policy, which exposes different application features to users based on their job

responsibilities.

v Wire components together at runtime instead of at development time.

v Use a common deployment and aggregation model for both Web-based and client-based applications.

The sample application exercises the following services:

v The composite application infrastructure to deploy an SWT based application.

v Dynamic provisioning and integration into the application catalog. When you open the application

from the catalog, it is downloaded and then launched without requiring the user to restart the client.

v Reading portlet preferences from the SWT view.

v Drag and drop capability using property broker property values.

v Declarative wiring through the property broker on the portal and client.

v Cross-page wiring, which means that a view action opens another page and sends the event to a view

on it.

v Click to Action control, which is a right-click menu that displays a list of any compatible property

broker actions that are available.

v Portlet component to SWT view component communication.

Developing data access applications

This section provides information on data access application development.

Understanding embedded database development

This section provides information on understanding embedded database development.

Databases

Database application developers use JDBC, the application programming interface that makes it possible

to access relational databases from Java programs. The JDBC API is part of the Java 2 Platform, Standard

Edition (J2SE) and is not specific to any particular database implementation, such as Cloudscape or DB2

Everyplace. It consists of the java.sql and javax.sql packages, which are sets of classes and interfaces

that make it possible to access databases (from a number of different vendors) from a Java application.

The JDBC specification defines several interfaces and types that application developers use to access the

database.

v A DataSource is the primary definition of a database, and typically defines database access properties

and locations.

v A Connection is the communication object that enables queries and updates to be performed against

the database. The preferred method for obtaining a connection in JDBC 3.0 is with a DataSource object,

as opposed to using DriverManager in a JDBC 2.0 specification implementation.

98 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 109: Lotus Expeditor: Developing Applications for Lotus Expeditor

v A Statement enables the application developer to affect specific actions on the database. There are

specialized types known as PreparedStatement or CallableStatement that provide additional advantages

and capabilities. A Statement is created from a Connection object.

v A ResultSet represents the result of a query. The ResultSet object is returned upon successful execution

of a query in a Statement.

As previously mentioned, the JDBC APIs are part of the J2SE specification. In order to get a clear picture

of the current JDBC APIs it is useful to review the history of them and their relationship to the J2SE

specification. J2SE 1.2 defined JDBC 2.0, which included definitions in the java.sql package. The main

way of accessing databases was with the java.sql.DriverManager interface. Sun then defined the JDBC

2.0 extension package, which introduced the javax.sql package and a new DataSource interface for

accessing databases in Java, as well as support for connection pooling. JDBC 3.0 was subsequently

defined and combined the two components of JDBC 2.0 into one JDBC specification. This was first

included in J2SE 1.4.

In addition to knowledge of the development of JDBC APIs, database application developers also need to

have a detailed understanding of the Structured Query Language (SQL). SQL is the standard query

language used with relational databases and is not tied to a particular programming language. No matter

how a particular relational database management system (RDBMS) has been implemented, the user can

design databases and insert, modify, and retrieve data using the standard SQL statements and

well-defined data types. SQL-92 is the version of SQL standardized by ANSI and ISO in 1992. Entry-level

SQL-92 is a subset of full SQL-92 specified by ANSI and ISO that is supported by nearly all major DBMSs

today. In 1999, another update to the SQL standard was made available called SQL-1999 or SQL-99.

Embedded databases: Lotus Expeditor provides two relational databases that are accessible using JDBC

interfaces, DB2 Everyplace and Cloudscape.

v DB2 Everyplace features a small footprint relational database and high performance data

synchronization solution that enables enterprise applications and data to be securely extended to

mobile devices such as personal digital assistants (PDAs), smart phones, other embedded mobile

devices, and desktops. With DB2 Everyplace, the mobile work force in industries such as health care,

telecommunications, retail, distribution, transportation, and hospitality can now easily access the

information they need to perform their work from any location, at any time, right from the palm of

their hand. It is especially suitable for embedded devices, where large databases and sophisticated

queries are not normally required, but can also be used on desktop platforms. DB2 Everyplace

provides transaction support covering updates to multiple tables within a single transaction, encrypted

tables, and zero client administration.

v Cloudscape is a 100% pure Java relational database, providing SQL-92, partial SQL-99, and Structured

Query Language for Java (SQLJ) support, indexes, triggers, transactions, encryption, and the standard

features that one expects of a relational database.

DB2 Everyplace and Cloudscape comparison: DB2 Everyplace and Cloudscape are similar, but have

features that might make one a better choice for client needs.

Table 2. DB2 Everyplace and Cloudscape comparison

DB2 Everyplace Cloudscape

Implementation Type High performance native

implementation (see DB2E

documentation for a complete list of

supported devices)

Java-based (platform independent)

implementation

On-Disk Footprint 250 KB 2 MB

Number of connections supported Allows multiple concurrent

connections to a database from the

same VM

Allows multiple concurrent

connections to a database

Developing applications 99

Page 110: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 2. DB2 Everyplace and Cloudscape comparison (continued)

DB2 Everyplace Cloudscape

SQL Support Limited set of SQL data types Full SQL-92 support, partial SQL-99

support

Schema Support No Yes

Database Creation Requirements Directory for database tables must be

created prior to use

Cloudscape creates directory

JDBC URL jdbc:db2e:location

If no database exists at the location, a

new database structure is created

jdbc:derby:location

Database creation requires the

addition of an explicit create=true

attribute to the URL

In addition, the database location can

also refer to a zip or JAR file in the

case of a read-only database

Lifecycle management provider

available

No Yes

Refer to the product documentation for more complete information about these products.

Deployment and synchronization

When dealing with databases, you can choose to use a database only as a local data repository or as a

repository that actively synchronizes with another node in the topology. In either case, if data needs to be

distributed to a database, you need to balance considerations of how much data needs to be distributed

and when (once only at initialization, one way from one node to another only on an infrequent basis,

frequent exchange between nodes), with the storage capabilities at each node in question, and the

networking requirements that would permit the exchange to take place. In addition, if you choose

synchronization, application developers should consider database organization, filtering, and conflict

resolution policies. Synchronization is useful for exchanging the current state of data between nodes,

where transaction boundaries or the order of state changes are not important.

When you use data synchronization, database tables are automatically created. If a database is used only

for local storage and will not be synchronized with a server database, you must perform the additional

step of creating the initial database.

There are a few options for creating an initial database without using database synchronization:

v Incorporate code to create the initial database within the application. The advantage of this is that the

application is fully responsible for creating the database. In addition, if there is a need to rebuild the

database, the code is already present. No additional steps are required by the user of the database. One

disadvantage is that the code must be carried along with the application, even though it might never

be used again. Another disadvantage is that the population of initial data into the database might be

too large, or not appropriate to include within Java code. For read-only databases, this is generally not

appropriate; if the data were available to populate into the database, then you probably would not

need a database. Database creation code could be provided in a separate OSGi bundle that is then

removed from the framework after the database has been constructed.

v Distribute the database files with the application. The database is constructed and populated outside of

the client environment. The resulting database files are then distributed with the application, either in

directory format or in a zip or JAR file. The advantage of this is that the code to build and populate

the database runs in another environment; it does not need to be distributed with the application. This

is an ideal choice for distribution of a read-only database, as the data can be distributed using CD,

memory cards, or other distribution mechanisms. The disadvantages are that the distribution of the

files might be more difficult than distributing code. Also, updates to the database typically require

redistribution of database files.

100 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 111: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Distribute Data Definition Language (DDL) (a set of database statements) and require the installation

application or the end user to create the database. While this overcomes some of the disadvantages of

incorporating database creation code within the application, it requires that the end user be sufficiently

knowledgeable to create the database, or the installation application becomes more complex. In

addition, this also typically requires additional tools (such as the command-line tools DB2eCLP for DB2

Everyplace, or ij for Cloudscape) to be present on the client or device.

Another option for database creation, and for continual update, is to use database synchronization

facilities. DB2 Everyplace and Cloudscape are both capable of synchronizing with the DB2 Everyplace

Sync Server, using the IBM ISync technology provided with Lotus Expeditor. The initial synchronization

activity creates the local database tables and also populates the initial set of data. As data is updated on

the client device, synchronization transfers that data to the DB2 Everyplace Sync Server and then to other

client devices that are configured to receive it. Database administrators set up the necessary subscriptions

for synchronization, and can also set up filtering of data to limit the amount of data distributed to client

devices.

Database application developers can use the ISync APIs provided with Lotus Expeditor to control the

synchronization process for their specific databases. This includes initiating the sync, monitoring events

during the process, and managing any conflicts or errors that occur.

A simple iSync sample is available in the Rational Samples Gallery under Technology Samples > Lotus

Expeditor.

It is also important to note some differences in database application programming when using database

synchronization:

v Any changes made to the local copy might appear much later in the server. Synchronization requires

the application or user to initiate the sync to the sync server; the replication cycle must kick in so that

changes are pushed back to the back end database server. Furthermore, the local changes can be

rejected for many reasons, for example, because conflicts were found at the database server side.

v There is a latency between synchronizing changes from a client to the server and then from the server

to other clients. In other words, if a change was made to a local database, these changes do not appear

on another client device until the local database is synchronized successfully to the sync server. Then

the sync server successfully replicates the changes to the back end database, the changes come back

down the sync server for other clients; the changes show up on another client device when it

successfully synchronizes.

v Database synchronization is based on row-level updates synchronized to and from the DB2 Everyplace

Sync Server and the client devices. Database synchronization captures only the current state of data for

synchronization. Because the database row contains only the current state of the data, there are two

situations in which the application might need to provide additional capabilities. The first situation is

when the ordering of updates that were applied to the database is important. The second situation is

when a historical record of the changes to the rows in the database is required. In either of these

situations, the application needs to provide this capability. The application can store each change in

value in a separate row in the main table, or use additional tables for history purposes. Optionally, the

application can use assured messaging to send the various updates to the server.

Security considerations: Server databases typically reside in a well-secured zone, with limited access to

applications residing in other network topologies. As a result, data in the database is secured because of

network location and access rights. In addition, database backup or sophisticated data management exists

to protect against data loss.

Databases existing on client systems have different levels of protection. Physical device security is the

first barrier in preventing unauthorized access to databases. This includes locking up or securing the

physical device as well as providing secure passwords to protect against others illicitly using the device

to access data. An additional way to protect the data in the database is to use the encryption technologies

provided by the databases. The entire database, or specific tables, can be encrypted using a key

Developing applications 101

Page 112: Lotus Expeditor: Developing Applications for Lotus Expeditor

(password) that must be provided by the user. This protects against someone being able to open the

database if they were to obtain the physical media storing the database (such as a CD for read-only

databases, memory keys, Compact Flash cards, and so on).

To protect against data loss, especially for local databases or local synchronized databases, you should

put a backup or synchronization strategy in place to ensure that data is synchronized on an appropriate

schedule. Incidentally, this also reduces the chances of data on the device becoming out of date.

Database lifecycle management

The Database Lifecycle Management framework offers Lotus Expeditor applications the ability to

interoperate with a relational database in a uniform and transparent manner (using the notion of

managed datasources). It provides the platform administrator/developer:

v A declarative way of specifying the required database structure

v The ability to initially populate databases prior to client access

v Supports migration from one database structure to another

The database population and migration is handled either by scripts or specialized database programming

tasks that have the power to manipulate a database’s contents. The granularity of this task falls along the

line of a datasource which simply refers to a database definition and its associated schemas (there are

also virtual datasources which allow for the reuse of already defined datasources). This allows for a finer

control over schema lifecycle within the framework. The framework empowers platform administrators to

define simple scripts that handle migration related tasks while being completely transparent to the

application developer. The application developer can access the framework via a standard JNDI context.

The framework automatically performs the necessary functions of the platform administrator.

The framework also defines a method to allow application developers to monitor changes to a

datasource. This can be useful when migration tasks take a long time and the administrator may offer

some relevant visual feedback to the end-user.

Another feature of this framework is the ability to define other database providers. By default, the

platform includes a default datasource that is based on the Apache Derby database. If a platform

administrator requires another database type, they have the power to define their own provider to be

accessed by datasources platform-wide. A good example of when a new database provider would be

defined is in the embedded space where Apache Derby is not the best database to use due to memory

constraints.

Included in the framework is a defined platform default datasource which is based on the Apache Derby

embedded database. The reason this datasource exists is because many applications have a need to store

encrypted data on the Lotus Expeditor platform so having a reusable platform datasource can allow

applications to do so. Applications can provide their own schemas through virtual datasources in order to

interact with the platform default datasource.

On the whole, the Database Lifecycle Management framework aims to simplify the tasks of a platform

administrator by offering lifecycle management and making the whole process transparent to the

application developer.

Enabling projects for data access application development

This section discusses enabling projects for data access application development.

Client Services target profile features

The Lotus Expeditor Toolkit provides Client Services target definition support. These target definitions

simplify the creation and configuration of database application projects, enabling you to select the

target-embedded database, and provide automatic management of the requisite JDBC libraries. When

developing a data access application, any of the Client Services target definitions can be selected for your

Client Services project. However, ensure you select the Cloudscape target feature for project access to the

102 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 113: Lotus Expeditor: Developing Applications for Lotus Expeditor

Cloudscape database engine, or the DB2 Everyplace client target feature for the DB2 Everyplace database

engine. If you are interested to developing code leveraging the DB2 Everyplace ISync APIs, be sure to

select the DB2 Everyplace Client Sync or the Cloudscape Client Sync for project access to the ISync APIs.

Finally, if you are developing implementations/extensions for the database lifecycle management

framework then select the Database Lifecycle Management target feature. For more information on Client

Services projects, refer to “Lotus Expeditor Toolkit” on page 11.

Developing database logic

This section details database logic development.

Data access application development best practices

There are typically two reasons for creating an application that needs to make use of database

technologies. One reason for using database technologies is to create a new lightweight client application.

Another reason is to adapt an existing server-side application for use as a lightweight client application.

Enterprise Java developers who have written applications requiring the use of JDBC typically rely on

obtaining access to the database through a DataSource object. The DataSource object will have already

been bound by the Java Naming and Directory Interface (JNDI). The application developer simply needs

to locate the DataSource using JNDI, and obtain from the DataSource a connection to the database. The

application deployer cooperates with the system administrator to define the mapping and access to a

physical database, causing the DataSource object to be bound into JNDI.

Also, in the server environment, database management often falls within the administration realm of a

database administrator. A database administrator is typically responsible for creating the physical

database, partitioning the database for use among several applications, creating tables and indexes for a

particular application, managing the access rights to a database, and monitoring the performance of the

database. When the application developer has successfully located a DataSource using JNDI, the

developer can obtain a Connection, and begin performing actions against the database.

When adapting a server-side application to run on a client, the application developer often takes more

responsibility, performing some roles typically handled by a database administrator. The application

developer might be responsible for initially creating the database, creating tables, and configuring the

database. In addition, depending upon the set of components available on the client, the application

developer might also be responsible for creating the DataSource objects, either directly within the

application, or within a JNDI environment on the client. If no JNDI support is available in the client

runtime environment, the application developer should use the standard JDBC 3.0 javax.sql.DataSource

creation methods. Regardless of how the DataSource object is created or located, application developers

still obtain Connection objects from the DataSource, and create Statement objects from the Connection.

In order to ensure minimum changes to applications that use JDBC, some best practices should be

followed:

v Use DataSource objects as they exist across the JDBC 3.0 specifications; DriverManager does not exist

in the JDBC Optional Package for CDC/Foundation Profile. Limiting the JDBC application usage to the

JDBC Optional Package for CDC Foundation Profile subset of JDBC 3.0 provides the most portability

from desktops to devices.

v Isolate the DataSource creation or location to a single class. Later, if the environment changes, a change

needs to be made in only one place.

v Ensure you close all objects (ResultSet, Statement, Connection) when you have completed work.

Servers typically include more sophisticated connection management known as connection pooling,

which can accommodate mismanagement of connections. However, on the clients, application

developers are directly responsible for the life cycle of the objects. By promptly closing objects, memory

requirements will remain at a minimum.

v Do not hard code a schema identifier during statement creation. DB2 Everyplace does not support

schema names, so all statements would need to be changed if an application needed to be migrated to

DB2 Everyplace.

Developing applications 103

Page 114: Lotus Expeditor: Developing Applications for Lotus Expeditor

v The SQL statements supported by a particular database might not match the statements used within an

existing application. The application either needs to adapt statements depending upon database type,

or obtain statement information from externalized information.

Lotus Expeditor includes the Lotus Expeditor Toolkit, which provides Target Profile support. These Target

Profiles simplify the creation and configuration of database application projects, enabling you to select the

target-embedded database, and provide automatic management of the requisite JDBC libraries. In an

Eclipse SDK plug-in development environment, you can use the standard plug-in dependency tooling to

provide the necessary access to DB2e and Cloudscape libraries during database application development.

Eclipse is an award-winning, open source platform for the construction of powerful software

development tools and rich desktop applications.

While for Lotus Expeditor development we recommend the use of the DataSource interface for JDBC

programming, there may also be cases where the DriverManager interface must be used for legacy code. If

this is the case, please note that while in previous releases of the Lotus Expeditor runtime, the platform

would load the database driver classes at platform startup, this is no longer the case. The method for

accessing a database via JDBC using the DriverManager interface involves 2 steps:

1. Loading the database driver via a Class.forName() method call.

2. Connecting to the database.

The DriverManager class to be loaded for IBM Cloudscape is org.apache.derby.jdbc.EmbeddedDriver and

the DriverManager class to be loaded for DB2 Everyplace is com.ibm.db2e.jdbc.DB2eDriver.

For more information on JDBC programming please see the SUN JDBC tutorial at http://java.sun.com/docs/books/tutorial/jdbc/index.html.

Database Lifecycle Management

This section provides information on Database Lifecycle Management.

Accessing a defined managed datasource: To look up a datasource, invoke a standard JNDI lookup:

InitialContext context = new InitialContext();

DataSource source = (DataSource) context.lookup("jdbc/MyDataSource");

Connection connection = source.getConnection();

For more information about JNDI, please see Sun’s documentation: http://java.sun.com/j2se/1.5.0/docs/api/javax/naming/package-summary.html.

Monitoring operations on a managed datasource: To define a listener, first create a class that

implements IProgressMonitor:

public class TestProgressMonitor implements IProgressMonitor {

...

public void done() {

System.out.println("Processing is done!");

}

...

}

Next, implement the com.ibm.rcp.database.core.listener extension point. The following sample listener

listens against the datasource jdbc/MyDataSource.

<extension point="com.ibm.rcp.database.core.listener">

<listener class= "com.ibm.rcp.database.tests.listeners.TestProgressMonitor"

jndiName="jdbc/MyDataSource"/>

</extension>

Accessing the default managed datasource: By default, the platform includes a default datasource based

on the Apache Derby database. To access it, perform a JNDI lookup using its defined JNDI name

(jdbc/DerbyDS):

104 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 115: Lotus Expeditor: Developing Applications for Lotus Expeditor

InitialContext context = new InitialContext();

DataSource source = (DataSource) context.lookup("jdbc/DerbyDS");

Connection connection = source.getConnection();

Developing Embedded Transaction applications

The Embedded Transaction capability of the Lotus Expeditor platform enables the development and

deployment of business logic components by supporting a subset of the Enterprise Java Bean (EJB)

specification. These business logic components are referred to as Embedded Transaction applications, and

are run by the platform’s Embedded Transaction Container. The Lotus Expeditor platform only supports

execution of and access to Embedded Transaction Applications executing within the Lotus Expeditor

runtime.

Note: Use of the Embedded Transaction development tools requires Rational Application Developer,

Rational Software Architect, or Application Server Tools. The Embedded Transaction development

tools are not supported with just the Web Tools Platform.

Embedded Transaction applications can be developed using many of the same EJB development tools

provided by the Rational Software Development platform. You should therefore refer to the Rational

online help section “Developing Enterprise applications” as your initial development tools reference. The

following topics discuss the additional development considerations and tool usage required when

targeting an Embedded Transaction application for the Lotus Expeditor platform.

The following table provides pointers to information on tasks that are unique to, or require special

consideration when developing Embedded Transaction applications for the Lotus Expeditor platform.

Table 3. Embedded Transaction application tasks

Task Reference

Understanding Embedded Transaction concepts,

including which elements of the EJB specification are

supported, and which are not.

“Understanding the Embedded Transaction Container”

Working with Client Services Embedded Transaction

projects versus EJB projects, and when to use one versus

the other.

“Creating Embedded Transaction projects” on page 108

Developing Embedded Transaction logic. This

encompasses any special development considerations

when coding and constructing the embedded transaction

logic.

“Developing Embedded Transaction Container logic” on

page 110

Performing embedded transaction deployment. The

Embedded Transaction container requires additional

deployment information beyond that provided for an

EJB.

“Packaging and deploying Embedded Transaction

applications” on page 119

Debugging and testing the Embedded Transaction

application.

“Debugging and testing applications” on page 323

Deploying the Embedded Transaction application to a

runtime.

“Deploying projects for local testing” on page 331

Understanding the Embedded Transaction Container

The Embedded Transaction Container provides tooling and runtime support for local Enterprise Java

Beans (EJBs). The current version supports the following features of the EJB 2.1 specification:

v Remote and Local Homes for local EJBs

v Stateless Session Beans

Developing applications 105

Page 116: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Entity Beans, both bean managed persistence (BMP) and container managed persistence (CMP) at both

the EJB 1.1 and EJB 2.1 specification levels (local homes, use of abstract persistence schema)

v Container-managed transactions

v Entity Bean tooling container managed persistence (CMP) support for container managed field types

that implement java.io.Serializable.

v CMP Support for DB2e 8.2.1 and Derby 10.0.2

v JDBC DataSource support

v JNDI support

v Container-managed Relationships

The following features are not supported:

v Stateful Session Beans

v Pass-by-Copy semantics for mutable serializable objects when running in a single address space

v For EJB 1.1, the Embedded Transaction Container does not persist references to an EJB’s remote or

remote home interfaces. Note that this capability is not required of EJB 2.1

v Message-driven Beans

v Java Security support

v EJB Query Language

v Home methods

v Select methods

v Bean managed transactions

v Enumeration return type for finders. Collection return type is supported.

v Specification of transaction isolation level

v Support for Collections and Iterators outside of the transactions in which they were created

The programming models for the Embedded Transaction container and WebSphere’s J2EE EJB

server/container are very similar. But, there are differences between the two models, primarily in how

they reduce runtime resource requirements. The development differences are covered in “Developing

Embedded Transaction Container logic” on page 110.

Concepts

The Embedded Transaction Container runtime is based on an extended subset of the EJB 2.1 spec. The

following are descriptions of EJB 2.1 concepts related to the Embedded Transaction Container.

EJB Container: The container provides runtime support for EJB components. This includes handling

such tasks as persistence, transaction scoping and management, database connection management, and

EJB instantiation/caching.

Home Interfaces: These interfaces define the EJB’s life-cycle methods, such as creating, locating, and

removing EJBs.

In the J2EE EJB programming model, there is a need to access data stored locally and/or stored on a

remote server. As a result, there are two types of home interfaces: Local Home Interfaces and (Remote)

Home Interfaces.

While the Embedded Transaction Container only allows access to data stored locally, both Local and

(Remote) Home Interfaces are supported for accessing that data. This provides more affinity with the

J2EE EJB 2.1 programming model. While J2EE EJB implementations recommend using the local home

interface for accessing local data for performance reasons, either local or remote home interfaces can be

used in the Embedded Transaction Container with little (if any) performance differences. Since the

Embedded Transaction Container never allows access to EJBs on other servers, the Embedded Transaction

Container’s (remote) home interface does not have the same overhead of the J2EE EJB’s implementations.

106 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 117: Lotus Expeditor: Developing Applications for Lotus Expeditor

Finder Methods: The home interface must contain a findByPrimaryKey method to locate/return an EJB

based on its primary key. Other finder methods locate/return EJB(s) based on other search criteria.

Note: The Embedded Transaction Container requires that these other finder methods on CMP entity

beans be implemented by subclassing an Embedded Transaction Container specific class,

BaseJBDCFinder.

Component interfaces: From an application programmer’s perspective, these interfaces provide access to

the application data or services on the EJB.

Transaction management: The J2EE EJB programming model provides for three forms of transaction

management:

1. Container managed

2. Bean managed

3. Programmatic managed.

The Embedded Transaction Container provides support 1 and 3. The Embedded Transaction Container

does not support bean managed transaction.

Container managed transactions: As the name implies, when using container managed transactions, the

container is responsible for the beginning, rolling back, and committing of transactions. The container

manages these transaction based on runtime transaction attributes that are defined for the beans. For

example, when calling a session bean method that has specifying “Required” as its runtime transaction

attribute, the container will check to ensure there already is a transactional context. If there is one, it will

continue on. If there isn’t one, a new transactional context will be established before continuing on.

The Embedded Transaction Container supports all the J2EE EJB 2.1 Runtime Transaction Attributes:

v NotSupported – suspends the transaction of the caller (if there is one) until the associated method

completes

v Supports – causes the bean to become part of the caller’s transaction (if there is one)

v Required – causes the bean to become part of the caller’s transaction (if there is one). If the caller is

not part of a transaction, a transaction is created for the life of this method call

v RequiresNew – when the caller is not part of a transaction, the behavior is the same as “Required”. If

the caller is part of a transaction, that transaction is suspended, and a new transaction is setup for the

life of the method call. After the new transaction’s scope ends, the old transaction is resumed.

v Mandatory - causes the bean to become part of the caller’s transaction (if there is one). If there isn’t

one, a TransactionRequiredException is thrown

v Never – if the caller is part of a transaction, a RemoteException is thrown. If the caller is not part of a

transaction, the method is called outside of a transactional scope.

Note: If no runtime transaction attribute is specified for a method, a default value of Required is used.

Programmatic transaction management: Letting the container manage transactions is much simpler than

dealing with the beginning, rollback and committing within the code itself. But, there are cases where the

programmatic approach is worthwhile. One case would be when method calls against several session

beans need to be treated as a transaction. While the Embedded Transaction Container does not provide a

J2EE-compliant Transaction Manager, it does provide a factory for creating user transactions, the

UTFactory. These user transactions provide a programmatic means of managing a transactional context.

DataSource/TxnDataSource: Typically connecting to a relational database is done via a JDBC Data

Source. These data sources are usually retrieved via JNDI.

The Embedded Transaction Container’s implementation of CMP beans uses a TxnDataSource, a subclass

of the JDBC Data Source. This class is defined in an internal package. While this TxnDataSource is

accessible by all via JNDI, it should only be used for CMP beans. Using a TxnDataSource in the

Developing applications 107

Page 118: Lotus Expeditor: Developing Applications for Lotus Expeditor

implementation of BMP beans or Session Beans could lead to a deadlock. So, when implementing BMP

beans or Session Beans that require relational persistence, a standard JBDC Data Source should be used.

Creating Embedded Transaction projects

This section details creating Embedded Transaction projects.

Using a Client Services Embedded Transaction project versus an EJB project

Embedded Transaction applications can be developed using either a Client Services Embedded

Transaction project or an EJB project. The choice of which to use depends on the application content and

its primary usage. In general, applications that primarily target the Lotus Expeditor platform or depend

on other OSGi services besides core Embedded Transaction support should be developed using a Client

Services project.

A Client Services Embedded Transaction project is an extension of the EJB project. Because of this, both

types of projects make use of the Rational Software Development EJB tools. In addition to this, a Client

Services Embedded Transaction project provides the following support for developing an application that

is targeting the Lotus Expeditor platform.

v The manifest file required by Lotus Expeditor application can be automatically managed by the tools.

v The project’s class path is maintained to match the class path environment that will exist in the Lotus

Expeditor runtime. This is useful for detecting class visibility problems at development time rather

than runtime.

An EJB project will not have the Lotus Expeditor specific tooling aids listed above, but can still be tested

and run on the Lotus Expeditor platform. This is accomplished by targeting the project’s server to the

Lotus Expeditor runtime through the project’s server properties. The tooling will automatically add the

proper manifest entries for Embedded Transaction support. However, if the application references other

OSGi services or bundles, the developer will have to manually add these dependencies to the manifest

file.

A Client Services Embedded Transaction project can also be tested and run on a platform other than

Lotus Expeditor by reassigning its targeted runtime through the project server properties. Refer to

“Debugging and testing applications” on page 323 for further general information. Refer to “Debugging

and testing Embedded Transaction applications” on page 120 for Embedded Transaction specific

debugging information.

Creating a Client Services Embedded Transaction project

Complete the following steps to create a new Client Services Embedded Transaction project:

1. Select File > New > Project. Under the Client Services folder, select Client Service Embedded

Transaction Project. The Embedded Transaction Project creation wizard displays.

2. On the first wizard page, specify the following options:

v Project name

v Project location (Default: current workspace)

Select either Finish or Next.

3. If you select Finish, the project will be created with the default project facets:

v EJB Module, 2.1

v Java, 5.0

v Embedded Transaction Bundle, 6.1

v The default Java Source Directory (ejbModule)

v The default Target Definition with Core OSGi, and Embedded Transaction Container service

selected.

108 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 119: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: The actual “service” definitions, which are now “features”, may change based on the new

“target platform” based definitions to be created by the runtime. The tools automatically select

the necessary “features” required for Embedded Transaction Container development.

4. If you selected Next, the Select Project Facets page displays. This page is for selecting facets and to

specify their versions. EJB Module, Java and Embedded Transaction Bundle facets are pre-selected,

and cannot be deselected. Select either Finish or Next.

5. If you selected Next, the EJB Module page displays. Use it to configure EJB module settings, such as

source folder information, and whether or not to create a client JAR. Select either Finish or Next.

6. If you selected Next, the Target Definition page displays. Use it to select target definitions and target

features. Core OSGI and Embedded Transaction Container services are pre-selected, and cannot be

deselected. You can add other Target Features if needed. Select Finish.

Note: Having a very large number of services selected can cause an IOException during deployment.

Do not use the Select All button.

Converting an EJB project to a Client Services Embedded Transaction project

You can convert an existing EJB project into a Client Services Transaction project by using the Convert

Project to Client Services project wizard.

1. Open the Convert Project to Client Services project wizard by selecting File > New > Other... Expand

Client Services, and select Convert Project to Client Services project.

2. The first wizard page contains a list of non-Client Services projects for conversion. Select the EJB

project to be converted. Only one project can be selected for conversion at a time.

3. If desired, select the Copy before creating option. When selected, the project will be copied before

being converted. You must specify the name of the new project copy. The new project copy will be

converted.

4. Selecting Finish assigns the project the default Target Definition with Core OSGi and Embedded

Transaction Container features.

5. If you select Next, the Target Platform page displays. Core OSGi and Embedded Transaction

Container features are pre-selected. If necessary, you may select additional features. Select either Next

or Finish.

6. Select Finish. a pre-conversion test is run, displaying any errors and warnings based on elements of

the existing EJB that may require modification when running against the Lotus Expeditor runtime. If

any errors or warning conditions are found, the user is prompted as to whether the conversion should

continue or be cancelled.

Embedded Transaction Container preferences

You can set Embedded Transaction Container preferences at the workspace level and on a per project

basis. For workspace preferences, select Window > Preferences... > Client Services > Embedded

Transaction. For project preferences, open the project’s pop-up menu and select Properties, then the

Embedded Transaction tab. In both cases, the Embedded Transaction properties page is displayed.

The following preferences are available:

Target database type

You can select either DB2e or Derby. Derby refers to Cloudscape v10 and higher.

ETC logging level

You can select the level of trace information logged to the console during deployment and

subsequent runtime testing. Levels include {fatal, error, warning, info, debug, trace}.

Modify the Embedded Transaction Container preferences and select OK to save, or select Cancel to exit

without saving your changes. The target database type preference can be set at both the workspace and

the project level.

The ETC logging level can be set at the workspace level.

Developing applications 109

Page 120: Lotus Expeditor: Developing Applications for Lotus Expeditor

When the “Use Default” option is selected for a project’s target database type, the value is retrieved from

the workspace’s target database type.

When the “Use Default” option is selected for a workspace’s target database type, “DB2e” is the default

value used.

When the “Use Default” option is selected for a workspace’s logging level, “error” is the default value

used.

Developing Embedded Transaction Container logic

The Embedded Transaction container is targeted for more constrained devices than typical J2EE EJB

servers/containers. While the programming models between the two are very similar, there are aspects

that are unique to Embedded Transaction Container.

The following tasks involve Embedded Transaction specific considerations:

v Implementing Finder Methods

v Configuring and Using Data Sources

v Locating EJBs

v Conserving JDBC Resources

v Working With User Managed Transactions

v Providing Custom Bundle Activation

There are also deployment related differences, such as the introduction of the eejb_deploy.xml file. These

differences are covered in “Packaging and deploying Embedded Transaction applications” on page 119.

Implementing finder methods

The Embedded Transaction Container uses the following approach to implementing custom finder

function. For each finder method declared on the Home interface (other than findByPrimaryKey), you

must provide the business logic required to build the corresponding collection. The tool requires that this

logic be packaged in an abstract finder helper class, which the tool extends as a concrete BaseJDBCFinder

helper class. Typically the business logic is encapsulated in a SQL SELECT statement.

The container provides a base BaseJDBCFinder class, com.ibm.pvc.txncontainer.BaseJDBCFinder, that

provides the bulk of the required finder functionality. By extending this class, you only need to supply

the actual finder logic. For every custom method, findXXX , defined on the Home interface, you must

code a corresponding ejbFindXXX method on the abstract finder helper class. BaseJDBCFinder provide the

methods getTableName() (returns String specifying the database table name) and

getPreparedStatement(String) (returns a PreparedStatement derived from the appropriate DataSource).

Finders can return single items or collections of items.

The following is a sample multi-result finder implementation, which returns a Collection:

public abstract class Customer20JDBCFinder extends BaseJDBCFinder

{

public Customer20JDBCFinder(DataSourceHome arg0, String arg1) {

super(arg0, arg1);

}

public Collection ejbFindByFirstName (String firstName) throws FinderException

{

final String selectSQL = "select * from customer where fname = ?";

PreparedStatement pstmt = null;

try {

pstmt = getPreparedStatement(selectSQL);

pstmt.setString(1, firstName);

110 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 121: Lotus Expeditor: Developing Applications for Lotus Expeditor

}

catch (SQLException e) {

throw new FinderException

("Problem executing Finder: "

+ selectSQL

+ ", Exception = "

+ e.toString());

}

return new BaseJDBCCollection(pstmt, this);

}

The following is a sample single-result finder implementation, which returns a single key:

public abstract class Customer20JDBCFinder extends BaseJDBCFinder

{

public Customer20JDBCFinder(DataSourceHome arg0, String arg1) {

super(arg0, arg1);

}

public Customer20Key ejbFindById (String Id) throws FinderException

{

final String selectSQL = "select id from customer where id = ?";

PreparedStatement pstmt = null;

try {

pstmt = getPreparedStatement(selectSQL);

pstmt.setString(1, Id);

}

catch (SQLException e) {

throw new FinderException

("Finder = "

+ selectSQL

+ ", Exception = "

+ e.toString());

}

return (Customer20Key) singleResultFinder(pstmt, true);

}

In addition to the SQL application logic, you should ensure the following requirements are met:

v Ensure that the finder helper is abstract.

v Ensure that the finder helper extends BaseJDBCFinder

v Code the appropriate two-parameter constructor, and invoke super()

v Collections must be used as the return type for mutli-result finders. An Enumeration return type is not

supported.

The Boolean parameter supplied to the singleResultFinder method determines whether only one object

can match the finder criteria. If true, the container will throw an exception if more than one object

matches; if false, one object will be returned from the result set, however, you will have no way of

determining which object is selected.

Suppose you have an entity bean to which you want to add additional searching/lookup capabilities. For

the purposes of these steps, assume you have an entity bean representing a customer, with the Customer

class representing the remote interface, CustomerBean the actual implementation, and CustomerHome as the

home interface. In order to add additional search methods, you need to do the following:

1. Update the CustomerHome class to define the new method (e.g. findByFirstName (String firstName).

2. Create a new class extending BaseJDBCFinder.

a. The constructor must call super( arg0, arg1 ).

b. You must implement a method ejb<findername>. For our example, therefore, you must implement

the method ejbFindByFirstName( String firstName ).

Developing applications 111

Page 122: Lotus Expeditor: Developing Applications for Lotus Expeditor

c. Use the method getPreparedStatement( sqlstring ) to obtain a statement to execute. The base

class provides the appropriate setup of requesting a connection, etc.

d. For a collection result, return a BaseJDBCCollection object.

e. For a single result finder, return the results of the singleResultFinder( ) method.

Configuring and using data sources

This section provides information on configuring and using data sources.

Creating and binding DataSource instances: Data base vendors provide implementation specific

DataSource classes for connecting to their databases. The Embedded Transaction Container requires a

specific DataSource, TxnDataSource, be used when connecting to the database for CMPs. This specific

DataSource is created via the TxnDataSourceFactory. The TxnDataSource is only used for CMP access to

the database. All other database access should be done using DataSource.

This “wrapping” of the vendor specific DataSource can be done before JNDI binding or after lookup.

Wrapping before JNDI binding is the best practice, since this is done once, as opposed to wrapping after

every lookup.

Note: For information on using JDBC DataSource to access JDBC data bases, refer to “Data access

application development best practices” on page 103.

Advanced topics: While the declarative JNDI means of wrapping and binding is the preferred method,

this can also be handled programmatically, as follows:

import java.util.Hashtable;

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.sql.DataSource;

import com.ibm.db2e.jdbc.DB2eDataSource;

import com.ibm.pvc.txncontainer.TxnDataSourceFactory;

private void createAndBindDataSource() throws NamingException {

// create DB2e specific Datasource object and set it’s jdbc url

DB2eDataSource db2eDS = new DB2eDataSource();

db2eDS.setUrl("jdbc:db2e:" + EJBDB_LOC);

// wrap and bind the vendor specific data source

DataSource ds = TxnDataSourceFactory.create(db2eDS);

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.pvc.jndi.provider.java.InitialContextFactory");

InitialContext context = new InitialContext(env);

context.bind(DATASOURCE_NAME, ds);

}

Where EJBDB_LOC is the physical location of the database, and DATASOURCE_NAME is the JNDI name of the

DataSource.

Locating and connecting to a DataSource: Session beans and client applications typically require a

database connection, and, according to the EJB specification, acquire the DataSource from JNDI in the

same way that it does when finding EJB homes (for more information, refer to “Finding EJB homes” on

page 113. The following sample shows how Session Beans and client applications can acquire a

Connection in the Embedded Transaction Container environment.

import java.sql.Connection;

import javax.sql.DataSource;

import javax.naming.InitialContext;

protected Connection getConnection() throws SQLException

{

DataSource ds = null;

try {

112 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 123: Lotus Expeditor: Developing Applications for Lotus Expeditor

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.pvc.jndi.provider.java.InitialContextFactory");

InitialContext context = new InitialContext(env);

ds = (DataSource) context.lookup(DATASOURCE_NAME);

}

catch (Exception e) {

e.printStackTrace();

throw new IllegalArgumentException("Cannot lookup DataSource:" + e);

}

return ds.getConnection();

}

Where DATASOURCE_NAME is the JNDI name of the DataSource.

Locating EJBs

The EJB deployment descriptor includes information about the EJB’s JNDI binding. As with J2EE EJBs,

the JNDI related values can be set via the Deployment Descriptor editor.

The actual timing of EJB binding is handled by the Expeditor Server JNDI provider and Declarative JNDI.

Finding EJB homes: Client applications perform the following operation to access deployed EJBs:

// Import the JNDI InitialContext class

import javax.naming.InitialContext;

// Name of the Home

final String jndiName = "java:comp/env/EmployeeFromJDBC";

// Get the reference to the Home

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY,

"com.ibm.pvc.jndi.provider.java.InitialContextFactory");

InitialContext context = new InitialContext(env);

final EmployeeHome localHome = (EmployeeHome)context.lookup(jndiName);

Conserving JDBC resources

EJBs provide abstractions that shield the programmer from the technical details of the underlying data

stores. These abstract layers need help managing the underlying data base resources to work within the

constraints of the embedded data base engines. For example, DB2e v8.2 supports a maximum of 20 open

statements. When working with Container Managed Persistence (CMP) Beans, statements may be opened

when a finder method creates a collection and when an iterator is used to walk the contents of that

collection. When an iterator has reached its end, the corresponding statement can be closed. While the

CMP abstraction layer will automatically close statements when it is certain they are no longer needed, it

is up to the application programmer to explicitly dispose of all Collections and Iterators to ensure that the

corresponding statements are closed prior to commit or garbage collection implicitly closing them. When

a program no longer needs a Collection or Iterator, if that object is an instance of IDisposable, the

dispose method should be called on it.

For example:

if (myCollection instanceof IDisposable) {

((IDisposable)myCollection).dispose();

}

Working with user managed transactions

The Embedded Transaction Container provides an implementation of a transaction manager. This

TransactionManager is used for automatically handling transaction management issues.

Note: Unlike a J2EE TranactionManager, the embedded transaction container’s transaction manager does

not provide an implementation of javax.transaction.TransactionManager, nor does it support two

phase commit.

Developing applications 113

Page 124: Lotus Expeditor: Developing Applications for Lotus Expeditor

Advanced topics: Applications generally do not work directly with the transaction manager. For the

advanced cases, the Embedded Transaction Container does provide a User Transaction Factory

(UTFactory) that enables applications to work with user transactions.

The UTFactory provides a static getUserTransaction() method that will return an implementation of the

javax.transaction.UserTransaction interface. This UserTransaction instance is used by developers for

handling typical transaction-related actions:

v begin() – creates a new transaction and associated it with the current thread

v commit() – completes the transaction associated with the current thread

v rollback() – rolls back the transaction associated with the current thread

v setRollbackOnly – after calling this method, a “rollback” is the only possible outcome of the

transaction associated with this thread

v getStatus() – obtains the status of the transaction associated with this thread

v setTransactionTimeout() – is not supported

Providing custom bundle activation

The Embedded Transaction Container tooling creates projects which reference the default bundle

activator, com.ibm.pvc.txncontainer.GenericActivator. This activator registers the EJB’s home interface.

The following information describes how to add a customized bundle activator to the project.

Advanced topics: A custom bundle activator would be required if the application needs to perform

OSGi specific operations. To create a custom bundle activator for an existing project, you can perform the

following steps:

1. Add the custom bundle activator class to the package in which the other EJB classes (home, interface,

implementation, finders) are located.

Note: The custom bundle activator class must extend the

com.ibm.pvc.txncontainer.GenericActivator class and call the start() and stop() methods of

GenericActivator inside its own start() and stop() methods.

2. Open the Bundle Manifest editor on the project’s META-INF/MANIFEST.MF file, and enter the custom

bundle activator class in the Class field of the Overview page. This will update the EJB manifest file

META-INF/MANIFEST.MF, by setting the Bundle-Activator property to the custom bundle activator class.

Custom bundle activator example:

import org.osgi.framework.BundleContext;

import com.ibm.pvc.txncontainer.GenericActivator;

/**

* Minimum bundle activator for EJBs

*/

public class MyBundleActivator extends GenericActivator {

public void start(BundleContext context) throws Exception{

// custom tasks here

super.start(context);

}

public void stop(BundleContext context){

// custom tasks here

super.stop(context);

}

}

Creating Session and Entity Beans

Typically, entity beans are used to model business Target Features. These services usually correspond to

“verbs” in the business domain. There are two types of Session Beans: Stateless and Stateful. The

difference between the two is whether the bean maintains a conversational state with a client. In stateless,

114 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 125: Lotus Expeditor: Developing Applications for Lotus Expeditor

every method call is independent. In stateful, information can be gathered and used for subsequent

method calls. In keeping with the goal of reducing the implementation size, the Embedded Transaction

Container only supports “Stateless”.

Typically, entity beans are used to model business objects that require persisting. These business objects

usually correspond to “nouns” in the business domain. Getters/Setters are used to access the state of

these objects. There are two types of Entity Beans: Bean Managed Persistence (BMP) Beans and Container

Managed Persistence (CMP) Beans. The difference between the two is whether or not the bean

programmer is responsible for implementing the actually storing of the bean’s data. For BMPs, the

programmer is responsible. For CMPs, the container is responsible.

Creating a Container Managed Persistence (CMP) bean: To create a Container Managed Persistence

bean, perform the following procedure:

1. Click File > New > Other > EJB > Enterprise Bean. The Create an Enterprise Bean wizard appears.

Note: Other EJB options, such as “XDoclet Enterprise JavaBean” should not be selected. The

“Enterprise Bean” option must be selected.

2. Select the Entity bean with container-managed persistence (CMP) fields radio button.

3. Select the EJB Component you want to add the bean to.

4. In the Bean name field, type the name you want to assign to the enterprise bean. By convention,

bean names should begin with an uppercase letter.

5. In the Source folder field, select the source folder for the new bean.

6. In the Default package field, enter the package name for the new bean.

7. If you are adding the bean to an EJB 2.0 or later project, in the CMP version drop-down list, select

the EJB specification level that you want to use for the new entity bean.

8. Optional: For EJB 2.x beans, you can select Generate an annotated bean class. If you select this

option, the wizard generates annotations at the beginning of the Java code for the bean class. The

annotations define the bean’s implementation as you specify in the wizard. The annotations are then

used by the EJB tools to generate the necessary bean classes, and to provide values that are inserted

in the EJB deployment descriptor (ejb-jar.xml). Select this option if you are familiar with

annotations and want to use the annotations to update the bean rather than using the deployment

descriptor.

9. Click Next.

10. In the Bean class field, enter the desired package and class name for the bean class. By default, the

wizard suggests a bean class based on the bean name and default package that you defined. A bean

class can be a new class that the wizard generates, or it can be an existing class in the project class

path. Click the Class button to open a dialog that lists the classes in the project that correspond to

the bean type. The name of the bean class appears blue for existing classes with source. The name of

the bean class appears red for existing binary classes.

11. Define the client views and interfaces. For EJB 2.0 or later beans, you can include a remote client

view, a local client view, or both. For EJB 1.1 beans, only a remote client view is supported. Every

session or entity bean must have at least one client view:

v Remote client view: Select this check box to include a remote client view for the session bean.

In the Remote home interface and Remote interface fields, enter the package and class names that

you want to use for the remote client view interfaces. The wizard uses the bean name and default

package to suggest values for the interface package and class names.

v Local client view: Select this check box to include a local client view for the session bean.

In the Local home interface and Local interface fields, enter the package and class names that you

want to use for the local client view interfaces. The wizard uses the bean name and default

package to suggest values for the interface package and class names.12. Optional: In the Key class field, enter the package and class name for the bean’s key class. By

default, the Use the single key attribute type for the key class check box is selected, and the type

Developing applications 115

Page 126: Lotus Expeditor: Developing Applications for Lotus Expeditor

of the key CMP attribute is used as the key class. Use this option if you have a single key attribute

whose type is a valid primary key field (for example, java.lang.Integer). If you include more than

one key attribute, a new compound key class is created. To specify a different key class, deselect the

Use the single key attribute type for the key class check box, and provide the name of the key

class.

13. Optional: Define the CMP attributes for the entity bean.

a. Click the Add button.

b. Specify the Name and Type for the attribute.

c. Optional: If the attribute is an array, select the Array check box. Specify the number of

Dimensions in the array.

d. Optional: Select Key field to make the attribute a key field for the entity bean.

e. Optional: Depending on the client views in your new bean, you can choose to promote the getter

and setter methods for the attribute to the remote and local interfaces.

f. Click Apply to create the attribute. Click Close when you are finished defining attributes.By default, the wizard specifies the following CMP attribute and declares it the key field:

v Name: id

v Type: java.lang.Integer

You can edit or remove this attribute.

Note: A key is required if the bean is not inherited. If a key is not defined, the bean will have

validation errors. After you create the bean, you can use the deployment descriptor editor to

add a key attribute or make an existing attribute the key.

14. Click Next.

15. Optional: In the Bean superclass field, type or select the desired class.

16. Optional: Define any interfaces that you want the remote or local client interfaces to extend:

v Click the Add button to open the Type Selection dialog box where you can select the interface that

you want to extend.

v If you added an interface that you no longer want to extend, select the interface in the list and

click Remove.17. Click Finish. The new entity bean is added to the specified EJB project.

Creating EJB CMP 1.1 beans: When a CMP 1.1 bean is created, its bean class contains code that is

specific to the WebSphere Application Server. This causes the following error in an Embedded Transaction

project: com.ibm.ivj cannot be resolved.

To fix this problem, perform the following editing changes to the CMP 1.1 bean’s Java source file:

v Delete all logic from method _removeLinks()

This will eliminate the project errors, and remove the WAS specific logic from the bean.

You can optionally remove the remaining generated associations logic from the bean as follows:

v Delete methods _initLinks(), _getLinks(), _removeLinks()

v Delete references to _initLinks()

v Delete contents of method ejbRemove()

Creating a stateless session bean: To create a stateless session bean, perform the following procedure:

1. Select File > New > Other > EJB > Enterprise Bean. The Create an Enterprise Bean wizard appears.

Note: Other EJB options, such as “XDoclet Enterprise JavaBean” should not be selected. The

“Enterprise Bean” option must be selected.

2. Select the Session Bean radio button.

116 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 127: Lotus Expeditor: Developing Applications for Lotus Expeditor

3. Select the EJB Component that you want to add the bean to.

4. In the Bean name field, type the name that you want to assign to the enterprise bean.

By convention, bean names should begin with an uppercase letter.

Note: You can use Unicode characters for the bean name, but Unicode characters are not supported

for enterprise bean packages and classes associated with enterprise beans.

5. In the Source folder field, select the source folder for the new bean.

6. In the Default package field, enter the package name for the new bean.

7. Optional: For EJB 2.x beans, you can select Generate an annotated bean class. If you select this

option, the wizard generates annotations at the beginning of the Java code for the bean class. The

annotations define the bean’s implementation as you specify in the wizard. The annotations are then

used by the EJB tools to generate the necessary bean classes, and to provide values that are inserted

in the EJB deployment descriptor (ejb-jar.xml). Select this option if you are familiar with

annotations and want to use the annotations to update the bean rather than using the deployment

descriptor.

8. Click Next.

9. Select Stateless as the session type for the new bean.

10. Select one of the following transaction types for the new bean:

v Container: Specifies that the transaction demarcation is performed by the container.

v Bean: Specifies that the transaction demarcation is performed by the bean.11. In the Bean class field, enter the desired package and class name for the bean class. By default, the

wizard suggests a bean class based on the bean name and default package that you defined. A bean

class can be a new class that the wizard generates, or it can be an existing class in the project class

path. Click the Class button to open a dialog that lists the classes in the project that correspond to

the bean type. The name of the bean class appears blue for existing classes with source. The name of

the bean class appears red for existing binary classes.

12. Define the client views and interfaces. For EJB 2.0 or later beans, you can include a remote client

view, a local client view, or both. For EJB 1.1 beans, only a remote client view is supported. Every

session or entity bean must have at least one client view:

v Remote client view: Select this check box to include a remote client view for the session bean. In

the Remote home interface and Remote interface fields, enter the package and class names that

you want to use for the remote client view interfaces. The wizard uses the bean name and default

package to suggest values for the interface package and class names.

v Local client view: Select this check box to include a local client view for the session bean. In the

Local home interface and Local interface fields, enter the package and class names that you want

to use for the local client view interfaces. The wizard uses the bean name and default package to

suggest values for the interface package and class names.13. Click Next.

14. Optional: In the Bean superclass field, type or select the desired class.

15. Optional: Define any interfaces that you want the remote or local client interfaces to extend:

v Click the Add button to open the Type Selection dialog box where you can select the interface that

you want to extend.

v If you added an interface that you no longer want to extend, select the interface in the list and

click Remove.16. Click Finish. The new session bean is added to the specified EJB project.

Creating a Bean Managed Persistence (BMP) bean: To create a Bean Managed Persistence bean,

perform the following procedure:

1. Click File > New > Other > EJB > Enterprise Bean. The Create an Enterprise Bean wizard appears.

Developing applications 117

Page 128: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: Other EJB options, such as “XDoclet Enterprise JavaBean” should not be selected. The

“Enterprise Bean” option must be selected.

2. Select the Entity bean with bean-managed persistence (BMP) fields radio button.

3. Select the EJB Component that you want to add the bean to.

4. In the Bean name field, type the name that you want to assign to the enterprise bean. By convention,

bean names should begin with an uppercase letter.

5. In the Source folder field, select the source folder for the new bean.

6. In the Default package field, enter the package name for the new bean.

7. Optional: For EJB 2.x beans, you can select Generate an annotated bean class. If you select this

option, the wizard generates annotations at the beginning of the Java code for the bean class. The

annotations define the bean’s implementation as you specify in the wizard. The annotations are then

used by the EJB tools to generate the necessary bean classes, and to provide values that are inserted

in the EJB deployment descriptor (ejb-jar.xml). Select this option if you are familiar with

annotations and want to use the annotations to update the bean rather than using the deployment

descriptor.

8. Click Next.

9. In the Bean class field, enter the desired package and class name for the bean class. By default, the

wizard suggests a bean class based on the bean name and default package that you defined. A bean

class can be a new class that the wizard generates, or it can be an existing class in the project class

path. Click the Class button to open a dialog that lists the classes in the project that correspond to

the bean type. The name of the bean class appears blue for existing classes with source. The name of

the bean class appears red for existing binary classes.

10. Define the client views and interfaces. For EJB 2.0 or later beans, you can include a remote client

view, a local client view, or both. For EJB 1.1 beans, only a remote client view is supported. Every

session or entity bean must have at least one client view:

v Remote client view: Select this check box to include a remote client view for the session bean. In

the Remote home interface and Remote interface fields, enter the package and class names that

you want to use for the remote client view interfaces. The wizard uses the bean name and default

package to suggest values for the interface package and class names.

v Local client view: Select this check box to include a local client view for the session bean. In the

Local home interface and Local interface fields, enter the package and class names that you want

to use for the local client view interfaces. The wizard uses the bean name and default package to

suggest values for the interface package and class names.11. In the Key class field, enter the desired package name and class for the entity bean’s key class. By

default, the wizard suggests a class name and package based on the bean name and default package

that you defined. A bean class can be a new class that the wizard generates, or it can be an existing

class in the project class path. Click the Class button to open a dialog that lists the classes in the

project that correspond to the bean type. The name of the bean class appears blue for existing classes

with source. The name of the bean class appears red for existing binary classes.

12. Click Next.

13. Optional: In the Bean superclass field, type or select the desired class.

14. Optional: Define any interfaces that you want the remote or local client interfaces to extend:

v Click the Add button to open the Type Selection dialog box where you can select the interface that

you want to extend.

v If you added an interface that you no longer want to extend, select the interface in the list and

click Remove.15. Click Finish. The new entity bean is added to the specified EJB project.

Customizing for target data base (DB2e and Derby)

Different code is generated based on what data base support is available on the platform to which the

EJB will be deployed.

118 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 129: Lotus Expeditor: Developing Applications for Lotus Expeditor

The project’s Embedded Transaction preferences can be used to specify the target data base to be used

when deploying. If the Use Default option is specified for the project, the workspace’s Embedded

Transaction preferences are used. Otherwise if Use Default is specified for the workspace, “DB2e” is the

defaulted value for the target data base.

Packaging and deploying Embedded Transaction applications

Embedded Transaction applications require a deployment step before they can be run. This is analogous

to the deployment step performed on an Enterprise Java Bean (EJB), and should not be confused with the

concept of deploying a bundle to the runtime (which involves methods of packaging and delivering the

bundle to the runtime). Embedded Transaction deployment involves specifying the proper deployment

information in deployment descriptors, and subsequently performing a deployment operation which

performs the necessary transformations on the project to enable it to be run by the Embedded Transaction

container.

Embedded Transaction applications require additional deployment information beyond that typically

provided when deploying an EJB. The standard EJB deployment descriptor, ejb-jar.xml , will still contain

proper deployment information. The Rational Software Development tools automatically manage this in

many cases, and provide an EJB Deployment Descriptor editor. For more information, refer to the EJB

Deployment Descriptor section of the Rational help. Refer to “Embedded Transaction Deployment

Descriptor” for the additional deployment information you must add for Embedded Transaction

applications, and “Embedded Transaction Deployment Editor” on page 120 for information on using the

editor to update this information.

Once the proper deployment information is specified, a deployment operation can be carried out to

enable the application to be run. “Invoking deployment”describes how and when the deployment

operation is carried out.

Invoking deployment

Deployment is automatically run whenever an Embedded Transaction project is selected to be run on a

Expeditor Server runtime that is launched through the tools. Refer to “Debugging and testing

applications” on page 323 for information on launching Lotus Expeditor runtimes through the tools.

Embedded Transaction Deployment Descriptor

The Embedded Transaction Container Tooling plug-in auto-generates the XML deployment file

(eejb_deploy.xml). This XML deployment file contains the custom deployment information required to

deploy the EJB. The information provided in the deployment file supplements the information already

included in the EJB deployment descriptor (ejb-jar.xml). To deploy the embedded EJB, you must supply

this information as an XML file that conforms to the schema file eejb-deployment.xsd, which is shipped

with the tooling. Information included in that file is as follows:

jndi-name

The name through which the deployed Home is accessed via the naming service (e.g., JNDI). It is

not assumed that the Home will be bound to a java:/comp/env/ejb Context, so the name

supplied in the deployment information is used exactly “as is”. Required for both session and

entity beans that use a (remote) home interface.

jndi-local-name

The name through which the deployed Home is accessed via the naming service (e.g., JNDI). It is

not assumed that the Local Home will be bound to a java:/comp/env/ejb Context, so the name

supplied in the deployment information is used exactly ″as is″. Required for both session and

entity beans that use a (local) home interface.

jdbc-bean

Supplies the information needed to deploy an entity bean to the Embedded Transaction Container

using a JDBC-based DataSource. In this element, the user specifies the name of the

Developing applications 119

Page 130: Lotus Expeditor: Developing Applications for Lotus Expeditor

abstract-finder-helper class that the user has supplied for the EJB, and also specifies the name

of the deployed finder-helper class that the tooling will generate. Required by container managed

persistence (CMP) entity beans only.

datasource-name

Specifies the name through which the TxnDataSource providing a connection to the data store

can be accessed from the naming service. Required by entity beans only.

table-name

Specifies the name of the relational database table that provides persistence for the

container-managed persistence (CMP) entity bean. This element is not required by bean-managed

persistence (BMP) entity beans.

deployed-class

Specifies the name of the deployed bean implementation class. Required for both session and

entity beans.

ejbivar

Specifies the name of the table column that provides persistence for the entity beans fields.

cmp-field

The name of the entity bean field to be persisted. The value of this field should match the value

specified in the EJB deployment descriptor, ejb-jar.xml.

Note: You must fill in the missing eejb_deploy.xml information for entity beans. No update to the

deployment file is necessary for stateless session beans.

Embedded Transaction Deployment Editor

Information in the “Embedded Transaction Deployment Descriptor” on page 119 can be managed through

the Embedded Transaction Deployment Editor. This editor can be opened as follows:

1. Locate the project’s Embedded Transaction Deployment descriptor file in the Explorer view. This is

file eejb_deploy.xml in the project’s source folder’s %SourceFolder%/META-INF folder.

2. Open the deployment descriptor by double clicking it, or right clicking and selecting Open. The

Embedded Transaction Deployment editor displays.

The editor will display all of the project’s defined beans in the Beans view. Select a bean from the Beans

view, and its associated Embedded Transaction deployment information will display on the right hand

side for editing.

Debugging and testing Embedded Transaction applications

This section includes Embedded Transaction Container specific debugging information.

For general debugging information, refer to “Debugging and testing applications” on page 323.

Enabling logging and tracing with the Embedded Transaction Container

Embedded Transaction Container logging enables a developer to associate logged messages with one of

six logging levels: fatal, error, warning, info, debug, and trace. These logging levels are ordered in

decreasing severity. Enabling a given log level implies that all log messages associated with that level, or

a higher log level, should be logged. Messages associated with a lower log level are ignored.

The value specified in the workspace’s Logging Level in the Embedded Transaction preferences is used

when deployment/testing is launched from the tooling. The logged messages are sent to the console.

The default logging configuration for the Embedded Transaction Container in the runtime is to log errors

using the OSGi LogService. To change the level of information being sent to that service, add the

following options to the VM arguments in the rcpinstall.properties file:

-Deejb.logging.priority.com=debug

-Deejb.logging.logwriters=com.ibm.pvc.txncontainer.internal.osgi.logger.OSGiLogWriter=debug

120 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 131: Lotus Expeditor: Developing Applications for Lotus Expeditor

This will turn on ″debug″ for all components of the Embedded Transaction Container.

Changing “debug” to “fatal”, “error”, “warning”, “info” or “trace” in the VM arguments will set the

logging level accordingly.

By default, the platform is configured to only persist error and warning messages. To change this level

for the Embedded Transaction Container in the runtime, add the following line to the

rcpinstall.properties file:

com.ibm.pvc.txncontainer.common.level=FINEST

Where FINEST would be the desired level.

For information on setting VM arguments when launching the runtime, refer to Configuring the platform

launcher.

For more information on platform logging, refer to Configuring platform logging and tracing

Run or debug Client Services Embedded Transaction Container projects using the

Client Services launcher

To run or debug a Client Services Embedded Transaction Container project from your workspace using

the Lotus Expeditor launcher, perform the following procedure:

1. Open the Run or Debug launcher by selecting Run > Run... (or Run > Debug...)

2. Select the Lotus Expeditor configuration type, and click New to create a new Lotus Expeditor launch

configuration.

3. Open to Plug-ins tab, and ensure the Embedded Transaction Container project to be tested is selected.

4. Select Run (or Debug).

5. Embedded Transaction Container deployment is performed on the Embedded Transaction Container

projects being run / debugged.

6. The Lotus Expeditor runtime is launched with the selected Client Services projects.

Run or debug a Client Services Embedded Transaction Container project on the

Lotus Expeditor runtime

To run or Debug Client Services Embedded Transaction Container projects from your workspace using a

“Run on Server” launch style on the Lotus Expeditor runtime, perform the following procedure:

1. Open the J2EE Perspective by selecting Window > Open Perspective > J2EE.

2. From the project Explorer view, select the project to be tested under Dynamic Web Projects folder

3. Right click the project to open the pop-up menu, and select Run As > Run on server...

4. Choose a Lotus Expeditor server if one exists, and click Next. If one does not exist, define a Lotus

Expeditor server:

a. Select IBM >Lotus Expeditor v6.1 as the server type. Click Next.

b. Choose a target definition and features, and click Next.5. Add or remove other projects that are configured on the server to test multiple projects.

6. Select the Finish button to launch.

7. Embedded Transaction Container deployment is performed on the Embedded Transaction Container

projects being run or debugged.

8. The Lotus Expeditor runtime is launched with the selected Client Services projects.

Run or debug a non-Client Services EJB project on the Lotus Expeditor runtime

To run or debug non-Client Services EJB projects from your workspace using a “Run on Server” launch

style on the Lotus Expeditor runtime, perform the following procedure:

1. You must update the project’s manifest file manually to add dependencies to Import-package or

Require-Bundle entries. Since the project is a non-Client Services project, it does not have the support

Developing applications 121

Page 132: Lotus Expeditor: Developing Applications for Lotus Expeditor

from Lotus Expeditor Toolkit to automatically manage the dependencies. Also, a default Embedded

Transaction deployment descriptor will be added to the project, if one does not exist.

2. Open the J2EE Perspective by selecting Window > Open Perspective > J2EE.

3. From the project Explorer view, select the (non-Client Services) EJB project to be tested.

4. Right click the project to open the pop-up menu, and select Run As > Run on server...

5. Choose a Lotus Expeditor server if one exists, and click Next. If one does not exist, define a Lotus

Expeditor server:

a. Select IBM > Lotus Expeditor v6.1 as the server type, and click Next.

b. Choose a target definition and features, and click Next. 6. Add or remove other projects that are configured on the server to test multiple projects.

7. Select the Finish button to launch.

8. EJB projects that are now targeted to the Lotus Expeditor runtime will be re-built. This will invoke

the Embedded Transaction Container validation logic, catching and tagging errors related to

unsupported function.

9. Embedded Transaction Container deployment is performed on the Embedded Transaction Container

projects being run or debugged.

10. The Lotus Expeditor runtime is launched with the selected Client Services projects.

Run or debug a Client Services Embedded Transaction Container project on a

non-Lotus Expeditor runtime

To run or debug Client Services Embedded Transaction Container projects from your workspace using a

“Run on Server” launch style on a non-Lotus Expeditor runtime, perform the following procedure:

1. Open the J2EE Perspective by selecting Window > Open Perspective > J2EE.

2. From the project Explorer view, select a project to be tested.

3. Right click the project to open the pop-up menu, and select Run As > Run on server...

4. Choose a non-Lotus Expeditor server if one exists, and click Next. If one does not exist, define a

non-Lotus Expeditor server:

a. Choose a server type, and click Next.

b. Specify the server settings depending on the server type selected. Potentially, there could be

multiple setup panels.5. Add or remove other projects that are configured on the server to test multiple projects.

6. Select the Finish button to launch.

Setting breakpoints on generated code

When setting breakpoints on generated code, you should open the corresponding class file from the

deployed-ejb.jar library. The editor will display the associated source, and you can set breakpoints.

Setting breakpoints on the Java files in the generated-source folder will not work, as this is not a project

source folder.

Developing management applications

This section provides information on management application development.

Developing applications to drive the Enterprise Management Agent

The Enterprise Management Agent enables a DM Server to manage a Lotus Expeditor client. It provides

the ability to perform software management (install, uninstall), update agent preferences, update

Configuration Admin information and retrieve hardware and software inventory. The Enterprise

Management Agent offers APIs for developers to drive the agent, access account information and update

agent preferences.

122 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 133: Lotus Expeditor: Developing Applications for Lotus Expeditor

Accessing the OSGiAgentService object

The OSGiAgentService class provides access to all the Enterprise agent related APIs.

com.ibm.pvc.osgiagent.core.OSGiAgentServiceFactory can be used to access the OSGiAgentService

Object.

The following sample code gets the OSGiAgentService object:

OSGiAgentService osgiAgentService = new com.ibm.pvc.osgiagent.core.

OSGiAgentServiceFactory().getAgentServiceObject();

The OSGiAgentService class provides APIs to:

v Add and modify SyncML Accounts

v Connect to the server

v Get the list of available software

v Modify polling properties

The following code creates a SampleAccount in the Agents managed SyncML tree:

OSGiAgentService OsgiAgentService = new com.ibm.pvc.osgiagent.core.

OSGiAgentServiceFactory().getAgentServiceObject();

Hashtable props = new Hashtable()

props.put(OSGiAgentConstants.keyAccountID, “SampleAccount”);

props.put(OSGiAgentConstants.keyUserName,”client1”);

props.put(OSGiAgentConstnats.keyClientPW,”Clientpw”);

props.put(OSGiAgentConstants.keyAddr,”http://sampleDMSServer/

dmserver/OMADMServletAuthRequired”);

OsgiAgentService.addAccount(“SampleAccount”,props);

The com.ibm.osg.service.osgiagent plug-in is required to access the OSGiAgentService.

Please refer to the Javadoc for com.ibm.pvc.osgiagent.core.OSGiAgentService and

com.ibm.pvc.osgiagent.core.OSGiAgentServiceFactory for more information.

Developing Enterprise Management Agent SyncML tree extensions

This section details developing Enterprise Management Agent SyncML tree extensions.

SyncML tree extensions overview

Applications can create, access and manage nodes within the SyncML tree which are managed by the

Enterprise Management Agent. An application can create SyncML Nodes so that it can be managed

remotely from a SyncML DM Server. Applications can request and access nodes by contributing

extensions to the tree within the application’s plug-ins. The Enterprise Management Agent gives the

ability to:

v Extend and manage a sub-node of the tree

v Register for a specific command for ./OSGi/Execute/exec SyncML leaf

Creating an Extension to the SyncML Tree

The com.ibm.osg.service.osgiagent plug-in provides the OSGiAgentTreeSyncmlNode extension point

which can be used to extend the SyncML tree and manage the new subtree. The extension must

implement the OSGiAgentSyncmlNodeExtension interface. The Enterprise Management Agent will read the

extension and create a node in the tree with the path provided in the nodeName attribute. It will then pass

the node back to the extension by instantiating the class provided by the attribute “class”. The plug-in

can create nodes and leaves within that node . For example, a plug-in that wants to extend the tree with

a new node called ./myplugin/newNode will define the following extension in its plugin.xml file:

<extension

point="com.ibm.osg.service.osgiagent.OSGiAgentTreeSyncmlNode">

<SyncmlSubtree

class="com.ibm.myplugin.MyNodesManager"

nodeName=" ./myApplication/permissions"

Developing applications 123

Page 134: Lotus Expeditor: Developing Applications for Lotus Expeditor

/>

</extension>

MyNodesManager:

public class MyNodesManager implements OSGiAgentSyncmlNodeExtension{

/* (non-Javadoc)

* @see com.ibm.pvc.osgiagent.syncml.extensions.OSGiAgentSyncmlNodeExtension#

manageSyncmlNode(com.ibm.syncml4j.dm.AbstractInterior)

*/

public void manageSyncmlNode(AbstractInterior subtree) {

AccessControlList acl = new AccessControlList();

acl.allowAll(AccessControlList.ADD);

acl.allowAll(AccessControlList.GET);

acl.allowAll(AccessControlList.REPLACE);

// This will create a new leaf ./myplugin/newNode/newLeaf

new Leaf((AbstractInterior)subtree,acl,null,"ModifyAppInfo" ,"Leaf which

indicates whether the client has authority to modify

the application

information",OSGiAgentConstants.textplain,

Meta.FORMAT_CHR,"yes",null);

}

}

From the above code, Enterprise agent creates the ./myplugin/newNode node, and MyNodesManager object

creates newLeaf leaf. If a different application registers the same node, then the class does not get

instantiated and the error CWPOA0039W is logged in the client logs.

Creating an Extension to register the command for Exec Leaf

The OSGiAgentTreeExecCmd extension point can be used for plug-ins that want to be called upon to

receive a particular command from the SyncML server. The main difference between

OSGiAgentTreeSyncmlNode and OSGiAgentTreeExecCmd is that in the OSGiAgentTreeSyncmlNode extension

point, the plug-in needs to know the SyncML classes and implement the set and get methods to get the

values of the sub-trees. On the other hand, the OSGiAgentTreeExecCmd extension point will get called

straight away if the server calls a particular command that the extension registers. The server calls the

command by setting the value of the command in the ./OSGi/Execute/exec leaf. The extension needs to

implement the OSGiAgentSyncmlCommand interface. For example, a plug-in that wants to be notified when a

dir command is sent from the server will define the following extension in its plugin.xml file:

<extension

point="com.ibm.osg.service.osgiagent.OSGiAgentTreeExecCmd">

<SyncmlCommand

CommandName="dir"

class="com.ibm.pvc.samples.osgiagent.syncmlcommand.exploiter.DirClass"/>

</extension>

DirClass:

public class DirClass implements OSGiAgentSyncmlCommand{

/* (non-Javadoc)

* @see com.ibm.pvc.osgiagent.syncml.extensions.OSGiAgentSyncmlCommand#

* commandCalled(java.lang.String[])

*/

public Hashtable commandCalled(String[] args) {

System.out.println("Dir got called from the server. The following

arguments were passed");

for (int i=0;i<args.length;i++)

{

System.out.println("Argument "+i+" = "+args[i]);

}

System.out.println("returning AOK as a standard out");

Hashtable h = new Hashtable();

124 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 135: Lotus Expeditor: Developing Applications for Lotus Expeditor

h.put(OSGiAgentSyncmlCommand.stdout, "file1 \n file2");

h.put(OSGiAgentSyncmlCommand.exitValue,"0");

return h;

}

The following plug-ins are required to access the Agent and Syncml Classes:

v com.ibm.osg.service.osgiagentc

v com.ibm.syncml4j

v com.ibm.syncml4j.dm

Please refer to com.ibm.pvc.osgiagent.syncml.extensions.OSGiAgentSyncmlCommand and

com.ibm.pvc.osgiagent.syncml.extensions.OSGiAgentSyncmlNodeExtension Javadoc and

com.ibm.osg.service.osgiagent.OSGiAgentTreeExecCmd and

com.ibm.osg.service.osgiagent.OSGiAgentTreeSyncmlNode extension point schema documentation for

more information.

For more information on SyncML, refer to “SyncML” on page 230.

Developing update manager applications

Lotus Expeditor for Devices provides the same application management API as Lotus Expeditor for

Desktop.

Developing messaging applications

Lotus Expeditor provides both enterprise class messaging through the Java Message Service (JMS), and

embedded messaging using WebSphere MQ Everyplace (MQe) and micro broker with the MQ Telemetry

Transport (MQTT) Java client APIs. MQe provides a point-to-point JMS provider, while the micro broker

with MQTT JMS provides a publish and subscribe JMS provider which enables Java developers to

leverage the JMS APIs to send and receive messages from the Lotus Expeditor runtime.

Understanding messaging applications

Messaging is intended to enable a wide variety of computers to exchange information. One of the main

benefits of messaging is to ’decouple’ a sending application from a receiving application. This decoupling

provides a very powerful abstraction, enabling the exchange of information to be independent of

manufacturer, application, operating system or connectivity reliability.

Traditionally, messaging is between large computers and a server. However, with the advent of Java

messaging implementations, now a new class of device interoperates with the messaging infrastructure.

This provides opportunities for an enterprise to broaden the reach of its networks.

Along with the transmission of simple messages, messaging is useful for transactional updates, or where

intermediate data updates or data ordering is required. Messages containing the complete update can be

sent to a server, where transaction managers can coordinate the update of multiple resources. Messaging

can also be paired with synchronization technology, such that transactions are sent by messages, and the

resulting database updates distributed back to the client through synchronization.

Messaging also can be used effectively in a disconnected environment (areas where connectivity is not

reliable), since a local queue manager is available to contain messages until the connection to the server

infrastructure is reestablished. After the connection is available, the queued messages are transferred to

the messaging server for further action.

Messaging, irrespective of the particular product or product group, is separated into two main categories:

v Point-to-point messaging

v Publish and Subscribe messaging

Developing applications 125

Page 136: Lotus Expeditor: Developing Applications for Lotus Expeditor

To take full advantage of the messaging capabilities of Lotus Expeditor, it is crucial to understand the

differences in these two messaging types.

Publish and subscribe messaging

Publish and subscribe is a style of messaging in which applications (subscribers) register interest in a

particular subject of interest (known as a topic) with an intermediary (a broker) that matches those

applications to messages sent by other applications (publishers) to the same subject of interest.

A single message sent by a publisher may be matched and sent to many subscribers. In publish and

subscribe messaging, one application can be both a publisher and subscriber to the broker. This

messaging style is of particular benefit when multiple components in a system need to receive

notification of a given event. For example, a temperature sensor may have many different systems

monitoring it for different reasons. The broker decouples the publisher from the subscribers and gives

flexibility for the adding or removal of publishers or subscribers without needing to perform application

specific integration between each component.

The following figure shows a simple publish and subscribe application that includes one publisher, one

broker, and three subscribers. A publication is sent from the publisher to the broker; a subscription is sent

from the subscriber to the broker; and the publication is then sent from the broker to the subscriber.

126 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 137: Lotus Expeditor: Developing Applications for Lotus Expeditor

A typical publish and subscribe application has more than one publisher, more than one subscriber, and

often more than one broker. An application can be both a publisher and a subscriber.

The publisher generates a message that it wants to publish and defines the topic of the message. This

message is sent to the broker that matches the message to the subscribers that have registered an interest

in the topic.

A subscriber registers a request for a publication by specifying the topic or topics that it is interested in.

Each message has a header and a body. The body contains the message content. The header, which is

similar to the subject field of an e-mail, describes the content of the message.

Related concepts

“Topics and hierarchical topic names” on page 128

“Publication and subscription messages” on page 130

Figure 4. A simple publish and subscribe application

Developing applications 127

Page 138: Lotus Expeditor: Developing Applications for Lotus Expeditor

Topics and hierarchical topic names: A topic is a character string that describes the data that is

published in a publish and subscribe system.

Topics are created in the broker when a client sends a request to subscribe or publish a message to a

given topic. For example, when a client subscribes to topic, that topic’s hierarchy is in place within the

broker because a client is subscribed to it and will receive any matching publications. It is not necessary

for a client to create topics as a specific step independently of these requests.

Topics are key to the successful delivery of messages in a publish and subscribe system. Instead of

including a specific destination address in each message, a publisher assigns a topic to the message. The

message broker matches the topic with a list of clients (subscribers) who have subscribed to that topic,

and delivers the message to each of those clients.

Note that a publisher can control which subscribers can receive a publication by choosing carefully the

topic that is specified in the message.

Only single byte (non-extended) characters are supported. However, there are three characters that have

special meanings. These characters (″/″, ″#″, and ″+″) are described in “Special topic characters” on page

129.

What is a topic tree

Although you can use any name for a topic, it is best to choose a name that fits into a hierarchical tree

structure. Thoughtfully designing topic names and topic trees facilitates these tasks:

v Subscribing to multiple topics

v Reacting automatically to messages about a specific topic, for example, by sending an alert to a

manager’s pager

Although you can construct a topic tree as a flat, linear structure, it is better to build a topic tree in a

hierarchical structure with one or more root topics. The following figure shows an example of a topic tree

with one root topic:

Each character string in the figure represents a node in the topic tree. A complete topic name is created

by concatenating the character strings from multiple levels of the tree. Use a forward slash (/) to separate

each part of a hierarchical name. For example, these are the topics from the tree shown in Figure 5:

Figure 5. Hierarchical topic tree

128 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 139: Lotus Expeditor: Developing Applications for Lotus Expeditor

finance

finance/stock

finance/stock/ibm

finance/stock/xyz

finance/stock/ibm/closingprice

finance/stock/ibm/currentprice

finance/stock/xyz/closingprice

finance/stock/xyz/currentprice

When you design a topic tree, remember that the broker cannot interpret or derive meaning from the

topic name. The broker uses the topic name to identify which messages to send (those that match the

subscription).

Special topic characters

A topic string can only include single byte (non-extended) characters. The topic level separator is used to

introduce structure into the topic, and can therefore be specified within the topic for that purpose. The

multi-level wildcard and single-level wildcard can be used for subscriptions, but they cannot be used

within a topic by the publisher of a message.

Topic level separator

The forward slash (/) is used to separate each level within a topic tree and provide a hierarchical

structure to the topic space. The use of the topic level separator is significant when the two

wildcard characters are encountered in topics specified by subscribers.

Multi-level wildcard

The number sign (#) is a wildcard character that matches any number of levels within a topic. For

example, if you subscribe to finance/stock/ibm/#, you receive messages on these topics:

finance/stock/ibm

finance/stock/ibm/closingprice

finance/stock/ibm/currentprice

The multi-level wildcard can represent zero or more levels. Therefore, finance/# can also match the

singular finance, where # represents zero levels. The topic level separator is meaningless in this

context, because there are no levels to separate.

The multi-level wildcard can be specified only on its own or next to the topic level separator

character. Therefore, # and finance/# are both valid, but finance# is not valid. The multi-level

wildcard must be the last character used within the topic tree. For example, finance/# is valid but

finance/#/closingprice is not valid.

Single-level wildcard

The plus sign (+) is a wildcard character that matches only one topic level. For example,

finance/stock/+ matches finance/stock/ibm and finance/stock/xyz, but not finance/stock/ibm/closingprice.

Also, because the single-level wildcard matches only a single level, finance/+ does not match

finance.

Use the single-level wildcard at any level in the topic tree, and in conjunction with the multilevel

wildcard. Specify the single-level wildcard next to the topic level separator, except when it is

specified on its own. Therefore, + and finance/+ are both valid, but finance+ is not valid. The

single-level wildcard can be used at the end of the topic tree or within the topic tree. For

example, finance/+ and finance/+/ibm are both valid.

Topic semantics and usage

When you build an application, the design of the topic tree should take into account the following

principles of topic name syntax and semantics:

v A topic must be at least one character long.

Developing applications 129

Page 140: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Topic names are case sensitive. For example, ACCOUNTS and Accounts are two different topics.

v Topic names can include the space character. For example, Accounts payable is a valid topic.

v A leading ″/″ creates a distinct topic. For example, /finance is different from finance. /finance matches

″+/+″ and ″/+″, but not “+”.

v Do not include the null character (Unicode \x0000) in any topic.

v Only single-byte (non-extended) characters are supported in topic names.

The following principles apply to the construction and content of a topic tree:

v The length is limited to 64k but within that there are no limits to the number of levels in a topic tree.

v There can be any number of root nodes; that is, there can be any number of topic trees.

Publication and subscription messages: This section describes terms that you should be familiar with

for developing publish and subscribe applications. For more information about the role of the broker in

publish and subscribe messaging, see “Understanding the micro broker components” on page 135.

What is a publisher?

A publisher is a client application that creates a publication message, associates it with a topic, and sends

the message into the broker. The broker is responsible for distributing the message to all applications

subscribed to the topic.

What is a publication?

A publication is a message that is associated with a particular topic. A client application publishes a

publication to the broker. The broker then matches the publication against all applications that have

subscribed to the topic and distributes the publication to those applications.

The broker also distributes the publication to all connected and networked brokers that have subscribers

for the publication. The network can include any applications that can connect to the broker, such as

WebSphere MQ and WebSphere Message Broker.

Retained publications

In general, after sending a publication to subscribers, the broker deletes it. However, the publisher can

request that the broker keep a copy of the publication, which is then called a retained publication. Then the

broker remembers the last message that was published on the retained topic.

The advantage of retained publications is that applications subscribing to the topic will immediately

receive the retained publication and do not have to wait until a publishing application publishes the next

message. This allows the application to initialize itself immediately.

What is a subscriber?

A subscriber is a client application that requests to receive messages published on a specific set of topics.

The application sends a subscription message to the broker specifying the topics in which it is interested.

The broker then sends publication messages to the subscribing application whenever a publication

matching the set of client topics is processed. When the application no longer wants to receive

publications, it can unsubscribe from topics to which it previously subscribed.

A publish and subscribe messaging topology is a flexible topology that allows applications to be added

and removed without impacting other applications. For example, you can add new applications to

subscribe to particular topics. When you add a new subscribing application, you do not need to modify

the publishing application to know that an additional subscriber has been added. Similarly, you can add

new applications to publish on particular topics, without the need for subscribing applications to be

modified to be made aware of this. The topic name and the format of the data in the message have to be

130 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 141: Lotus Expeditor: Developing Applications for Lotus Expeditor

well defined, as these are the common pieces of information shared between a publishing and

subscribing application. Once you have done so, you can add or remove applications to publish or

subscribe as required.

Table 4. Example topologies

Topology type Description

One publisher to many subscribers One publishing application is generating publications

that are used by many subscribing applications. An

example is an application that publishes stock prices.

Many applications might subscribe for this information,

including brokers, Web sites, portfolios and many other

applications.

Many publishers to one subscriber The subscribing application is aggregating information

from different sources together to make a decision. An

example is a weather forecasting application which needs

to receive information from air pressure sensors, wind

speed sensors, humidity sensors, and temperature

sensors to make an accurate forecast.

Many publishers to many subscribers An example of this topology is an extension of the

weather forecasting example above. Here, multiple

forecasting simulations might be running in parallel.

Each simulation is a subscribing application aggregating

data from all the publishing applications.

When subscribing, either an absolute topic name or a topic name with wildcard characters can be used.

See “Topics and hierarchical topic names” on page 128 for more information about topic names.

When a publisher sends a message that has multiple subscribers, the broker sends a copy of the message

to each subscriber. Once a system has been deployed, new applications can be added at a later date

without having to change the applications already deployed. The new applications simply subscribe to

the existing topics set.

What is a subscription?

A subscription is created by the subscriber to define a set of publications that the subscriber should

receive from the broker. A subscription in its simplest form consists of one or more topics.

Some clients also allow additional filtering to be performed based on properties associated with the

publication. Publication property filtering is achieved using SQL syntax, so a subscriber would only

receive a matching publication if the subscription topic matched the publication topic and the SQL query

of the publication properties returned a true result. The SQL filter associated with a subscription is

referred to as the selector.

An application can create multiple subscriptions if required.

An example use of properties in subscriptions would be an application that is only interested when a

stock price rises above a certain value. Suppose the current stock price is published on topic

finance/stock/ibm/currentprice and the publication also contains a property called CURRENT_PRICE.

The subscribing application would subscribe to topic finance/stock/ibm/currentprice and specify a

selector of ’CURRENT_PRICE > 90’. This would ensure that while the stock price was below or $90, the

subscriber would not receive any publications.

Select from two types of subscriptions available to applications:

Non-durable subscriptions

A non-durable subscription is one whose lifetime is limited to the duration of the connection

Developing applications 131

Page 142: Lotus Expeditor: Developing Applications for Lotus Expeditor

between the subscribing application and the broker. A non-durable subscription is removed from

the broker when the application disconnects or when the application explicitly unsubscribes.

Durable subscriptions

A durable subscription is one whose lifetime is beyond the duration of the connection between

the subscribing application and the broker. A durable subscription is only removed from the

broker when the application explicitly unsubscribes. While the application is not connected,

matching publication messages are stored in the broker until the application reconnects.

Point-to-point – queues and queue managers

Queue managers handle queues that store messages. Applications communicate with a local queue

manager, and get or put messages to queues. If a message is put to a remote queue (a queue owned by

another queue manager), the message is transmitted over connections to the remote queue manager. In

this way, messages can hop through one or more intermediate queue managers before reaching their final

destination. You can configure queue managers with or without local queuing. All queue managers

support synchronous messaging operations. A queue manager with local queuing also supports

asynchronous message delivery.

The point-to-point messaging paradigm provides one-to-one messaging. In other words, messages are

consumed by only one receiver, unlike publish-and-subscribe where messages are consumed by multiple

receivers.

The following graphic shows the topology for point-to-point messaging:

Java Message Service

Java Message Service (JMS) is the standard Java API for messaging. It supports the two messaging

categories: point-to-point messaging and publish/subscribe messaging. JMS is defined as part of the Java

2 Enterprise Edition 1.3 and 1.4 definitions. It defines a package of Java interfaces, which allows for

provider-independence, but does not necessarily allow for provider interoperability.

The JMS APIs are provided with the Lotus Expeditor runtime. This runtime also includes a point to point

JMS provider based on MQe messaging and a publish and subscriber provider based on MQTT

messaging. The MQe classes for JMS are a set of Java classes that implement the JMS interfaces to enable

JMS programs to access MQe systems, while the MQTT client classes for JMS enable JMS applications to

access Lotus Expeditor micro brokers. Both MQe and micro broker support the bridging of messages to

enterprise messaging systems as well.

There are several benefits to using JMS as the API to write MQe messaging applications. Some

advantages are derived from JMS being an open standard with multiple implementations. Using an open

standard provides the following benefits:

v The protection of investment, both in skills and application code

v The availability of people skilled in JMS application programming

MessageMessage Sender Receiver

Message Server

MessageQueue

Figure 6. Point-to-point messaging

132 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 143: Lotus Expeditor: Developing Applications for Lotus Expeditor

v The ability to plug in different JMS implementations to fit different requirements

IBM has several implementations of JMS. Interoperability is provided between them.

More information about the benefits of the JMS API is available at: http://java.sun.com

The JMS application is written to use only references to the interfaces in the javax.jms package. All

vendor-specific information is encapsulated in implementations of the following JMS administered

objects:

v QueueConnectionFactory

v TopicConnectionFactory

v Queue

v Topic

Note: The Lotus Expeditor runtime provides both an MQe point-to-point JMS provider, which supports

the QueueConnectionFactory and Queue objects and an MQTT client JMS provider supporting

TopicConnectionFactory,ConnectionFactory and Topic objects.

These JMS administered objects are stored in a Naming Directory Interface (JNDI) namespace. A JMS

application can retrieve these objects from the namespace and use them without needing to know which

vendor provided the implementation.

WebSphere MQ Everyplace

WebSphere MQ Everyplace (MQe) is a member of the IBM WebSphere MQ family of business messaging

products. It exchanges messages with various applications, providing once and once-only assured

delivery leveraging the point to point message paradigm.

MQe provides an integrated set of security features enabling the protection of message data both when

held locally and when being transferred.

With synchronous message delivery, the application puts the message to MQe for delivery to the remote

queue. MQe simultaneously contacts the target queue and delivers the message. After delivery, MQe

returns immediately to the application. If the message cannot be delivered, the sending application

receives immediate notification. MQe does not assume responsibility for message delivery in the

synchronous case (non-assured message delivery).

With asynchronous message delivery, the application puts the message to MQe for delivery to a remote

queue. MQe immediately returns to the application. If the message can be delivered immediately, or

moved to a suitable staging post, it is sent. If not, it is stored locally. Asynchronous delivery provides

once and once-only assured delivery. After the message is provided to MQe, control is returned to the

application. MQe next takes responsibility for assured delivery of the message. Delivery occurs in the

background allowing the application to carry on its processing.

MQe also has the ability to exchange messages with WebSphere MQ host queue managers and brokers.

To do this, configure a MQe queue manager with bridge capabilities. Without the bridge, a queue

manager can communicate directly only with other MQe queue managers. However, it can communicate

indirectly through other queue managers in the network that have bridge capabilities.

As mentioned previously, a point-to-point JMS provider is included with MQe. Initially MQe must be

bootstrapped using the supplied connection factory. From then on, standard JMS APIs can be used.

Lotus Expeditor micro broker

This section introduces the Lotus Expeditor micro broker and describes the Lotus Expeditor micro broker

environment.

Developing applications 133

Page 144: Lotus Expeditor: Developing Applications for Lotus Expeditor

The Lotus Expeditor micro broker component is a small message broker that provides a messaging fabric

for integrating various parts of a solution such as applications, sensors, and actuators. A message broker

ensures that messages arrive at the correct destination and are transformed to the format required by

each destination. The micro broker is a Java implementation that runs on a wide range of standard

devices including PDAs, laptops, and desktops. In addition, micro broker runs on more specific devices,

such as programmable logic controllers (PLCs), smart home information hubs (for example, TV set-top

boxes), and automobile-mounted devices.

The micro broker is suitable for embedding in applications and solutions that have a need for messaging,

notification, and event services. The micro broker uses a publish and subscribe, one-to-many message

distribution pattern. It provides a messaging infrastructure that lightweight messaging clients use to

communicate with each other, within a single device, across a network, and when integrating with

enterprise brokers. This enables an end-to-end integration fabric, reaching from sensor and actuator

devices, to client applications and up to back-end applications. The micro broker provides an integration

capability near the edge of the network, as well as providing a gateway to the enterprise services bus

(ESB).

Before going into details of how the micro broker works, it is important to know some of the principles

and technologies that are used in the micro broker.

Related concepts

“Publish and subscribe messaging” on page 126Publish and subscribe is a style of messaging in which applications (subscribers) register interest in a

particular subject of interest (known as a topic) with an intermediary (a broker) that matches those

applications to messages sent by other applications (publishers) to the same subject of interest.

“Scenarios and applications”This section describes some use cases that use the micro broker.

“Understanding the micro broker components” on page 135This section describes the components of the micro broker.

Scenarios and applications:

This section describes some use cases that use the micro broker.

FloodNet: FloodNet is a UK project sponsored by the Department of Trade and Industry. Its mission is to

develop technologies to monitor flood levels through the use of pervasive computing technologies.

Technologies are initially being tested on a tidal estuary in the UK which is subject to daily tidal flooding.

The FloodNet system architecture uses a network based on the IEEE specification 802.11 for wireless LAN

technologies. Each node consists of an embedded computer mounted on a post in the estuary. The nodes

measure the water level at regular intervals and transmit the data over the network to a micro broker

running on a customized node called the gateway node. The data is consolidated and subsequently

transmitted over GPRS to a central WebSphere Message Broker where the sensor data is transformed and

delivered to any application that subscribes to the data.

The sensor data is used for various applications such as simulation models, GIS Visualization and

archiving. Using the publish and subscribe model, additional applications can be developed that make

use of the same data. Also, additional sensors could be added to the nodes, to measure say air pressure,

and the data flowed back through the brokers without disrupting existing applications. The intent is to

create a suite of applications that can accurately monitor, model, analyze and predict the state of rivers so

that agencies and the media can be notified on a timely basis when flooding is likely to occur.

RFID: Radio Frequency Identification (RFID) is a technology that allows items to be labelled with RFID

tags and the tags to be automatically read when passing within the vicinity of an RFID antenna and

reader. Tags can be read through a variety of substances such as paint, grime, and other visually and

134 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 145: Lotus Expeditor: Developing Applications for Lotus Expeditor

environmentally challenging conditions, where barcodes or other optically read technologies would be

useless. RFID tags can also be read in challenging circumstances at remarkable speeds, in most cases

responding in less than 100 milliseconds.

The micro broker has been used in a retail solution for tracking the location of pallets in shops,

warehouses, and distribution centers. The aim being to ensure the location of pallets is known at all times

and to ensure that pallets are delivered to the correct store in a timely manner.

The architecture is comprised of four tiers:

Devices

The edge of the network such as RFID readers, motion sensors, and light stacks.

Edge server

A small footprint computer that handles connectivity and manages the devices. Monitoring,

control and notifications together with business logic for implementing RFID use cases is handled

by the edge server.

Premises server

Manages a retail location, warehouse, or distribution center. Multiple edge servers can be

connected to a premises server.

Enterprise server

Manages global information from all premises servers.

A basic use case validates that a pallet that is being delivered is expected at the location. The pallet is

removed from the delivery vehicle and moved into the warehouse through the dock bay doors. A motion

sensor located at the dock bay door detects the pallet is moving into the warehouse. This results in the

edge server sending a control command to activate the RFID reader. Once the pallet has moved into to

the RFID field, the reader reads the tags and sends them to the edge server. A tag may be read multiple

times, producing multiple messages to the edge server. The edge server filters the tags, for instance,

removing duplicates. The filtered tags are then sent to the premises server for validation. The premises

server checks with a repository to confirm that the tag is expected in this retail location. (The premises

server may send a message to the enterprise server to do this validation). The result is sent back down to

the edge server. If the pallet (tag) is expected, then a green light is switched on and the pallet is accepted

into the warehouse. If not, a red light is switched on, and the pallet is returned to the delivery vehicle.

On the edge server, every device has an agent that contains an MQTT client. The agent receives output

from the device, creates well-defined messages that are sent to the micro broker, and accepts command

and control messages that are mapped to the device inputs.

Certain messages are routed to the premises server for processing. A good example is a tag is sent to the

premises server to validate if it is expected at this retail location. The micro broker accepts messages

destined for the premise servers and ensures the message is delivered to a micro broker on the premises

server. Typically, a bridging component in the micro broker is then used to route messages into enterprise

level servers for processing.

Understanding the micro broker components:

This section describes the components of the micro broker.

The micro broker logically consists of three parts: the broker, the bridge, and the clients.

Broker

The broker is the component to which client applications connect to perform publish and subscribe

messaging. It handles the matching of publications with subscriptions, the distribution of publications to

subscribing applications, and the persistence of messages to ensure message delivery at the quality of

Developing applications 135

Page 146: Lotus Expeditor: Developing Applications for Lotus Expeditor

service required. The broker acts as a hub for routing messages between clients, and with the aid of the

bridge, other messaging servers. The broker can store messages on behalf of a client that is not connected

and make them available to the client when it reconnects. In addition, the broker can store messages on

behalf of the bridge and make them available when the messaging servers that the bridge connects to are

available.

The broker supports different types of persistence for storing messages and subscriptions. The type of

persistence is selected when a broker is created and is dependent on how the broker is to be used. Types

of persistence supported include:

Memory only

Where data (messages and subscriptions) only ever reside in memory. In the event of a failure or

the broker being shutdown, the data will be lost.

Shutdown

Data resides in memory until the broker is shutdown, at which point the data is persisted. In the

event of a failure, the data will be lost.

Full persistence

Data is always written to a persistent store using transactions and will survive both a failure and

shutdown.

Bridge

The micro broker bridge is an extension of the micro broker that routes messages between the micro

broker and other messaging servers to form more sophisticated messaging topologies. The bridge allows

messages to be routed between the micro broker and the following messaging servers:

v Other micro brokers

v WebSphere MQ

v WebSphere Message Broker

v WebSphere Application Server

v Any JMS provider

The bridge can route messages between one or more messaging servers. If the bridge cannot connect to a

messaging server, messages destined for the messaging server can be stored by the broker. When the

messaging server becomes available, the bridge will connect to it and transfer the stored messages. In

addition, the bridge can transfer pending messages from the messaging server to the broker.

Typically, each type of messaging server supports its own messaging protocol and its own message

formats. The bridge plays the role of intermediary, routing messages across different protocols and

transforming messages to a format acceptable by each messaging server.

Client

Application programs interact with the broker using a client library. The client library enables the

application program to be executed in a number of ways:

v Within the same Java runtime process as the micro broker itself.

v On the same machine as the micro broker but within a different runtime process.

v On a different machine to the micro broker.

The broker is able to handle multiple clients concurrently exchanging messages.

Clients do not persist messages; they simply provide a means for an application to interact with other

clients (applications and services) using a broker. Before a client can interact with a broker, it must first

connect to the broker. Once connected, messages can be sent and received. A client does not need to be

continuously connected to a broker to receive messages. The broker can store messages on behalf of a

136 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 147: Lotus Expeditor: Developing Applications for Lotus Expeditor

client, allowing the client to receive stored messages when it reconnects. This provides an additional level

of decoupling between sending and receiving clients. Put another way, a client can send messages to

other clients that may not be running when the message is sent.

Two clients are provided for use with the micro broker:

v A JMS client that supports the publish and subscribe domain of the JMS specification. The JMS client is

the recommended client library to use when developing applications for the micro broker.

v A Java MQTT client. This client is used for more specialized situations such as devices with

constrained environments or where there is a specific requirement to use the MQTT protocol.

Java MQTT client: The API closely maps the MQTT protocol.

The Java client provides an event-driven model such that an application is informed when a message is

delivered to it.

As both WebSphere Message Broker 6 and WebSphere Event Broker 6 support the MQTT protocol, the

clients can also directly connect to them.

Micro broker topologies:

Combinations of the micro broker, clients, and bridges can be linked together in a number of ways. This

section describes some of the common patterns that are used when linking components together.

Stand-alone: The simplest combination of components is to have a single micro broker with one or more

clients connected to it.

MicroBroker

Client

Client

Client

Client

Client

Client

Developing applications 137

Page 148: Lotus Expeditor: Developing Applications for Lotus Expeditor

The micro broker acts as a message hub for clients connected to it. These clients can send messages to

each other. Clients can run in the same process (VM) as the micro broker, in a different process on the

same computer, or even a different computer providing a powerful messaging infrastructure.

It allows multiple applications running in their own processes to communicate with each other using

publish and subscribe messaging. The applications do not need to know about each other and more

importantly do not need to all be up and running at the same time.

It can act as a hub for multiple off board clients. For instance, a broker can act as a home message hub.

There are a wide range of devices that could be connected to the hub. On the whole, most devices have

their own interface. Adapters are used to map between the device interface and MQTT. In a home, you

can imagine creating many different types of adapter; a good example is an X10 adapter that can be used

for controlling X10-enabled devices such as lights, power sockets, and the heating system. Adapters can

be created for home weather stations, alarm systems, and central heating control. The broker then

provides a hub for monitoring and controlling of all the devices.

It can be used as a message hub in one process (VM). It may sound like a strange thing to use a message

broker to allow Java applications in one process to communicate with each other. But there are a number

of advantages that it brings:

v The applications are decoupled from each other.

v The programming model remains the same whether the application runs in the same process space as

the broker or whether it is off board.

v It is a simple matter to move an application out of the process the broker is running in and either run

it in a different process or different box. This requires either no change to the application or a simple

change to specify the network address that the broker is using.

v If an application is not running when a message is sent, the broker queues messages and delivers them

when the application starts.

Typically, a combination of the above connectivity patterns will be used. For instance, in the case of the

home automation example, clients that directly interact with devices will be off-board, yet the monitoring

and controlling application will be on-board with the micro broker.

Three tier: There are a limited number of examples particularly when talking about enterprise businesses

that run small stand-alone message hubs.

Typically an enterprise will have a main message hub that is fed by messaging clients, by smaller

message hubs in the enterprise, or by other businesses.

Prior to the advent of the micro broker, the device could directly connect to the enterprise brokers using

MQTT clients. The micro broker allows small message hubs to be created in locations where this was

previously not possible or not cost effective. For instance, a hub can be created in a gas station, an RFID

edge controller, an electricity sub station or pumping station. Clients connected to it then have a message

infrastructure that carries on running if there are problems with connectivity to the enterprise. It also

brings with it the benefit that messages can now flow more directly between devices and applications

without having to go all the way back to the enterprise.

The micro broker can communicate with the following enterprise servers:

WebSphere Event Broker and WebSphere Message Broker

The bridge maps the micro broker topic space to the enterprise broker topic space.

WebSphere MQ

The bridge maps the micro broker publish and subscribe topic space to the WebSphere MQ

point-to-point queue space or publish and subscribe topic space.

138 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 149: Lotus Expeditor: Developing Applications for Lotus Expeditor

JNDI-enabled JMS providers

The bridge maps the micro broker publish and subscribe topic space to the JMS provider’s

point-to-point queue space or publish and subscribe topic space.

These systems can also route messages on to other systems.

Peer to peer: Multiple micro broker components can also connect and send messages between each other.

For example, a retail store application uses multiple micro broker components. Each micro broker handles

messages from a set of RFID readers. A tag is read by the reader that it passes through as well as

additional readers; hence, the tag is passed to multiple micro broker components. By linking micro broker

components together, RFID tag messages are correlated across brokers.

Any combination: It is possible to link these patterns together to produce ever more sophisticated

networks of messaging components. For example, Figure 7 shows a set of micro broker components that

are linked together as peers, some of which are linked to the enterprise.

It is good practice to keep the messaging network as simple as possible. The more complex the system,

the harder it is to diagnose problems and to extend it in the future.

MQTT

The MQTT protocol is a messaging protocol designed to enable messaging from tiny devices such as

sensors and actuators.

MicroBroker

Client

Client

BridgeBridgeMicroBroker

Client

Bridge

MicroBroker

ClientClie

nt

Client

Client

Client

Bridge

EnterpriseEnterprise

Figure 7. A set of micro broker components linked together as peers

Developing applications 139

Page 150: Lotus Expeditor: Developing Applications for Lotus Expeditor

An example of a sensor is a thermometer and an actuator is a valve. Refer to WebSphere MQ Telemetry

Transport and http://www.mqtt.org for more information about the MQTT protocol specification.

The micro broker implements the server half of the MQTT protocol.

Quality of Service: MQTT delivers messages according to service levels defined in a Quality of Service

(QoS) parameter.

The levels are described below:

QoS 0 At most once delivery.

Messages are delivered according to the best efforts of the underlying TCP/IP network. No

response is expected. No retry semantics are defined in the protocol. Consequently, the message

will arrive at the destination broker either not at all or once. QoS 0 is also known as fire and

forget.

QoS 1 At least once delivery.

The arrival of a QoS 1 message at the broker, including its successful placement in a persistent

store is acknowledged. In the event of identifiable failure of the communications link, or of the

sending device, or after some period of time of non-receipt of the acknowledgement message, the

sender will resend a duplicate message. Consequently, the message is certain to arrive, but could

arrive more than once.

QoS 2 Exactly once delivery.

For QoS 2, additional protocol flows are employed above QoS 1 to ensure that duplicate

messages are not delivered to the receiving application. This is the highest level of service, and is

used when duplicate messages are undesirable. Of course, there is a price to be paid in terms of

network traffic, but often this is acceptable because of the importance of the message content.

The QoS can vary by message, allowing non-important messages to be delivered using QoS 0 and

important messages to be delivered using a QoS of 2.

Publishing and subscribing clients both specify a QoS to use. When they differ, the micro broker

negotiates the QoS by using the lower of the two specified values.

Assumptions for QoS levels 1 and 2

In any network, it is possible for devices or communication links to fail. If this happens, one end of the

link might not know what is happening at the other end. These are known as in doubt windows. In these

scenarios, assumptions have to be made about the reliability of the devices and networks involved in

message delivery.

MQTT assumes that the client and broker are generally reliable, and that the communications channel is

more likely to be unreliable. If the client device fails, it is typically a catastrophic failure, rather than a

transient one. The possibility of recovering data from the device is low.

Some devices have non-volatile storage, for example, flash ROM. The provision of more persistent storage

on the client device protects the most critical data from some modes of failure. Beyond the basic failure of

the communications link, the failure mode matrix becomes complex, resulting in more scenarios than the

specification for MQTT can handle.

The time delay (retry interval) before resending a message that has not been acknowledged is specific to

the application, and is not defined by the protocol specification.

Clean session: Clean session is a property that when set to true notifies the broker that it should remove

any state held in relation to the client on connect and remove any state after the client disconnects. State

140 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 151: Lotus Expeditor: Developing Applications for Lotus Expeditor

can be maintained by setting the clean session to false. If the client is disconnected, it can resume its

work with the server from the point of disconnection. State held in the broker includes subscriptions

registered by the client and any publications destined for the client. This state also includes information

about any in-flight message delivery at the point of disconnection. This means that if a QoS 1 or QoS 2

message flow is in progress and the client is disconnected, if clean session is set to false, the client and

broker will attempt to complete this flow when reconnected. Note that this does not mean that the client

can continue to send messages while disconnected from a broker, but that any in-flight message flows at

disconnect time may be resumed. Therefore, a consequence of setting clean session to true is that the

delivery of QoS 1 and QoS 2 messages can not be assured. This is because if your client disconnects half

way through sending a message, when the client reconnects the broker removes all the state related to the

client, including the message that should have been sent to it.

WebSphere MQ Everyplace and micro broker comparison

While MQe and micro broker products are similar in that they provide embedded messaging capabilities;

their specific set of features might make a better choice for certain client applications.

Table 5. MQ Everyplace and micro broker comparison

WebSphere MQ Everyplace Micro broker and MQTT

JMS provider included Yes. point-to-point provider. Yes; Publish and Subscribe

Messaging paradigm point-to-point (queue-based) Publish and Subscribe (topic-based)

Implementation type Java-based (platform-independent)

implementation

Java-based (platform-independent)

implementation

Bridging Supports bridge to MQe and

WebSphere Business Integration

Message and Event Brokers

Support bridge to WebSphere MQ,

and WebSphere Business Integration

(WBI) Message and Event Brokers

Wire protocol MQe- specific MQTT standards based

Separate small footprint client No Yes; Java and ‘c’

QOS for message delivery At least once and exactly once. Fire and forget, at least once, and

exactly once

Local and remote queues Yes No

Build in security Yes No

This is not an exhaustive comparison of the two products. See the product documentation for more

complete information about these products.

Enabling projects for messaging

This section provides information to enable projects for messaging.

Client Services target profile features

The Lotus Expeditor Toolkit provides Client Services target profile support. These target profiles simplify

the creation and configuration of messaging application projects, enabling you to select the

target-embedded messaging APIs, and provide automatic management of the requisite messaging

libraries. When developing a messaging application, you can select any of the Client Services target

profiles for your Client Services project. The following table provides a list of tasks and the appropriate

target feature for each profile in a Client Services project.

Table 6. Client Services project tasks

Task Target Feature

Embedded point to point messaging MQ Everyplace

JMS point-to-point messaging MQ Everyplace JMS Support and Java Message Service

(JMS) APIs

Developing applications 141

Page 152: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 6. Client Services project tasks (continued)

Task Target Feature

MQTT programming MQ Telemetry Transport Client

JMS publish and subscribe messaging MQ Telemetry Transport Client JMS Support and Java

Message Service (JMS) APIs

Embedded publish and subscribe messaging Lotus Expeditor micro broker

Bridging micro broker messages to WebSphere MQ Lotus Expeditor micro broker JMS Bridge(These target

features are only supported on J2SE 1.4 and Java 5

runtimes.)

Bridging micro broker messages to other JMS Providers

that support JNDI

Lotus Expeditor micro broker JNDI JMS Bridge1

For more information on Client Services projects, refer to “Lotus Expeditor Toolkit” on page 11.

Developing messaging application logic

This section provides information on messaging application logic development.

MQ Telemetry Transport

Documentation is available on the MQTT Web site at: http://mqtt.org.

Developing network aware applications

The network layer is a base network management layer in Lotus Expeditor that provides a framework to

applications and platform components for network invocations and network error handling. It provides

users with the capability to determine the current status of the client platform as well as their

connectivity to remote servers, and HTTP resources including Web Services. The application can choose

to be notified of a client status change or to check the client platform status by using the public APIs for

the offline manager. The application can also check the real network status by using the public APIs for

netstatus. This layer also includes the RCP version of the HTTP URL Handler which integrates with the

account API and offline manager.

Understanding network aware applications

The network framework provides a base framework to handle network errors and provides a network

monitoring service. It consists of the following plug-ins:

Table 7. Network Layer Plug-ins

Plug-in Contribution

com.ibm.rcp.net.faults(NetFaults) The main framework handling all kinds of network

Faults. It provides detector extension points for platform

applications to extend. It provides handler extension

points for platform and application components to

extend. It has been enhanced to take a context parameter

in the Fault object, the detectors and the handlers.

com.ibm.rcp.net.http Handles failures at the HTTP protocol level. New:

change the WMC 2.6 URLHandler implementation to

support Accounts integration and update NetFaults to

support multiple server status concept.

com.ibm.rcp.offline (OfflineManager) Manages the client state transitions and provide a service

for querying the state of the client. New: Manages the

multiple remote resources state transitions and provides

a service for querying of the state of the remote

resources.

142 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 153: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 7. Network Layer Plug-ins (continued)

Plug-in Contribution

com.ibm.rcp.net.status (NetStatus) Detects the network adapter status

com.ibm.rcp.net.status.linux Native implementation of NetStatus service on Linux

com.ibm.rcp.net.status.win32 Native implementation of NetStatus service on Win32

com.ibm.rcp.os.events (OS Events) Detects the OS power events like standby or hibernate

com.ibm.rcp.os.events.linux Native implementation of OS events on Linux

com.ibm.rcp.os.events.win32 Native implementation of OS events on Win32

com.ibm.rcp.os.powerawareness The interface layer on top of os.events and is to be used

by other plug-ins to query the system power status

com.ibm.net.faults.default (platform default

configuration)

The default configuration to order detectors and

handlers. It also provides some default implementation

of handlers and detectors.

When an application throws a network error and calls DetectAndHandle.detectAndHandle(), the

NetFaults component will walk through the detectors and handlers in the order specified by the default

configuration or its customized configuration. The platform provides all the detectors in a predefined

order. The application component can contribute its customized handlers.

The Http plug-in within the network layer replaces the default VM implementation of HTTP and HTTPS

URLStreamHandler’s to be based on the Apache HTTP client.

Enabling network aware applications

Lotus Expeditor client provides Client Services target definition support in the Rational tooling

environment. These target definitions simplify the creation and configuration of network aware

application projects, enabling you to select the target-embedded network layer APIs and libraries.

When developing a network aware application, you can choose the ″Network Components Feature″

available in the Default Target definition.

Developing network aware application logic

Any application component interested in the remote/local resource status and client status should

implement the INetworkAware interface or extend the NetworkAwareBase object. It also should call the

DetectAndHandle.detectAndHandle(e,contextKey) when an network error occurs.

The application components can create their customized handlers by using the NetFaults public API .

Lotus Expeditor platform components can also create customized Faults and detectors by using the

NetFaults internal API.

Applications can use the NetStatus public API to detect the real network status.

The Lotus Expeditor network framework replaces the default VM implementations of HTTP and HTTPS

UrlStreamHandler’s which are based on the Apache HTTP client. The UrlStreamHandler implementation

will utilize the Apache HTTP client.

The platform does not provide default implementations for remote resource monitors.

Component registration

Application components register to use the framework by implementing the INetworkAware interface.

INetworkAware is an interface that must be implemented by a network aware class, that is, one that

wishes to receive callback notifications for online/offline related events and network connectivity related

Developing applications 143

Page 154: Lotus Expeditor: Developing Applications for Lotus Expeditor

events. This interface replaces IOfflineService which is deprecated as of WCT2.6/IR4D1.01. Callers

should migrate to INetworkAware and need to implement the violent transition, disconnected() and

reconnected().

The following is an example of an implementation of this interface detailing the platform’s state change:

public class MyNetworkAwareImpl implements INetworkAware {

IOfflineServiceHelper _helper;

public INetworkAware init() {

_helper = IOfflineServiceHelperFactory.INSTANCE.create(this);

return this;

}

public IOfflineServiceHelper getOfflineServiceHelper() {

return _helper;

}

public void disconnected(){

//do things accordingly if the system state changed to offline. e.g if the

//network connectivity is lost.

//e.g if application calls IOfflineManager.disconnected(), IOfflineManager

//will fire a DISCONNECTED event, which directly call INetworkAware.disconnected()

// method here.

// no intermediate states.

}

public void reconnected(){

//do things accordingly if the system state changed to online.e.g. if the

//network connectivity is back.

//e.g if application calls IOfflineManager.reconnected(), IOfflineManager will

//fire an RECONNECTED event, which directly call INetworkAware.reconnected()

//method here.

//no intermediate states.

}

public void goOffline(){

//do things accordingly if the client state changed to offline.

//e.g if application calls IOfflineManager.goOffline(), IOfflineManager will

//fire an OFFLINE_REQUESTED event, which call INetworkAware.offlineRequested()

//method

//If INetworkAware.offlineRequested() return true, IOfflineManager will proceed

//and eventually fire an GO_OFFLINE event, which call the code here in

//INetworkAware.goOffline()

}

public void goOnline(){

//do things accordingly if the client state changed to online.

//e.g if application calls IOfflineManager.goOnline(), IOfflineManager will

// fire an ONLINE_REQUESTED event, which call INetworkAware.onlineRequested()

//method

//If INetworkAware.onlineRequested() return true, IOfflineManager will proceed and

// eventually fire an GO_ONLINE event, which call the code here in

//INetworkAware.goOnline()

}

...

}

Example of an implementation of this interface if you are interested in a remote server/resource state

change - whether it is up or down. Since the client can not change the remote server state (that is, call

IOfflineManager.goOnline() and IOfflineManager.goOffline()), there is no need to implement the

callback methods goOnline() or goOffline().

144 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 155: Lotus Expeditor: Developing Applications for Lotus Expeditor

public class MyNetworkAwareImpl implements INetworkAware {

IOfflineServiceHelper _helper;

public INetworkAware init(String context) {

_helper = IOfflineServiceHelperFactory.INSTANCE.create(this,context);

return this;

}

public IOfflineServiceHelper getOfflineServiceHelper() {

return _helper;

}

public void disconnected(){

//do things accordingly if the system state changed to offline. e.g if the remote

//server is down. e.g if application calls IOfflineManager.disconnected(),

//IOfflineManager will fire an DISCONNECTED event, which directly call

//INetworkAware.disconnected() method here.

// no intermediate states.

}

public void reconnected(){

//do things accordingly if the sytem state changed to online.e.g. if the remote

//server is back. e.g if application calls IOfflineManager.reconnected(),

//IOfflineManager will fire an RECONNECTED event, which directly call

//INetworkAware.reconnected() method here.

// no intermediate states.

}

...

}

The following, is an example of using the INetworkAware class if the INetworkAware object wishes to

receive callback notifications for client state change:

INetworkAware myImpl= new MyNetworkAwareImpl().init();

The following is an example of the INetworkAware object requesting to receive callback notifications for a

remote server:

String contextKey="http://www.yahoo.com"

getOfflineServiceHelper().closeService();

An example of using DetectAndHandle:

String contextKey = "http://www.yahoo.com";

try {

URL url = new URL(contextKey);

url.openConnection();

}catch(Exception e){

//Application code asserts to the platform that a network failure occurred.

DetectAndHandle.detectAndHandle(e,contextKey);

//still handle the Exception.

throw e;

}

Once you are finished with the network framework service, it must unregister its listener as follows:

getOfflineServiceHelper().closeService();

Creating and configuring handlers

An application can create its own handlers by extending the public handlers interface, and adding the

extensions in the plugin.xml file in the application plug-in.

The following is an example of the default plugin.xml file:

Developing applications 145

Page 156: Lotus Expeditor: Developing Applications for Lotus Expeditor

<?xml version="1.0" encoding="UTF-8"?>

<?eclipse version="3.0"?>

<plugin

id="com.ibm.rcp.net.defaults"

name="com.ibm.rcp.net.defaults_2.6.0"

version="2.6.0.4"

provider-name="IBM">

<requires>

<import plugin="com.ibm.rcp.net.faults"/>

<import plugin="com.ibm.rcp.net.http"/>

</requires>

<extension

point="com.ibm.rcp.net.faults.detector">

<detector

order="2"

detectorClass="com.ibm.rcp.net.http.faults.HttpFaultDetector"

id="com.ibm.workplace.faults.detector2"/>

<detector

order="3"

detectorClass="com.ibm.rcp.net.faults.internal.power.PowerMonitor"

id="com.ibm.workplace.faults.detector3"/>

<detector

order="5"

detectorClass="com.ibm.rcp.net.faults.internal.netstatus.

NetStatusFaultDetector"

id="com.ibm.workplace.faults.detector5"/>

<detector

order="6"

detectorClass="com.ibm.rcp.net.faults.internal.detectors.

TransientFaultDetector"

id="com.ibm.workplace.faults.detector6"/>

</extension>

<extension

id="com.ibm.workplace.faults.handler"

point="com.ibm.rcp.net.faults.handler">

<handler

order="1"

handlerClass="com.ibm.rcp.net.faults.internal.handlers.

AdvancedHandler"

id="com.ibm.workplace.faults.handler1"/>

</extension>

</plugin>

Adding and configuring customized handlers

You can add handlers and configure the platform to use its customized handlers. You must first create the

handler, then add the handler to the platform. The following is an example for creating a handler:

public class MyHandler implements Handler {

IOfflineManager _offlineManager = IOfflineManagerFactory.INSTANCE.create();

public MyHandler (){

}

public void handle(Fault[] faults) {

for(int i=0; i<faults.length; i++){

//check if there is a power fault.

Fault f = faults[i];

if( (f instanceof PowerFault)

||(f instanceof MultipleTransientThresholdFault)

||(f instanceof NetStatusFault)){

146 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 157: Lotus Expeditor: Developing Applications for Lotus Expeditor

disconnect();

break;

}

}

}

private void disconnect(){

_offlineManager.disconnected();

}

}

To add this extension to a plugin.xml:

<extension

id="com.ibm.workplace.faults.handler"

point="com.ibm.rcp.net.faults.handler">

<handler

handlerClass="com.ibm.rcp.handlers.MyHandler"

id="com.ibm.rcp.handlers1"/>

</extension>

Using the NetStatus API to detect the real network status

Applications can use the Netstatus API to detect if the network is on or off. The following is an example

of how to use the API (however, ensure you call the update() method first).

private static final NetStatusMonitor _monitor = new NetStatusMonitor();

_monitor.update();

if(!_monitor.hasAnyLinkConnection()){

//network is off

}

Note: If your system is connected using a device emulator, such as VMWare, or other connections that

share your LAN or wireless network connection, the netstatus API always returns true, even after

you disconnect the LAN cable and wireless. This is because of the existence of the virtual adaptor.

If you want your application to be notified of a true offline state (or plan to disconnect the system),

go to Start > My Network Places, right-click on Properties, and disable the shared connections.

The Netstatus API returns the correct status.

Using enhanced HttpClient

No special coding is required to use the replacement URLStreamHandlers/URLConnections for HTTP and

HTTPS. Simply create a URL object and then open the connection (with openConnection or openStream),

as such:

URL myURL = new URL(http://my.server.com/path/to/resource/);

HttpURLConnection myConn = (HttpURLConnection) myURL.openConnection();

InputStream in = myConn.getInputStream();

// read input stream

The HTTP URLConnection is a subclass of java.net.HttpURLConnection. The HTTPS URL Connection is a

subclass of javax.net.ssl.HttpsURLConnection but the methods introduced by

javax.net.ssl.HttpsURLConnection are not implemented. Otherwise, the HTTPS URLConnection subclass

operates normally.

The URLConnection subclasses will always consult the Accounts API to locate login credentials for the

subject URL. If credentials are present for the URL, then those credentials will be used to authenticate

access to the URL.

Developing applications 147

Page 158: Lotus Expeditor: Developing Applications for Lotus Expeditor

Monitoring remote resources

If an application wants to monitor the status of remote resources, it can create a customized handler and

kick off the monitor from the handler. It must also add the handler extension in the plugin.xml. The

following example illustrates adding a handler extension:

<extension

id="com.ibm.workplace.faults.handler"

point="com.ibm.rcp.net.faults.handler">

<handler

handlerClass="com.ibm.rcp.net.defaults.internal.handlers.RemoteResourceMonitor"

id="RemoteResourceMonitor"/>

</extension>

Monitors must call OfflineManager.reconnected() or OfflineManager.reconnected(contextKey) in order

for components to be notified of the reconnection once it is detected.

If taking advantage of the net faults framework and creating a handler to monitor local/remote resources,

monitoring should not be done within the handler itself. The handler may be used to initiate a monitor. It

is suggested that an Eclipse Job be used.

It is important that the application only monitors the connectivity to a remote resource when the state of

that resource is offline and the global state is online. Therefore, if a network disconnection occurs while a

monitor is active, the monitor should sleep until the client becomes reconnected.

Code example for an HTTP monitor:

import java.io.IOException;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.core.runtime.IStatus;

import org.eclipse.core.runtime.Platform;

import org.eclipse.core.runtime.Status;

import org.eclipse.core.runtime.jobs.IJobManager;

import org.eclipse.core.runtime.jobs.Job;

import com.ibm.rcp.net.faults.ConnectFault;

import com.ibm.rcp.net.faults.Fault;

import com.ibm.rcp.net.faults.Handler;

import com.ibm.rcp.offline.api.manager.IOfflineManager;

import com.ibm.rcp.offline.api.manager.IOfflineManagerFactory;

public class RemoteResourceMonitor implements Handler {

String myContext = "http://www.myWebService.com";

HttpURLConnection webServiceConn = null;

URL webServiceURL = null;

IOfflineManager _offlineManager = IOfflineManagerFactory.INSTANCE.create();

public void handle(Fault[] f) {

//iterate through faults

for (int i = 0; i < f.length; i++) {

//if ConnectFault is found for given context

if (f[i] instanceof ConnectFault && ((String)f[i].getContext()).

equals(myContext)) {

Job monitorJob = new MonitorJob("webService monitor"){

protected IStatus run(IProgressMonitor arg0) {

while(isOffline) {

try {

webServiceURL = new URL(myContext);

148 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 159: Lotus Expeditor: Developing Applications for Lotus Expeditor

} catch (MalformedURLException e) {

e.printStackTrace();

}

try {

webServiceConn = (HttpURLConnection)webServiceURL.openConnection();

int webServiceResponse = webServiceConn.getResponseCode();

//if good response from webService, discontinue monitoring

if (webServiceResponse == HttpURLConnection.HTTP_ACCEPTED ||

webServiceResponse == HttpURLConnection.HTTP_CREATED ||

webServiceResponse == HttpURLConnection.HTTP_OK) {

//set offline state to false

isOffline = false;

//notify offline manager

_offlineManager.reconnected(myContext);

}

} catch (IOException e) {

e.printStackTrace();

}

}

//return status

return Status.OK_STATUS;

}

};

//schedule job

monitorJob.schedule();

break;

}

}

}

/**

* Internal class that extends the Eclipse Job framework. Contains a

* boolean housing the state of the remote resource for which the

* monitoring job was instantiated.

*/

private static abstract class MonitorJob extends Job {

boolean isOffline = true;

String id;

public MonitorJob(String id) {

super(id);

this.id = id;

}

}

}

Using the notification and check models

Lotus Expeditor supports both notification and check models as methods for checking client status.

Notification model: You should use the Notification model if you want your application to either react

to a state change on the client platform (for example, whether the platform goes online or offline), or

react after listening to a remote server.

The Notification model flows as such:

1. The application implements both the INetworkAware object and the callback method (such as,

disconnected() or reconnected()).

2. The application calls DetectAndHandle() when an error occurs.

3. DetectAndHandle() will walk through the detectors, which generate the Faults, and pass the Faults to

the handlers.

Developing applications 149

Page 160: Lotus Expeditor: Developing Applications for Lotus Expeditor

For example, if you have a networking error, the NetStatusFaultDetector will generate a

NetStatusFault by the NetStatusDetector. When you use the HTTP plug-in, if the server is down or

if there are networking errors, the exception type SocketException, ConnectException

,NoRouteToHostException will generate a ConnectFault by the httpDetector.

4. The handler calls IOfflineManager.

5. IOfflineManager generates the corresponding event (for example, EVENT_DISCONNECTED, which calls the

INetworkAware object’s disconnected() method.

Check model: If you just want to check the state of the client platform, you can call

IOfflineManager.isOnline().

IOfflineManager offmgr = IOfflineManagerFactory.INSTANCE.create();

If you want like to check the state of a remote server, you need to implement an INetworkAware object,

and use IOfflineHelper to check the state of a remote server.

Developing portlet applications

The Lotus Expeditor platform supports portlet applications that conform to the JSR 168 specification. The

portlet development tooling component of the Lotus Expeditor Toolkit allows users to create, develop,

launch/test and debug OSGi based Client Services portlet applications, as well as convert existing J2EE

server based portlet applications to run on the Lotus Expeditor platform. The portlet development tools

also assist in providing a Portal-like development experience by allowing users to wire and aggregate

portlet applications.

A portlet application bundle can be developed using many of the same portlet development tools

provided by the Rational Software Development platform. You should therefore refer to the Rational

online help section Developing Portlet applications as your initial portlet development tools reference.

The following table provides pointers to information on portlet development activities and information

on tasks that are unique to, or require special consideration when developing portlet applications for the

Lotus Expeditor platform.

Table 8. Portlet development activities

Task Reference

Understanding Client Services Portlet development. “Understanding Portlet applications”

Working with Client Services Portlet projects. “Creating Portlet projects” on page 154

Developing Client Services Portlet application logic. This

encompasses any special development considerations

when coding and constructing the Portlet application

logic.

“Developing Portlet application logic” on page 155

Importing Portlet application projects. “Importing Client Services portlet projects” on page 155

Debugging and testing Portlet applications. “Debugging and testing Client Services Portlet

applications” on page 157

“Client Services Server” on page 324

Deploying Client Services Portlet applications. “Deploying projects for local testing” on page 331

Using the command line WAB tool to convert a WAR to

a WAB.

“WAB Utility” on page 247

Understanding Portlet applications

Client Services portlet applications run on the Lotus Expeditor platform. A primary difference between a

Client Services portlet application and one that is deployed to run on a WAS or Portal runtime is that the

150 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 161: Lotus Expeditor: Developing Applications for Lotus Expeditor

Client Services portlet application must also be a valid OSGi bundle. Refer to “Working with OSGi

bundles” on page 366 for more information on bundles and the Lotus Expeditor platform.

The Lotus Expeditor Toolkit automatically handles many of these bundle specific details, which is why

developing the portlet application through a Client Services portlet project is the recommended

development path for portlet applications that are to be run on the Lotus Expeditor platform.

Nevertheless, it is also possible to develop the portlet application through a J2EE portlet project, and

subsequently test run it on the Lotus Expeditor platform. It is also possible to transform an existing

Portlet Web Application Archive (WAR) file into a Portlet Web Application Bundle (WAB) suitable for

running on the Lotus Expeditor platform through the use of the “WAB Utility” on page 247.

The following lists aspects of a Client Services portlet application that differ from a standard portlet

application.

v The Lotus Expeditor platform does not support deploying Enterprise Applications through an EAR.

The portlet application is directly deployed to the runtime.

v A Client Services portlet application has a manifest file, located in META-INF/MANIFEST.MF, that

contains bundle information including package and bundle dependencies. This is associated with the

bundle, and is separate from the manifest file found under the portlet application’s content folder.

v A Client Services portlet application contains additional deployment information in wab.properties.

This is located in the web content WEB-INF folder.

v JSP files are translated into their respective servlet classes before the web application is deployed to the

runtime as a WAB.

In most cases, these artifacts and differences are handled transparently by the Lotus Expeditor tools.

These differences do not affect the functionality of the portlet application. There are, however, some

development considerations you should take into account. These are described in Client Services Portlet

Application Development section.

A Client Services portlet application can be developed using many of the same portlet development tools

provided by the Rational Software Development platform. The primary differences are:

v Use the Client Services Portlet project wizard to create a Client Services portlet project, as described in

Creating a Client Services Portlet project.

v Since the Lotus Expeditor platform does not support EARs, EAR projects are ignored.

v When testing the project, target the Lotus Expeditor runtime when using the Run / Run on Server

action. Or, use the Lotus Expeditor launch configuration when using the Eclipse Run / Debug launch

feature. This is explained in Debugging and testing applications.

v When exporting the portlet application, use the Plug-in Development > Deployable plug-ins and

fragments wizard.

URL Addressability

The Portlet Container allows a user to call a portlet directly using an URL. Therefore a special URL

format is defined for portlets. This URL format allows portlets to be called just like servlets (by

context/portlet-name), but also provides the possibility to add additional portal context information, such

as the portlet mode or window state.

The portlet can be accessed by a URL mapping that has the following structure: http://host:port/context/portlet-name [/portletwindow[/ver [/action] [/mode] [/state] [rparam]]]

Any differing URL structure results in a com.ibm.wsspi.portletcontainer.InvalidURLException. Empty

Strings are not allowed as parameter value and throws an InvalidURLException.

http://host:port/context/portlet-name/portletwindow

The basic URL that is minimum to access a portlet. A default portletwindow called ‘default’ is

created.

Developing applications 151

Page 162: Lotus Expeditor: Developing Applications for Lotus Expeditor

/portletwindow

Mandatory parameter used to identify the portletwindow. This parameter must be set if choosing

to add more PortalContext information to the URL.

/ver=major.minor

Optional parameter to define the version of the portlet API that should be used. This parameter

must be set if choosing to add more PortalContext information to the URL. For now only the

version ‘1.0’ is allowed. Any differing version would throw an InvalidURLException.

/action

Parameter that needs to be set if the action method of the portlet should be called

The action parameter causes the action process of the portlet to be called. After the action has

been executed, a redirect is automatically issued to call render.

To control the subsequent render process, a document servlet filter can set a request attribute

with name com.ibm.websphere.portlet.action and value redirect to specify that the portlet

serving servlet directly returns after action without calling render.

/mode=view | edit | help | custom-mode

An optional parameter to define the portlet mode that should be used to render the portlet.

Default is the mode view. The value is not case-sensitive, e.g. View or VIEW result in the same

mode view.

/state=normal | maximized | minimized | custom-state

An optional parameter to define the window state that should be used to render the portlet.

Default is the state normal.

The value is not case-sensitive, e.g. Normal or NORMAL result in the same state normal.

* [ /rparam=name *[=value] ]

An optional parameter to specify render parameters for the portlet. Repeat this parameter chain

to provide more than one render parameter, e.g. /rparam=invitation/rparam=days=Monday=Tuesday

?name=value name2=value2 ...

Query parameters may follow optionally. They are not explicitly supported by the

portletcontainer, but they do not invalidate the URL format.

Client Services Portlet projects

This section describes Client Services Portlet projects.

Portlet API and Type support

The Portlet API and Type support in the Portlet Tooling component is entirely based on the Lotus

Expeditor Portlet runtime support.

v Portlet APIs supported - JSR 168

v Portlet Types supported - Empty, Basic, and Faces

Please note that there is no support for Struts Portlet in Lotus Expeditor. Additionally, only the Empty

portlet type will be supported in an AST integrated build. All three portlet types are supported on the

Rational Software Development Platform.

The following list illustrates which portlet type is created for each type option available:

Table 9. Portlet types

Portlet Type Description

Empty Portlet A portlet application that extends the GenericPortlet

class with minimum code in it. You are required to write

the code to complete the portlet.

152 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 163: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 9. Portlet types (continued)

Portlet Type Description

Basic Portlet A portlet application that extends the GenericPortlet

class defined in the Java Portlet Specification version 1.0

(JSR 168). You will be asked to select several options for

generating sample code.

Faces Portlet A portlet application that uses the JavaServer Faces

Portlet Framework (JSR 168).

For more JSR 168 information, refer to http://www.jcp.org/en/jsr/detail?id=168.

Unsupported features

The following feature is not supported by the Portlet Container:

v Displaying custom mode icons in portlet title bar - The Portlet Container does not provide a

mechanism whereby the portlet container branding can be updated to include custom mode icons in

the portlet title bar. Only the maximize, minimize, view, edit and help icons are supported and

displayed in the portlet title bar when the portlet is accessed. The same restriction applies to the portlet

aggregator page as well. To access the custom mode pages, developers should provide links within

their application to these pages.

The following optional feature is not supported by the Portlet Container:

v Expiration based caching - The JSR 168 Specification defines an expiration based caching mechanism.

The Portlet Container provides a caching mechanism to allow for the portlet content to be cached per

portlet per user client. This feature is optional.

The following optional service is not supported by the Portlet Container:

v User Information Service - The JSR 168 Specification allows portlets to define user attributes the

portlets might be interested in. The Portlet Container provides a mechanism to expose the available

user information to portlets. This feature is optional.

Using the Portlet Aggregation Tag Library

The Lotus Expeditor 6.1 runtime provides a Tag Library that can be used by developers to write JSPs that

aggregate multiple portlets on one page. This capability will not provide the developer with a full feature

portal aggregation implementation, but provides a very good migration scenario for developers who

already have aggregating servlets and JSPs and want to switch to portlets.

The biggest advantage for developers is that they can re-use portlets that currently run on the WebSphere

Portal Server on the Lotus Expeditor 6.1 client runtime. However, the Tag Library and the JSPs that use

this Tag Library can only be run on the WebSphere portlet container implementation (the protocol

between the tags and the portlet container is not standardized).

A brief description of the Aggregation Tags is provided below (for a more in-depth look at the

Aggregation Tags, please refer to “Aggregation tag library” on page 378):

v Init - This tag initializes the portlet framework and has to be used in the beginning of the JSP. All

other tags described in this section are only valid in the body of this tag, therefore the init tag usually

encloses the whole body of a JSP.

v State - This tag creates a URL pointing to the given portlet using the given state. This URL can either

be placed into a variable specified by the var attribute or can be written directly to the output stream.

v Insert - This tag calls the render method of the portlet and retrieves the content as well as title. The

content and title of the specified portlet can optionally be placed into variables using the contentVar

and titleVar attributes.

v urlParam – This tag adds a render parameter to the newly created URL.

Developing applications 153

Page 164: Lotus Expeditor: Developing Applications for Lotus Expeditor

v initBranding – This tag is to provide the branding theme information to the portlet aggregator page.

The theme includes - stylesheet, the title bar images, the title bar background color and the content

background color.

v initUrlPrefix – This tag is used to provide the URL prefix information for all the portlet URLs

including the render and action URLs. The URL prefix includes the server address and the port

number.

“Aggregating portlets to JSPs” on page 155 describes how to use the Lotus Expeditor 6.1 portlet tools to

write an aggregation JSP.

Note: If you manually create the aggregator JSP, then include the following tag library references in the

JSP:

<%@ taglib uri="http://ibm.com/portlet/aggregation" prefix="portlet"%>

<%@ taglib uri="http://ibm.com/portlet/aggregation/ext" prefix="portlet_ext"%>

Adding these tag library references will allow the Lotus Expeditor tools to automatically process

the tags during compilation of the aggregator JSP. The Lotus Expeditor portlet tools will

automatically add the above tag library references if you follow the procedure described in

“Aggregating portlets to JSPs” on page 155.

Creating Portlet projects

This section provides information on creating Portlet projects.

Creating a Client Services Portlet project

To create a new Client Services Portlet project that can be developed and deployed to a Lotus Expeditor

platform, perform the following procedure:

1. Start the RSDP or AST platform workbench with the Lotus Expeditor Toolkit installed.

2. Start the Portlet Project creation wizard by selecting File > New > Project > Client Services > Client

Services Portlet Project.

3. On the first page of the new Client Services Portlet project creation wizard, provide a unique Client

Services Portlet project name. Select the Client Services v6.1 target runtimes from the drop down list

if it is not already selected by default. The Portlet APIs selection should be auto-selected for JSR 168

portlet APIs. Finally, select the Portlet type from the drop-down list as per your needs.

Note: Please note that there is no support for Struts portlet projects in Lotus Expeditor 6.1. Refer to

“Portlet API and Type support” on page 152 for more details.

4. Click Next and go to the Portlet Settings page. Click Finish if you would like to accept the rest of the

default settings for your new portlet project.

5. To continue, click Next to either go to the Action and Preferences page or the Advanced Settings page,

based on the portlet type.

6. Click Next to open the Target Profile page to make target definition and target features and plug-ins

selections. The Target profile page displays the current default Target definition which is set on the

Client Services Preference page. The Core OSGi, Web Application and Portlet Application target

features are pre-selected and you may make additional choices if needed. You may select a different

target definition from the drop down list.

7. Select Finish to create the new Client Services Portlet project.

Converting a J2EE portlet project to a Client Services Portlet project

To convert an existing J2EE server (WebSphere Application/Portal server) based JSR 168 portlet project

into a Client Services Portlet bundle project that can be targeted to run on the Lotus Expeditor runtimes

platform, perform the following procedure:

1. Start the Rational Software Development Platform or AST with the Lotus Expeditor Toolkit installed.

154 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 165: Lotus Expeditor: Developing Applications for Lotus Expeditor

2. Start the Convert Project to Client Services Project wizard by selecting File > New > Other > Client

Services > Convert Project to Client Services Project.

3. The first page will display all the projects in the user’s workspace that are not already Client Services

projects. Select the project that you wish to convert and click Next. You can optionally choose to

create a copy of the project that is being converted to create a backup. To do so, run the wizard with

create a copy of the original project option checked before conversion and make all the

transformation changes to the new copy.

4. You can click Finish to perform the conversion and receive the default Target definition and features

selections.

5. Selecting Next displays the Target Profile selection page. Core OSGi, Portlet Application and Web

Application are pre-selected. Select additional target features if needed.

6. Click Next to open the next page, for providing options for automatically managing the project’s

manifest file. This is enabled by default, and set to prefer Import-Package or Require-Bundle

(depending on the workspace default settings) for resolving package dependencies.

7. Select Finish to perform the project conversion.

Refer to “Convert Project to Client Services Project Wizard” on page 375 for information on how to use

this wizard.

Importing Client Services portlet projects

To import Client Services Portlet projects that could be deployed to a Lotus Expeditor platform, perform

the following procedure. The import functionality is provided by the Eclipse Platform Development

Environment. Portlet Tooling provides no additional support for importing Client Services portlet

projects.

1. Start the Rational Software Development Platform workbench with Lotus Expeditor installed.

2. Select File > Import to invoke the import wizard.

3. Select the appropriate import type for importing Client Services portlet projects:

v Project Interchange

v Zip file4. Follow the wizard pages and select the Client Services portlet project that needs to be imported, then

click Finish.

The Client Services portlet project is imported into your workspace.

Adding a portlet to a Client Services Portlet project

To add portlets to a Client Services Portlet Project, perform the following procedure:

1. Select File > New > Other > Portal > Portlet to invoke the wizard to add portlets to an existing

Client Services portlet project.

2. Ensure that the project you wish to add the new portlet to is selected.

3. Enter the new portlet name and select the type from the drop down list.

4. Follow the wizard steps to select other settings for your new portlet.

Developing Portlet application logic

This section discusses Portlet application logic development.

Aggregating portlets to JSPs

Server based portal implementations (such as WebSphere Portal Server) dynamically generate portal

aggregator JSPs using portal configuration information provided by portal application developers. The

Lotus Expeditor platform does not have such dynamic support, and requires the portal layout

information to be specified in the aggregator JSP (using the HTML table element) with the packaged

application before deployment. The <HTML> table model allows application developers to arrange

Developing applications 155

Page 166: Lotus Expeditor: Developing Applications for Lotus Expeditor

portlets into rows and columns of cells. Using this model, multiple portlets can be rendered on a single

aggregator JSP page which can be viewed either in the Lotus Expeditor browser or an external platform

browser.

To create a JSP page that aggregates multiple Client Services Portlet applications, perform the following

procedure:

1. Select a Client Services Portlet or Web project where you wish to add the aggregated JSP.

2. Right click the Client Services Portlet or Web project and select New > Other > Web > JSP File to

create a new JSP file. Create the new JSP file in the Web Content directory of the project.

3. Open the JSP file in the JSP editor if it does not already open in the editor.

4. Ensure that the Palette view for the JSP is visible. If the Palette view is not available, then select

Window > Show View > Other > Basic > Palette to display the view.

5. Use the actions in the HTML category in the Palette to create the HTML content in the JSP. Add an

HTML table to the JSP page to create a framework for the layout of your perspective. Note that you

are expected to configure your HTML layout before and after adding the Portlet content into the JSP.

6. Select a table cell in the JSP editor and select the Add Portlet to JSP action in the Client Services

category from the Palette.

7. The Add Portlet to JSP action dialog is displayed to the user. The following table explains the various

options of the dialog:

Table 10. Add Portlet to JSP Dialog

Option Description Default Value

Servlet Mapping Select the servlet mapping that will

handle your aggregation JSP request

List of available servlet mappings

defined in the selected project’s Web

Deployment Descriptor

Select different project Allows the selection of a different

project to add Portlets

Provides a list of available Client

Services Portlet projects in the user’s

workspace

Portlet Select the portlet you wish to add (or

aggregate) to the JSP

List of available Portlets that are

defined in the selected project’s

Portlet Deployment Descriptor

Portlet Variables Portlet variables that are required to

generate JSP code that will aggregate

the portlet into the JSP

None

8. Click Finish to insert the code that will insert the portlet in the table cell of the JSP. Repeat the steps

to add additional portlets in other cells within the table.

9. The add portlet code will be compiled and built with the JSP and you can test and debug the

aggregated JSPs by right clicking on the JSP and selecting the Run on Server method.

Securing Portlet application resources

Though the J2EE specification does not specify the requirements for Portlet security with regards to

authentication and authorization, the Portlet Container will protect the portlet resources similar to the

way the J2EE servlet resources are protected when accessed through a URI. In declarative security the

application’s web descriptor specifies the application’s security policy (roles, access control, etc.) without

changing the applications code. As you can see the authentication and authorization aspects for Portlets

are similar to Servlet/JSPs.

Transport level security (HTTPS): The portlet specification requires that portlets which must be

accessed through HTTPS specify a security-constraint in the portlet.xml. The following is an example of

a security-constraint indicating that the portlet TestPortlet be allowed access only through HTTPS.

<security-constraint>

<display-name>Secure Portlets</display-name>

<portlet-collection>

156 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 167: Lotus Expeditor: Developing Applications for Lotus Expeditor

<portlet-name>TestPortlet</portlet-name>

</portlet-collection>

<user-data-constraint>

<transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint>

</security-constraint>

Programmatic security: The portlet specification also supports programmatic security using the

isUserInRole method, just like servlets do. The following is an example indicating that when the

isUserInRole(role1) is called within a portlet TestPortlet, it should return true if the user who is

accessing the portlet is in the Employee role.

<portlet>

<portlet-name>TestPortlet</portlet-name>

<portlet-class>portlet.TestPortlet</portlet-class>

<security-role-ref>

<role-name>role1</role-name>

<role-link>Employee</role-link>

</security-role-ref>

</portlet>

To configure a portlet application to use declarative / programmatic security on the Portlet Container, the

web descriptor must define a list of valid User Admin roles in the <role-name> tag. This list of roles can

include user and group roles. The above example uses the default User Admin role of Employee. The

Portlet Container assumes that all User Admin users store their passwords as a credential with the key

″password″. If no valid users are created with User Admin then the Portlet Container will not let anyone

access the portlet application resources that have been secured.

Debugging and testing Client Services Portlet applications

This section provides information for debugging and testing Client Services Portlet applications.

Debugging and testing Client Services Portlet projects on a test environment

To launch/debug a Client Services Portlet project on the packaged Lotus Expeditor test environment

using the Client Services launcher, perform the following procedure:

1. Using the J2EE, Web or Plug-in Development Environment perspective, bring up the Launch, Run or

Debug panel by clicking Run > Run... (or Run > Debug...).

2. Select the Lotus Expeditor configuration type and click New to create a new launch configuration.

3. Select the Client Services launcher as the target platform to launch on the Main tab.

4. Select the Plug-ins tab and ensure that the portlet applications you wish to test are selected, as well as

any other dependency plug-ins.

5. Click Run or Debug to launch.

Debugging and testing Client Services Portlet projects on non-Lotus Expeditor

runtimes

To debug and test Client Services portlet projects on a non-Lotus Expeditor runtime, perform the

following procedure:

1. Using the J2EE or Web perspective, select the portlet application project you wish to test or debug.

2. Right click on the project to bring up the context menu, and select Run As > Run on Server...

3. When the list of server configurations displays, select a non-Lotus Expeditor server (either WebSphere

Portal Server or WAS 6.1).

4. Add the Client Services Project that you wish to run/debug.

5. Click Finish to test or debug the application.

Developing Rich Client applications

This section provides information on Rich Client application development.

Developing applications 157

Page 168: Lotus Expeditor: Developing Applications for Lotus Expeditor

Creating a simple Rich Client Platform application

The Rich Client Platform is the minimal set of Eclipse SDK plug-ins needed to build an application with

a UI. However, rich client applications are free to use any API necessary for their feature set, and can

require any plug-ins beyond the bare minimum. The key differentiator of a rich client application from

the standard SDK workbench is that the application is responsible for defining which class should be run

as the main application. Your RCP application is an Eclipse plug-in. As such, you can use a plugin.xml

file to specify your application’s start-up class, which creates the workbench window.

In order to create a Java-UI application that can be contributed to the client platform, there is a minimal

set of objects that must be created:

v A plug-in for the application

v A view to display some data

v A perspective to contain the view

v An extension point declaration of the application for Lotus Expeditor

Note: The above objects are enough to run an application within the development environment. In order

to deploy and install the application, a feature and an update site are also required.

The following procedure illustrates how to create an application that can be contributed to the client

platform. In these steps, you will make use of the Plug-in Development Environment Plug-in Project, as it

provides a set of templates that will reduce the number of steps necessary to build the application.

1. Start Rational Software Development Platform.

2. Create a plug-in project to contain the application that you are providing. You will use a template that

provides a view in order to quickly build an application. Later, you can modify the code generated by

the template to meet your own requirements.

a. Select File > New > Other > Plug-in Development > Plug-in Project to create the initial project,

then select Next.

Note: If you do not see the Plug-in Development entry as one of the selections, select the Show

all wizards option to enable the display of all of the new project wizards. Selecting a new

Plug-in Project will cause a dialog to display inquiring whether you want to enable Eclipse

Plug-in Development. You will need to enable this capability to allow appropriate choices to

be populated on menus.

b. On the Plug-in Project panel, enter a name for your plug-in project, such as MyApplication. You

can use the defaults already entered on the rest of the panel. Select Next.

c. Use the default information on the Plug-in Content panel. Select Next.

d. On the Templates panel, check Create a plug-in using one of the templates. Then select Plug-in

with a view. Then select Finish.

e. A project called MyApplication will now be created in your workspace. Selected files will have

already been created within the project based on your selections to create a plug-in with a view.

The MyApplication and MyApplication.views packages will have been created in the src folder.3. Create the initial Java class for the perspective for the application. This class organizes the view

created by the template.

a. First, create a package to contain your perspective:

1) Highlight the src folder in your plug-in project.

2) Select File > New > Package. Enter MyApplication.perspectives as the Name, then select OK.b. Now, create the Java class for the perspective:

1) Select the MyApplication.perspectives package that you just created.

2) Select File > New > Class.

3) Enter a Name for the class, such as MyPerspective.

158 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 169: Lotus Expeditor: Developing Applications for Lotus Expeditor

4) The superclass will remain java.lang.Object.

5) Your class will implement the org.eclipse.ui.IPerspectiveFactory interface. Select the Add...

button next to Interfaces. Begin typing IPerspectiveFactory and the panel will complete the

name for you as you type. Select OK.

6) Select Finish to complete your class creation.c. You will need to add some code to the class that you just created in order to layout the view

created by the template:

1) Edit the MyPerspective.java file.

2) Locate the method createInitialLayout and replace the method with this code:

public void createInitialLayout(IPageLayout layout) {

String editorArea = layout.getEditorArea();

layout.addView( "MyApplication.views.SampleView",

IPageLayout.BOTTOM, 0.7f,editorArea);

layout.setEditorAreaVisible(false);

}

This code adds the view created during the project creation to this perspective.

3) Save and close the Java file.4. Now add an extension point to the plug-in to define the perspective that you just created:

a. Open the plugin.xml file contained in your project.

b. Select the Extensions tab within the editor. You should already see some extensions defined, such

as org.eclipse.ui.views and org.eclipse.ui.perspectiveExtensions.

c. Select Add..., then select org.eclipse.ui.perspectives, then OK.

d. Once org.eclipse.ui.perspectives has been added to the All extensions list, right click on the

entry, then select New > perspective.

e. The Extension Element Details information will display. Use the default information for the id and

name.

f. Select the Browse... button next to the class and select the

MyApplication.perspectives.MyPerspective class that you created in Step 3.5. Create the WctApplication extension point to enable contribution of the application to the client

platform

a. Select Add... again, uncheck the box for Show only extension points from the required plug-ins,

then select com.ibm.eswe.workbench.WctApplication, then OK.

b. Select the plugin.xml tab in the editor.

c. Replace the content:

<extension

point="com.ibm.eswe.workbench.WctApplication">

</extension>

with

<extension id="MyApplication"

point="com.ibm.eswe.workbench.WctApplication">

<DisplayName>MyPerspective</DisplayName>

<PerspectiveId>MyApplication.perspective1</PerspectiveId>

<Version>1.0.0</Version>

</extension>

d. Save and close the plugin.xml file.

Note: The LauncherSet extension point can also be used to contribute the application to the client

platform.

At this point, you can launch the platform from the workbench including this application. Clicking

Launch will display MyApplication as one of the selectable applications. Refer to “Debugging and testing

applications” on page 323 for more information on how to launch the client platform.

Developing applications 159

Page 170: Lotus Expeditor: Developing Applications for Lotus Expeditor

These are the basic steps towards creating the initial application. Once you have the basic application

created, you can continue to enhance your application, adding additional views, menus and menu items,

preference pages, dialogs, messages, and more. You can use the same plug-in that you created above, or

you can separate your user interface logic into additional plug-ins, depending upon your requirements.

In step 5, you implemented an extension point that defined the perspective ID to contribute to the Lotus

Expeditor workbench.

For more information on API specs and usage notes/best practices, refer to “UI toolkits” on page 82 and

“Using widgets on devices” on page 84.

Creating a simple Rich Client Application for devices

This section provides device specific information for creating Rich Client Applications.

Creating a Rich GUI application for devices

A Client Services Rich GUI application uses eSWT to draw its user interface. Similar to an Eclipse eRCP

workbench application, a Rich GUI application draws its user interface within a View. In eRCP, views are

displayed inside a workbench application. In Lotus Expeditor, when running on a desktop computer,

views are also displayed in a workbench, but on a device they are displayed as individual windows. No

matter how they are displayed, embedded Rich GUI applications are referred to as workbench

applications since they never create their own top level window.

Setup: Before creating a Rich GUI application for devices, you must first create a new workspace:

1. Select File > Switch Workspace.

2. Enter a folder name and click OK.

3. When asked if you want to set the Preferences to use the Lotus Expeditor Toolkit, click OK.

4. Select Go to the workbench.

Next, prepare the IDE to build applications for devices. For detailed information, refer to “Setup for

Device development” on page 13.

Creating the basic parts of a Rich GUI application: A Rich GUI application, contains the following

parts:

UIPlugin class: The application must have a class which

extends org.eclipse.ui.plugin.AbstractUIPlugin. This provides the base functionality for starting and

stopping the application within the OSGi framework. This class is created automatically when you create

a Client Services project.

To create a new application project:

1. Select File > New > Project.

2. Expand Plug-in Development and double-click Client Services Project.

3. Enter a project name and click Next.

4. Click Finish.

Add the necessary imports:

1. Resolve any error resulting from the AbstractUIPlugin import by switching to the Dependencies tab.

2. Click Add from the Imported Packages section.

3. Select org.eclipse.swt, org.eclipse.swt.widgets, org.eclipse.ui.plugin, org.eclipse.ui.part, then click

OK.

4. Click Save.

160 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 171: Lotus Expeditor: Developing Applications for Lotus Expeditor

View class(es): The application must have at least one class which extends

org.eclipse.ui.part.ViewPart. These classes provide the GUI implementation for the application. In

addition to the required “normal” view that is usually displayed on devices, Rich GUI applications may

also provide a “large” view that is more appropriate for desktop displays. A third “status” view may be

used to display minimal information on very small screens. The application launcher determines which

view is used.

To add a view class for your application:

1. In the Package Explorer, right click on your package.

2. Click New > Class.

3. Fill in a class name for your view class.

4. Change SuperClass to org.eclipse.ui.part.ViewPart.

5. Uncheck Inherit abstract methods and click Finish.

6. Edit the class to add the following methods.

A View class must implement the createPartControl() method. This is where the application initially

creates its GUI on an eSWT Composite widget.

public void createPartControl(Composite parent) {

Label label = new Label(parent, SWT.NONE);

label.setText("Hello World");

}

A View class must implement the setFocus() method in order to give focus to an appropriate control

when the View as a whole gains focus.

public void setFocus() {}

You must also need to add import statements for the SWT classes used.

import org.eclipse.swt.SWT;

import org.eclipse.swt.widgets.Composite;

import org.eclipse.swt.widgets.Label;

7. Click Save.

Extensions: For an application to appear in the workbench or be launchable it must implement two

extensions. These are org.eclipse.ercp.eworkbench.applications and org.eclipse.ui.views.

For the org.eclipse.ercp.eworkbench.applications extension, the properties of “application” must be

set. An application ID is required and is typically the application package name. Name is a human

readable description. For the properties of “views”, at least the normal field must be set. This is the

reference ID of a specific view.

First, make your application a workbench application:

1. Switch to the manifest Extensions tab and click Add.

2. Uncheck Show only extension points from the required plug-ins.

3. Select org.eclipse.ercp.eworkbench.applications and click Finish.

4. Click No on the New Plug-in dependency popup.

5. Right click org.eclipse.ercp.eworkbench.applications in the All Extensions list.

6. Click New > Application.

For the org.eclipse.ercp.eworkbench.views extension, the properties of “view” must be set. A view ID is

usually defined as the combination of the view’s package name with a “.normal” postfix. Name is a

human readable description. Class specifies the particular View class (from above) that implements the

view. Category must be one of:

v org.eclipse.ercp.category.normal

v org.eclipse.ercp.category.large

v org.eclipse.ercp.category.status

Developing applications 161

Page 172: Lotus Expeditor: Developing Applications for Lotus Expeditor

Next, add a view for your application:

1. On the Extensions tab click Add.

2. Uncheck Show only extension points from the required plug-ins.

3. Select org.eclipse.ui.views and click Finish.

4. Right click org.eclipse.ui.views in the All Extensions list.

5. Select New > View.

6. Change the view name to something user friendly.

7. Change the class name to match the view class created above.

8. Set the category.

Connect your view to your application:

1. Right click the application element.

2. Click New > Views.

3. Add the view ID specified in step 6 above to the Normal field.

4. Click Save.

Running your application on the development runtime: You can run your application on the Lotus

Expeditor for Devices runtime by launching the workbench. The workbench will detect your application

and list it as an application you can start.

To run the workbench:

1. Select Run > Run...

2. Double-click Client Services.

3. Change the new configuration’s name.

4. For Runtime JRE, select jclDevice Win32 x86.

5. Switch to the Profile tab and select Default Device Target.

6. Press Apply and then Run.

Creating an eRCP workbench application from an existing project

To create an eRCP workbench application from an existing project, perform the following procedure:

1. Select File > New > Other.

2. Select CVS > Projects from CVS.

3. Select the Next button.

4. Enter the Repository Location Information:

a. Input “dev.eclipse.org” in the Host field.

b. Input “/cvsroot/dsdp” in the Repository path field.

c. Input “anonymous” in the User field.

d. Input your E-mail address in the Password field.

e. Select pserver in the Connection type list box.

f. Select the Next button.5. Select the Module:

a. Select Use an existing module.

b. Open org.eclipse.ercp.

c. Select org.eclipse.ercp.app.

d. Select the Finish button.6. Open the Plug-in Development perspective:

a. Select Window > Open Perspective > Other.

162 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 173: Lotus Expeditor: Developing Applications for Lotus Expeditor

b. Select Plug-in Development.

c. Select the OK button.7. Refactor/Rename the template project:

a. Select org.eclipse.ercp.app [dev.eclipse.org].

b. Select Refactor > Rename.

c. Enter “my.app”.

d. Select the OK button.8. Expand the template project and Refactor/Rename the source files:

a. Select src > org.eclipse.ercp.app.

b. Select Refactor > Rename.

c. Enter my.app.

d. Ensure you select the check box for Update textual occurrences in comments and strings (forces

preview).

e. Select preview.

f. Select OK.9. Modify the sample code:

a. Open my.app.

b. Modify the manifest to uniquely identify the plug-in:

1) Open META-INF.

2) Select MANIFEST.MF.

3) Change org.eclipse.ercp.app reference in Bundle-SymbolicName to my.app.c. Modify the extension IDs:

1) Select the Extensions tab.

2) Expand everything under org.eclipse.ercp.eWorkbench.applications.

3) Change application ID to my.app.

4) Change views normal to my.app.views.normal.

5) Change views large to my.app.views.large.

6) Expand the views and preferences extensions and similarly change all org.eclipse.ercp.app

references to my.app.

Note: Alternately, you can change the extension IDs by editing the plugin.xml directly from

the plugin.xml tab and replacing all org.eclipse.ercp.app occurrences to my.app.d. Modify the resource file to uniquely identify the plug-in in the user interface:

1) Select plugin.properties.

2) Modify appname to the following:

v My App3) Close the properties file.

Deploying an eRCP workbench application

To deploy an eRCP workbench application, perform the following procedure:

1. Create feature for deploying the plug-in:

a. Select File > New > Other.

b. Select Plug-in Development.

c. Select Feature Project.

d. Input My App as the Project name.

e. Select Next.

f. Select my.app and Finish.

Developing applications 163

Page 174: Lotus Expeditor: Developing Applications for Lotus Expeditor

2. Create an update site for the feature:

a. Select File > New > Other.

b. Select Plug-in Development.

c. Select Update Site Project.

d. Select Next.

e. Input My Site as the Project name.

f. Select Finish.

g. Select Add Feature in the Update Site Map.

h. Select My_App in the Feature Selection.

i. Select OK.3. Modify the update site’s site.xml file to be compatible with devices:

If you want the features on this site to only be deployable to devices, you can modify the update

site’s site.xml file to make it a device specific site (as in step b below). You may want to do this if

you have similarly named features which are targeted to desktops and do not want users to

accidentally install the device versions of these features. Generally, you will not want to do this

because device applications can also run on the desktop runtime and there is no need to restrict them

to devices.

a. Select the site.xml tab.

b. Replace <site> with <site type="org.eclipse.ercp.update.http">.

c. Select File > Save.4. Synchronize the update site:

a. Select Synchronize in Update Site Map.

b. Select Finish in Feature Properties Synchronization.5. Build the update site:

a. Select Build All in Update Site Map.6. Export the update site:

a. Select File > Export.

b. Select General > File System.

c. Select My Site.

d. Specify a location in the To directory field.

e. Select Finish.

f. Copy the exported directory onto the device.

Installing an eRCP workbench application

To install an eRCP workbench application, perform the following procedure:

1. On the device, select Start > Programs > Lotus Expeditor.

2. Select Application Manager.

3. Select Install New Application/Features.

4. Select Command.

5. Select Add Location.

6. Select Local and Next.

7. Select My Site on the device file system.

8. Select Finished.

9. Check the new location and select Next.

10. Expand the My Site feature, and check My App. Select Next.

11. Accept the license agreement and Next.

164 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 175: Lotus Expeditor: Developing Applications for Lotus Expeditor

Running an eRCP eWorkbench application

To run an eRCP eWorkbench application, perform the following procedure:

1. Select Start > Programs > Lotus Expeditor.

2. Select My App.

Managing an eRCP eWorkbench application

Once the application is installed on the device, it is necessary to manage the versions of the application

when making additional changes. There are several methods available for performing this task.

1. The standard development method is to use the Lotus Expeditor Application Manger to uninstall the

application and reinstall using the methods described above.

2. A shortcut method of updating an application is to export the application and copy the plug-in

directly to the device:

a. Select File > Export.

b. Select Plug-in Development > Deployable plug-in and fragments.

c. Select the plug-in.

d. Specify a location in the Directory field.

e. Close all Lotus Expeditor Applications on the device.

f. Copy the plug-in jar from the exported plug-ins directory to the device’s /eclipse/plugins

directory.3. A third way of performing the task is to update the version number of the plug-in and use the

methods described above to create an update site. Then use Application Manager to update the

existing plug-in. As long as the version of the plug-in greater then the previously installed version it

will install correctly. In the event that the version isn’t managed correctly, the application can be

uninstalled and reinstalled using the Application Manager.

Extending the capabilities of your application

There are common conventions that have been adopted in order to construct applications that are

intuitive and easy to use. By following the conventions and guidelines, you will enable your users to

become quickly productive, and will reduce the training required and the frustrations experienced in

using the application.

The subsections of this chapter focus on specific areas with suggestions and guidelines in how to build

your application to work in a pluggable, cooperative environment. In addition, since Lotus Expeditor is

based on Eclipse, you can also refer to the Eclipse User Interface Guidelines. To view the Eclipse User

Interface Guidelines, visit: http://www.eclipse.org/articles/Article-UI-Guidelines/Contents.html.

Customizing the user interface

Lotus Expeditor is a platform that enables multiple applications to run within a single workbench. It

therefore provides a mechanism for applying a common style to the user interface of the applications that

are contributed to it. It does so by supporting not only standard SWT controls, but also a set of custom

widgets for which you can extend the customization.

If you use these custom widgets to build the user interface of your application, you get the added

capability of reflecting the workbench style or theme in your application to ensure that it looks like a

member of the suite of application offerings. You can also apply a static style to the widgets to give your

application a look and feel that is different from the other application offerings, if that is what you want

to do.

Using themes:

The platform provides a set of widgets that are theme-aware. Being theme-aware means that the color,

font and background styles of the controls are managed by a centralized theme definition.

Developing applications 165

Page 176: Lotus Expeditor: Developing Applications for Lotus Expeditor

This theme definition is defined by a Cascading Style Sheet (CSS). CSS is a standard developed by the

World Wide Web Consortium (W3C) to provide a mechanism for adding style to Web documents. When

the platform starts, the StyleManager class is initialized with CSS content that was defined either through

administrator or end user preferences. If no CSS content is available, the user interface defaults to a

native look and feel. When the CSS content is parsed, the style manager is initialized with CSS content

and any widgets that have registered themselves with the style manager are updated with style

properties that reflect the new CSS content.

After you construct a widget, you can call the StyleManager to apply the proper styling to it. The

StyleManager initializes the paint delegate for the given SWidget internally and applies the style specified

by CSS to it.

The style manager is provided in the com.ibm.rcp.ui.css plug-in and depends on the W3C SAC (Simple

API for CSS) and the W3C Flute implementation of SAC. See http://www.w3.org/TR/SAC/ for more

details.

The default personality class provided in the com.ibm.rcp.personality plug-in manages the initialization

of the StyleManager and retrieves the CSS content.

To register a widget with the style manager:

1. Use or extend the default personality or if you are implementing your own personality, make sure it

calls one of the getInstance() methods of the StyleManager class and initialize the sytle manager with

CSS content by calling the parseURL() method.

For example:

URL cssURL = new URL(cssLocation);

StyleManager.getInstance().parse(cssURL);

2. Make a single call to the style() method for the widget.

For example, the following code registers an instance of SButton with the style manager:

SButton myButton = new SButton(parent, SWT.PUSH);

StyleManager.getInstance().style(myButton, false);

The parameters of the style() method let you specify whether you want to do the following:

v Apply the specified style to any child controls of a widget if the widget is a composite.

v Register the widget to be notified of any changes to the theme at runtime.3. In some cases, you may need to specify a CSS Class and set an ID on the widget to achieve the

proper styling. Use the setData(String key, Object value) method of SWidget to specify these

attributes.

For example:

// Create a button widget and style it

SButton myButton = new SButton(parent, SWT.PUSH);

StyleManager.getInstance().style(myButton);

...

// Create a composite widget of class MainWindow that

// contains a button and style it but do not style the button

Composite myComposite = new Composite(parent, SWT.NONE);

SButton myButton = new SButton(myComposite, SWT.PUSH);

myComposite.setData(StyleManager.CSS_CLASS, “MainWindow”);

StyleManager.getInstance().style(myButton, false);

...

// Create a button widget of class LaunchButton and style it

// but do not update the button if the styles change

166 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 177: Lotus Expeditor: Developing Applications for Lotus Expeditor

SButton myButton = new SButton(parent, SWT.PUSH);

myButton.setData(StyleManager.CSS_CLASS, “LaunchButton”);

StyleManager.getInstance().style(myButton, false, false);

Customizing the workbench:

Eclipse provides an SPI that allows clients to customize the look and feel of the Eclipse workbench. Lotus

Expeditor provides an implementation of this SPI called the Styled Presentation Factory, which is an

implementation of the Eclipse Presentation Factory SPI.

The styled presentation factory is theme-aware, which means that it leverages the style manager to drive

the look and feel. You can use the SPI to format the user interface framework by providing the style to

use for the trim for view parts, editor parts, the sidebar, toolbars, menu bars, and status bars. The styled

presentation factory uses many of the custom widgets in the SWTEX custom widget collection, including

the SViewForm, SViewStack, SToolBar and STabFolder widgets.

You cannot implement the Styled Presentation Factory using an API. Instead you contribute it to the

Eclipse platform using the org.eclipse.ui.presentationFactories extension point. This extension is provided

in the com.ibm.rcp.ui plug-in.

To customize the workbench, perform the following steps:

1. Initialize the Styled Presentation Factory by declaring the StyledPresentationFactory class in a factory

tag within the org.eclipse.ui.presentationFactories extension tag.

For example:

<extension point="org.eclipse.ui.presentationFactories">

<factory

class="com.ibm.rcp.ui.presentations.StyledPresentationFactory"

id="com.ibm.rcp.ui.presentations.StyledPresentationFactory"

name="Styled Presentation">

</factory>

</extension>

2. Enable the Styled Presentation factory using the Eclipse preference presentationFactoryId. Specify the

presentation factory class that you want to use with the following key:

org.eclipse.ui/presentationFactoryId=

com.ibm.rcp.ui.presentations.StyledPresentationFactory

Custom widgets:

The SWidgets are a collection of custom SWT widgets that are designed for use in Lotus Expeditor

applications.

The custom widget library embraces the SWT programming model and enables applications to mix and

match these widgets with standard SWT widgets. SWidgets extend the capabilities for customizing the

look and feel of controls provided by standard SWT widgets. SWidgets, like all standard custom widgets

based on SWT, subclass the Canvas class and register all the necessary event handlers. For SWidgets that

are similar to SWT controls, such as the SMenu and SMenuItem classes, the SWidget API is compatible

with the API of the equivalent SWT control. The advantage of using SWidgets is that the look and feel of

controls created using SWidgets is customizable. SWidgets are customizable because they use a paint

delegate pattern that enables all the rendering for the widgets to be done by a pluggable delegate object.

The paint delegate objects act like the skin of the control, and are referred to as skins. In fact, the S in

front of the widget class names stands for skinnable.

The library contains the following SWidgets:

v SButton – Represents a button. It is used, for example, as the control that a user clicks to activate the

launch menu. The SButton custom widget provides support for customizable rendering and some

alignment options that the standard SWT button does not support.

Developing applications 167

Page 178: Lotus Expeditor: Developing Applications for Lotus Expeditor

v SMenu – Represents the launch menu and other menus in the client. The SMenu custom widget

provides support for customizable rendering. It also provides functionality that the standard SWT

menu does not provide, such as support for context menus. The SCoolBar supports tearing out and

floating menu items or docking SMenu items in a SCoolBar in the form of a floating SToolBar.

v SToolbar and SCoolbar – Represent the main window toolbar. A SCoolbar is a container widget that

contains instances of SToolbars that may be repositioned or floated. The SToolbar widget also

represents the toolbar inside view parts and editor parts in the workbench. A toolbar that displays in a

view or editor is commonly referred to as an actionbar. The widgets provide support for a

customizable rendering and functionality that the standard SWT toolbar and coolbar do not. For

example, the SCoolBar supports tearing out and floating toolbars. The SToolBar and SCoolBar widgets

both have corresponding Jface contribution and wrapper classes. The API for these classes is very

similar to the API for the standard Jface manager and contribution classes.

v STabFolder – Represents a “grouped tab.” Grouped tabs allow for child tabs to be consolidated under a

parent tab and made accessible through a pop-up menu. The STabFolder is used in the main launcher

user interface and to represent tabs in many other places in the user interface.

v STable – Represents a table that structures the data that displays in views or editors. The custom table

widget provides support for a customizable rendering and functionality that the standard SWT table

does not provide.

v SViewForm and SViewStack – The SViewForm widget represents the area surrounding sidebar and

stand–alone views within a perspective. The SViewStack widget represents the container for a

collection of sidebar panels and enables you to resize and collapse the stack horizontally.

The custom widgets are provided in the com.ibm.rcp.swtex plug-in, which has dependencies on the

org.eclipse.swt plug-in. The library also contains a set of JFaceEX action classes.

Custom toolbar:

The Lotus Expeditor provides custom toolbar APIs that you can use to implement a toolbar and

contribute items to it in the user interface of a Lotus Expeditor application.

The custom toolbar provides the following features:

v Renders the toolbar skin, which means it formats the toolbar to make its style consistent with the style

defined for the application it displays in.

v Manages drag and drop of items within the toolbar.

v Saves and loads the last state of toolbar items using the Eclipse memento pattern, which uses the

saveState and restoreState methods to remember the position of each toolbar item when the user shuts

down the client so that the same toolbar items display when the user restarts it.

You can contribute Eclipse-based or custom controls to the main toolbar statically or dynamically. If you

contribute a toolbar item statically, when the user or administrator uninstalls the associated application

from the client, the toolbar item is not removed from the ActionSets extension point unless the user or

administrator removes it explicitly. The toolbar item will not be displayed because the view it is

associated with is no longer available, but it does add unnecessary clutter to the ActionSets extension

point. Contributing toolbar items dynamically allows for more flexibility. If a user or administrator

uninstalls an application, the dynamically-added menu item associated with it is automatically removed

from the extension point as well. Adding items dynamically takes advantage of the plug and play

capabilities of applications built for the Lotus Expeditor.

The com.ibm.rcp.swtex plug-in contains classes that are equivalent to those provided in the Eclipse

org.eclipse.swt plug-in, but that provide in addition support for rendering the skin of the control

appropriately. This plug-in provides the following APIs:

v com.ibm.rcp.swt.widgets.skins.SCoolBar

v com.ibm.rcp.swt.widgets.skins.SCoolItem

v com.ibm.rcp.swt.widgets.skins.SToolBar

168 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 179: Lotus Expeditor: Developing Applications for Lotus Expeditor

v com.ibm.rcp.swt.widgets.skins.SToolItem

The com.ibm.rcp.jfaceex plug-in contains classes that are equivalent to those provided in the Eclipse

org.eclipse.jface plug-in, but that provide in addition support for rendering the skin of the control

appropriately. This plug-in provides the following APIs:

v com.ibm.rcp.jface.action.SCoolBarManager

v com.ibm.rcp.jface.action.SToolBarManager

v com.ibm.rcp.jface.action.SToolBarContributionItem

v com.ibm.rcp.jface.action.SActionContributionItem

v com.ibm.rcp.jface.action.SControlContribution

Contributing Eclipse-based controls to the toolbar statically:

You can add pre-defined Eclipse buttons, such as push, radio, toggle or pulldown buttons to the main

toolbar statically by extending the standard Eclipse ActionSet or ActionSetPartAssocation extension

points.

You can also enable or disable the controls or toolbar items in the main toolbar and show or hide a group

of items in the main toolbar

To add an Eclipse-based control to the main toolbar, complete the following steps:

1. Contribute the control to the ActionSets extension point in the plugin.xml file for the application. For

example:

<extension point="org.eclipse.ui.actionSets">

<actionSet

label="Sample Action Set"

visible="true"

id="sample.toolbar.actionSet">

<action

label="Sample Action"

icon="icons/sample.gif"

class="sample.toolbar.actions.SampleToolBarAction"

toolbarPath="END_GROUP"

id="sample.toolbar.actions.SampleToolBarAction">

</action>

</actionSet>

</extension>

2. Associate the action set with a specific view by extending the actionSetPartAssociation extension

point. For example:

<extension point="org.eclipse.ui.actionSetPartAssociations">

<actionSetPartAssociation targetID="sample.toolbar.actionSet">

<part id="sample.ui.view"/>

<part id="sample.ui.view2"/>

</actionSetPartAssociation>

</extension>

When one of the associated views, the sample.ui.view or sample.ui.view2, is activated, the action set you

defined displays in the main toolbar.

Contributing custom controls to the main toolbar statically:

You can add any custom control that implements the com.ibm.rcp.jface.actions.ISContributionItem

interface to the main toolbar and enable or disable it statically by extending the ControlSet extension

point.

You can use the ControlSet extension point to add controls to the status bar as well.

Developing applications 169

Page 180: Lotus Expeditor: Developing Applications for Lotus Expeditor

To add a custom control to the main toolbar, complete the following steps:

1. Contribute to the ControlSet extension point in the plugin.xml file for the application. For example:

<extension point="com.ibm.rcp.platform.controlSets">

<controlSet visible="true" id="com.ibm.app.toolbar.controlset">

<control

toolBarPath="SampleGroup"

id="sample.FontFaceDropdownControlContribution"

class="sample.FontFaceDropdownControlContribution">

</control>

</controlSet>

</extension>

2. Create a corresponding class called sample.FontFaceDropdownControlContribution that extends the

com.ibm.rcp.jface.actions.SControlContribution class. The

com.ibm.rcp.jface.actions.SControlContribution class implements the

com.ibm.rcp.jface.actions.ISContributionItem interface. For example:

public class FontFaceDropdownControlContribution extends

com.ibm.rcp.jface.actions.SControlContribution {

/**

* the default constructor.

*/

public FontFaceDropdownControlContribution () {

super();

}

/* (non-Javadoc)

* @see com.ibm.rcp.jface.action.SControlContribution#createControl(

* org.eclipse.swt.widgets.Composite)

*/

protected Control createControl(Composite parent) {

// create a font face combo box in a tool item.

Combo combo = new Combo(parent, SWT.READ_ONLY);

for (int i = 0; i < faces.length; i++) {

combo.add(faces[i]);

}

return combo;

}

}

Contributing items to a toolbar dynamically:

You can add custom controls, such as coolitems or a coolbar to the main toolbar dynamically and enable

or disable them dynamically by using the Eclipse dynamic extension API.

Before completing the steps below, you must complete the steps defined in Completing custom controls to

the main toolbar statically.

To contribute toolbar items to the main toolbar dynamically, complete the following steps:

1. Call the addContribution method of the org.eclipse.core.runtime.IExtensionRegistry interface provided

by the Eclipse dynamic extension API in the org.eclipse.equinox.registry plug-in to add an extension

dynamically.

For example, the following code adds a custom fontface dropdown control to the main toolbar:

public void addFontFaceDropdownControl() {

StringBuffer sb = new StringBuffer();

sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

sb.append("<plugin>");

sb.append("<extension point=\"com.ibm.rcp.platform.controlSets\"");

sb.append(" id=\"com.ibm.app.toolbar.controlsets\">");

sb.append("<controlSet ");

sb.append(" visible=\"true\"");

170 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 181: Lotus Expeditor: Developing Applications for Lotus Expeditor

sb.append(" id=\"com.ibm.app.toolbar.controlset\">");

sb.append("<control");

sb.append(" id=\"sample.FontFaceDropdownControlContribution\"");

sb.append(" toolbarPath=\"ToolSetId/SampleToolGroup\"");

sb.append(" class=\"sample.FontFaceDropdownControlContribution\"/>");

sb.append("</controlSet>");

sb.append("</extension>");

sb.append("</plugin>");

try {

addExtension(sb.toString());

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

}

void addExtension(String xmlsrc) throws UnsupportedEncodingException {

// use Eclipse Dynamic Extension API

IExtensionRegistry reg = RegistryFactory.getRegistry();

Object key = ((ExtensionRegistry)reg).getTemporaryUserToken();

Bundle bundle = Activator.getDefault().getBundle();

IContributor contributor =

ContributorFactoryOSGi.createContributor(bundle);

ByteArrayInputStream is =

new ByteArrayInputStream(xmlsrc.getBytes("UTF-8"));

reg.addContribution(is, contributor, false, null, null, key);

}

Note: See the Eclipse API javadoc for the org.eclipse.core.runtime.IExtensionRegistry#addContribution

for more information on the addContribution method.

2. Call the removeExtension method of the org.eclipse.core.runtime.IExtensionRegistry interface to

remove the custom control from the toolbar.

For example, the following methods remove the custom fontface dropdown control from the toolbar:

public void removeFontFaceDropdownControl()() {

// specify extension point and extension id

removeExtension("com.ibm.rcp.platform.controlSets",

"com.ibm.app.toolbar.controlsets");

}

void removeExtension(String extensionPointId, String extensionId) {

// use Eclipse Dynamic Extension API

IExtensionRegistry reg = RegistryFactory.getRegistry();

Object token = ((ExtensionRegistry)reg).getTemporaryUserToken();

IExtension extension =

reg.getExtension(extensionPointId, extensionId);

reg.removeExtension(extension, token);

}

Note: See the Eclipse API javadoc for the

org.eclipse.core.runtime.IExtensionRegistry#removeExtension for more information on the

removeExtension method.

Hiding or displaying items in the toolbar:

You can display or hide a group of items, both custom controls and standard buttons, in the main toolbar

using the standard Eclipse Activities API.

To hide or display a toolbar item in the toolbar, complete the following steps:

1. In the plugin.xml file, define a toolbar activity and associate the toolbar activity with a control set ID.

For example, the following code defines a toolbar activity called ″sample.toolbar″ and associates it

with the control set ID, ″com.ibm.rcp.platform.controlSet″:

Developing applications 171

Page 182: Lotus Expeditor: Developing Applications for Lotus Expeditor

<extension

point="org.eclipse.ui.activities">

<activity name="Sample ToolBar Activity"

id="sample.toolbar">

</activity>

<activityPatternBinding

activityId="sample.toolbar"

pattern=""sample\.dynamic\.toolbar\.plugin/

com\.ibm\.app\.toolbar\.controlset">

</activityPatternBinding>

</extension>

2. In the code, add a part listener to enable or disable the toolbar activity that displays the toolbar item.

For example:

IPartListener partListener = new IPartListener() {

public void partActivated(IWorkbenchPart part) {

if (part != null) {

IWorkbenchActivitySupport workbenchActivitySupport =

PlatformUI.getWorkbench().getActivitySupport();

IActivityManager activityManager =

workbenchActivitySupport.getActivityManager();

Set enabledActivityIds =

new HashSet(activityManager.getEnabledActivityIds());

if (part.getTitle().equals("Sample UI View") != -1) {

// add toolbar activity.

enabledActivityIds.add("sample.toolbar");

}

else {

// remove toolbar activity.

enabledActivityIds.remove("sample.toolbar");

}

workbenchActivitySupport.setEnabledActivityIds(enabledActivityIds);

}

}

public void partBroughtToTop(IWorkbenchPart part) {

}

public void partClosed(IWorkbenchPart part) {

}

public void partDeactivated(IWorkbenchPart part) {

}

public void partOpened(IWorkbenchPart part) {

}

};

public void setupControlSetActivities() {

/** create an UI thread to add the partListener to disable the

* toolbar activity.

*/

UIJob job = new UIJob("Setup controlSet Activities") {

public IStatus runInUIThread(IProgressMonitor monitor) {

IWorkbenchWindow window =

PlatformUI.getWorkbench().getActiveWorkbenchWindow();

window.getPartService().addPartListener(partListener);

return new Status(IStatus.OK,

Activator.PLUGIN_ID,

IStatus.OK,

"Setting up controlSet Activities complete",

null);

}

};

job.schedule();

}

Custom table control:

172 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 183: Lotus Expeditor: Developing Applications for Lotus Expeditor

The custom table control uses the Eclipse JFace model, view, controller (MVC) framework to present data

to users in a clearly structured format.

The custom table control supports generic SWT widgets. It provides interfaces and listeners to support an

asynchronous data loading mechanism. An asynchronous data loading mechanism enables the table to

load data only on an as-needed basis, improving the performance and reducing the memory cost

normally associated with retrieving data. The custom table control has the following features:

v Supports flat list and vertical layouts; supports a tree model.

v Provides a customizable user interface. It enables users to highlight text strings, edit cell content, add

alternating row background colors, color-code text, show, hide, or resize columns, and drag and drop

columns or data.

v Enables users to quick find data.

v Supports nested tables.

v Its widgets are skinnable, which means the color and font of the table, table body, and header match

the style of the application if the application is using a custom theme.

v Supports gutter selection (used in Notes) or Ctrl+ key selection (used in standard operating systems).

v Provides listeners to report user selections.

v Provides widgets that support the SWT accessibility APIs.

v Provides bidirectional support.

The Custom Table Control is comprised of the following parts:

v Content Provider

v Table Viewer

v Table widgets

Content provider:

The Content Provider is a set of interfaces that are implemented by applications to supply data to the

table control.

The table control has a paging mechanism that it uses to limit the amount of data it displays to one

subset of the available data at a time. It maintains a virtual mapping of the data divided into multiple

pages. You can specify the amount of data for the table to display per page by passing the following

parameters to the provider.

v count – Defines how many data items to load into memory at a time; it uses an integer value, such as

50.

v offset – Defines the first data element to load into memory using an index value, such as 0.

For example, a flat list table with a provider that is passed an offset parameter of 0 and a count

parameter of 50, would display data elements 1 through 49. If the entire data set included 75 items, items

50 through 75 would be displayed on a second page.

The following types of content providers are available:

v IPagedContent – Provides access to a content provider that returns one page of data at a time. The

getPage method returns the elements with a given offset and count. It also provides find methods that

enable users to search the data items for a specific data element.

v ITreePagedContent – Extends the IPagedContentProvider. It provides access to a content provider that

checks if the data item has children and preserves its relationship to those child objects and other

objects when it displays the data item.

Creating a hierarchical or categorized table:

Developing applications 173

Page 184: Lotus Expeditor: Developing Applications for Lotus Expeditor

You can create a table that has entries that can be categorized, or that display hierarchically, such as the

documents and responses that comprise a thread in a discussion view, by using a tree provider to define

the structure of the table control.

The tree label provider that you implement creates labels that can do either of the following:

v Span more than one column.

v Display a +/- sign to indicate that the item is expandable and has child documents that can be

displayed.

Adding listeners to expandable table rows enables you to track changes to rows, which can be expanded

in the following ways:

v Users can click the +/- sign displayed beside an entry that is hierarchical to expand or collapse the

row.

v Applications can programmatically expand or collapse a row.

To create a tree table:

1. Implement the ITreePagedContentProvider interface to indicate that you want the table to be

implemented as a tree control that has expandable columns. The ITreePagedContentProvider interface

inherits from the IPagedContentProvider interface.

2. Implement the IExpandTableLabelProvider.

For example:

public int columnSpan(Object element, int columnIndex) {

// TODO Auto-generated method stubif (arg0 instanceof GroupedMetadata){

if (element instanceof Categories){

switch(columnIndex){

case 0:

return _viewer.getTable().getColumnCount();

}

}

return 0;

}

public boolean isExpandable(Object element, int columnIndex) {

// TODO Auto-generated method stub

if (element instanceof Categories){

switch(columnIndex){

case 03:

return true;

}

}

return false;

}

3. Register a listener to the table that listens for the expansion or collapse of a table row.

For example:

Document doc = (Document)root;

//expand this level

this.expandItem(doc, doc.needExpanded());

//The application can monitor the event when a table item which has

//children is expanded or collapsed.

table.addTreeListener(new TreeListener(){

public void treeCollapsed(TreeEvent e) {

// TODO Auto-generated method stub

System.out.println("treeCollapsed(TreeEvent e) : " + e.toString());

TableItem item = (TableItem)e.item;

_viewer.refresh(item.getData(), true);

}

public void treeExpanded(TreeEvent e) {

174 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 185: Lotus Expeditor: Developing Applications for Lotus Expeditor

// TODO Auto-generated method stub

System.out.println("treeExpanded(TreeEvent e) : " + e.toString());

TableItem item = (TableItem)e.item;

item.setText(0, " 3 Messageing in threading " + item.getText(3));

// item.setImage(0, TestView.unread_descriptor);

}

});

Optimizing table performance:

You can decrease the time it takes to initially display data in a table by creating a table that pages and

trims the data it displays.

Paging data means that instead of showing all the rows of the table when a user first opens it, you

specify a number of rows to display per page and enable users to page through the table. Limiting the

number of rows per page enables the page to display more quickly because it has less data to retrieve

initially. It also makes the table easier for users to read and use. Trimming data means that the table does

not store any data in memory that does not need to be displayed immediately. For example, if an entry

has child documents, but the entry is collapsed, a trimmed table does not store the child entries in

memory, but instead retrieves them at the time that the row is expanded. By default, the table control

stores all data related to the currently displayed page in memory.

To optimize table performance:

1. Implement the IPagedContentProvider interface.

2. Use the void setItemTrimming(boolean enabled) method to enable automatic item trimming in virtual

tables.

Table viewer:

The Table viewer is a viewer that interacts with the table widgets.

It is responsible for associating data with the widgets that manipulate the data. It updates the widget

labels, adds or removes data from the table, and searches and sorts elements in the table.

The table viewer requests data from the provider and retrieves the data elements using an asynchronous

loading thread. The AsyncStructureViewer is the super class for the TableViewer.

Adding and removing table entries:

Use the methods in the Table Viewer to add and remove entries to the table.

The methods add or remove the table entries in-memory, but do not add or remove them from the data

source. You can register listeners to monitor adding and removing events, and then add or remove the

corresponding entries from the data store.

1. Create the data object you want to add to the table. For example:

Mail mail3 =new Mail();

mail3.setAuthor("New Data-3");

mail3.setSubject("Add Row form Menu");

mail3.setSendDate(new Date(System.currentTimeMillis()));

mail3.setSize(20);

mail3.setParent((Mail)DataUtil.getDatas().get(3));

2. Use the table viewer add() method to add the object to the table. For example:

TestView.getInstance().getViewer().add(mail3);

3. Use the table viewer remove() method to remove the object from the table. For example:

TestView.getInstance().getViewer().remove(mail3);

Developing applications 175

Page 186: Lotus Expeditor: Developing Applications for Lotus Expeditor

Implementing inline editing:

You can create cells that are editable by users by implementing the ICellModifier and CellEditor classes in

the TableViewer.

The ICellModifier interface indicates whether a cell can be changed, and if it can be, enables users to

provide a value for the cell. The interface has the following methods:

v public boolean canModify(Object arg0, String arg1) -- arg0 is the data of the row which contains the

cell, arg1 is the column ID of parent column of the cell. The returned value tells table if value of this

cell can be modified.

v public Object getValue(Object arg0, String arg1) -- arg0 and arg1 has same meaning as above method.

This method returns the value of specified cell.

v public void modify(Object arg0, String arg1, Object arg2) -- arg0 is the table item which contains the

cell, and arg1 is the column id of parent column of the cell, arg2 is the value to be changed to.

The CellEditor class is a JFace class that you must implement to keep the table JFace-compatible.

To implement inline editing, perform the following steps:

1. Implement the ICellModifier interface for the table viewer.

2. Call the setCellModifier method.

3. Use the setCellEditor() method to add an inline editor to the cell.

4. To disable an inline editor, pass a null parameter to the setCellEditor() method.

_viewer.setCellModifier(new ICellModifier(){

public boolean canModify(Object arg0, String arg1) {

return true;

}

public Object getValue(Object arg0, String arg1) {

if(arg0 instanceof Mail){

if(arg1.equalsIgnoreCase("ID_SUBJECT")){

return ((Mail)arg0).getSubject();

}

}

return null;

}

public void modify(Object arg0, String arg1, Object arg2) {

System.out.println("Please modify it");

}

});

CellEditor[] editors=new CellEditor[tableColCount];

for(int k=0;k<editors.length;k++){

editors[k]=null;

}

//disable the cell editor

editors[1]=new TextCellEditor(_viewer.getTable().getBody());

if(isEnableEditor)

_viewer.setCellEditors(editors);

else

_viewer.setCellEditors(null);

Adding listeners to tables:

You can pass a parameter called eventType to the addCellListener() method of the table control to register

a listener for an SWT event.

176 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 187: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 11. Adding listeners to table cells

Table widget How to add a listener to it

Cell Specify a col parameter for the SWT.Selection event. The col parameter

identifies the column in which the listener should listen for events.

Row (all cells in) Do not specify a col parameter.

Table (all cells in) Specify a col parameter with the value -1.

First column (all cells in) Specify a col parameter with the value 0.

You can use the element parameter to set up a condition under which the event should be added to the

cell. Use it to compare an object passed into the method with the object currently stored in the table cell.

If the object in the cell which gets the mouse event is equal to the object you pass into the method, the

corresponding cell listener is invoked. If the parameter is null, the table viewer ignores the condition and

adds the event to the corresponding cells.

You can use the interface named public boolean equals(Object obj) of the Object class to facilitate the

comparison of the objects. By default, the objects in the Object class are equal while the instances of those

objects are equal in memory.

1. Implement a table viewer.

private ITableViewer _viewer;

2. Implement the addCellListener() method.

public void addCellListener(int eventType, int col, Object element,

ICellListener listener)

The following example adds a listener to a column:

private ITableViewer _viewer;

/**

* Adds a listener to the first column and ignores the object parameter.

*/

_viewer.addCellListener(SWT.MouseHover, 0,null,new ICellListener(){

public void cellResponse(CellEvent e) {

switch(e.type){

case SWT.MouseHover:

System.out.println("the first cell detect: mouse hover on ");

break;

}

}

});

The following example adds a listener to a row:

private ITableViewer _viewer;

/**

* Adds a table row listener by setting the column value to -1.

* All the cells can be selected because cell selection is enabled.

*/

_viewer.addCellListener(SWT.Selection, -1,null,new ICellListener(){

public void cellResponse(CellEvent e) {

}

}

});

Developing applications 177

Page 188: Lotus Expeditor: Developing Applications for Lotus Expeditor

The following example tests whether the author of the mail message, which displays in the first column,

is Dave, and if it is, adds a listener to it:

/**

* Add the listener to monitor the first column cell but it’s author must

* be “Dave.â€

*/

Mail mail = new Mail();

mail.setAuthor("Dave");

_viewer.addCellListener(SWT.MouseUp, 0,mail,new ICellListener(){

public void cellResponse(CellEvent e) {

switch(e.type){

case SWT.MouseUp:

System.out.println("A user has clicked a cell with author equal to

Dave.");

}

}

});

…

/*In the Mail Object class*/

/**

* The method to compare the mail’s author with given object

*

*/

public boolean equals(Object obj){

if(obj instanceof Mail){

Mail mail=(Mail)obj;

return author.equals(mail.getAuthor());

}

return false;

}

// turn off the cell selection, mouse click will cause row to be selected.

table.disableCellSelection();

Adding controls to tables:

You can display controls, such as a Link, CheckBox, and ProgressBar control in the table cells of tables

built using the custom table control.

To add a control to a table cell, perform the following steps:

1. Specify a control layout for the control you want to add to the table cell so that it displays in the

correct position in the table. For example:

final ControlLayoutData layoutData = new ControlLayoutData();

layoutData.leftMargin =5;

layoutData.topMargin =5;

layoutData.rightMargin=8;

layoutData.bottomMargin=5;

final ControlLayoutData linkLayoutData =new ControlLayoutData();

linkLayoutData.bottomMargin =3;

2. Implement a Control provider, which implements the IControlProvider interface, to add a table

widget to a table cell. For example:

_viewer.setControlProvider(new IControlProvider(){

3. Depending on the element type of the cell contents, activate different controls for different columns in

the table row. For example, the following code checks to see if the cell contains a mail element. If it

178 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 189: Lotus Expeditor: Developing Applications for Lotus Expeditor

does, it then checks to see which column the current cell is in. If it’s in column 3, it adds a link

control to the cell. If it’s in column 2, it adds a button control to the cell. If it’s in column 5, it adds a

progress bar control to the cell.

public Control getCellControl(Object element, int column) {

if(element instanceof Mail){

Mail mail = (Mail)element;

if(column==3 && mail.getSubject().toLowerCase().indexOf("<a")

!= -1 && mail.getSubject().toLowerCase().indexOf("</a>") != -1){

final Link link = new Link(table.getBody(),

SWT.NO_FOCUS|SWT.NO_BACKGROUND);

link.setText(mail.getSubject());

link.setBackground(table.getBody().getBackground());

link.setLayoutData(linkLayoutData);

return link;

}

// the first cell

if(column ==2){

Button btn = new Button(table.getBody(),

SWT.CHECK|SWT.NO_FOCUS|SWT.NO_BACKGROUND);

btn.setBackground(table.getBody().getBackground());

btn.setLayoutData(layoutData);

return btn;

}

if(column == 5){

ProgressBar bar= new ProgressBar(table.getBody(),

SWT.INDETERMINATE|SWT.SMOOTH);

return bar;

}

}

return null;

}

});

Creating a table with a vertical layout:

A table with a vertical layout displays all the text of a row by forcing it to wrap and display in the

subsequent row.

A vertical layout is useful for displaying portrait-style documents within the Preview window, for

example. Use the setVerticalLayoutData() method of the STable class to set the table to use a vertical

layout. Using a vertical layout also enables you to apply different styles to different rows.

1. Construct a verticalLayoutData object that provides column layout information.

2. Call the setVerticalLayoutData() method of the STable class and pass to it the verticalLayoutData

object you constructed in Step 1.

3. Set the value of the setVerticalLayoutMode() method to true.

For example:

VerticalLayoutData layoutdata = new VerticalLayoutData();

TableColumn[] cols = table.getColumns();

//add these column into row 0

layoutdata.add(cols[0],0); //threading column

layoutdata.add(cols[3],0); //important

layoutdata.add(cols[4],0); //attachment

// next row, the column 1 align to column 3

layoutdata.setAlignColumn(cols[3]);

//add these column into row 1

layoutdata.add(cols[1], 1); //author

Developing applications 179

Page 190: Lotus Expeditor: Developing Applications for Lotus Expeditor

layoutdata.add(cols[2], 1); //date

cols[2].setAlignment(TableColumn.HORZ_ALIGNMENT_RIGHT); //right align

layoutdata.setWrapWidth(600); //width

table.setVerticalLayoutData(layoutdata); // set layout data

table.setVerticalLayoutMode(true); // turn on vertical layout

Another example:

VerticalLayoutData layoutdata = new VerticalLayoutData();

TableColumn[] cols = _table.getColumns();

layoutdata.add(cols[0],0); //add col 0 to the first row

layoutdata.add(cols[1], 0); //add col 1 to the first row

layoutdata.add(cols[2], 1); //add col 2 to the second row

Customizing tables:

You can customize a table by aligning the content of table columns and applying a style to the table

border.

To customize a table, complete the following steps:

1. Use the setAlignment() method on the table object to define how to align the content of the table

columns. Choose an alignment style from the following list of options:

v HORZ_ALIGNMENT_CENTER

v HORZ_ALIGNMENT_LEFT

v HORZ_ALIGNMENT_RIGHT

For example, the following code sets the alignment of the content of the columns to be centered:

tableCols[i].setAlignment(TableColumn.HORZ_ALIGNMENT_CENTER);

2. Use the set TableBorderStyle() method on the table object to apply a border style to the table. Choose

a table border style from the following list of options:

v TABLE_BORDER_NONE

v TABLE_BORDER_RECT

v TABLE_BORDER_ROUND

For example, the following code applies rounded borders to the table:

table.setTableBorderStyle(STable.TABLE_BORDER_ROUND);

Highlighting table text:

You can highlight specified strings in a table view built using the custom table control. Highlighted text

is useful in identifying instances of a text string in the documents returned by a search.

To implement text highlighting in a table, perform the following steps:

1. Specify the color or colors to use to highlight the text by calling the setHightlightingColor() method. If

you specify more than one color and the highlighted string contains more than one word, the first

word uses the first color specified and the subsequent words use the subsequent colors. For example:

table.setHightlightingColor(new Color[]{

Display.getCurrent().getSystemColor(SWT.COLOR_CYAN),

Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN),

Display.getCurrent().getSystemColor(SWT.COLOR_DARK_YELLOW),

Display.getCurrent().getSystemColor(SWT.COLOR_DARK_RED)});

2. Enable highlighting for the table. For example:

table.setHighlighting(true);

3. Provide the following parameters to the highlighting method to specify a hashmap which contains a

group of words to highlight.

180 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 191: Lotus Expeditor: Developing Applications for Lotus Expeditor

v keys -- Contains a hashmap of strings to search for.

v isHiding -- Boolean value that determines whether or not to highlight words that do not match the

strings in the hashmap specified by the keys parameter. If true, words that do not match the strings

in the keys parameter are not highlighted.

v ignoreCase -- Boolean value that determines whether to highlight only words that have the same

capitalization as the strings specified by the keys parameter. If true, words that have the same

characters are returned even if they use different capitalization.

For example:

table.highlighting(keys, false, true);

Alternating the color of rows in the table:

You can add alternating background colors to the rows in a table view.

To alternate the background color of a table view, perform the following step:

Define the color of the alternating row using the setAlternateBackgroundColor() method. For example:

table.setAlternateBackgroundColor(

table.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND),

Item_Alter_bgColor, true);

Nesting tables:

You can display a table widget as the child of another table widget.

The nested table, the table that displays within the parent table, is associated with a table item. Its size is

set by the application and its location is adjusted by the parent table when a user scrolls through it. You

cannot create a nested table that is larger than the parent table. If you do, the size of the nested table is

automatically reduced to fit within the parent table.

Use the following constructor of the STable class to make a Table widget that displays within another

table.

public STable(STableItem parent, int style)

This constructor method establishes the relationship of a nested table, a parent table item, and the parent

table.

For example:

table = new STable(_parentItem,

SWT.TITLE|SWT.SHADOW_IN | SWT.MULTI | SWT.HIDE_SELECTION );

Adding a titlebar to a table:

The titlebar of a table contains title images and title text and displays at the top of a table control.

To add a titlebar to a table, perform the following step:

Do one of the following:

v To add a titlebar to a new table, when constructing the table widget, pass SWT.TITLE as the style

parameter.

table = new STable(_parentItem,

SWT.TITLE|SWT.SHADOW_IN | SWT.MULTI | SWT.HIDE_SELECTION );

v To add a titlebar to an existing table, programmatically construct the titlebar using the setTitle(),

setImage(), and setFont() methods of the table class.

Developing applications 181

Page 192: Lotus Expeditor: Developing Applications for Lotus Expeditor

table.getTitleBar().setTitle(title);

table.getTitleBar().setImage((ImageDescriptor.createFromFile(

TestView.class, "Minus.gif")).createImage());

table.getTitleBar().setFont(new Font(Display.getCurrent(),

"Arial", 12, SWT.BOLD));

final STable _table = table;

table.getTitleBar().addImageClickedListener(new Listener() {

public void handleEvent(Event event) {

System.out.println("child tableimage clicked");

_table.setVisible(false);

//_table.dispose();

_parentItem.setExpanded(false);

_parentItem.justify();

_parentTable.justify();

_parentTable.redraw();

}

});

Implementing search:

Applications can register quick find listeners on a table. A quick find listener is invoked when a user

types a string into the quick find field. The listener retrieves the user’s input and then invokes the search

method provided by the table viewer.

The table invokes the quick find listener when a user inputs the first character and passes that first

character to it. The application then reacts and displays the supporting quick find user interface, such as

a dialog box that contains a text field, into which users can finish entering the string they want to search

for. The listener must pass that first character to the user interface control that displays the full search

string.

1. Implement the IQuickFindListener interface.

table.addQuickFindListener(new IQuickFindListener(){

2. Retrieve the first character of the string that the user enters in the quick find field using the

FindStartWithListener listener. For example:

public void quickFind(String findString) {

FindStartsWithListener listener = new FindStartsWithListener() {

public void FindStartsWith(String inputText) {

if (inputText.length() > 0) {

3. To perform a search, set the FindOptions object to the current table viewer. For example:

TableViewer viewer = getViewer();

FindOptions findOp = new FindOptions();

viewer.setFindOptions(findOp);

4. In the FindOptions object, indicate the direction of the search. For example:

findOp.setSearchDirectionDown(false);

5. Use the quickFindInColumn() method to retrieve the first table item which contains the search string.

Identify the column in which to search using the columnId parameter. The findString parameter

identifies the string to search for. The filter parameter is optional and indicates whether or not to

display items that do not contain the string specified in the findString parameter. If filter is set to true,

the table items that do not contain the findString are hidden. If it is set to false, they are displayed.

For example:

TableItem item = null;

item = viewer.quickFindInColumn("ID_AUTHOR", inputText);

if (item != null) {

ISelection selection = new StructuredSelection(item.getData());

viewer.setSelection(selection, true);

}

182 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 193: Lotus Expeditor: Developing Applications for Lotus Expeditor

}

}

};

6. Call the FindStartsWithDialog() method to display the results. For example:

new FindStartsWithDialog(getSite().getShell(), findString, listener);

}

});

For example:

table.addQuickFindListener(new IQuickFindListener(){

public void quickFind(String findString) {

FindStartsWithListener listener = new FindStartsWithListener() {

public void FindStartsWith(String inputText) {

if (inputText.length() > 0) {

TableViewer viewer = getViewer();

FindOptions findOp = new FindOptions();

viewer.setFindOptions(findOp);

findOp.setSearchDirectionDown(false);

TableItem item = null;

item = viewer.quickFindInColumn("ID_AUTHOR", inputText);

if (item != null) {

ISelection selection = new StructuredSelection(item.getData());

viewer.setSelection(selection, true);

}

}

}

};

new FindStartsWithDialog(getSite().getShell(), findString, listener);

}

});

Launcher:

The launcher is a button control that displays in the workbench area below the main menu and is labeled

Launch. When a user clicks the Launch button, a hierarchical drop-down list of items displays. Users can

click an item in the list to start an application, open an application document, or open a bookmark.

The WorkbenchWindowAdvisor on the client does the work of instantiating the controls used to represent

the launcher in the user interface. The default personality provided in the

com.ibm.rcp.platform.personality plug-in implements the DefaultWorkbenchWindowAdvisor. The

DefaultWorkbenchWindowAdvisor creates a SButton widget to represent the Launch button. It

instantiates the LauncherManager and passes a reference for it to the button. It then schedules a Job to

build the LauncherRegistry. The LauncherRegistry builds a list of launcher contributions. Upon

completion of that job a UIJob is scheduled to fill the Launcher with the contributions resulting from the

LauncherRegistry build.

The following classes are a few of the classes provided by the package com.ibm.rcp.jface.launcher:

v LauncherManager - The class that is used to manage launcher contributions and the UI of those

contributions. It uses SMenuManager to render launcher contributions in a SMenu and uses a given

IBookmarkProvider for dynamically fetching a bookmark provider’s content. The LauncherManager is

a singleton enforced by making the constructors private and providing a static

getInstance(WorkbenchWindow) method for obtaining the singleton LauncherManager for a given

WorkbenchWindow.

v LauncherContributionItem – This class is the base class that all contributions that to the Launcher must

inherit from in order to be launched. The exceptions are a Separator or a GroupMarker.

Developing applications 183

Page 194: Lotus Expeditor: Developing Applications for Lotus Expeditor

v EnvironmentVar - Used by the NativeProgramLauncherContributionItem to define system environment

variable for configuring the environment to run a native program.

The following class is provided by the package com.ibm.rcp.jface.action:

v SMenuManager - A subclass of Eclipse’s MenuManager that has been enhanced to use SMenu rather

than Menu.

You can populate the launcher either dynamically through extensions or through direct calls into the

Launcher public APIs located in the platform personality bundle.

If you are using WebSphere Portal to create a Portal-based applications that you are pushing to the client

through the Composite Application Infrastructure, you can add the page to the launcher by specifying the

following page parameter: com.ibm.rcp.launcher=true.

Populating the launcher:

You can add items to the launcher dynamically or programmatically.

To contribute items to the launcher dynamically, you can implement the following extension points:

v launcherSet -- Contributes items to the extension point registry when the client starts and displays all

items in the launcher drop-down list.

v bookmarkProvider -- Contributes items to the launcher drop-down list lazily. The bookmarked items

are not loaded in memory until a user accesses the folder containing the items from the launcher

drop-down list. The list of bookmarks are updated when items are added or removed or when the

bookmark provider sends notification of some other change.

You can also contribute items to the launcher programmatically. The client provides the following classes

that are derived from the LauncherContributionItem class:

v NativeProgramLauncherContributionItem – Creates a link in the launcher to a native application.

v PerspectiveLauncherContributionItem – Creates a link in the launcher to a standard client application.

v UrlLauncherContributionItem – Creates a link in the launcher to a specified URL.

You can also create a custom implementation of a LauncherContributionItem-derived class.

If you are using WebSphere Portal to create a Portal-based applications that you are pushing to the client

through the Composite Application Infrastructure, you can add the page to the launcher by specifying the

following page parameter: com.ibm.rcp.launcher=true.

To populate the launcher, complete the following steps:

1. Use or extend the default personality or create your own personality which has a workbench window

advisor that initializes the LauncherManager class located in the com.ibm.rcp.jfaceex plug-in, and the

LauncherRegistry class located in the com.ibm.rcp.ui plug-in.

2. Do one of the following:

v Implement the launcherSet extension point and in it, define the type of contribution you are

providing. This method allows you to make a contribution without activating the contributing

plug-in. The plug-in’s compiled code is not loaded into memory, which helps the program to start

up quickly and requires fewer system resources. You can use one of the following elements to

implement a corresponding class, which are predefined LauncherContributionItem-derived classes

provided in the com.ibm.rcp.jfaceex plug-in

– nativeProgramLaunchItem -- Identifies the item as being a

NativeProgramLauncherContributionItem class, which is a contribution item that starts a native

program.

184 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 195: Lotus Expeditor: Developing Applications for Lotus Expeditor

– perspectiveLaunchItem -- Identifies the item as being a PerspectiveLauncherContributionItem

class, which is a contribution item that starts a standard client application by specifying an

Eclipse perspective.

– urlLaunchItem -- Identifies the item as being a UrlLauncherContributionItem class, which is a

contribution item that opens a URL.v Directly instantiate a LauncherContributionItem-derived class or create a custom one and add it

directly to the LauncherManager. If you use this method your plug-in must declare a dependency

on the com.ibm.rcp.jfaceex plug-in.

Creating custom launcher contribution items:

The client enables you to open standard items, such as an application or a URL from the launcher by

providing a collection of classes that extend the LauncherItemContribution class. You can implement your

own custom contribution item.

To create a custom launcher contribution item, perform the following steps:

1. Implement the launcherSet extensions point and define a launchItemType and launchItem for it in the

plugin.xml for your application.

2. Write the supporting launchContributionItem class that extends the LauncherContributionItem class

and name it with the name referenced in the launchItemType element definition.

For example:

package com.ibm.rcp.launcher.tests;

import org.eclipse.core.commands.Category;

import org.eclipse.core.commands.Command;

import org.eclipse.core.commands.CommandManager;

import org.eclipse.core.commands.Parameterization;

import org.eclipse.jface.action.IContributionManager;

import com.ibm.rcp.jface.launcher.LauncherContributionItem;

import com.ibm.rcp.jface.launcher.LauncherItemParameter;

import com.ibm.rcp.jface.launcher.LauncherManager;

import com.ibm.rcp.jface.launcher.Param;

public class TestURILauncherContributionItem

extends LauncherContributionItem {

static final String TEST_URI_ITEM_COMMAND_ID =

"com.ibm.rcp.launcher.tests.testURICommand"; //$NON-NLS1$

public static final String TEST_URI_ITEM_ATTRIBUTE_URI = "uri";

private String uri;

public TestURILauncherContributionItem() {

super();

}

public Command getCommand() {

Command command = null;

IContributionManager contributionManager = getParent();

if (contributionManager != null &&

contributionManager instanceof LauncherManager) {

LauncherManager lm = (LauncherManager)contributionManager;

CommandManager commandManager = lm.getCommandManager();

if (commandManager != null) {

Category category =

commandManager.getCategory(LauncherManager.COMMAND_MANAGER_CATEGORY);

if (category != null) {

command = commandManager.getCommand(TEST_URI_ITEM_COMMAND_ID);

Developing applications 185

Page 196: Lotus Expeditor: Developing Applications for Lotus Expeditor

command.define("TestURICommand",

"Command for testing URI launching.", category, null);

command.setHandler(new TestURILauncherItemHandler());

}

}

}

return command;

}

3. Write the supporting Item class and name it with the name referenced in the launchItem element

definition. Use the Param class to define the item’s attributes.

For example:

public Parameterization[] getParameters() {

Parameterization[] parameters = null;

String uriString = getUri();

if (uriString != null) {

parameters = new Parameterization[1];

LauncherItemParameter parameter =

new LauncherItemParameter(TEST_URI_ITEM_ATTRIBUTE_URI,

"Launcher TestURI item uri attribute.");

parameters[0] = new Parameterization(parameter, uriString);

}

return parameters;

}

public void setUri(String uri) {

this.uri = uri;

}

public String getUri() {

return uri;

}

public void addAttribute(Param param) {

if (param == null) {

return;

}

String name = param.getName();

if (name.compareToIgnoreCase("uri") == 0) {

setUri(param.getValue());

}

}

}

Contributing bookmarks to the launcher:

Bookmarks are user-created references to applications, application documents or Web sites and are stored

within a folder in the launcher.

The DefaultWorkbenchWindowAdvisor provided in the com.ibm.rcp.platform.personality plug-in

schedules a Job to build the BookmarkProviderRegistry. Upon completion of that job it sets the bookmark

provider (IBookmarkProvider) to the LauncherManager. When a user expands a folder on the Launch

drop-down menu, the LaunchManager uses a working thread to query the bookmark provider to retrieve

any available bookmarks for the selected folder.

To contribute a bookmark to the launcher, complete the following steps:

1. Use or extend the default personality or create your own personality which has a workbench window

advisor that initializes the LauncherManager class located in the com.ibm.rcp.jfaceex plug-in, and the

186 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 197: Lotus Expeditor: Developing Applications for Lotus Expeditor

LauncherRegistry class located in the com.ibm.rcp.ui plug-in as well as uses the

BookmarkProviderRegistry located in the com.ibm.rcp.ui plug-in to retrieve the bookmark provider, if

any, and set it to the LauncherManager.

2. Do one of the following:

v Contribute bookmarks dynamically by implementing the bookmarkProvider extension point. This

method allows you to make a contribution without activating the contributing plug-in. The

plug-in’s compiled code is not loaded into memory, which provides for faster program startup and

requires fewer system resources. For example:

<extension point="com.ibm.rcp.ui.bookmarkprovider">

<provider

id="com.ibm.rcp.my.bookmark.provider"

class="com.ibm.rcp.my.boomark.provider"

name="My Bookmark"

ranking="20" />

</extension>

v Directly instantiate the bookmark by Implementing the IBookmarkProvider interface and

implementing the IBookmark interface to add the bookmark to the Launcher. If you use this

method, your plug-in must declare a dependency on the com.ibm.rcp.jfaceex plug-in. For example:

package com.ibm.rcp.launcher.bookmark.tests;

import java.text.DateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Set;

import java.util.logging.Level;

import java.util.logging.Logger;

import org.eclipse.core.runtime.ListenerList;

import org.eclipse.swt.widgets.Display;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ui.themes.ITheme;

import com.ibm.rcp.jface.launcher.BookmarkEvent;

import com.ibm.rcp.jface.launcher.IBookmark;

import com.ibm.rcp.jface.launcher.IBookmarkProvider;

import com.ibm.rcp.jface.launcher.IBookmarkProviderListener;

public class TestBookmarkProvider implements IBookmarkProvider {

private static final String CLAZZ_NAME =

TestBookmarkProvider.class.getName();

private static final String PKG =

TestBookmarkProvider.class.getPackage().getName();

private static Logger logger = Logger.getLogger(PKG);

private ListenerList bookmarkListeners;

private boolean testAutoLaunch;

private ArrayList parentFolderItems;

static private HashMap testBookmarks;

static {

testBookmarks = new HashMap();

testBookmarks.put("Iris Office Notes",

"Notes://Ella/8525561F006EC144/2DE43156D1B5E6AB85256673004D9E25");

testBookmarks.put("Partner Forum 2006",

"Notes://CAMDB10/85257106005B472D/C742E0C537B8236F85256F90006C73D6");

testBookmarks.put("RCP Tasks Database",

"Notes://wrangle/85256E8B004CA57C/51D5AAF548E20AA685256E90004F3639");

testBookmarks.put("Clearcase Help Db",

"Notes://Everclear/8525675900776AA5/8178B1C14B1E9B6B8525624F0062FE9F");

Developing applications 187

Page 198: Lotus Expeditor: Developing Applications for Lotus Expeditor

}

static private HashMap testBookmarkFolders;

static {

testBookmarkFolders = new HashMap();

testBookmarkFolders.put("Build Dbs", "1");

testBookmarkFolders.put("RCP", "2");

testBookmarkFolders.put("Databases", "3");

}

static int[] folderIds = {IBookmark.FOLDER_ID_ROOT, 2, 1969, 1980};

private Runnable randomBookmarkUpdateGenerator = new Runnable() {

public void run() {

long folderCount = Math.round((Math.random() * folderIds.length));

if (folderCount > 0) {

int[] foldersToUpdate = new int[(int)folderCount];

for (int i = 0; i < folderCount; i++) {

long index = Math.round((Math.random() * (folderIds.length -1)));

foldersToUpdate[i] = folderIds[(int)index];

}

fireBookmarkFolderUpdate(foldersToUpdate);

}

/* Fire off again. */

long minutes =

Math.round((Math.random() * 4)) + 1; /* 1 to 5 minutes */

DateFormat df = DateFormat.getTimeInstance();

System.out.println("TFS -->> TestBookmarkProvider update interval =

" + Integer.toString((int)minutes) + " minutes at " +

df.format(new Date()) + ".");

Display.getDefault().timerExec((int)(minutes * 60000),

randomBookmarkUpdateGenerator);

}

};

public TestBookmarkProvider() {

/*

* Start random bookmark updating... can be newed from any thread.

* Make sure runs in ui thread.

*/

Display.getDefault().asyncExec(new Runnable() {

public void run() {

long minutes =

Math.round((Math.random() * 4)) + 1; /* 1 to 5 minutes */

DateFormat df = DateFormat.getTimeInstance();

System.out.println("TFS -->> TestBookmarkProvider update interval =

" + Integer.toString((int)minutes) + " minutes at " +

df.format(new Date()) + ".");

Display.getDefault().timerExec((int)(minutes * 60000),

randomBookmarkUpdateGenerator);

}

});

ITheme currentTheme =

PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();

testAutoLaunch =

currentTheme.getBoolean("com.ibm.rcp.launcher.tests.TEST_AUTO_LAUNCH");

}

public List populate(int parentFolderId) {

if (logger.isLoggable(Level.FINER)) {

logger.entering(CLAZZ_NAME, "populate with parentFolderId =

" + Integer.toHexString(parentFolderId)); //$NON-NLS-1$

}

188 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 199: Lotus Expeditor: Developing Applications for Lotus Expeditor

List items = null;

if (parentFolderId == IBookmark.FOLDER_ID_ROOT) {

if (parentFolderItems == null) {

parentFolderItems = new ArrayList();

Set keySet = testBookmarks.keySet();

for (Iterator i = keySet.iterator(); i.hasNext(); ) {

IBookmark bm = createBookmark(IBookmark.FOLDER_ID_ROOT, false);

String key = (String)i.next();

bm.setLabel(key);

bm.setURL((String)testBookmarks.get(key));

parentFolderItems.add(bm);

}

keySet = testBookmarkFolders.keySet();

for (Iterator i = keySet.iterator(); i.hasNext(); ) {

String key = (String)i.next();

IBookmark bm = createBookmark(IBookmark.FOLDER_ID_ROOT, false);

if (bm instanceof TestBookmark) {

TestBookmark tbm = (TestBookmark) bm;

String val = (String)testBookmarkFolders.get(key);

tbm.setFolderId(Integer.parseInt(val));

}

bm.setLabel(key);

parentFolderItems.add(bm);

}

}

items = parentFolderItems;

} else if (parentFolderId == 2) {

items = new ArrayList();

IBookmark bm = createBookmark(2, false);

bm.setLabel("RCP sub bookmark 1 (Partner Forum url)");

bm.setURL("Notes://CAMDB10/85257106005B472D/

C742E0C537B8236F85256F90006C73D6");

items.add(bm);

bm = createBookmark(2, false);

bm.setLabel("RCP sub bookmark 2 (nothing is launched)");

if (bm instanceof TestBookmark) {

TestBookmark tbm = (TestBookmark) bm;

tbm.setFolderId(1969);

}

items.add(bm);

bm = createBookmark(2, false);

bm.setLabel("RCP sub bookmark 3 (Iris Office Notes url)");

bm.setURL("Notes://Ella/8525561F006EC144/

2DE43156D1B5E6AB85256673004D9E25");

items.add(bm);

} else if (parentFolderId == 1969) {

items = new ArrayList();

IBookmark bm = createBookmark(1969, false);

bm.setLabel("sub RCP sub bookmark 1 (nothing is launched)");

items.add(bm);

bm = createBookmark(1969, false);

bm.setLabel("sub RCP sub bookmark 2 (nothing is launched)");

items.add(bm);

bm = createBookmark(1969, false);

bm.setLabel("sub RCP sub bookmark 3 (nothing is launched)");

if (bm instanceof TestBookmark) {

TestBookmark tbm = (TestBookmark) bm;

tbm.setFolderId(1980);

}

items.add(bm);

} else if (parentFolderId == 1980) {

items = new ArrayList();

IBookmark bm = createBookmark(1980, false);

bm.setLabel("sub sub RCP sub bookmark 1 (nothing is launched)");

Developing applications 189

Page 200: Lotus Expeditor: Developing Applications for Lotus Expeditor

items.add(bm);

bm = createBookmark(1980, false);

bm.setLabel("sub sub RCP sub bookmark 2 (nothing is launched)");

items.add(bm);

bm = createBookmark(1980, false);

bm.setLabel("sub RCP sub bookmark 3 (nothing is launched)");

items.add(bm);

}

if (logger.isLoggable(Level.FINER)) {

logger.exiting(CLAZZ_NAME, "populate with parentFolderId =

" + Integer.toHexString(parentFolderId)); //$NON-NLS-1$

}

return items;

}

public void add(IBookmark newBookmark) {

// TODO Auto-generated method stub

}

public void remove(IBookmark bookmark) {

// TODO Auto-generated method stub

}

public void move(IBookmark bookmark, int folderId) {

// TODO Auto-generated method stub

}

public IBookmark getStartupFolder() {

if (logger.isLoggable(Level.FINER)) {

logger.entering(CLAZZ_NAME, "getStartupFolder"); //$NON-NLS-1$

}

IBookmark bm = null;

if (testAutoLaunch) {

bm = createBookmark(IBookmark.FOLDER_ID_ROOT, false);

bm.setLabel("RCP");

if (bm instanceof TestBookmark) {

TestBookmark tbm = (TestBookmark) bm;

tbm.setFolderId(2);

}

}

if (logger.isLoggable(Level.FINER)) {

logger.exiting(CLAZZ_NAME, "getStartupFolder"); //$NON-NLS-1$

}

return bm;

}

public IBookmark createBookmark(int parentFolderId, boolean isFolder) {

TestBookmark bm = new TestBookmark();

bm.setParentFolderId(parentFolderId);

if (isFolder) {

//TODO "Create" a new folder and set its id to the bookmark’s folder id.

// bm.setFolderId(folderId);

}

return bm;

}

public boolean isDirty(int folderId) {

return false;

}

190 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 201: Lotus Expeditor: Developing Applications for Lotus Expeditor

private void fireBookmarkFolderUpdate(int[] folderIds) {

if (bookmarkListeners != null) {

Object[] listeners = bookmarkListeners.getListeners();

if (listeners.length <= 0) {

return;

}

for (int i = 0; i < listeners.length; i++) {

IBookmarkProviderListener listener =

(IBookmarkProviderListener) listeners[i];

/* Handler can modify the array so just give each one their own copy */

int[] ids = new int[folderIds.length];

System.arraycopy(folderIds, 0, ids, 0, folderIds.length);

BookmarkEvent be =

new BookmarkEvent(BookmarkEvent.BOOKMARK_EVENT_FOLDER_MODIFIED,

ids);

listener.bookmarksUpdated(be);

}

}

}

}

3. Register the IBookmarkProviderListener on the LauncherManager to listen for bookmark updates or

changes on the launcher. When a bookmark changes, a BookmarkEvent object is sent to

IBookmarkProviderListeners.

For example:

public void addBookmarkProviderListener(

IBookmarkProviderListener listener) {

if (bookmarkListeners == null) {

bookmarkListeners = new ListenerList();

}

bookmarkListeners.add(listener);

}

public void removeBookmarkProviderListener(

IBookmarkProviderListener listener) {

if (bookmarkListeners != null) {

bookmarkListeners.remove(listener);

}

}

Use a working thread to read the launcherSet and bookmarkProvider registries and to fetch Bookmark

objects when users open folders in the launcher.

Sidebar:

The sidebar is a view that displays vertically at the side of the workbench window.

The sidebar can contain one or more panels. Panels contain views associated with applications. For

example, a user that has a mail Inbox view open in the main workbench window could start a chat with

a contact in the instant messaging buddy list that displays in one panel of the sidebar and check his

availability for a meeting in the personal calendar that displays in another panel. The sidebar is useful

because it enables users to conveniently view information and perform actions in more than one

application at a time.

Users can customize the sidebar by resizing the sidebar, resizing the panels in the sidebar, dragging and

dropping the panels to reorganize them, and adding or removing panels by selecting or deselecting the

panels from the View → Sidebar Panels menu.

Developing applications 191

Page 202: Lotus Expeditor: Developing Applications for Lotus Expeditor

The sidebar can be displayed in the following modes:

v Open -- Displays all available panels.

v Thin -- Only displays icons representing the applications contributing panels to the sidebar. Users can

click on an icon to expand the associated panels both vertically (if the panel is collapsed) and

horizontally. When the sidebar is open, users can click the double arrow icon to minimize the size of

sidebar or put it into ″thin″ mode. If the sidebar sash is dragged such that the width becomes small

enough, the sidebar goes into thin mode automatically.

v Hidden -- The sidebar does not display. Users can open the sidebar from the View menu.

The personality does the work of instantiating the user interface controls used to create the sidebar. The

WorkbenchWindowAdvisor provided in the default platform, in the com.ibm.rcp.platform.personality

plug-in, creates the sidebar by instantiating the ShelfPage class provided in the com.ibm.rcp.ui.shelf

plug-in. The ShelfPage creates a SViewStack widget to represent the sidebar and create SViewForm

widgets to represent each panel. Sidebars are populated with panels when the first application or

perspective starts and its content is subsequently updated when enabled Eclipse activities change. When

all applications or perspectives close and the workbench page closes, each panel reference and

SViewForm is disposed. Finally, when a user shuts down the client, the Shell is disposed, causing the

sidebar’s parent composite and any of its children (SViewStack, along with any SViewForms that have

not been disposed yet), to be disposed.

Creating a sidebar:

You can create a single sidebar that displays views for an application.

To create a single sidebar, perform the following step:

Instantiate a sidebar by passing a String ID, parent composite, and a configurer window to the ShelfPage

constructor.

private Composite myPageForm;

IWorkbenchWindow window = configurer.getWindow();

myShelfPage = new ShelfPage(EXPANDED, myPageForm, window);

Creating two sidebars:

You can create more than one sidebar for an application.

To create two sidebars, perform the following step:

Instantiate two ShelfPage objects. Provide different IDs, but the same parent composite in the ShelfPage

constructors for each sidebar.

For example, the following code from the

com.ibm.rcp.platform.personality.DefaultWorkbenchWindowAdvisor class creates sidebars that display on

the right and left side of the main window:

private MultiPageForm pageSwitcherForm;

IWorkbenchWindow window = configurer.getWindow();

shelfPage = new ShelfPage(RIGHT, pageSwitcherForm, window);

final Control shelfControl = shelfPage.getControl();

pageSwitcherForm.setShelfControl(shelfControl);

leftShelfPage = new ShelfPage(LEFT, pageSwitcherForm, window);

leftShelfPage.setOrientation(ShelfPage.LEFT);

final Control leftShelfControl = leftShelfPage.getControl();

pageSwitcherForm.setLeftControl(leftShelfControl);

192 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 203: Lotus Expeditor: Developing Applications for Lotus Expeditor

where pageSwitcherForm is the parent composite that defines where to position the two sidebar controls.

The setOrientation() method called on the leftShelfPage defines the direction for the sidebar to collapse.

Contributing a panel to a sidebar:

The sidebar can contain one or more panels. Panels contain views associated with applications.

To contribute a panel to a sidebar, perform the following steps:

1. Use the com.ibm.rcp.ui.shelfViews extension point to define a panel contribution. Define values for

the following attributes in the <shelfview> element.

v id -- Unique ID to distinguish each contributing view. If there are repeated IDs, only one of the

views will be displayed.

v view -- ID of the view to be displayed.

v region -- Positions the view within the stack of views set to be displayed in the sidebar. Options are

TOP, MIDDLE, or BOTTOM. BOTTOM is the default; if you do not specify a value, the panel is

added to the bottom of the stack.

v page -- Determines which sidebar the view should be displayed in. This value must match the

ShelfPage ID specified when the ShelfPage was instantiated. For example, if you are adding a panel

to the a sidebar for which you created two ShelfPage objects, with the IDs RIGHT and LEFT, the

options for the page value would be RIGHT and LEFT.

v showTitle -- Boolean value. Determines whether or not to show the title bar.

Note: Note: The com.ibm.rcp.platform.shelfViews extension point has been deprecated, but is being

maintained for backwards compatibility.

2. Create the sidebar.

3. Display the sidebar in the window. For example:

setShowShelf(true);

4. Call the update method of ShelfPage to display the panels. For example:

ShelfPage.update()

Hiding a sidebar:

You can hide a panel within the sidebar or the sidebar itself.

You can use activities to associate a sidebar panel with a specific application. Activities prevent toolbar

icons, custom menu options, sidebar panels, and control sets in one application from being displayed in

another application. When an activity is enabled in the platform, the user interface contributions

associated with that activity are shown. When an activity is disabled in the platform, its user interface

contributions are not shown. You can associate a panel with an activity to enable the panel to be

displayed or hidden based on whether the associated application is in use or is not. The patterns used by

the Workbench are composed of two parts. The first part uses the identifier of the plug-in that is

contributing the user interface extension. The second part is the ID used by the plug-in itself when

defining the contribution. The following format is used:

plug-in-identifier + "/" + local-identifier

where the identifiers include a backslash (\) before each period in their namespaces.

Do one of the following

v Set the value of the showShelfArea property in the theme to false. The theme is specified in the

plugin_customization.ini file of the branding plug-in.

v Use the org.eclipse.ui.activities extension point to filter out a sidebar view.

Developing applications 193

Page 204: Lotus Expeditor: Developing Applications for Lotus Expeditor

For example, in the following plugin.xml excerpt, the regional settings editor activity defined in the

com.ibm.myeditor.supereditor.baseview plug-in associates itself with the

com.ibm.supereditor.preferences.documenteditors.RegionalSettingsEditor contribution:

<extension point="org.eclipse.ui.activities">

<activity

name="RegionalSettingsEditor"

description="RegionalSettingsEditor Activities"

id="com.ibm.myeditor.RegionalSettingsEditor">

</activity>

<activityPatternBinding

activityId="com.ibm.myeditor.RegionalSettingsEditor"

pattern="com\.ibm\.myeditor\.supereditor\.baseview/com\.ibm\

.supereditor\.preferences\.documenteditors\.RegionalSettingsEditor">

</activityPatternBinding>

</extension>

Table widgets:

The table widgets are the parts of the graphical user interface that represent the table.

The widgets enable users to make changes to the data and customize the table. The following table

widgets are available:

v Body -- Paints the items to be rendered in the current window. An attribute of the body widget defines

the background color to use to fill the table body.

v Cell -- Part of an item widget. Occupies a single row and single column. Users can select cells. Cells

support listeners that listen for mouse and key events.

v Header -- Represents the text and image at the top of each column. Users can customize the table using

the header widget. They can reset the width of a column, hide a column, or reorder the columns in the

table.

v Item -- Represents an object in the table. Occupies a row in the table. Users can select and remove item

widgets from the table.

v Table -- The parent widget that manages all components in the table. It creates the header and body

and adds the items into the table. The table widget uses the tree nodes to arrange the items according

to the specified data model and preserves the appropriate relationships amongst the items in the table.

Sorting table entries:

The table control supports sorting entries in columns by reflecting the change in the sorting indicator in

the column header.

The actual reorganization of the data must be handled by the data model. The data model is also

responsible for refreshing the table after the data has been reorganized.

1. Retrieve the column’s sort indicator. For example:

private void SortBy(SelectionEvent e) {

STableColumn column = (STableColumn)_viewer.getTable().

getColumn(new Point(e.x, e.y));

SortIndicator indicator = column.getSortInidcator();

2. Set up logic to change the indicator based on the current setting of the sort order. For example:

if(indicator == SortIndicator.None) return;

if(indicator == SortIndicator.IsSortable) {

column.setSortIndicator(SortIndicator.Ascending);

}

else if (indicator == SortIndicator.Ascending) {

column.setSortIndicator(SortIndicator.Descending);

194 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 205: Lotus Expeditor: Developing Applications for Lotus Expeditor

}

else {

column.setSortIndicator(SortIndicator.IsSortable);

}

3. Retrieve the table data based on the new sort order. For example:

model.sortedBy(column.getSortInidcator());

_viewer.setInput(model);

}

4. Add a listener to listen for changes to the sort order. For example:

tableCols[i].addSelectionListener(new SelectionListener(){

public void widgetSelected(SelectionEvent e) {

SortBy(e);

}

public void widgetDefaultSelected(SelectionEvent e) {

}

});

Table color and font:

By default, the table uses the system default colors and fonts. You can specify different colors and fonts

using methods provided by the table control.

You can set the default color using a theme. See Using themes to customize the user interface.

The following list identifies the code you can use to set colors and fonts in a table. It lists the code

according to the order of priority they are given, the first one having the highest priority:

1. Cell paint modifier

2. Item paint modifier

3. Font only: TableCell methods and TableItem.setFont(int column, Font font) method

4. TableItem and TableHeader methods

5. Table methods

Color support

You can set a background and foreground color for the table, the table header, and individual rows. To

implement custom colors, use the setBackground() and setForeground() methods provided by the STable,

STableHeader, and STableItem classes. You can also use the IPaintModifier interfaces to set the color of

cells and items in the table.

Font support

You can set the font for the text that displays in a table, table header, and table rows using the setFont()

method of the STable, sTableHeader, and STableItem classes. You can also use the IPaintModifier

interfaces to set the font of cells and items in the table.

Specifying the color of table text:

You can use the IPaintModifier interface to apply a different color or font style to table items, including a

row, column, and a cell.

Developing applications 195

Page 206: Lotus Expeditor: Developing Applications for Lotus Expeditor

When painting a cell, the table uses the paint modifier added to the first column cell to get the color and

font settings. If no cell paint modifier is specified, the table checks whether a paint modifier is specified

for an item in the cell. A cell paint modifier has higher priority than an item paint modifier.

1. Implement the IPaintModifier interface using the setItemPaintModifier() method of the table class to

set the colors of a cell item. For example:

table.setItemPaintModifier(new IPaintModifier(){

public void dispose() {

}

2. Define the colors to use for the foreground and background of the item. For example:

public Color getForeground(Object element) {

if(element instanceof Mail){

Mail mail=(Mail)element;

boolean unread = mail.isUnread();

if (unread && isMarkedUnRead)

return table.getDisplay().getSystemColor(SWT.COLOR_RED);

}

return null;

}

public Color getBackground(Object element) {

if (!isMarkPeople) return null;

if(element instanceof Mail){

Mail mail=(Mail)element;

String author = mail.getAuthor();

if (author.equals("Jong Leng Zhang"))

return Item_bgColor;

if (author.equals("Lu Guang Zu"))

return Item_bgColor_1;

}

return null;//table.getDisplay().getSystemColor(SWT.COLOR_RED);

}

public int getStyle(Object element) {

return 0;

} });

tableCols[i].setCellPaintModifier(new IPaintModifier(){

...

});

3. Implement the IPaintModifier interface calling the setCellPaintModifier() method from a column in

the table to set the colors of the table cells in that column. For example:

tableCols[i].setCellPaintModifier(new IPaintModifier(){

...

});

Customizing the table header:

The table header control displays at the top of each table column and contains a title that describes the

information provided in that column.

You can use methods of the STable class to hide or show the table column header as well as set the font

and background color of the header.

To

1. Specify whether you want the header to display in the column using the setHeaderVisible() method of

the STable class. For example, if this represents the current table object, use the following code to

display the column header:

this.setHeaderVisible(true);

2. Define the font style for the text in the header using the setHeaderFont() method of the STable class.

For example:

196 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 207: Lotus Expeditor: Developing Applications for Lotus Expeditor

FontData fontdata = new FontData("Arial", 10, SWT.NORMAL);

Font font = new Font(parent.getDisplay(), fontdata);

this.setHeaderFont(font);

3. Define the background color for the header using the setBackground() method. For example:

this.getHeader().setBackground(new Color(null, new RGB(255,255,255)));

Custom JFace and SWT Widgets: The client UI provides a collection of custom SWT widgets, commonly

referred to as “SWidgets” that support the ability to customize the look and feel of the user interface.

This customization made possible through the StyledWidget interface. Each of the custom widgets

provided by the UI implement this interface. The UI also provides the respective Jface-like action and

model classes to simplify and provide a consistent programming model with Eclipse Rich Client

Platform. All of these custom widgets are located in the com.ibm.rcp.swtex plug-in.

This collection of custom widgets includes things like buttons, toolbars and tab folders. These widgets are

ubiquitous in the Lotus Expeditor client and are used by not only the Lotus Expeditor platform but by

applications and components that plug-in and extend the platform.

For example, the custom button widget (SButton) is used to represent the launch button that provides the

user with access to all of the applications that are installed on the Lotus Expeditor client. This same

custom button widget is also used by clients to build things like views and forms and because the

rendering of these widgets is extremely flexible, it takes on a different look and feel depending on its

context.

Using SWidgets

The SWidgets constructors take two parameters: the parent of the widget or NULL if the parent is the

Display and a style parameter.

To implement an SWidget, perform the following steps:

1. Create an instance of the widget.

For example:

// Create an instance of an SButton

SButton button = new SButton(parent, SWT.PUSH);

button.setText(“Launch”);

2. Add the button to the application user interface.

3. After the widget is used, dispose of it.

For example:

// Dispose of the SButton since it’s no longer needed

button.dipose();

Eclipse also provides several facilities to enable resource sharing among components. For example, if

several widgets must access the same Color, the Color can be added to, and referenced from, the JFace

color registry. This allows one Color instance to be shared by any number of widgets. Resources that are

shared should never be disposed. JFace provides these registries for fonts, images, and colors.

Managing contributions to the user interface

The JFaceEX plug-in provides action and model classes that simplify programming with SWTEX by

enabling you to manage contributions to the user interface.

The com.ibm.rcp.jfaceex plug-in provides a collection of JFace style action and contribution classes that

enable clients to implement shared behaviors between two or more widgets components such as toolbars

and menu bars. The API for these action and contribution classes are similar if not compatible with the

standard Eclipse action classes. The contribution API lends itself well to implementing extension

point-driven user interface components.

Developing applications 197

Page 208: Lotus Expeditor: Developing Applications for Lotus Expeditor

The JFaceEX action classes are provided in the com.ibm.rcp.jfaceex plug-in, which has dependencies on

the org.eclipse.jface plug-in.

To manage contributions using JFace actions, perform the following steps:

1. Create the action manager classes used to manage contributions to things like toolbars and menu bars

using one of the following constructors:

v A constructor that allows you to pass the toolbar or menu bar that may have been created

externally.

// create a toolbar manager with a toolbar created externally

SToolBar toolbar = new SToolBar(parent, SWT.NONE);

SToolBarManager toolbarManager = new SToolBarManager(toolbar);

v A constructor that takes no parameters or just a style parameter and the toolbar or menu bar is

later created internally.

// create a toolbar manager with a toolbar created internally

SToolBarManager toolbarManager = new SToolBarManager(SWT.NONE);

SToolBar toolbar = toolbarManager.createControl(parent);

2. Use a JFaceEX action to add the same action object to a toolbar and a menu bar. The action is

rendered as a tool item in a toolbar and a menu item in a menu bar.

For example:

Action exitAction = new ExitAction();

mySToolbarManager.add(exitAction);

mySMenuManager.add(exitAction);

3. When it is not longer needed, dispose of the JFaceEx action manager.

Note: The dispose method disposes of the toolbar or menu bar that it manages so clients must

remember not to reference those objects after the manager has been disposed.// dispose of the toolbar manager when it is no longer needed

toolbarManager.dipose();

Accessing SWidgets and JFaceEX objects

All widget and action classes must be accessed from the UI thread.

In SWT-based applications, the UI thread is the main thread. Accessing these classes from any other

thread results in an invalid thread access exception. If this exception is thrown while the client is starting,

it will fail to start.

To access a widget or JFaceEX object from a worker thread:

Do one of the following:

v Use the syncExec() or asyncExec() methods of Display.

// Update the text of my button from a worker thread

Display.getDefault().asyncExec( new Runnable() {

Public void run() {

myButton.setText(“My Button”);

}

});

v Use the org.eclipse.ui.progress.UIJob class. The UIJob class is a subclass of Job that is designed to

always run in the main thread. UIJob uses Display.asyncExec() internally.

Adding and contributing menus

The views and editors that are created and displayed will typically provide a visual representation of

data for the users. In order to control the application environment, such as opening or closing views, or

performing specific actions, such as syncing data, you will probably want to consider creating menu and

menu items to enable access to the actions.

198 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 209: Lotus Expeditor: Developing Applications for Lotus Expeditor

Menu contributions: You can make a feature you have created available to users by adding it to the

menu bar as a menu item. You can create and contribute menu items by implementing one of the

following contribution types:

v Global menu contributions -- These menu contributions persist across every application. These menu

items are universal and can be used from any context. These menu items are also ″retargetable,″ so

your application can write code to retarget these global menu items, such as Cut, Copy, and Paste, for

application-specific purposes.

v Part-associated action set contributions -- These menu contributions are specific to a single application

or view. By default, most menu items are local, meaning that if the view associated with those menu

items is not displayed, those menu items are not displayed. Contributing view-specific menu items

enables you to create discrete menu items for a page of your application that are not shared with other

products on the client.

Global menu contributions: You can add a menu item to one of the Lotus Expeditor global menus using

the org.eclipse.ui.actionSets extension point. You can also associate a new action set to a specific

perspective or view to ensure that the menu contributions defined in the action set appear in the user

interface only when the specified view is active using the org.eclipse.ui.actionSetPartAssociation

extension point. See the Platform Plug-in Developer’s Guide for more information on part associations.

For details on the ids used by the Lotus Expeditor Top Level Menus, refer to “Lotus Expeditor top level

menus” on page 365.

If actions are defined by the extension points within plug-ins, but are not associated with a particular

perspective, then the menu items/actions will be displayed at all times. By associating menu items and

actions with a particular perspective through perspectiveExtension extension points, the menu items and

actions will be displayed only when the application’s perspective is displayed.

The File menu provided by the workbench contains entries for Preferences and Exit. Usability guidelines

suggest that Exit always be the last menu item. The Preferences action is provided by the workbench, and

launches a dialog that aggregates all provided preference pages.

Part-associated action set menu contributions: In addition to having the global menus, each product

contributes its own menu items on the existing menus. A product can also contribute entire menus to the

menu system.

Pop-up menus: A pop-up menu is the menu that is displayed when a user right-clicks the background of

a user interface component, such as a view or editor. Pop-up menus should repeat pertinent menu items

that are available on the menu bar or pertinent actions on a dialog box triggered from a menu item. The

contents of the pop-up menu must change to be appropriate to the object that has focus or the object that

is selected.

A pop-up menu item should not be the only way a user accesses a piece of functionality. All pop-up

menu items must have access keys for accessibility. Indicate the access key by underlining the key text in

the menu item label. If possible, use the same access key as the one used for the menu item in the menu

bar.

You should give context menus to the following objects:

v Objects in a navigator view, such as folders or document libraries

v Items selected in a list.

Icons in menus: If a menu item is represented by a toolbar button with an icon, include that icon on the

menu. If your application does not have a toolbar or the toolbar does not include icons, do not include an

icon on the menu. Include icons to the left of the menu items.

Developing applications 199

Page 210: Lotus Expeditor: Developing Applications for Lotus Expeditor

Creating a top-level menu: You can write code that performs a task and enable users to trigger that task

from a corresponding menu item in the user interface by creating a menu item contribution and adding it

to the application menu. The File, Application, View and Help menus appear at the top level. You can

contribute a menu item that displays at the top-level as well.

The following steps make use of the templates provided with the Plug-in Development Environment to

show you how to create an action, an actionSet, and a top-level menu.

1. Start your Rational Software Development Platform.

2. Create a plug-in project to contain the menu and action that you are providing. You will use a

template that creates a Java class for the action, and adds all of the appropriate extension points.

Later, you can modify the code generated by the template to meet your own requirements.

a. Select File > New > Other > Plug-in Development > Plug-in Project to create the initial project,

then select Next.

b. On the Plug-in Project panel, enter a name for your plug-in project, such as MyAction. You can use

the defaults already entered on the rest of the panel. Select Next.

c. Use the defaults on the Plug-in Content panel. Select Next.

d. On the Templates panel, check Create a plug-in using one of the templates. Select Hello, World.

Then select Finish.

e. A project called MyAction will now be created in your workspace. Selected files will have already

been created within the project based on your selections to create a plug-in with a view. The

MyAction and MyAction.actions packages will have been created in the src folder.

At this point, you can launch the platform from the workbench including this plug-in (for more

information, refer to “Debugging and testing applications” on page 323). A new top level menu, Sample

Menu, will be displayed along with File, Application, View and Help. This menu will contain an action

labeled Sample Action.

As you launch the platform, you will notice that regardless of the application that you open, the same

Sample Menu always appears. If you want to change this menu so that it appears only with a particular

application, you will need to create a perspectiveExtension. To illustrate these steps, the following steps

assume that the Simple Rich Client Platform application was created in “Creating a simple Rich Client

Platform application” on page 158.

1. Open the plugin.xml file for the MyAction project you just created

2. Now Add an extension point to the plug-in to define the perspective Extension that you want to

create.

a. Open the plugin.xml file contained in your MyAction project.

b. Select the Extensions tab within the editor. You should already see the org.eclipse.ui.actionSets

defined.

c. Select Add..., then select org.eclipse.ui.perspectiveExtension, then select OK.

d. Once org.eclipse.ui.perspectiveExtensions has been added to the All extensions list, right click

on the entry, then select New > perspectiveExtension.

e. The Extension Element Details information will display. Enter MyApplication.perspective1 as the

target id. (This is the perspective created in “Creating a simple Rich Client Platform application”

on page 158).

f. Now select the MyApplication.perspective1 perspectiveExtension. Right click and select New,

then select actionSet.

g. The Extension Element Details information will display. Enter MyAction.actionSet as the target id.

h. Expand the org.eclipse.ui.actionSets, and select the Sample Action Set.

i. The Extension Element Details information will display. Change the value of visible from true to

false.

j. Save and close the plugin.xml file.

200 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 211: Lotus Expeditor: Developing Applications for Lotus Expeditor

As you launch the platform, you will notice that the Sample Menu displays only when your application

is visible.

You can further limit or associate a menu with a particular view. By using the

org.eclipse.ui.actionSetPartAssociation extension point, you can assign a particular action set to a

view or editor such that the action set displays only when the view or editor is active. To modify the

MyAction plug-in to associate with a particular view instead of just a perspective, you would need to

make the following changes:

1. Open the plugin.xml file contained in your MyAction project.

2. Select the Extensions tab within the editor. You should already see the org.eclipse.ui.actionSets

defined.

3. Remove the org.eclipse.ui.perspectiveExtensions extension point, as it is no longer necessary for

the actionSet to be associated to the perspective.

4. Select Add....

5. Select org.eclipse.ui.actionSetPartAssociations, then OK.

6. Once org.eclipse.ui.actionSetPartAssociations has been added to the All extensions list, right click

on the entry, then select New > actionSetPartAssocation.

7. The Extension Element Details information will display. Enter MyAction.actionSet as the target id.

This is the action set you want to associate with a view.

8. Select the MyAction.actionSet actionSetPartAssociation. Right click and select New, then select part.

9. The Extension Element Details information will display. Enter MyApplication.views.SampleView as the

part.

When you launch, the SampleMenu will now only display when the Sample View is active. Since

MyApplication only has the single view available, you won’t really notice an immediate difference.

However, if you were to modify MyApplication to add another view, then you would notice that Sample

Menu only displays when Sample View is active.

Creating views

A perspective can show one or more views simultaneously. Depending upon the application

requirements, the number of views that are simultaneously displayed views may change in response to

events occurring within the application. Application developers may force views to maintain a specific

size or location, or to remain open, when displayed in the perspective. Alternatively, application

developers may allow users to close views. While the Lotus Expeditor workbench application enables the

ability to “reset” a perspective to its initial configuration, you may want to also provide menu options

that enable users to open specific views if they are inadvertently closed.

Applying Capitalization and punctuation guidelines

Use appropriate punctuation, such as a periods, exclamation points, or question marks at the end of

complete sentences. Add a colon at the end of labels for controls in forms and dialog boxes.

For more information, see the Eclipse User Interface guidelines.

The following table describes when to use headline-style capitalization and when to use sentence-style

capitalization:

Developing applications 201

Page 212: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 12. Capitalization and punctuation

Capitalization style Guideline Use for

Headline Capitalize the first letter of each

word, except the following:

v Articles such as: a, an, and, the

v Short prepositions that are between

words such as: for, in, of, on, and

to

v Command buttons (push buttons)

v Dialog box title bars

v Menu items

v Menu titles

v Section headers (For example, the

header to a section on a form.

Section headers should also be

bold.)

v Tabs

v Title bars

v ToolTips (When the toolTip is for a

toolbar item; all other tooltips use

sentence-style capitalization.)

v Window titles

Sentence Capitalize the first letter of the first

word and any proper nouns, such as

Workplace.

v Check box labels

v Dialog box labels

v Group box or group bar titles

v Radio buttons

v Text field labels

Creating helpful messages

Whenever possible use the standard message dialog boxes provided in the MessageDialog class as part of

the org.eclipse.jface.dialogs package. The error message can be modeless, which means it allows the

user to continue to interact with the application or modal, which means it requires that the user respond

to the error dialog box before continuing to use the application. The following sections describe the

available Eclipse message types.

Critical: Informs users of a serious problem that prevents them from continuing their work. Critical

error messages are always modal.

Example code:

MessageDialog.openError

(parent.getShell(),

"Error Title",

"Error Message");

Warning: Alerts users to a condition that requires a decision before proceeding. In many cases you must

add buttons to support the Yes, No, and Yes, No, Cancel conditions. Warning messages are usually

modal; that is, users must respond before continuing to interact with the application.

Example code:

MessageDialog.openWarning

(parent.getShell(),

"Warning Title",

"Warning Message");

Customizing existing applications

This section provides information on customizing existing applications.

202 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 213: Lotus Expeditor: Developing Applications for Lotus Expeditor

Activities

An activity is a logical grouping of function that is centered on a certain kind of task. For example,

developing Java software is an activity commonly performed by users of the Eclipse SDK platform, and

the Java Development Tooling defines many UI contributions (views, editors, perspectives, preferences,

etc.) that are only useful when performing this activity. Before we look at the mechanics for defining an

activity, let’s look at how they are used to help ″declutter″ the UI.

The concept of an activity is exposed to the user, although perhaps not apparent to a new user. When an

activity is enabled in the platform, the UI contributions associated with that activity are shown. When an

activity is disabled in the platform, its UI contributions are not shown.

Activities are defined using the org.eclipse.ui.activities extension point. Refer to the Platform Plug-in

Developer’s Guide for more information on activities and how to define them.

Activities can be used in a static manner to “hide” UI contributions that other plug-ins may have

provided.

Lotus Expeditor supports the use of activities.

Using activities: Activities are associated with UI contributions using activity pattern bindings, patterns

that are matched against the id of the UI contributions made by plug-ins. The process to “filter out” UI

contributions is a two-step process described below:

Step 1: Defining an activity: Activities are defined using the org.eclipse.ui.activities extension point.

Activities are assigned a name and description that provide information about an activity. The id of the

activity is used when defining pattern bindings or other relationships between activities.

An example activity definition:

<extension

point="org.eclipse.ui.activities">

<activity

name="Lotus Expeditor Specific"

description="Filters out Lotus Expeditor UI contributions"

id="Lotus Expeditor Activities">

</activity>

Step 2: Binding activities to UI contributions: Activities are associated with UI contributions using pattern

matching. The pattern matching used in activity pattern bindings follows the rules described in the

java.util.regex package for regular expressions. The patterns used by the workbench are composed of

two parts. The first part uses the identifier of the plug-in that is contributing the UI extension (the

plug-in namespace). The second part is the id used by plug-in itself when defining the contribution

(which may or may not also include the plug-in id as part of the identifier). The following format is used:

plug-in-identifier + "/" + local-identifier

For example, the following activity pattern binding states that all UI contributions from the Lotus

Expeditor workbench plug-in (com.ibm.eswe.workbench) are associated with the Lotus Expeditor Specific

activity. When this activity is enabled or disabled, the state of the UI contributions within the workbench

are affected.

<activityPatternBinding

activityId="Lotus Expeditor Specific"

pattern="com\.ibm\.eswe\.workbench/.*" />

</activityPatternBinding>

The next binding is more specific. It states that the contribution named install defined in the

InstallUpdate Launcher plug-in (com.ibm.eswe.installupdate.launcher) is associated with the Lotus

Expeditor Specific activity. As this activity is enabled or disabled, the specific contribution will be

included

Developing applications 203

Page 214: Lotus Expeditor: Developing Applications for Lotus Expeditor

<activityPatternBinding

activityId="Lotus Expeditor Specific"

pattern="com\.ibm\.eswe\.installupdate\.launcher/install" />

</activityPatternBinding>

Lotus Expeditor does not define any activities for use by applications. However, applications may define

activities to group Lotus Expeditor UI contributions. Refer to “Lotus Expeditor top level menus” on page

365 for specific details about the menu identifiers defined by the client platform.

Integrating existing RCP applications into Lotus Expeditor

Lotus Expeditor is based upon the Eclipse Rich Client Platform, but has added a set of Eclipse plug-ins

above and beyond the set normally part of RCP. In addition, Lotus Expeditor has provided a workbench

advisor and an application that can be used for many situations.

Application developers may have constructed applications based solely upon the Eclipse Rich Client

Platform (or other Eclipse-based platforms), without necessarily targeting Lotus Expeditor.

Generally, you can run applications which are written for generic RCP on Lotus Expeditor. However,

there may be some differences between the generic Eclipse RCP or SDK and Lotus Expeditor:

v Because the workbench advisor and application are already provided, applications that include a

workbench advisor or RCP application may no longer need to use those capabilities. However, some

application function may have been included in the advisor or application. You may be able to re-use

the plug-ins without necessarily running the application

v Actions that may have been defined by the advisor class could be defined as actionSets in a new or

existing plug-in.

v Lotus Expeditor has provided a set of menus as identified in “Lotus Expeditor top level menus” on

page 365. Note that applications that provide action sets may expect certain other menus to be present.

If those menus are not present, then actionSets that do not include a menu option will not display

their actions.

v To enable applications written as perspectives to contribute to Lotus Expeditor, you will need to update

the application plug-in that defines the perspective to also define the Lotus Expeditor WctApplication

extension point.

v Lotus Expeditor may not include all of the plug-ins typically provided in the Eclipse SDK. If the

Eclipse SDK was the target for application development, then attempting to run the application on

Lotus Expeditor may not be successful. In general, plug-ins that exist in the Eclipse SDK could be

added to Lotus Expeditor along with the application plug-ins. Note that IBM will not provide support

for these plug-ins if added to the platform.

Developing with user interface widgets

This section provides information on developing with user interface widgets.

Adding spell checking to applications

Applications can perform spell checking with the SpellChecker interface methods. In order to spell check,

a series of dictionaries must be set as a comparing library. Applications can use the setLocale() method

in SpellChecker interface to set the dictionaries.

There are four ways to performing spell checking:

v Checking misspelled words using the dictionaries supported by given locale

v Checking misspelled words using the dictionaries supported by the platform default locale

v Checking misspelled words using given dictionaries

v Checking misspelled words using given dictionaries and a customized user dictionary

Using dictionaries supported by a given locale:

204 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 215: Lotus Expeditor: Developing Applications for Lotus Expeditor

SpellChecker isc = TextAnalyzerFactory.getSpellCheckerInstance();

isc.setLocale(TextAnalyzerConstant.LANGUAGE_ID_EN_US);

MisspelledWord[] misWords = isc.checkSpelling(txtToCheck,5,true);

The core spell checking methods have been defined in the SpellChecker interface. An application needs

to get an instance of SpellChecker to perform the spell check. The application can acquire the instance

through the TextAnalyzerFactory’s getSpellCheckerInstance() method. In this case, applications need

to set the locale name for which you wish to check misspelled words in. checkSpelling(String

theInputText, int numSuggestions, boolean autoCorrect) is the concrete method to do spell check

using the input string. It returns an array of MisspelledWord. The suggestion words are stored in

theMisspelledWord.suggestions field. You can also get one misspelled word‘s suggestions using the

getSuggestions(String word, int numSuggestions, int suggestionType) method.

Using dictionaries supported by the platform default locale:

SpellChecker isc = TextAnalyzerFactory.getSpellCheckerInstance();

MisspelledWord[] misWords = isc.checkSpelling(txtToCheck,5,false);

If an application wishes to do spell checking with the platform default locale, it can invoke the

SpellChecker’s checkSpelling(String theInputText, int numSuggestions, boolean autoCorrect)

method directly after getting the instance of SpellChecker. It does not need to call the SpellChecker’s

setLocale() method.

Using given dictionaries:

SpellChecker isc = TextAnalyzerFactory.getSpellCheckerInstance();

String locale = TextAnalyzerConstant.LANGUAGE_ID_EN_US;

//get all the main dictionaries

DictionaryManager dm = TextAnalyzerFactory.getDictionaryManager();

DictionaryInfo[] mainDic = dm.getDictionaryInfo(locale,

DictionaryInfo.DICT_TYPE_SPELL_MAIN);

isc.setLocale(locale, mainDic, null);

MisspelledWord[] misWords = isc.checkSpelling(txtToCheck,5,true);

If you wish an application to do a spell check in appointed dictionaries, and know the location

information for those dictionaries, you can set them directly using the setLocale(String locale,

DictionaryInfo[] mainDictArray, UserDictionary[] userDictArray) method. Ensure you set the

userDictArray parameter to null.

Using given dictionaries and a customized user dictionary:

SpellChecker isc = TextAnalyzerFactory.getSpellCheckerInstance();

String locale = TextAnalyzerConstant.LANGUAGE_ID_EN_US;

//get all the main dictionaries

DictionaryManager dm = TextAnalyzerFactory.getDictionaryManager();

DictionaryInfo[] mainDic = dm.getDictionaryInfo(locale,

DictionaryInfo.DICT_TYPE_SPELL_MAIN);

//get all the user dictionaries

UserDictionaryManager udm = TextAnalyzerFactory.getUserDictionaryManager();

UserDictionary[] uDict = udm.getUserDictionaries(locale);

isc.setLocale(locale, mainDic, uDict);

MisspelledWord[] misWords = isc.checkSpelling(txtToCheck,5,true);

To check misspelled words with a user dictionary, the application must put the user dictionaries info into

the third parameter of the setLocale(String locale, DictionaryInfo[] mainDictArray,

UserDictionary[] userDictArray) method. The application can get the user dictionaries info from the

UserDictionaryManager interface.

Using the getSuggestions string:

SpellChecker isc = TextAnalyzerFactory.getSpellCheckerInstance();

isc.setLocale(TextAnalyzerConstant.LANGUAGE_ID_EN_US);

MisspelledWord[] misWords = isc.checkSpelling(txtToCheck,5,true);

// ......

Developing applications 205

Page 216: Lotus Expeditor: Developing Applications for Lotus Expeditor

String[] suggestions = misWords[i].suggestions; // one way

//......

Stirng misspeltWord = misWords[i].word;

// another way

String[] suggestions = isc.getSuggestions(misspeltWord,5,

TextAnalyzerConstant.SUGGESTION_TYPE_SPELL_AID);

An option to get one misspelled word’s suggestions, is with the getSuggestions(String word, int

numSuggestions, int suggestionType) method. There are two types of applications that can use the

suggestionType parameter:

v TextAnalyzerConstant.SUGGESTION_TYPE_SPELL_AID

Standard spell suggestion

v TextAnalyzerConstant.SUGGESTION_TYPE_WILDCARD

Get suggestions based on wildcards in the input word

User dictionary manager: The user dictionary manager of TextAnalyzer is used to manage the user

dictionary data and maintain the consistency of concrete binary dictionaries between different engines of

the same locale. The manage user dictionary functions include:

v Create/delete a user dictionary

v Add/remove words in a user dictionary

v Get all user dictionaries

v Get words in a user dictionary

Create/delete user dictionary:

UserDictionaryManager udm =

TextAnalyzerFactory.getUserDictionaryManager();

String locale = TextAnalyzerConstant.LANGUAGE_ID_EN_US;

UserDictionary ud= udm.createUserDictionary(locale, “common_1”);

// ......

udm.deleteUserDictionary(ud);

In this example, all user dictionary manage methods have been declared in the UserDictionaryManager

interface. An application needs to get an UserDictionaryManager instance with the TextAnalyzerFactory’s

getUserDictionaryManager () method to manage user dictionaries. The application can invoke

UserDictionaryManager’s createUserDictionary(String locale, String suggestionName) to create a

user dictionary. It returns a UserDictionary object. The user dictionary’s name can not be the same in the

current locale, but can be the same in a different locale. The application invokes

deleteUserDictionary(UserDictionary targetDict) to delete a user dictionary. The targetDic parameter

value can be acquired from the return value of createUserDictionary(), getUserDictionary(String

locale, String dictName), or getUserDictionaries(String locale) method in UserDictionaryManager.

Get user dictionary:

UserDictionaryManager udm =

TextAnalyzerFactory.getUserDictionaryManager();

String locale = TextAnalyzerConstant.LANGUAGE_ID_EN_US;

// Get a user dictionary with locale and dictionary name

UserDictionary ud = udm.getUserDictionary (locale,”common_1”);

// Get all user dictionaries with the given

UserDictionary[] uds = udm.getUserDictionary (locale);

In the above code, the application first acquires an instance of the UserDictionaryManager interface, then

invokes the UserDictionaryManager’s getUserDictionary(String locale, String dictName) method to

get the specified user dictionary. The returned value is a UserDictionary object. The application can also

acquire the UserDictionary object through the UserDictionaryManager’s getUserDictionaries(String

locale) method. Please note that the returned value is an array of the UserDictionary object.

Add/remove user word:

206 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 217: Lotus Expeditor: Developing Applications for Lotus Expeditor

UserDictionaryManager udm =

TextAnalyzerFactory.getUserDictionaryManager();

String locale = TextAnalyzerConstant.LANGUAGE_ID_EN_US;

UserDictionary ud= udm.createUserDictionary(locale, ”common_1”);

ud.addUserWord(”tst”); // Add a use word

UserWord word = new UserWord();

word.userWord = ”Hello”;

word.type = UserWord.TYPE_EXCEPTION_WORD;

ud.addUserWord(word); // Add an exception word

UserWord uWord = new UserWord();

uWord.userWord = ”Pls”;

uWord.replaceWord = ”Please”;

uWord.type = UserWord.TYPE_EXCEPTION_WORD;

ud.addUserWord(uWord); // Add an auto correct word

ud.removeUserWord(”tst”);

ud.removeUserWord(word);

ud.removeUserWord(uWord);

In the above code, the application first acquires an instance of the UserDictionaryManager interface, and

creates a user dictionary to get an instance of UserDictionary. Of course, the application can also use

other methods in UserDictionaryManager to get an instance of UserDictionary. Next, the application can

invoke the addUserWord(String word) or addUserWord(UserWord userWord) methods in UserDictionary to

add a word into the user dictionary. The same word cannot be added into a user dictionary. The words

stored in the user dictionary are UserWord objects. The UserWord has two types: TYPE_USER_WORD(1) and

TYPE_EXCEPTION_WORD(2). The number in parenthesis is the integer value for each of the types. There are

thee kinds of words made by the two types:

v common user word - a UserWord object without a replaceWord value, whose type is TYPE_USER_WORD.

This kind of word is commonly a misspelled word, and treated as a correct word when spell checking

is performed.

v exception word - a UserWord object without a replaceWord value, whose type is TYPE_EXCEPTION_WORD.

This kind of word commonly is a correct word, and treated as a misspelled word when spell checking

is performed.

v auto-correction word - a UserWord object with a replaceWord value, whose type is

TYPE_EXCEPTION_WORD. This kind of word can be misspelled or correct, and treated as a misspelled

word. It will set a value into MisspelledWord’s autoCorrectReplacement field, for auto-correction by

the application when spell checking is performed.

When an application creates a UserWord object, the default type is TYPE_USER_WORD. If the application

wants to create an exception word or an auto-correction word, it must set the word’s type manually.

Next, the application invokes removeUserWord( String word) or removeUserWord(UserWord userWord) to

delete a user word from the user dictionary.

Get user words in a user dictionary:

UserDictionaryManager udm =

TextAnalyzerFactory.getUserDictionaryManager();

String locale = TextAnalyzerConstant.LANGUAGE_ID_EN_US;

UserDictionary ud= udm.createUserDictionary(locale, ”common_1”);

ud.addUserWord(”tst”); // Add a use word

UserWord uword = new UserWord();

uword.userWord = ”Hello”;

uword.type = UserWord.TYPE_EXCEPTION_WORD;

ud.addUserWord(uword); // Add an exception word

UserWord[] words = ud.getUserWords();

In the above sample code, the application first acquires an instance of the UserDictionaryManager

interface, and creates a user dictionary to get an instance of UserDictionary. Of course, the application

can also use other methods in UserDictionaryManager to get an instance of UserDictionary. For example,

the getUserDictionary(String locale, String dictName) method. The application can acquire the words

which the user stored in a user dictionary. The return value is an array of UserWord objects.

Developing applications 207

Page 218: Lotus Expeditor: Developing Applications for Lotus Expeditor

Contributing custom spell checking services: The TextAnalyzer framework defines two extension

points: com.ibm.rcp.textanalyzer.Engines and com.ibm.rcp.textanalyzer.Dictionaries. These extension

points for applications are used to contribute custom spell check engines and custom dictionaries. By

default, the TextAnalyzer framework provides two spell check engines: POE (IBM LanguageWare 2.7

engine), jFrost (IBM LanguageWare 5 engine) and 29 dictionaries which are the main dictionaries used for

spell checking within various languages. Applications can use them directly. You can contribute a custom

spell check engine or a custom dictionary into the framework as well.

Contributing a custom spell checking engine: You can contribute a custom engine to spell check the existing

29 dictionaries or a custom engine to spell check your custom dictionaries.

To contribute a custom spell checking engine, perform the following procedure:

1. Create a plug-in project to extend the com.ibm.rcp.textanalyzer.Engines extension point.

2. Add com.ibm.rcp.textanalyzer as its required bundle.

3. Create a class to implement the com.ibm.rcp.textanalyzer.spellchecker.SpellCheckerEngine

interface.

4. Create a class to implement the com.ibm.rcp.textanalyzer.spellcheck.UserDictionaryListener

interface to share the user dictionaries between different applications.

5. Complete the custom spell check engine extension in the plugin.xml file.

6. Build the project.

7. Package the project in a feature.

The following is an example of contributing a simple engine which can check format dictionaries (such

as, misspelt word(suggestion 1, suggestion 2,...., into the TextAnalyzer) is:

ss(as,sos,sis)

tst(test,tat,tot)

examplee(example,examples,exampled)

First create a plug-in project named com.ibm.contributed.custom.engine. Then open its META-INF or

MANIFEST.MF file. In the Dependencies tab, add the com.ibm.rcp.textanalyzer plug-in as its require

bundle. The MANIFEST.MF file will look like:

Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-Name: Engine Plug-in

Bundle-SymbolicName: com.ibm.contributed.custom.engine;singleton:=true

Bundle-Version: 1.0.0

Bundle-Vendor: IBM

Bundle-Localization: plugin

Require-Bundle: com.ibm.rcp.textanalyzer

Next, create a com.ibm.contributed.custom.engine package in its src directory. In the same directory,

create a class named CustomEngine, which implements the

com.ibm.rcp.textanalyzer.spellchecker.SpellCheckerEngine interface. In the CustomEngine class, an

inner class of UserDictionaryHandler which implements the

com.ibm.rcp.textanalyzer.spellchecker.UserDictionaryListener interface is created to handle

DataChangedEvent and UserDictionaryEvent for sharing the user dictionary data between applications.

SpellCheckerEngine.java file:

package com.ibm.contributed.custom.engine;

import java.util.ArrayList;

import com.ibm.rcp.textanalyzer.TextAnalyzerConstant;

import com.ibm.rcp.textanalyzer.TextAnalyzerFactory;

import com.ibm.rcp.textanalyzer.dictionarymanager.DictionaryInfo;

import com.ibm.rcp.textanalyzer.spellchecker.MisspelledWord;

import com.ibm.rcp.textanalyzer.spellchecker.SpellCheckerEngine;

import com.ibm.rcp.textanalyzer.spellchecker.udm.DataChangedEvent;

208 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 219: Lotus Expeditor: Developing Applications for Lotus Expeditor

import com.ibm.rcp.textanalyzer.spellchecker.udm.UserDictionaryEvent;

import com.ibm.rcp.textanalyzer.spellchecker.udm.UserDictionaryListener;

import com.ibm.rcp.textanalyzer.spellchecker.udm.UserDictionaryManager;

public class CustomEngine implements SpellCheckerEngine

{

// The locale for this instance

private String locale;

// The engine name for this instance

private String engineName="CustomEngine";

// The activated dictionaries for this instance

private ArrayList masters = new ArrayList();

// User dictionaries for this instance

private ArrayList userDics = new ArrayList();

// User dictionary handler for this instance

private UserDictionaryHandler udHandler=new UserDictionaryHandler(this.locale,

this.engineName, this.masters);

public boolean addIgnoreWord(String word) {

return SimpleUtils.ignoreWord(word);

}

public MisspelledWord[] checkSpelling(String texttoCheck, int numSuggestions,

boolean autoCorrect) {

if(texttoCheck.equalsIgnoreCase(""))

return new MisspelledWord[0];

return SimpleUtils.checkWordsInDictionary(texttoCheck, numSuggestions,

autoCorrect);

}

public MisspelledWord[] checkSpelling(String texttoCheck, int begin, int end,

int numSuggestions, boolean autoCorrect) {

String checkText=texttoCheck.substring(begin,end);

return checkSpelling(checkText, numSuggestions, autoCorrect);

}

public String[] getSuggestions(String misSpelledWord, int numSuggestions,

int suggestionType) {

if (suggestionType != TextAnalyzerConstant.SUGGESTION_TYPE_SPELL_AID){

return null;

}

if(numSuggestions==0)

return new String[0];

return SimpleUtils.getSuggestions(misSpelledWord, numSuggestions);

}

public boolean closeSession() {

closeAllDictionaries();

// Remove from listener list

UserDictionaryManager udm = TextAnalyzerFactory.getUserDictionaryManager();

udm.removeUserDictionaryListener(udHandler);

return true;

}

public boolean openSession(String locale, DictionaryInfo[] dicInfo) {

// Open the given dictionaries

if(locale==null)

return false;

if(dicInfo==null)

return false;

this.locale=locale;

for(int i=0; i<dicInfo.length; i++)

{

DictionaryInfo dict=dicInfo[i];

if(dict.getDictType()==DictionaryInfo.DICT_TYPE_SPELL_USER)

{

Developing applications 209

Page 220: Lotus Expeditor: Developing Applications for Lotus Expeditor

// Open the user dictionary

this.masters.add(0,dict);

this.userDics.add(dict);

}

else

{

// Open the main dictioary

this.masters.add(dict);

}

}

openDictionaries();

// Register with the user dictionary manager. Set event handlers

UserDictionaryManager udm = TextAnalyzerFactory.

getUserDictionaryManager();

udm.addUserDictionaryListener(udHandler);

return true;

}

public boolean setBooleanPreference(int prefID, boolean prefValue) {

return SimpleUtils.setBooleanPreference(prefID, prefValue);

}

// Create an inner class to handle the UserDictioanry event

private class UserDictionaryHandler implements UserDictionaryListener

{

private String locale;

private String engineName;

private ArrayList masters;

public UserDictionaryHandler(String locale, String engineName,

ArrayList masters)

{

this.locale=locale;

this.engineName=engineName;

this.masters=masters;

}

public void dataChanged(DataChangedEvent event) {

// Get the target dictionary to which to add or remove words

DictionaryInfo dicInfo = event.getTargetDictionary();

UserDictionaryManager udm = TextAnalyzerFactory.getUserDictionaryManager();

// Check event is for this engine and this locale

while (dicInfo.getLocale().equalsIgnoreCase(this.locale)

&& dicInfo.getEngineName().equalsIgnoreCase(this.engineName)) {

// Get the target dictionary

SimpleDictionary dict=SimpleUtils.getDictionaryContent

(dicInfo.getDictionaryName());

if (event.getType() == DataChangedEvent.EVENT_ADD_WORD) {

// Add the word to the target dictionary

SimpleUtils.addWordsToDictionary(dict, event.getData());

// Update the Eclipse xml file

udm.updateBinaryUserDictionaryStatus(dicInfo,

UserDictionaryManager.DICTIONARY_INFO_UPDATE);

break;

}

if (event.getType() == DataChangedEvent.EVENT_REMOVE_WORD) {

// Remove the word from the target dictionary

SimpleUtils.removeWordsToDictionary(dict, event.getData());

// Update the Eclipse xml file

udm.updateBinaryUserDictionaryStatus(dicInfo,

UserDictionaryManager.DICTIONARY_INFO_UPDATE);

break;

}

210 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 221: Lotus Expeditor: Developing Applications for Lotus Expeditor

break;

} // end of while

}

public void userDictionaryChanged(UserDictionaryEvent event) {

DictionaryInfo dicInfo = event.getTargetDictionary();

UserDictionaryManager udm = TextAnalyzerFactory.getUserDictionaryManager();

// Check event is for this engine and this locale

while (dicInfo.getLocale().equalsIgnoreCase(this.locale)

&& dicInfo.getEngineName().equalsIgnoreCase(this.engineName)) {

if (event.getType() == UserDictionaryEvent.EVENT_CREATE_USER_DICTIONARY) {

// Create new user dictionary and add to masters array

SimpleDictionary dict=SimpleUtils.createPhysicalDictionaryFile

(dicInfo.getDictionaryName(), dicInfo.getFilePath());

// Add new dictionary to the head of the masters ArrayList

this.masters.add(0, dict);

// Reopen the dictionaries

openDictionaries();

// Update the Eclipse xml file

udm.updateBinaryUserDictionaryStatus(dicInfo,

UserDictionaryManager.DICTIONARY_INFO_UPDATE);

break;

}

if (event.getType() == UserDictionaryEvent.EVENT_DELETE_USER_DICTIONARY) {

// Find the targetDictionary within the masters ArrayList

SimpleDictionary dict=getDictionaryFromMasters(dicInfo.getDictionaryName());

// Remove it from materdic list and delete the physical file

if (dict != null) {

this.masters.remove(dict);

SimpleUtils.deletePhysicalDictionaryFile(dicInfo.getDictionaryName(),

dicInfo.getFilePath());

// Reopen the dictionaries

openDictionaries();

// Update the Eclipse xml file

udm.updateBinaryUserDictionaryStatus(dicInfo,

UserDictionaryManager.DICTIONARY_INFO_DELETE);

break;

}

} // end of if delete event

break;

} // end of while locale applies loop

} // end of try block

}

private void openDictionaries()

{

SimpleUtils.openDictionaries(this.masters);

}

private void closeAllDictionaries()

{

SimpleUtils.closeDictionaries(this.masters);

}

Developing applications 211

Page 222: Lotus Expeditor: Developing Applications for Lotus Expeditor

private SimpleDictionary getDictionaryFromMasters(String dictName)

{

return SimpleUtils.findDictionaryInList(dictName, this.masters);

}

}

SimpleDictionary.java file:

package com.ibm.contributed.custom.engine;

import java.util.HashMap;

public class SimpleDictionary {

public String dictName;

public String filePath;

public HashMap words;

}

SimpleUtils.java file:

package com.ibm.contributed.custom.engine;

import java.util.HashMap;

import java.util.List;

import com.ibm.rcp.textanalyzer.spellchecker.MisspelledWord;

import com.ibm.rcp.textanalyzer.spellchecker.SpellCheckerPreference;

import com.ibm.rcp.textanalyzer.spellchecker.udm.UserWord;

public class SimpleUtils

{

private static HashMap allWords = new HashMap();

private static int ignorePrefs = 0;

private String token =" ";

public static SimpleDictionary createPhysicalDictionaryFile

(String dicName, String dicFilePath)

{

// TODO Create a dictionary file.

return null;

}

public static boolean deletePhysicalDictionaryFile(String dicName,

String dicFilePath)

{

//TODO Delete the dictionary file

return false;

}

public static SimpleDictionary getDictionaryContent(String dicName)

{

//TODO Read the physical dictionary file

return null;

}

public static void setDictionaryContent(String dicName)

{

//TODO Write the physical dictionary file

}

public static void addWordsToDictionary(SimpleDictionary dict,

UserWord[] words)

{

//TODO Append the words to the end of the dictionary

}

public static void removeWordsToDictionary(SimpleDictionary dict,

UserWord[] words)

{

212 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 223: Lotus Expeditor: Developing Applications for Lotus Expeditor

//TODO Append the words to the end of the dictionary

}

public static boolean openDictionaries(List dictionaries)

{

//TODO Open all the dictionaries and collect all misspelt words into a map

return false;

}

public static boolean closeDictionaries(List dictionaries)

{

//TODO Close all the dictionaries and dispose the data collect in

//openDictionaries() method

return false;

}

public static SimpleDictionary findDictionaryInList(String dicName,

List dictionaries)

{

//TODO Find the dictionary in the dictionaries list

return null;

}

public static boolean ignoreWord(String word)

{

if(allWords.containsKey(word))

allWords.remove(word);

return true;

}

public static String[] getSuggestions(String misSpelledWord,

int numSuggestions)

{

String strSuggestion;

if(allWords.containsKey(misSpelledWord))

strSuggestion = (String)allWords.get(misSpelledWord);

else

strSuggestion = "";

String[] aSuggestion=strSuggestion.split(",");

int len=aSuggestion.length;

if(len<numSuggestions)

return aSuggestion;

else

{

String[] retV=new String[numSuggestions];

for(int i=0;i<numSuggestions; i++)

retV[i]=aSuggestion[i];

return retV;

}

}

public static boolean setBooleanPreference(int prefID, boolean prefValue) {

if (prefValue) {

// Turn on the flag

ignorePrefs |= prefID;

}

else {

// Turn off the flag

ignorePrefs &= ~prefID;

}

return true;

}

private static boolean canIgnore(String word, int ignorePrefs) {

if ((ignorePrefs & SpellCheckerPreference.PREF_IGNORE_WORD_FILE) ==

SpellCheckerPreference.PREF_IGNORE_WORD_FILE) {

Developing applications 213

Page 224: Lotus Expeditor: Developing Applications for Lotus Expeditor

return false;

}

if ((ignorePrefs & SpellCheckerPreference.PREF_IGNORE_WORD_URLS) ==

SpellCheckerPreference.PREF_IGNORE_WORD_URLS) {

return false;

}

if ((ignorePrefs & SpellCheckerPreference.PREF_IGNORE_WORD_IN_UPPERCASE) ==

SpellCheckerPreference.PREF_IGNORE_WORD_IN_UPPERCASE) {

int len = word.length();

for(; len > 0; len--){

if (Character.isLowerCase(word.charAt(len-1)))

break;

}

if (len == 0) return true;

}

if ((ignorePrefs & SpellCheckerPreference.PREF_IGNORE_WORD_WITH_NUMBER) ==

SpellCheckerPreference.PREF_IGNORE_WORD_WITH_NUMBER) {

int len = word.length();

for(; len > 0; len--){

if (Character.isDigit(word.charAt(len-1)))

return true;

}

}

return false;

}

public static MisspelledWord[] checkWordsInDictionary(String texttoCheck,

int numSuggestions, boolean autoCorrect)

{

//TODO

return null;

}

}

Next, complete the engine extension in plugin.xml file. The finished plugin.xml file looks like:

<?xml version="1.0" encoding="UTF-8"?>

<?eclipse version="3.2"?>

<plugin>

<extension

point="com.ibm.rcp.textanalyzer.Engines">

<engine

class="com.ibm.contributed.custom.engine.CustomEngine"

interface="com.ibm.rcp.textanalyzer.spellchecker.SpellCheckerEngine"

locales="en-US,zh-CN"

name="CustomEngine"

platform="All"

provider="IBM"

thirdParty="true"/>

</extension>

</plugin>

Next, build the project, if you are using Eclipse PDE tools, the build.properties file looks like:

source.. = src/

output.. = bin/

bin.includes = META-INF/,\

.,\

plugin.xml

After completing the above steps, the project structure looks like:

com.ibm.contributed.custom.engine/

src/

com.ibm.contributed.custom.engine/

214 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 225: Lotus Expeditor: Developing Applications for Lotus Expeditor

CustomEngine.java

SimpleDictionary.java

SimpleUtils.java

META-INF/

MANIFEST.MF

build.properties

plugin.xml

Finally, you should include the plug-in in your feature project:

<plugin

id="com.ibm.contributed.custom.engine"

download-size="0"

install-size="0"

version="0.0.0"

unpack="false"/>

The feature/plug-in containing the custom engine can be added into the TextAnalyzer framework after

installation. In this sample, after installation this plug-ins will be packaged into a jar file:

com.ibm.contributed.custom.engine_1.0.0.jar.

Contributing custom dictionaries: You can contribute your existing custom dictionary files into the

TextAnalyzer framework. The framework supports two engines:

v jFrost - IBM LanguageWare 5 engine

v POE - IBM LanguageWare 2.7 engine

LanguageWare provides the underlying functionality required to enable all types of applications to

process and understand natural language text. The IBM LanguageWare provides the LanguageWare

Resource Workbench (LRW) to create custom dictionaries based on the jFrost engine. If you wish to use

the default provided jFrost or POE engine as your dictionary’s check engine, your dictionary should be

jFrost or POE format, otherwise it will not be checked successfully.

To contribute a custom dictionary, perform the following procedure:

1. Create a plug-in project to extend the com.ibm.rcp.textanalyzer.Dictionaries extension point.

2. Put the custom dictionary .dic file into a directory in the plug-in project.

3. Complete the custom dictionary extension in plugin.xml file.

4. Build the project.

5. Package the project in a feature.

The following is an example of contributing an English (United States) medical dictionary that can be

checked by the jFrost engine into the TextAnalyzer framework.

First, create a plug-in project named com.ibm.sample.dic.en_US_Medical.

Then, create a directory named dictionaries in the project, and put the custom dictionary file

en_US_medical.dic into that directory;

Next, complete the dictionary extension in the plugin.xml file. The finished

plugin.xml file should look like:

<plugin>

<extension

point="com.ibm.rcp.textanalyzer.Dictionaries">

<dictionary

description="English medical dictionary"

dict_name="en_US_medical.dic"

engine="jFrost"

filePath="./dictionaries/en_US_medical.dic"

language="en-US"

locale="en-US"

provider="IBM"

Developing applications 215

Page 226: Lotus Expeditor: Developing Applications for Lotus Expeditor

version_info="1.0.0"

type="spell"/>

</extension>

</plugin>

Next, build the project. If you are using Eclipse PDE tools, make sure that the dictionaries directory is

built into the binary. The build.properties file should look like:

bin.includes = plugin.xml,\

META-INF/,\

dictionaries/

After completing the above steps, the project structure should look like:

com.ibm.sample.dic.en_US_Medical/

dictionaries/

en_US_medical.dic

META-INF/

MANIFEST.MF

build.properties

plugin.xml

At last, you should include this plug-in in your feature project, make sure this plug-in will unpack after

installation. To do this: either check Unpack the plug-in archive after the installation in the feature

Plug-ins and Fragments view. Or, add the following lines to you feature.xml file:

<plugin

id="com.ibm.sample.dic.en_US_Medical"

version="1.0.0"

unpack="true"/>

The feature/plug-in containing the custom medical dictionary can now be added into the TextAnalyzer

framework after installation. In this sample, the file structure after installation should look like:

com.ibm.sample.dic.en_US_Medical_1.0.0/

dictionaries/

en_US_medical.dic

META-INF/

MANIFEST.MF

plugin.xml

Implementing an embedded Web browser

Lotus Expeditor Client supports running a Web browser that is embedded in the client window.

The embedded browser is a configurable and manageable browser that you can embed in a client

application. The com.ibm.rcp.ui.browser plug-in provides APIs that you can use to implement a web

browser view.

The embedded browser plug-in does the following:

v Provides default user interface controls, such as a toolbar, status bar, and history bar.

v Is based on the DOM Browser developed by IBM. The DOM Browser is based on the Eclipse Standard

Widget Toolkit (SWT) Browser, and also leverages APIs that are native to the supported browsers.

v Supports Internet Explorer on Windows and Mozilla on Linux.

v Supports displaying pages in HTML/DHTML(CSS/Script), and XML format. Supports displaying

plug-ins, applets, activeX, flash, and PDF content.

v Provides APIs that you can use to customize it and configure its security.

v Supports the com.ibm.rcp.ui.browser.portal-feature feature in a managed client environment, which you

can install to add the Managed Browser Administration Portlet to WebSphere Portal. Administrators

can use this portlet to further customize the browser view.

To implement an embedded browser, perform the following steps:

216 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 227: Lotus Expeditor: Developing Applications for Lotus Expeditor

1. Create an embedded browser view.

2. Enhance the embedded browser.

Creating an embedded browser:

You can use the APIs provided with the client to create an embedded browser.

To create an embedded browser, use one of the following APIs:

v BrowserFactory.launch API – Returns a full instance of an EmbeddedBrowser object that the application

can continue to interact with by registering to be notified of browser events and reacting to them. For

example, you could implement the addTitleListener to listen for events that make it suitable for the

application to change the browser title and code the application to do so.

v IWorkbenchPage.showView API – Opens a URL in a browser view. Use this method if you do not want

to subsequently perform advanced interactions with the browser.

To instantiate an embedded browser, perform the following steps:

1. Define the embedded browser configuration ID.

String id = browserAppId + ".browserview." + Integer.toString(++counter);

2. Construct an embedded browser configuration hash map and pass in the ID you defined in the

previous Step.

Map configMap = new HashMap();

configMap.put(BrowserPreference.ID, id);

configMap.put(BrowserPreference.INITIAL_URL, "http://www.ibm.com");

...

3. Retrieve a reference to the current page using the getActivePage() method of the IWorkbenchPage

interface.

IWorkbenchPage activePage=

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()

4. Do one of the following:

v Use the launch() method of the BrowserFactory interface to instantiate the embedded browser.

For example:

EmbeddedBrowser browser = BrowserFactory.launch(activePage, configMap, id);

v Use the IWorkbenchPage interface to start the embedded browser, by providing the configuration

map to the setBrowserConfigMap() method. Then use the showView() method of the

IWorkbenchPage interface to create the view, and finally, the getBrowser() method to display it.

For example:

BrowserFactory.setBrowserConfigMap(id, configMap);

activePage.showView(BrowserPreference.BROWSER_VIEW_ID, id,

IWorkbenchPage.VIEW_ACTIVATE);

EmbeddedBrowser browser = BrowserFactory.getBrowser(id);

Enhancing an embedded browser view:

Use the EmbeddedBrowser interface to enhance the view by adding listeners to handle events and

implementing navigation.

To enhance an embedded browser view, you can perform the following steps:

1. Add listeners to handle any of the following events:

v Close window event:

Developing applications 217

Page 228: Lotus Expeditor: Developing Applications for Lotus Expeditor

myEmbeddedBrowser.addCloseWindowListener(new

EmbeddedBrowserCloseWindowListener(){

Public void close(){

//dispose of my widget

}

});

v Completed document event:

myEmbeddedBrowser.addDocumentCompleteListener(new

EmddedBrowserDocumentCompleteListener(){

Public void changed(EmbeddedBrowserDocumentCompleteEvent event){

//get the HTML document

}

});

v URL change event:

myEmbeddedBrowser.addLocationListener(new

EmbeddedBrowserLocationListener(){

Public void changed(EmbeddedBrowserLocationEvent event){

//get the url.

}

Public void changing(EmbeddedBrowserLocationEvent event){

//get the changing url, and set doit.

}

});

v Open window event:

myEmbeddedBrowser.addOpenWindowListener(new

EmbeddedBrowserOpenWindowListener(){

public void onAfterOpenWindow(EmbeddedBrowserWindowEvent event) {

//do some task after a new window opens.

}

public void onBeforeOpenWindow(EmbeddedBrowserOpenWindowEvent event) {

//do some task before a new window opens.

}

});

v Title change event:

myEmbeddedBrowser.addTitleListener(new EmddedBrowserTitleListener(){

Public void changed(EmbeddedBrowserTitleEvent event){

//get the changed title and set it as the new title

}

});

2. You can implement navigation using one of the following methods:

v Get the current URL

String url= myEmbeddedBrowser.getUrl();

v Set the URL

myEmbeddedBrowser.setUrl(“http://www.ibm.com”);

v Stop the retrieval of a URL

myEmbeddedBrowser.stop();

3. You can define a cookie and pass it to a Web address.

String url=http://www.ibm.com;

//set a cookie before navigating to the Web address.

String cookie=”aaa=bbb”;//cookie string

myEmbeddedBrowser.setCookie(url,cookie);

myEmbeddedBrowser.setUrl(“http://www.ibm.com”);

218 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 229: Lotus Expeditor: Developing Applications for Lotus Expeditor

Setting browser preferences: You can define default preference settings for the embedded browser in

the following ways:

v Programmatically using the fields defined in the BrowserPreferences class.

v By defining Eclipse preferences.

Setting browser preferences programmatically:

Use a configuration map to programmatically define preferences for the embedded browser.

You can define values for the following embedded browser preferences:

Field name Description

static java.lang.String ALLOW_DOWNLOAD_OVERWRITE Determines whether to overwrite the local file

static java.lang.String ALLOW_SCRIPTS Determines whether Javascript and ActiveX are

enabled.

static java.lang.String BROWSER_EDITOR_ID Defines the embedded browser editor id.

static java.lang.String BROWSER_VIEW_ID Defines the embedded browser view id.

static java.lang.String CONFIG_ID Specifies the configuration id of the embedded

browser configuration.

static java.lang.String CONFIG_TITLE Specifies the title of the embedded browser

configuration.

static java.lang.String

CONTROLLED_DOWNLOAD_DOMAIN_LIST

List of domains from which a user cannot

download unsolicited files.

static java.lang.String CONTROLLED_DOWNLOAD_PATH Local path to which to save a downloaded file.

static java.lang.String DOMAINS_DENY If set to true, specifies that navigation to the

domains in the DOMAINS_LIST field is prohibited.

If set to false, specifies that navigation to the

domains in the domainsList preference is permitted.

The default is to ″deny nothing.″ When a user

navigates to a restricted domain, an error restricted,

a message is displayed for the user.

static java.lang.String DOMAINS_LIST List of domains for restricting navigation.

static java.lang.String DOWNLOAD_DOMAINS_DENY If set to true, the list in the

DOWLOAD_DOMAINS_LIST field specifies

domains from which downloading files is

prohibited. If set to false, it specifies a list of

domains from which downloading files is

permitted. The default is to ″deny nothing.″

static java.lang.String DOWNLOAD_DOMAINS_LIST List of domains for restricting unsolicited file

download.

static java.lang.String ENABLE_APPLET Determines whether to support Java2 Applets.

Applies to Internet Explorer browsers only.

static java.lang.String ENABLE_BOOKMARKS Determines whether Bookmark functions are

enabled.

static java.lang.String ENABLE_CONTEXT_MENU Determines whether a right click displays a context

menu. Applies only to Internet Explorer.

static java.lang.String ENABLE_HELP Determines whether the F1 key displays an

associated Help topic.

static java.lang.String FILE_PERMIT Determines whether a browser can access local files

and certain Mozilla ″about:″ pages.

Developing applications 219

Page 230: Lotus Expeditor: Developing Applications for Lotus Expeditor

Field name Description

static java.lang.String HOME_URL The Web address that displays when a user clicks

the Home button. If useBrowserHome = ″true″, the

browser’s home page defaults to the home page

address defined by the native browser and ignores

the value you define here. If useBrowserHome =

″false″, the browser’s home page uses this value.

The default value for this preference is the value of

the initialURL preference.

static java.lang.String ID Specifies the ID of the embedded browser

configuration.

static java.lang.String INITIAL_URL Default Web address for the browser. This is the

address that displays when the browser first opens.

static java.lang.String LAUNCH_TYPE Specifies the launch type for the browser instance.

Options are ″editor″ or ″view.″

static java.lang.String LOCK_TOOL_BAR Determines whether toolbar items can be dragged

and dropped by users. Not applicable if

showToolbar is set to false.

static java.lang.String LTPA_TOKEN_MANAGER Provided by the launcher, this object implements

the ILTPATokenManager interface.

static java.lang.String POPUP_DOMAINS_DENY If set to true, the list in the

POPUP_DOMAINS_LIST field specifies a list of

domains from which popups are prohibited. If set

to false, it specifies a list of domains from which

popus are permitted. The default is to ″deny

nothing.″

static java.lang.String POPUP_DOMAINS_LIST List of domains for restricting unsolicited popups.

static java.lang.String POPUP_STYLE Defines the style of the popup window. The options

are:

default – If the browser window does not have a

status bar or a tool bar, a new window opens.

Otherwise, the window opens in a tab view.

popup – opens a new window.

embedded – opens a window in the active tab

view.

static java.lang.String PROXY_AUTO_CONFIG_URL Specifies the automatic proxy configuration URL. If

this field is set, other proxy setting fields are

ignored.

static java.lang.String PROXY_BY_PASS Web addresses that do not use the proxy server. For

Mozilla, use a comma as a separator and for

Internet Explorer, use a semicolon.

static java.lang.String PROXY_FTP_PORT Defines the proxy port for the FTP protocol.

static java.lang.String PROXY_FTP_SERVER Proxy server for the FTP protocol.

static java.lang.String PROXY_GOPHER_PORT Defines the proxy port for the Gopher protocol.

static java.lang.String PROXY_GOPHER_SERVER Proxy server for the Gopher protocol.

static java.lang.String PROXY_HTTP_PORT Defines the proxy port for the HTTP protocol.

static java.lang.String PROXY_HTTP_SERVER Proxy server for the HTTP protocol.

static java.lang.String PROXY_PORT Unified proxy port. Defines the port number for the

proxy server. If set, this setting is used for all

network protocols.

220 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 231: Lotus Expeditor: Developing Applications for Lotus Expeditor

Field name Description

static java.lang.String PROXY_SERVER Unified proxy server. If this field is set, proxies for

separate network protocols, such as HTTP, Gopher,

and FTP are ignored. Proxies for each network

protocol are set to this proxy.

static java.lang.String PROXY_SOCKS_PORT Defines the proxy port for SOCKS.

static java.lang.String PROXY_SOCKS_SERVER Proxy server that supports SOCKS packages.

static java.lang.String PROXY_SSL_PORT Defines the proxy port for the SSL protocol.

static java.lang.String PROXY_SSL_SERVER Proxy server for the SSL protocol.

static java.lang.String SHOW_BOOKMARK Determines whether the Bookmark button is

enabled.

static java.lang.String SHOW_HISTORY Determines whether the Back and Forward buttons

are enabled.

static java.lang.String SHOW_HOME Determines whether the Home button is enabled.

static java.lang.String SHOW_PAGE_CONTROL Determines whether the Stop and Refresh buttons

are enabled.

static java.lang.String SHOW_PRINT Determines whether the Print button is enabled.

static java.lang.String SHOW_TOOL_BAR Determines whether the toolbar is displayed. If

false, showHistory, showPageCtrl showHome,

showPrint, and showBookmark are all forced false.

static java.lang.String SHOW_URL_ENTRY Determines whether the URL entry field is

displayed. If false, the user cannot type in URLs.

static java.lang.String TITLE Embedded Browser preference name: title String

specifying the browser title

static java.lang.String USE_BROWSER_HOME If set to false, the Home button opens the page

defined in the homeURL field or in the initialUrl

field if no homeURL value is defined. If set to true,

the Home button opens the home page defined for

the native browser. The home page for a native

Internet Explorer browser is specified using the

Internet Options menu. The home page for a native

Mozilla browser is specified using a private profile

preference, called ″browser.startup.homepage.″ On

Windows, this configuration item only applies to

Internet Explorer.

static java.lang.String USE_BROWSER_ICON Determines which view icon to display based on

the embedded browser type, Internet Explorer or

Mozilla.

static java.lang.String USE_BROWSER_STATUS Determines whether status text is obtained from

Browser StatusText events or from DOM mouseover

events.

static java.lang.String USE_BROWSER_TITLE Determines whether view title is derived from

BrowserTitle events (typically title of a displayed

webpage) or from the TITLE field.

static java.lang.String USER_PREFERENCE_NAMES Array of embedded browser preferences for an end

user.

static java.lang.String WEB_BROWSER Internal field.

To set embedded browser preferences programmatically, perform the following steps:

1. Define the embedded browser configuration ID.

Developing applications 221

Page 232: Lotus Expeditor: Developing Applications for Lotus Expeditor

String id =

browserAppId + ".browserview." + Integer.toString(++counter);

2. Construct an embedded browser configuration map and pass values for the preferences into it.

Map configMap = new HashMap();

configMap.put(BrowserPreference.browser_field, value);

configMap.put(BrowserPreference.browser_field, value);

...

where the browser_field variables are preferences you want to set for the browser.

3. Create the embedded browser.

Setting browser preferences as Eclipse preferences:

Use Eclipse preferences to define default preferences for the embedded browser.

You can use Eclipse preferences to define values for the following subset of embedded browser

preferences:

Key Value options Default value Description

embeddedBrowser ″platform″

″MSIE″

″Mozilla″

″platform″ ″platform″ – Defaults to

″MSIE″ on Windows and to

″Mozilla″ on Linux.

″MSIE″ – Microsoft Internet

Explorer for the Windows

platform. If specified on the

Linux platform, ″Mozilla″ is

used instead and a warning

is logged.

″Mozilla″ – Browser for the

Linux platform.

enableApplet Boolean string false Determines whether to

support Java2 Applets.

Applies to Internet Explorer

browsers only.

enableBookmarks Boolean string true Determines whether

Bookmark functions are

enabled.

homeURL String null The Web address that

displays when a user clicks

the Home button. If

useBrowserHome = ″true″,

the browser’s home page

defaults to the home page

address defined by the

native browser and ignores

the value you define here.

If useBrowserHome =

″false″, the browser’s home

page uses this value. The

default value for this

preference is the value of

the initialURL preference.

222 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 233: Lotus Expeditor: Developing Applications for Lotus Expeditor

Key Value options Default value Description

initialURL String ″about:blank″ Default Web address for the

browser. This is the address

that displays when the

browser first opens. The

URL may contain

%USERID% and

%PASSWORD% tokens that

are replaced by the values

you define for the

%USERID% and

%PASSWORD%

preferences.

popupStyle String null string or ″default″ Defines the style of the

popup window. The

options are:

default – If the browser

window does not have a

status bar or a tool bar, a

new window opens.

Otherwise, the window

opens in a tab view.

popup – opens a new

window.

embedded – opens a

window in the active tab

view.

proxyByPass String null Web addresses that do not

use the proxy server. For

Mozilla, use a comma as a

separator and for Internet

Explorer, use a semicolon.

proxyFtpPort Integer 0 Defines the proxy port for

the FTP protocol.

proxyFtpServer String null Proxy server for the FTP

protocol.

proxyGopherPort Integer 0 Defines the proxy port for

the Gopher protocol.

proxyGopherServer String null Proxy server for the Gopher

protocol.

proxyHttpPort Integer 0 Defines the proxy port for

the HTTP protocol.

proxyHttpServer String null Proxy server for the HTTP

protocol.

proxyPort Integer 0 Unified proxy port. Defines

the port number for the

proxy server. If set, this

setting is used for all

network protocols.

Developing applications 223

Page 234: Lotus Expeditor: Developing Applications for Lotus Expeditor

Key Value options Default value Description

proxyServer String null Unified proxy server. If this

item is set, proxies for

separate network protocols,

such as HTTP, Gopher, and

FTP are ignored. Proxies for

each network protocol are

set to this proxy.

proxySocksPort Integer 0 Defines the proxy port for

SOCKS.

proxySocksServer String null Proxy server that supports

SOCKS packages.

proxySslPort Integer 0 Defines the proxy port for

the SSL protocol.

proxySslServer String null Proxy server for the SSL

protocol.

showBookmark Boolean string false Determines whether the

Bookmark button is shown.

showHistory Boolean string true Determines whether the

Back and Forward buttons

are shown and enabled.

showHome Boolean string true Determines whether the

Home button is shown and

enabled.

showPageCtrl Boolean string true Determines whether the

Stop and Refresh buttons

are shown enabled.

showPrint Boolean string true Determines whether the

Print button is shown and

enabled.

showToolbar Boolean string true Determines whether the

toolbar is displayed. If

false, showHistory,

showPageCtrl, showHome,

showPrint, and

showBookmark are all

forced false. This

configuration item can be

deprecated since it can be

determined from those

other configuration items.

showURLEntry Boolean string true Determines whether the

URL entry field is

displayed. If false, the user

cannot type in URLs.

title String ″title″ Title that displays in the

embedded browser title bar.

1. Modify the plugin_customization.ini file in the com.ibm.rcp.platform.personality.branding plug-in to

provide values for the keys you want to set. Use the following syntax:

com.ibm.rcp.ui.browser/key=value

For example, to specify that bookmarks should be enabled in all browser views, add the following

key and value:

224 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 235: Lotus Expeditor: Developing Applications for Lotus Expeditor

com.ibm.rcp.ui.browser/showBookmark=true

com.ibm.rcp.ui.browser/enableBookmarks=true

2. Save and close the plugin_customization.ini file. These default settings will be in effect for any users

that provision the com.ibm.rcp.platform.personality.branding plug-in to their client machines.

Using the Rich Text Editor

The Rich Text Editor is a text editor that provides a full set APIs to control text elements and wrapper. It

is based on the DOM browser widget, which itself is based on the SWT browser widget.

The Rich Text Editor has the advantage of being completely configurable, manageable, and easily

modified. It is based on DOM Browser, can be embedded in a Java application, and provide a default UI

(such as a tool bar). It provides APIs for application development, and can extend an application’s

functions, such as handling events and contents.

Creating a custom Rich Text Editor: To create a custom Rich Text Editor, use RichTextEditorFactory

class to get a RichTextEditor instance:

1. Add com.ibm.rcp.rte to the Require Bundles item in the MANIFEST.MF file.

2. Import com.ibm.rcp.rte.RichTextEditor and com.ibm.rcp.rte.RichTextEditorFactory into your

code.

3. Create RichTextEditor using the RichTextEditorFactory class:

RichTextEditorFactory .createRichTextEditorInstance(Composite parent,

int compositeStyle, int toolBarStyle, int rteStyle)

v The argument parent is the container composite for the Rich Text Editor

v The argument compositeStyle is the SWT style of the Rich Text Editor

v The argument toolBarStyle is used to configure the toolbar

v The argument rteStyle is used to configure rte, for example, setting it as a Read-Only property

The Rich Text Editor uses about:blank as the default editing page. You can specify a page or set the

string content after the Rich Text Editor builds.

Using and controlling the custom Rich Text Editor: After you create a RichTextEditor instance, you

can use it as a composite. It provides its own UI interface for configuration. You can either click the

toolbar to execute the function, or use the API to implement your requirement.

Using APIs to control Rich Text Editor documents: APIs are provided for controlling Rich Text Editor

documents. You can use them to modify the document. For example, rte.bold is to set the bold or

unbold status of selected elements.

Adding custom listeners to Rich Text Editor documents: The Rich Text Editor provides add/remove listener

methods. You can use them to add custom listeners to documents, implement new functions, or attach

new components to the Rich Text Editor.

For example:

rte.addDocumentEventListener("contextmenu",new EventListener() {

public void handleEvent(org.w3c.dom.events.Event e) {

....

}

});

Sample code:

package com.ibm.rcp.samples.rte;

import org.eclipse.swt.SWT;

import org.eclipse.swt.events.KeyEvent;

import org.eclipse.swt.events.KeyListener;

import org.eclipse.swt.layout.GridLayout;

Developing applications 225

Page 236: Lotus Expeditor: Developing Applications for Lotus Expeditor

import org.eclipse.swt.widgets.Composite;

import org.eclipse.ui.part.ViewPart;

import org.w3c.dom.events.EventListener;

import com.ibm.rcp.rte.RichTextEditor;

import com.ibm.rcp.rte.RichTextEditorFactory;

public class RTEView extends ViewPart {

public static final String ID = "RTEWrapper.view";

private Composite parent;

private Composite realParent;

public void createPartControl(Composite parent) {

realParent = parent;

this.parent = new Composite(parent, SWT.NONE);

RichTextEditor rte=

RichTextEditorFactory.createRichTextEditorInstance(

this.parent,

SWT.BORDER | SWT.FLAT,

RichTextEditor.TOOLBAR_STYLE_ALL,

RichTextEditor.RTE_STYLE_DEFAULT

);

// rte.setUrl("file:///xxxx.html."); This line can set a

// local file as default editing page.

// rte.setUrl("http://www.ibm.com"); This line can set a

// website page as default editing page.

rte.setSourceContent(

"<html>" +

"<head>" +

"<title>setSourceContent</title>" +

</head>" +

"<body>" +

"test" +

"<a href=\"http://www.ibm.com\">link</a>" +

"</body>" +

"</html>"

);

rte.addKeyListener(new KeyListener() {

public void keyPressed(KeyEvent key) {

System.out.println(" keyPressed");

}

public void keyReleased(KeyEvent key) {

System.out.println(" keyReleased");

}

});

rte.addDocumentEventListener("contextmenu",new EventListener() {

public void handleEvent(org.w3c.dom.events.Event e) {

System.out.println("contextmenu");

}

});

rte.addDocumentEventListener("focusin",new EventListener() {

public void handleEvent(org.w3c.dom.events.Event e) {

System.out.println("focusin");

}

});

GridLayout layout = new GridLayout();

realParent.layout();

this.parent.setLayout(layout);

this.parent.layout();

}

public void setFocus() {

// TODO Auto-generated method stub

}

}

226 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 237: Lotus Expeditor: Developing Applications for Lotus Expeditor

Accessing a Web address with the integrated browser application

Lotus Expeditor has an integrated browser application within the workbench. You can use the

com.ibm.rcp.ui.browser.launcher code provided in Lotus Expeditor to implement a hypertext link in

your application that, when clicked, opens the Web address in a browser view. You can set the browser

view to be an embedded browser in the application tabs or an external browser, which is set as default.

To access a web address in your application by launching an integrated browser application, perform the

following procedure:

1. Set the Required Bundle as: Require-Bundle: com.ibm.rcp.ui.browser.launcher.

2. In the class that implements the API, import the following class:

import com.ibm.rcp.ui.browser.launcher.BrowserLauncher;

3. Get the BrowserLauncher instance using the BrowserLauncher class.

BrowserLauncher launcher=BrowserLauncher.getLauncher();

4. Launch the given URL with the integrated browser application through the default method.

launcher.launchURLasDefault("http://www.ibm.com");

This will launch a browser view with web address http://www.ibm.com. The default behavior is set

by the user through the Web Browser preference page. The user can select the embedded web browser

in the client or the external browser set as the default to launch this web address.

5. Launch the given URL with the embedded browser view.

final String secondaryId = BROWSER_VIEW_ID + Integer.toString(++counter);

Map configMap = new HashMap();

configMap.put(BrowserPreference.ID, secondaryId);

BrowserLauncher bLauncher=BrowserLauncher.getLauncher();

bLauncher.launchURLasEmbedded("http://www.ibm.com",null, configMap);

This will force the launch of an embedded browser in the application tab of the workbench. You can

have advanced control of the browser view by configuring the configMap object. All configurations are

described in “Setting browser preferences” on page 219.

Note: This sample code requires the bundle com.ibm.rcp.ui.browser, and should import

com.ibm.rcp.ui.browser.launcher.BrowserLauncher in the class.

6. Launch the given URL with an external browser.

launcher. launchURLasExternal ("http://www.ibm.com");

This will force the launch of an external browser with a given URL.

The following is sample code illustrates the urlLauncher.java.

package com.ibm.rcp.samples.ui.browser.launcher;

import java.util.HashMap;

import java.util.Map;

import com.ibm.rcp.ui.browser.BrowserPreference;

import com.ibm.rcp.ui.browser.launcher.BrowserLauncher;

public class urlLauncher{

private static final String BROWSER_VIEW_ID =

"com.ibm.rcp.ui.samples.browsertab"; //$NON-NLS-1$

private static int counter;

public boolean launchURL(String url){

BrowserLauncher launcher=BrowserLauncher.getLauncher();

return launcher.launchURLasDefault(url);

}

public boolean launchURLasEmbed(String url){

final String secondaryId = BROWSER_VIEW_ID + Integer.toString(++counter);

Map configMap = new HashMap();

configMap.put(BrowserPreference.ID, secondaryId);

BrowserLauncher bLauncher=BrowserLauncher.getLauncher();

Developing applications 227

Page 238: Lotus Expeditor: Developing Applications for Lotus Expeditor

return bLauncher.launchURLasEmbedded(url,null, configMap);

}

public boolean launchURLasExternal(String url){

BrowserLauncher launcher=BrowserLauncher.getLauncher();

return launcher.launchURLasExternal(url);

}

}

Customizing the integrated browser application with Eclipse preferences: Application developers can

customize the behavior of the integrated browser application by editing the plug-in customization file

(plugin_customization.ini). The default settings control the behavior of the user’s client after

provisioning.

Table 13. Configurable items

Preferences Values Default Descriptions

showPreferencePage True

False

True Toggle the Web Browser preference

page

enableBrowserSSO True

False

True Toggle support for pre-authentication

allowUserDefinedHomePage True

False

True Toggle home page setting UI. This

depends on the setting of

showPreferencePage.

adminHomePage String value about:blank Configures the admin default home

page

For example, if an application developer wants to set the admin home page with his company’s web site,

he can modify its plug-in customization file by adding the following lines:

#Set home page for browser application

com.ibm.rcp.ui.browser.launcher/adminHomePage=http://www.ibm.com

Using the Portlet Viewer

The Portlet Viewer is an Eclipse view wrapper for a JSR 168 portlet. It consists of a SWT browser instance

whose URL points to a JSR 168 portlet deployed onto the Portlet Container. The main benefit of the

Portlet Viewer is that it provides a unified rich client component for the composite application

framework, for portlet presentation and interaction.

A Portlet Viewer instance can be instantiated and contributed to the Lotus Expeditor platform in two

ways:

v In the Portal-managed environment, portlet information will be stored in the Composite Application

(CA) XML file and passed down to the Lotus Expeditor platform through the Composite Application

Infrastructure. The portlet information from the CA XML file will be translated to a Portlet Viewer

instance by the Topology Handler. Its important to note that the portlets are deployed as part of a

composite application and that the Portlet Viewer instances are merely views within the application

perspective.

v In the non Portal managed environment, the Portlet Viewer instances can be defined and contributed

using the Portlet Viewer extension point - com.ibm.rcp.portletviewer.portlets.

To declaratively define and contribute a Portlet Viewer instance to the Lotus Expeditor platform, perform

the following procedure:

1. Select the Client Services Portlet project you want to wrap with the Portlet Viewer instance.

2. Right click the plugin.xml descriptor file and select Open With > Plug-in Manifest Editor.

3. Select the Extensions tab.

228 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 239: Lotus Expeditor: Developing Applications for Lotus Expeditor

4. Select Add.

5. Locate the com.ibm.rcp.portletviewer.portlets extension point and select Finish.

6. Update the <portletData> element attributes.

7. Save the plugin.xml file.

Portlet Viewer extension examples: Sample definition for a JSR 168 portlet

<extension point="com.ibm.rcp.portletviewer.portlets">

<portletData

entityId="com.bank.portletviewer.helloworldportlet"

portlettype="JSR168"

portletname="HelloWorldPortlet"

portletwindowid="HelloWorldPortletWindow1"

contextroot="/HelloWorld ">

</portletData>

</extension>

Using the Portlet Viewer with WSRP portlets: The Portlet Viewer can also be used to view a remote

WSRP portlet, through the WSRP feature in Lotus Expeditor. Just like the Portlet viewer for a local JSR

168 portlet, you have two choices to view a WSRP portlet:

v In the Portal-managed environment, you can deploy a WSRP rich client enablement portlet as part of a

composite application, which will be configured to store the WSRP related meta-data of a WSRP

provider portlet. The WSRP rich client enablement portlet will export the WSRP meta-data into the

Composite Application (CA) XML file and pass it down to the Lotus Expeditor platform through the

Composite Application Infrastructure. The meta-data will be used by the portlet viewer to start the

WSRP facility in Lotus Expeditor and present the WSRP provider portlet.

v In the non Portal managed environment, the Portlet Viewer instances can be defined and contributed

using the Portlet Viewer extension point - com.ibm.rcp.portletviewer.WsrpPortlets.

To declaratively define and contribute a Portlet Viewer instance to the Lotus Expeditor platform, perform

the following procedure:

1. Select the Client Services Portlet project you want to wrap with the Portlet Viewer instance.

2. Right click the plugin.xml descriptor file and select Open With > Plug-in Manifest Editor.

3. Select the Extensions tab.

4. Select Add.

5. Locate the com.ibm.rcp.portletviewer.WsrpPortlets extension point and select Finish.

6. Update the <wsrpData> element attributes.

7. Save the plugin.xml file.

Extension examples: Below is a sample definition for a WSRP portlet:

<extension point="com.ibm.rcp.portletviewer.WsrpPortlets">

<wsrpData

entityId="com.bank.portletviewer.helloworldWSRPPortlet"

wsrp_wsdl="http://host:port/wps/wsdl/wsrp_service.wsdl"

handle="111222333444"

need_client_clone="true"

isSecured="true"

tokenType="LTPA">

</wsrpData>

</extension>

Note: If you configure the Portlet Viewer in your development environment, always set

need_client_clone as true, and do not use the pop_handle in the extension. To get the wsrp_wsdl,

handle, and security information, you need to refer to your portal product’s documentation. If you

use IBM WebSphere Portal, you can use the XMLAccess tool to retrieve the portlet handle.

Developing applications 229

Page 240: Lotus Expeditor: Developing Applications for Lotus Expeditor

Widgets for devices

On certain devices, the TextExtension widget does not function as documented. When the device

language is set to an Asian language and the TextExtension widget style is UPPERCASE, lowercase

letters can still be input.

Creating help for the application

If you are creating a set of Help information for your application, and you intend on using the built-in

Lotus Expeditor help plug-ins, you should use the Eclipse PDE to create a help plug-in. The Help Plug-in

provides for XML configuration of the Table of Contents, and content specified as HTML.

For more information on creating a help plug-in, refer to the section Plug-in Help in the Platform Plug-in

Developer’s Guide located in the Eclipse Help system.

Developing synchronization applications

This section provides information on synchronization application development.

SyncML

This section provides information on SyncML.

Understanding SyncML development

As desktop computers, laptops, personal digital assistants (PDAs) and advanced phones have become

part of our business and personal life, the need to access current, consistent data in multiple locations has

become a pressing need. The term synchronization, often abbreviated to sync, is broadly used to address

this requirement. This section discusses synchronization, along with a description of SyncML4J, an IBM

offering that enables ISVs and developers to implement SyncML based applications.

Resources can either be standalone items on the file system, such a word processor document, or items

managed within an application, such as a calendar within a Personal Information Manager (PIM)

application. If a single user accesses the resources that are required from a single location, such as when

using a standalone desktop computer, there is no synchronization issue; the user is always working with

the single, and thus current, version. In a local area network, where multiple users access resources on a

shared file system, there is no inherent synchronization facility. If two users open and edit the same file,

the last person to save the file overwrites the content input by the other user. As applications have

become more sophisticated, they often provide support for multi-user access to the resources they

manage; however this usually assumes continuously connected devices on a network.

Contacts, calendars, and memos are three common resources that a user might want access to on a

variety of devices, beyond the desktop. The most significant problem with situation is that these devices

often operate disconnected from the desktop computer for significant periods and it is possible to edit the

data on these devices, as well as on the desktop. To merge the edits from both locations, the data must be

synchronized between these two devices.

Previously, these resources were synchronized between a desktop machine and single PDA using the

synchronization software that was provided with the PDA. Often this meant data was synchronized to a

desktop application provided by the device manufacturer; this might not have been the default

application used on the desktop, particularly in a corporate scenario. Facilities were often provided to

import data to the PDA desktop counterpart application, but this was usually a one-off activity, with no

facility to update or merge ongoing edits between the applications.

The situation became worse as the facilities of mobile phones improved. Now there was a third device,

usually from a different manufacturer, to synchronize. One possible solution was to ensure that all three

devices ran software from one manufacturer and expect manufacturers to ensure compatibility, but this is

not the way the market evolved.

230 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 241: Lotus Expeditor: Developing Applications for Lotus Expeditor

Within this context a consortium of companies began the SyncML Initiative to develop an open

synchronization standard appropriate to server, desktop, and handheld devices. The organization

developed data synchronization (DS), then device management (DM) specifications and regularly held

SyncFests, where software and device manufacturers were able to test interoperability between various

servers and devices. In November 2002, the SyncML Initiative was integrated into the Open Mobile

Alliance (OMA), with the following mission:

“The mission of the Open Mobile Alliance is to facilitate global user adoption of mobile data services by

specifying market driven mobile service enablers that ensure service interoperability across devices,

geographies, service providers, operators, and networks, while allowing businesses to compete through

innovation and differentiation.”

Technology overview: This section provides an introduction to the SyncML4J toolkit available from IBM

for the development of sync clients based on the OMA DS and DM standards.

The DS and DM standards needed to take into account the differing device and the network

characteristics. To achieve the widest adoption, the protocol had to be suitable for implementation on

resource-constrained devices. As a ‘wire’ protocol, it does not specify either an implementation language

or application programming interface (API); rather, the protocol is a sequence of XML packages

exchanged between client and server during a sync session. Some key protocol features defined in the

specifications include support for:

v Multiple data types, including binary

v XML and WBXML encodings

v Multiple transports, including HTTP, HTTPS, OBEX, IrDA

v Client and server authentication and message integrity

The specifications are available for download on the OMA Web site. The adoption of the specifications is

progressing; some manufacturers are shipping devices that are DS enabled, several software vendors have

toolkits available, and there are open source, C and Java toolkits available.

The latest IBM offering for DS and DM is called SyncML4J, and is part of Lotus Expeditor v6.1.

SyncML4J enables the creation of DS and DM clients for the Java 2 Platform. SyncML4J is pure Java,

delivered as an Eclipse feature. Eclipse is an award-winning open source platform for the construction of

powerful software development tools and rich desktop applications. SyncML4J comprises plug-ins for the

runtime libraries necessary for creating data synchronization, applications, and device management client

applications.

SyncML4J common: In the same way that the DS and DM specifications are based on a common

representation and protocol, SyncML4J is built on common components for protocol handling and

transport. All mandatory wire commands are supported, as are Basic and MD5 authentication and

HMAC message integrity.

The DM device tree represents all manageable settings on the device. The DM specification defines how

the tree is used to maintain account information for the DM agent. SyncML4J uses a similar approach to

maintain account information for the DS agent; it also uses the tree to maintain a list of data sources

capable of interacting with the DS agent. In this way, the developer has the option to manage the client.

The applications are loosely coupled to the agents, so there is no dependency on a particular user

interface (UI) library within the base framework. A variety of UIs can be used to build an application,

sharing the framework sync code.

SyncML4J data synchronization: SyncML4J provides support for all the mandatory DS 1.1.2 client wire

commands. As a framework, SyncML4J supports user-defined data sources (or databases). These can

range from simple opaque resources, such as memos and images, to complex schema-aware data types

such as relational databases or PIM databases. The framework enables the data sources and their

Developing applications 231

Page 242: Lotus Expeditor: Developing Applications for Lotus Expeditor

capabilities to be modeled by implementing the SyncSource and SyncSourceCap interfaces respectively.

The implementation is then registered into the device tree as a DSSource node. A new (or existing) DSAcc

node models the account information, such as server address and credentials and the set of local

databases that can be synchronized by this account. Within the DSAcc, for each DSSource node there is a

corresponding DSTarget node, recording the corresponding remote database URI, and credential and

anchor information. No support is provided in the framework to assist with conflict resolution or

duplicate detection; these are implicit responsibilities of implementers of the SyncSource interface.

SyncML4J device management: SyncML4J provides support for all the mandatory DM 1.1.2 client wire

commands, together with an API for manipulating the device tree locally. Custom nodes are created by

subclassing and implementing the abstract methods in AbstractInterior, then adding instances of the

class into the device tree.

As previously noted, the device tree represents all manageable settings on the device, including in

volatile or non-volatile memory and file or I/O system. Custom nodes enable resources that are external

to the framework to be manipulated. For example, you can implement a custom node to set the time and

declare it into the device tree as ./device/time. Subsequent commands to get and replace the value of

that node could then trigger JNI code to get and set the actual OS system time.

You can save memory, by virtualizing sub-trees using custom nodes, rather than by providing a

one-to-one mapping between persistent device tree nodes and resources. A reference to a URI that is a

logical child to the custom node dynamically instantiates an appropriate node, enabling it to be

manipulated by the wire commands. For example, to make the files of a computer disk drive manageable

using the device tree, rather than populate the tree with hundreds of interior nodes and thousands of leaf

nodes, you can implement and add a single custom node to the device tree as ./device/driveC,

referencing the drive root. In this example, as wire commands to manipulate files on the drive are

received, the custom node dynamically creates nodes to model the addressed file, to which the wire

commands are forwarded.

Enabling projects for SyncML development

This section provides information on enabling projects for SyncML development.

Client Services target definition components: Lotus Expeditor Toolkit provides Client Services target

definition support. These target definitions simplify the creation and configuration of synchronization

application projects, enabling you to select the SyncML components and provide automatic management

of the requisite SyncML libraries. When developing a SyncML application any of the Client Services

target definitions can be selected for your Client Services project, but be sure to select the SyncML4J

target features on the Target Profile page. For more information on Client Services projects please refer to

“Lotus Expeditor Toolkit” on page 11.

SyncManager

This section provides information on the SyncManager.

Understanding the SyncManager

The Lotus Expeditor Synchronization UI provides a synchronization page and a schedules page for

viewing and managing all synchronization applications, as well as the menus for launching

synchronization and changing options.

The Synchronization page provides users the ability to quickly view all types of synchronizable

applications with their synchronization status. Each synchronizable application is displayed in a row with

its name, enabled/disabled, priority, last run time, scope, summary, server, and status. Offline Composite

Applications are displayed on this page. This page also provides users the ability to start or stop

synchronization, as well as a quick way to set synchronization schedules and change options.

232 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 243: Lotus Expeditor: Developing Applications for Lotus Expeditor

The Synchronization schedules page is part of the Lotus Expeditor preferences dialog. It provides users

the ability to set two sets of schedules for normal and high priority applications respectively. It also

provides the synchronization triggers settings applied to all the synchronizable applications.

The Synchronization UI is built on the SyncManager. The SyncManager is a framework that provides a

consistent interface to basic synchronization functionality (e.g., start sync) for heterogeneous applications

and services. It also enables synchronization application or service specific extensions. The SyncManager

provides a public API which supports development of a synchonization UI, as well as the basic

SyncManager functionality.

Enabling projects for the SyncManager

Besides the SyncManager APIs mentioned in the previous section, the SyncManager defines three

extension points:

v SyncService

v TypeService

v SchedulerService.

By implementing extensions to the first two extension points, developers can have their own application

specific entities appear in the Synchronization UI and participate in scheduled sync. By implementing an

extension to the third extension point, developers can define their own scheduler.

SyncService extension point: The first step to having your project’s objects appear in the

Synchronization UI is to define a SyncService extension. This extension provides functionality, such as

defining and persisting your project’s object instances, and starting sync for one or more of these

instances. The com.ibm.rcp.sync.syncServices is the SyncService extension point.

The SyncService implementation defines a SyncService specific SyncUnit interface. This service’s primary

responsibilities are:

v The management of the persistence of instances of this interface

v The synchronization of the data associated with its sync unit instances

v Sending events related to its sync units, such as the status of the synchronization of a sync unit’s data

(for example, sync starting, sync progress, sync completed or sync aborted).

Please refer to the SyncManager Javadoc for more information on the interface the SyncService must

implement and the events it must send.

TypeService extension point: The next step to having your project’s objects appear in the

Synchronization UI is to define a TypeService extension. This extension provides the “typing” of the

objects that appear in the Synchronization UI. It is this typing that associates different icons and different

preference pages with the different types of objects that appear in the UI. The

com.ibm.rcp.sync.typeServices is the TypeService extension point.

Since there must be at least one TypeService defined for each SyncService, the SyncService and the first

TypeService are typically packaged together in the same project. The following example details a

plugin.xml for this setup:

Developing applications 233

Page 244: Lotus Expeditor: Developing Applications for Lotus Expeditor

To implement the specific Options Dialog for your synchronizable application (sync unit), perform the

following procedure. By doing so, the existing Synchronization UI will allow you to open your Options

Dialog from the main synchronization page.

1. The TypeService implementer must implement a specific SyncUnit class, which implements the

org.eclipse.core.runtime.IAdaptable interface. And this class should be different from all other

SyncUnits provided by this or other type services. For example, different type services should not

create the SyncUnit instances of the same class, if they want to show different Options pages for each

type.

2. Contribute to Eclipse’s org.eclipse.ui.propertyPages extension point to implement the

PropertyPages for each specific SyncUnit class. The objectClass attribute defined in this extension

point must be the full qualified name of your sync unit class. For example:

<extension point="org.eclipse.ui.propertyPages">

<page

objectClass="com.ibm.rcp.sync.services.syncml.typeservice.

SyncmlSubscription"

name="SyncML Subscription Base Properties"

class="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlBasePropertyPage"

id="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlBasePropertyPage">

</page>

<page

objectClass="com.ibm.rcp.sync.services.syncml.typeservice.

SyncmlSubscription"

name="SyncML Subscription Extended Properties"

class="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlExtendedPropertyPage"

id="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlExtendedPropertyPage">

</page>

</extension>

3. If a common Options page is for more than one types of applications (sync units), you must declare

extension for each, though they are associated to the same property page class. For example,

SyncmlSubscription implements SyncUnit and SyncmlHierarchySubscription extends

SyncmlSubscription.

<extension point="org.eclipse.ui.propertyPages">

<page

objectClass="com.ibm.rcp.sync.services.syncml.typeservice.

SyncmlSubscription"

name="SyncML Subscription Properties"

class="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlPropertyPage"

id="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlPropertyPage ">

</page>

<page

objectClass="com.ibm.rcp.sync.services.syncml.typeservice.

SyncmlHierarchySubscription"

name="SyncML Subscription Properties"

class="com.ibm.rcp.syncui.syncml.propertypages.

<?xml version="1.0" encoding="UTF-8"?>

<?eclipse version="3.0"?>

<plugin>

<extension point="com.ibm.rcp.sync.syncServices">

<syncService factoryClass="com.ibm.rcp.sync.test.syncservice1.smextension.SyncServiceFactoryImpl"

type="com.ibm.rcp.sync.test.syncservice1">

</syncService>

</extension>

<extension point="com.ibm.rcp.sync.typeServices">

<typeService factoryClass="com.ibm.rcp.sync.test.syncservice1.smextension.TypeServiceFactoryImpl">

</typeService>

</extension>

</plugin>

234 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 245: Lotus Expeditor: Developing Applications for Lotus Expeditor

SyncmlPropertyPage "

id="com.ibm.rcp.syncui.syncml.propertypages.

SyncmlPropertyPage">

</page>

</extension>

SchedulerService extension point: The com.ibm.rcp.sync.schedulerServices is the SchedulerService

extension point.

<?xml version="1.0" encoding="UTF-8"?>

<?eclipse version="3.0"?>

<plugin>

<extension point="com.ibm.rcp.sync.schedulerServices">

<schedulerService class = " com.ibm.rcp.sync.test.schedulerservice.smextension.TestSchedulerService"

id = "com.ibm.rcp.sync.test.TestSchedulerService">

</schedulerService>

</extension>

</plugin>

Lotus Expeditor provides an extension for this SchedulerService extension point and an associated

preference page. So, there is no need to provide one. This extension point can be used by developers to

replace the default scheduler service that is provided. To do this, you must:

1. Remove the com.ibm.rcp.syncui.schedule plug-in from Lotus Expeditor.

2. Create your own schedule plug-in.

3. Implement your own SyncScheduler, SyncSchedulerService, and SchedulerEventListener, making

sure you have a scheduler associated with SyncManager.NORMAL_PRIORITY_FILTERNAME and

SyncManager.HIGH_PRIORITY_FILTERNAME respectively.

4. Implement your schedule preference page. You should contribute to org.eclipse.ui.preferencePages

extension point.

5. Install your schedule plug-in to Lotus Expeditor.

Developing SyncManager application logic

The SyncManager provides public APIs that enable developers to call SyncManager functionality from their

applications, or to write their own Synchronization UI if they desire.

A factory is provided to gain access to the SyncManager instance.

SyncManager sm = SyncManagerFactory.getSyncManager();

The SyncManager sends events to listeners about changes in its state and synchronization job progress.

Once you get the SyncManager instance, you will register a listener.

private EventListener listener = new EventListener();

sm.addSyncEventListener(listener);

Here is an example EventListener that simply prints out info on the events received.

public class EventListener implements SyncEventListener {

public EventListener() {}

public void receive(SyncEvent event) {

Object context = event.getEventContext();

StringBuffer sb = new StringBuffer();

sb.append("\nEvent received: " + event.getEventType());

/*

if (syncUnit != null) {

sb.append("\n ");

sb.append(syncUnit);

sb.append(" listener");

} else {

Developing applications 235

Page 246: Lotus Expeditor: Developing Applications for Lotus Expeditor

sb.append("\n SyncManager listener");

}

*/

if (context instanceof SyncUnitContext) {

SyncUnitContext suContext = (SyncUnitContext) context;

sb.append("\n syncUnitEvent: ");

sb.append(suContext.getSyncUnitUri());

sb.append(", ");

sb.append(suContext.getSyncUnitType());

} else if (context instanceof JobContext) {

JobContext jContext = (JobContext) context;

sb.append("\n jobEvent: ");

sb.append(context.getJobId().getId());

} else {

sb.append("\n " + context);

}

if (context instanceof ProgressContext) {

ProgressContext pContext = (ProgressContext) context;

sb.append("\n totals :");

sb.append(“pContext.getCompletedWorkUnits());

sb.append("/");

sb.append(pContext.getTotalWorkUnits());

}

System.out.println(sb.toString());

}

}

Once you have the SyncManager instance, there are various actions that can be performed with it. These

actions include tasks related to the creating/updating/deleting of the items that appear in the

Synchronization Page and also synchronization related things like starting sync for a subset of the

defined items.

The defined items will be instances of various classes that are provided by the TypeServices. Each item

has a URI associated with it, and it is the responsibility of the SyncService implementation to guarantee

the uniqueness of their objects’ URIs across all SyncServices in the system.

Each of these instances will implement the SyncUnit interface that is defined by the SyncManager. This

SyncUnit interface includes the attributes that would generally be common to all items that appear on the

Synchronization Page.

These instances are value objects with getters/setters for read/write attributes and getters for read-only

attributes. The most commonly used SyncUnit attributes are:

v Uri – this read-only attribute uniquely identifies an instance within the system

v Type – this read-only attribute is the name provide by the TypeService for a specific kind of SyncUnit

v ServerName – the server name that this item will use for synchronization, this will be null if there is

no such server name.

v Session Scope – during a specific sync session, a different type of sync may be desirable. For example,

the user may choose to only send changed data up to the server, as opposed to having all the updated

data on both the client and server synchronized. This attribute defines this session configuration info.

v DisplayName – provides a means of associating a user-friendly name with a SyncUnit, rather than

relying on the URI.

v Enabled/Disabled flag – this attributes is used to prevent a SyncUnit from synchronizing.

v Priority – this attribute enables different SyncUnits to synchronize more often than others. The

SyncScheduler determines when to synchronize SyncUnits based on their priority.

v IconUrl – the attribute is used by the Synchronization page when displaying icons.

Other SyncUnit attributes are described in the SyncManager Javadoc.

236 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 247: Lotus Expeditor: Developing Applications for Lotus Expeditor

Like the SyncManager, SyncUnits also sends events to its listeners. The events sent are specific to the

SyncUnit instance that sends them. Events include information about on-going synchronization of the

SyncUnit, and information about the SyncUnit state, such as that it has been updated. The SyncManager is

responsible for receiving the events sent by the SyncService related to a specific SyncUnit and redirecting

them so that they will be sent out from the SyncUnit itself.

One important thing to notice about the SyncUnit interface is that the Uri attribute is read-only. An

implication of this is the SyncUnit interface alone can not be used to create a new SyncUnit. A

TypeService/SyncService defined interface that extends the SyncUnit interface would be used in the

creation of a SyncUnit using the SyncManager APIs. This class would provide its own service specific

methods for getting/setting attributes that would be used to derive the SyncUnit Uri. For example:

public interface SyncService1SyncUnit extends SyncUnit {

public String getSourceUri();

public void setSourceUri(String sourceUri);

public String getTargetUri();

public void setTargetUri(String targetUri);

}

In this case, when a sync unit is added, the SyncService uses the sourceUri and/or the targetUri to

derive the SyncUnit’s Uri. The TypeService extends the SyncService defined SyncUnit interface providing

a name for the type. Since the first typed sync unit is typically provided along with the SyncService,

there is usually no need to add any additional methods when extending the SyncService defined

interface.

public interface TypeService1SyncUnit extends SyncService1SyncUnit {

public static String TYPE = TypeService1SyncUnit.class.getName();

}

The following steps add a SyncUnit of a given type through the SyncManager APIs. First, an instance of

the proper class for the type is created. This is done via the createSyncUnit API. This API takes the type

as a parameter. Based on the input type, the SyncManager will return an instance of the class that

corresponds to the type that was retrieved from the associated TypeService. The returned instance will

have default values assigned to all of its attributes. Next, the returned instance is cast to the appropriate

TypeService defined interface, and the attribute values are set. Lastly, this instance is added to the

SyncManager via the addSyncUnit call. This call will return a new instance that has the Uri set.

Note: The original instance can then be re-used. There is no need to call createSyncUnit multiple times

when adding multiple SyncUnits. This original instance continues to have no Uri set. So, it can not

be used as a parameter to other SyncManager methods, such as sync or update. The SyncUnit

instance returned from the createSyncUnit call is to be used for those other SyncManager method

calls.

The following code demonstrates how to add to SyncUnits using a single createSyncUnit call:

TypeService1SyncUnit tempSyncUnit = (TypeService1SyncUnit) sm.createSyncUnit(TypeService1SyncUnit.TYPE);

tempSyncUnit.setSourceUri("MySourceUri1");

tempSyncUnit.setTargetUri("MyTargetUri1");

TypeService1SyncUnit syncUnit1 = (TypeService1SyncUnit) sm.add(tempSyncUnit);

tempSyncUnit.setSourceUri("MySourceUri2");

tempSyncUnit.setTargetUri("MyTargetUri2");

TypeService1SyncUnit syncUnit2 = (TypeService1SyncUnit) sm.add(tempSyncUnit);

Similarly, to update a SyncUnit, when you do not have the instance, you would issues a getSyncUnit, cast

it if necessary, make the updates to the instance and then call updateSyncUnit.

Developing applications 237

Page 248: Lotus Expeditor: Developing Applications for Lotus Expeditor

Removing a SyncUnit can be done with or without a SyncUnit instance. There is no need to get the

instance to remove it from SyncManager. It can be removed using just the SyncUnit’s Uri.

The values, such as SessionScope, that are stored with the SyncUnit are the values the scheduler uses

when kicking off synchronization of that sync unit. Besides supporting scheduled sync, the SyncManager

provides methods for performing synchronization on demand. These sync methods allow for the

synchronization of subsets of SyncUnits. To sync using the stored SyncUnit values, use the methods that

take the Uri(s) of the SyncUnit(s) to sync. Sync methods are also provided that take SyncUnit instances.

Use these methods when it is desirable to change the configuration for a single sync session. For

example, a slow sync is not something that is usually repeated over and over. To perform a one time

slow sync, a SyncUnit would be retrieved using the get SyncUnit API. The sessionScope would be set to

slow sync, and then that sync unit would be passed in to the sm.sync(SyncUnit) method. The values

used for that sync session will not be persisted.

Developing Web applications

The Lotus Expeditor platform supports Servlet 2.4 and JSP 2.0 web applications as well as Servlet 2.3 and

JSP 1.2 web applications. Web applications targeting the Lotus Expeditor platform are called Client

Services web applications. Since components in the Lotus Expeditor platform are called bundles, a web

application targeting this platform is also referred to as a Web Application Bundle or WAB.

A WAB can be developed using many of the same web development tools provided by the Web Tools

Platform and Rational Software Development platform. You should therefore refer to the online help

section Web Application Development User Guide as your initial web development tools reference. The

following topics discuss the additional development considerations and tool usage required when

targeting a web application for the Lotus Expeditor platform.

The following table provides pointers to information on web development activities and information on

tasks that are unique to, or require special consideration when developing web applications for the Lotus

Expeditor platform.

Table 14. Web development activities

Task Reference

Understanding Client Services web application concepts. “Understanding Web Applications” on page 239

Working with Client Services Web projects versus

Dynamic Web projects, and when to use one versus the

other.

“Creating Web Application projects” on page 239

Developing Client Services web application logic. This

encompasses any special development considerations

when coding and constructing the web application logic.

“Accessing resources” on page 242

“Using JSP Standard Tag Libraries” on page 243

“Java Server Faces (JSF) development” on page 243

“Struts development” on page 243

Exporting web application bundles. “Exporting Web Application bundles” on page 247

Securing the web application through user authentication

and authorization.

“Securing Web Application resources” on page 244

Debugging and testing the web application. “Debugging and testing applications” on page 323

Deploying the web application to a runtime. “Deploying projects for local testing” on page 331

Using the command line WAB tool to convert a WAR to

a WAB.

“WAB Utility” on page 247

Configuring the web container. Refer to the Web Container configuration information in

the documentation Assembling and Deploying Lotus

Expeditor Applications

238 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 249: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 14. Web development activities (continued)

Task Reference

Web container logging. “Web Container Logging” on page 249

Understanding Web Applications

Client Services web applications run on the Lotus Expeditor platform. A primary difference between a

Client Services web application and one that is deployed to run on a WAS or Tomcat runtime is that the

Client Services web application must also be a valid OSGi bundle. Refer to “Working with OSGi bundles”

on page 366 for more information on bundles and the Lotus Expeditor platform. The Lotus Expeditor

Toolkit automatically handles many of these bundle specific details, which is why developing the web

application through a Client Services web project is the recommended development path for web

applications that are to be run on the Lotus Expeditor platform. Nevertheless, it is also possible to

develop the web application through a Dynamic Web project, and subsequently test run it on the Lotus

Expeditor platform. Refer to “Using a Client Services Web project versus a Dynamic Web project” on

page 240 for more details. It is also possible to transform an existing Web Application Archive (WAR) file

into a Web Application Bundle (WAB) suitable for running on the Lotus Expeditor platform through the

use of the WAB Utility.

The following lists aspects of a Client Services web application that differ from a standard web

application.

v The Lotus Expeditor platform does not support deploying Enterprise Applications through an EAR.

The web application is directly deployed to the runtime.

v A Client Services web application has a manifest file, located in META-INF/MANIFEST.MF, that contains

bundle information including package and bundle dependencies. This is associated with the bundle,

and is separate from the manifest file found under the web application’s content folder.

v A Client Services web application has a plugin.xml file that contains extension point contributions to

lazily start the web application.

v A Client Services web application contains additional deployment information in wab.properties. This

is located in the web content WEB-INF folder.

v JSP files are translated into their respective servlet classes before the web application is deployed to the

runtime as a WAB.

In most cases, these artifacts and differences are handled transparently by the Lotus Expeditor Toolkit.

These differences do not affect the functionality of the web application. There are, however, some

development considerations you should take into account depending on the web technologies you will be

using. These are described in “Developing Web Application logic” on page 242.

A Client Services web application can be developed using many of the same web development tools

provided by the Web Tools Platform and Rational Software Development platform. The primary

differences are:

v Use the Client Services Web project wizard to create a Client Services web project, as described in

“Creating a Client Services Web project” on page 240.

v Since the Lotus Expeditor platform does not support EARs, EAR projects are ignored.

v When testing the project, target the Client Service runtime when using the Run As/Run on Server

action. Or, use the Client Service launch configuration when using the Eclipse Run / Debug launch

feature.

v When exporting the web application, use the Plug-in Development > Deployable plug-ins and

fragments wizard, as described in “Exporting Web Application bundles” on page 247.

Creating Web Application projects

This section provides information on Web Application project creation.

Developing applications 239

Page 250: Lotus Expeditor: Developing Applications for Lotus Expeditor

Using a Client Services Web project versus a Dynamic Web project

Web applications can be developed using either a Client Services web project or a Dynamic Web Project.

The choice of which to use depends on the application content and its primary usage. In general, web

applications that primarily target the Lotus Expeditor platform or depend on other OSGi services besides

core servlet and JSP support should be developed using a Client Services web project.

A Client Services web project is an extension of the dynamic web project. Because of this, both types of

projects make use of the dynamic web project tools. In addition to this, a Client Services web project

provides the following support for developing a web application that is targeting the Lotus Expeditor

platform.

v The OSGi manifest file required by Lotus Expeditor applications can be automatically managed by the

tools.

v The project’s class path is maintained to match the class path environment that will exist in the Lotus

Expeditor runtime. This is useful for detecting class visibility problems at development time rather

than runtime.

A Dynamic web project will not have the Lotus Expeditor specific tooling aids listed above, but can still

be tested and run on the Lotus Expeditor platform. This is accomplished by targeting the project’s

runtime to the Client Service runtime through the project’s Targeted Runtimes properties. The tooling will

automatically add the proper OSGi manifest entries for Servlet and JSP support. However, if the

application references other OSGi services or bundles, the developer will have to manually add these

dependencies to the manifest file.

Client Services web project can also be tested and run on a platform other than Lotus Expeditor by

reassigning its targeted runtime through the project Targeted Runtimes properties. Refer to “Debugging

and testing applications” on page 323 for further information.

Creating a Client Services Web project

Perform the following procedure to create a new Client Services Web project:

1. Select File > New > Project. The new project wizard displays.

2. Expand the Client Services folder. This lists the Client Services project wizards. Choose Client

Services Web Project, then select Next. The Client Services Web Project panel displays.

3. Specify a project name in the Project name field. This is the only field you are required to fill in. Select

Finish to create a project with default settings.

The additional settings that can be configured through this wizard are described in the following tables,

along with their default values. Access the additional wizard panels through the Next and Back buttons.

Selecting Finish on any of the wizard pages will create the project with the settings you have specified

up to that point.

Client Services Web Project panel

Table 15. Client Services Web Project panel

Option Description Default value

Project name Enter a name for the new Client

Services Web Project.

None

Project location You may click Browse to select a file

system location for the new project.

The default location creates the

project in your current workspace.

Project Facets panel

240 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 251: Lotus Expeditor: Developing Applications for Lotus Expeditor

Allows you to set and configure the facets that should be enabled for the project.

Table 16. Project Facets panel

Option Description Default value

Configurations Select the project facet configuration. <custom>

Project Facet Select project facets associated with

this project, and their versions.

Web Bundle (version 6.1)

Dynamic Web Module (version 2.4)

Java (version 5.0)

The above facets are pre-selected, and

cannot be de-selected. You can

modify the versions.

Web Module panel

Allows you to configure the web module settings.

Table 17. Web Module panel

Option Description Default value

Context Root Specify the project’s context root. Project name

Content Directory Specify the project’s web content

directory.

WebContent

Java Source Directory Specify the project’s Java source

directory.

src

Target Profile page

Allows the selection of a target definition and associated features and/or plug-ins to be selected for the

project. By default, the necessary features for supporting web projects will be selected.

Table 18. Target Profile page

Option Description Default value

Target Definition Select from the list the Target

Definition this Client Services project

will target. You can change your

selection later in the Client Services

property page.

Default Target

Developing applications 241

Page 252: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 18. Target Profile page (continued)

Option Description Default value

Target Features Check the Target Features that your

Client Services project will require.

You can change your selection later

in the Client Services property page.

Grey entries are required by the

Target Definition and cannot be

deselected.

The ″Core OSGi Interfaces″ Target

Feature is required by all Target

Definitions.

The following features (if they exist

in the Target Definition) are

automatically selected (and cannot be

de-selected) by Web Application

Tools:

v IBM JavaServer Faces (JSF)

Extensions

v JavaServer Pages (JSP) API

v JSP Standard Tag Library (JSTL)

v Reliability, Availability,

Serviceability (RAS)

v Servlet API

v Web Application Compatibility

v Web Target Feature

v Web Container

v Web Container - HTTP Service

v Apache MyFaces

Converting a Dynamic Web project to a Client Services Web project

You can convert an existing Dynamic Web project into a Client Services Web project by using the Convert

Project to Client Services project wizard. Refer to “Convert Project to Client Services Project Wizard” on

page 375 for information on how to use this wizard.

This will retain the existing web application logic of the project, and will add Client Services tooling

support.

Note: There is no wizard to convert a Client Services Web project back to a Dynamic Web Project. If you

wish to retain the original Dynamic Web Project, you must copy the project before converting it.

This can be done by selecting the Copy project before conversion check box in the wizard.

Developing Web Application logic

This section provides information on Web Application logic development.

Accessing resources

The Servlet and JSP specifications do not guarantee that a web application’s resources will be represented

as files in the host machine’s file system. Many web container implementations do expand web

applications into the file system, and some existing web applications take advantage of this

implementation detail to reference resources as Java Files. However, web applications that target a Lotus

Expeditor runtime are represented as jar bundles that do not have to be expanded in the file system to

run. Because of this, your web application should use the ServletContext.getResourceAsStream() API

when accessing web application resources. It should not assume these resources will be available as files.

The API ServletContext.getRealPath() should also not be used as it is implementation dependant. For

the Lotus Expeditor runtime, it will return null since the web application resources are not expanded in

the file system. Again, such resources can be accessed as IO streams through

ServletContext.getResourceAsStream().

242 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 253: Lotus Expeditor: Developing Applications for Lotus Expeditor

Using JSP Standard Tag Libraries

The Lotus Expeditor platform includes the JSP Standard Tag Libraries (JSTL) version 1.1 as part of the

runtime. These libraries will support both Servlet 2.4 / JSP 2.0 compliant applications as well as Servlet

2.3 / JSP 1.2 applications. If your application makes use of JSTL tags, you do not need to include copies

of the JSTL libraries in your web application’s WEB-INF/lib directory.

Java Server Faces (JSF) development

JavaServer Faces is a technology that helps you build user interfaces for dynamic Web applications that

run on the server. The JavaServer Faces framework manages UI states across server requests and offers a

simple model for the development of server-side events that are activated by the client. JavaServer Faces

is consistent and easy to use. For additional information on JavaServer Faces, refer to the Developing

Web sites and applications and Web Tools Features section in the Help Contents of the Rational

Software Development Platform.

The client platform supports the use of JavaServer Faces based web applications. The required JAR files

are provided as part of the client platform runtime.

By default, the project will be configured to use the Apache MyFaces JSF implementation. Refer to “Using

the Sun JSF Reference Implementation” for instructions on how to use the Sun Reference Implementation.

When creating a new Client Services web project, select Base Faces and JSTL facets from the Project

Facets page in the wizard.

For an existing Client Services web project, select the Base Faces and JSTL facets by performing the

following procedure:

1. Right click your project in the Project Explorer view, and select Properties.

2. Select Project Facets > Add/Remove Project Facets...

3. From the Project Facets window, select the Base Faces and JSTL facets, then click Finish.

You should now be able to continue development of your JSF based web application.

Using the Sun JSF Reference Implementation: The Sun JSF Reference Implementation is part of the

Device Runtime Environment (DRE). You must first install the DRE into the toolkit using the installation

instructions for the DRE.

Configuring a project: Perform the following steps to configure a project to use the Sun JSF Reference

Implementation:

1. Create a Client Services project with JSF support. See instructions in “Java Server Faces (JSF)

development.” The project will be configured to use Apache JSF by default.

2. Open the Manifest editor for the project, and select the Dependencies tab.

a. If org.apache.myfaces is listed under Required Plug-ins, remove it.

b. Add com.ibm.pvc.servlet.jsf to the Required Plug-ins.3. Edit the project’s Client Services properties.

a. Right click the project and select Properties. Select the Client Services page.

b. Deselect the Apache MyFaces feature from the project’s Target features, and click OK.

When running the project, you must manually select the proper plug-in to include it in the runtime. On

the launch configuration Plug-ins tab, ensure that com.ibm.pvc.servlet.jsf is selected.

Note: When using Run on Server, you can get to this tab through the Advanced... button.

Struts development

Struts is a framework of open-source software that can help you build Web applications quickly and

easily. It relies on standard technologies such as Java beans, Java servlets, JavaServer Pages (JSP), and

Developing applications 243

Page 254: Lotus Expeditor: Developing Applications for Lotus Expeditor

XML. Struts encourages application architectures based on the Model 2 approach, which is basically the

same as the model-view-controller (MVC) design pattern. For additional information on Struts, refer to

the Developing Web sites and applications and Web Tools Features sections in the Help Contents of the

Rational Software Development Platform.

The client platform supports the use of Struts-based web applications. All web applications that intend to

use Struts must include the Struts jars within the web application.

The Web tools in the Rational Software Development Platform enable development of Struts-based

applications by adding libraries to the WebContent\WEB-INF\lib directory of each web application.

When creating a new Client Services web project, select Struts facet from the Project Facets page in the

wizard.

For an existing Client Services web project, select Struts facet by performing the following steps:

1. Right click on your project in the Project Explorer view, and select Properties.

2. Select Project Facets > Add/Remove Project Facets...

3. From the Project Facets window, select the Struts facet, then Finish.

Securing Web Application resources

This section provides information on securing Web Application resources.

Configuring a Web Application: The Web Container supports the declarative J2EE security model. In

declarative security the application’s web descriptor specifies the application’s security policy (roles,

access control etc.) without changing the applications code. The following is an example code snippet

from a web descriptor that shows the declarative security syntax. This example secures web application

resources with url-pattern=/secure/* -

<security-constraint>

<display-name>myLoginTest</display-name>

<web-resource-collection>

<web-resource-name>LoginTest</web-resource-name>

<url-pattern>/secure/*</url-pattern>

<http-method>GET</http-method>

<http-method>PUT</http-method>

<http-method>HEAD</http-method>

<http-method>TRACE</http-method>

<http-method>POST</http-method>

<http-method>DELETE</http-method>

<http-method>OPTIONS</http-method>

</web-resource-collection>

<auth-constraint>

<description>Any user</description>

<role-name>user.anyone</role-name>

</auth-constraint>

</security-constraint>

<login-config>

<auth-method>FORM</auth-method>

<form-login-config>

<form-login-page>/login.jsp</form-login-page>

<form-error-page>/error.jsp</form-error-page>

</form-login-config>

</login-config>

<security-role>

<role-name>user.anyone</role-name>

</security-role>

To configure a web application to use declarative security on the Web Container, the web descriptor must

define a list of valid User Admin roles in the <role-name> tag. This list of roles can include user and

group roles. The above example uses the default User Admin role of user.anyone. This means any valid

user can be used to log into this web application. The Web Container assumes that all User Admin users

244 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 255: Lotus Expeditor: Developing Applications for Lotus Expeditor

store their passwords as a credential with the key ″password″. If no valid users are created with User

Admin then the Web Container will not let anyone access the web application resources that have been

secured.

Note: Developers may also use programmatic security to control access to a web application. For more

information on the Web descriptor, declarative and programmatic security models refer to the

Servlet 2.3 specification.

Supported authentication mechanisms: As a prerequisite for gaining access to any web application

resources which are protected by an authorization constraint, a user must be authenticated using one of

the supported authentication mechanisms. The Web Container supports the following authentication

mechanisms:

v Basic Authentication (BASIC)

v Form-based Authentication (FORM)

DIGEST and CLIENT-CERT authentication mechanisms are not supported.

Using the User Admin Service to create users and roles: The Web Container uses the User Admin

service to authenticate and authorize requests for secured web application resources. You can use the

User Admin API to add, modify, or delete properties and credentials for existing users. The following

snippets of code show how you can add a user and delete a user:

Add a user

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceReference;

import org.osgi.service.useradmin.UserAdmin;

public class MyWebApplication {

/**

* Used to store reference to UserAdmin service

*/

private static UserAdmin userAdmin = null;

/**

* Plug-in bundle context

*/

private BundleContext context;

/**

* Plug-in start method

*/

public void start(BundleContext bc) throws Exception {

String username = “Joe”;

this.context = bc;

ServiceReference ref = bc.getServiceReference(“org.osgi.service.useradmin”);

userAdmin = (UserAdmin) bc.getService(ref);

useradmin.createRole(username, Role.User);

}

/**

* Plug-in stop method

*/

public void stop(BundleContext bc) throws Exception {

}

}

Delete a user

Developing applications 245

Page 256: Lotus Expeditor: Developing Applications for Lotus Expeditor

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceReference;

import org.osgi.service.useradmin.UserAdmin;

public class MyWebApplication {

/**

* Used to store reference to UserAdmin service

*/

private static UserAdmin userAdmin = null;

/**

* Plug-in bundle context

*/

private BundleContext context;

/**

* Plug-in start method

*/

public void start(BundleContext bc) throws Exception {

String username = “Joe”;

this.context = bc;

ServiceReference ref = bc.getServiceReference(“org.osgi.service.useradmin”);

userAdmin = (UserAdmin) bc.getService(ref);

useradmin.removeRole(username);

}

/**

* Plug-in stop method

*/

public void stop(BundleContext bc) throws Exception {

}

}

For more information on the User Admin service, please refer to the OSGi Release 3 specification and the

OSGi Javadoc.

Using the Admin Utility for OSGi to create users and roles: With the Admin Utility for OSGi, you can

use the User Admin Service to manipulate user definitions. You can add, modify, or delete properties and

credentials for existing users.

To add a user:

1. Launch the Lotus Expeditor platform.

2. Install the Admin Utility for OSGi feature.

3. Select Application Open > Admin Utility for OSGi to run the application

4. Once the application is started, select the User Admin label in the left-side frame.

5. Select Create New User. The Create New User input fields display.

6. Enter a user name and select Create User.

To delete a user:

1. Launch the Lotus Expeditor platform.

2. Install the Admin Utility for OSGi feature.

3. Select Application Open > Admin Utility for OSGi to run the application

4. Once the application is started, select the User Admin label in the left-side frame.

5. Check the check box for the user to be deleted and select Delete. You will need to refresh the data

before removing the user from the form

246 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 257: Lotus Expeditor: Developing Applications for Lotus Expeditor

To create a group:

1. Launch the Lotus Expeditor platform.

2. Install the Admin Utility for OSGi feature.

3. Select Application Open > Admin Utility for OSGi to run the application

4. Once the application is started, select the User Admin label in the left-side frame.

5. Select Create New Group. The Create New Group form displays.

6. Add members to the group by selecting a member in the Available Roles box and choosing either

Basic or Required to move the member to the New Member Roles box.

7. Select Create Group to finish creating the group.

Exporting Web Application bundles

A Client Services Web project can be exported as a bundle by performing the following procedure:

1. Select File > Export...

2. From the Plug-in development folder, select Deployable plug-ins and fragments, and click Next.

3. Select the Client Services web project to be exported under Available plug-ins and fragments, then

define the Export options and Destination.

4. Select Finish.

WAB Utility

The WAB utility is a command line utility for transforming Web Application Archive (WAR) files into

Web Application Bundle (WAB) files that are suitable for running in the Lotus Expeditor platform. Note

that the web development tools provide a wizard for exporting both Client Services web projects as

WABs. See “Exporting Web Application bundles” and “Using Ant tasks to build a deployable bundle” on

page 331. These tools should be used when you are dealing with web projects under the Lotus Expeditor

Toolkit. The WAB utility is a standalone utility that can be used to transform existing WAR files

independent of any projects managed by the Lotus Expeditor Toolkit.

WAB Utility installation: Perform the following procedure to install the WAB utility:

1. Install a J2SE 5.0 JRE on your development machine, and set the environment variable JAVA_HOME to

the location of this JDK.

2. The WAB utility is delivered as one of the plug-ins installed with the Lotus Expeditor Toolkit. For the

WTP environment, it is located in the following directory (where WTP_HOME is the directory that your

Web Tool Platform has been installed to):

WTP_HOME/common/plugins/com.ibm.pvc.tools.web.translator_6.1.0

For the WTP environment, it is located in the following directory (where WTP_HOME is the directory

that your Rational Software Development platform has been installed to):

WTP_HOME/eclipse/plugins/com.ibm.pvc.tools.web.translator_6.0.0

You can copy this directory elsewhere on your development machine, if desired, or use it in place. For

convenience, you should add the WAB utility directory to your system’s PATH environment variable.

This will enable you to invoke the WAB utility scripts without specifying their full path.

3. The invocation scripts for the WAB utility are within the WAB utility directory described in step 2.

v wab.bat - Windows script for invoking the WAB utility

v wabc - Linux script for invoking the WAB utility

Refer to “WAB Utility usage and parameters” for details on how to use the WAB utility.

WAB Utility usage and parameters: The WAB utility is invoked through a script. On Windows systems,

this script is wab.bat. On Linux systems this script is wabc. The following will use the Windows wab.bat

script in examples, and assumes that the WAB utility directory has been added to the system’s PATH

environment.

The WAB utility performs the following transformations on your web application:

Developing applications 247

Page 258: Lotus Expeditor: Developing Applications for Lotus Expeditor

v All JSP files are translated to their underlying servlet classes. In addition to the standard J2SE libraries,

the utility automatically adds required javax.servlet* class libraries to the class path during

translation. Any other classes referenced by the application’s JSPs, that are not part of the application

itself (through WEB-INF/classes or WEB-INF/lib), must be specified through the utility’s –classpath

parameter.

v If an OSGi compliant manifest file does not exist in the web application, one will be added. It will have

the necessary package dependency statements for supporting web applications. If your application is

referencing additional external packages, you will need to include your own custom

META-INF/MANIFEST.MF manifest file that includes these package dependencies through either the

Import-Package or Require-Bundle fields, or use the -requirebundle parameter to add them to the

Require-Bundle field. Note that the utility will augment an existing manifest file to contain any missing

dependencies, and will not overwrite any preexisting entries.

v A plugin.xml file will be created by default to contain the extension point contribution to lazily start

the web application. If you use the WAB tool with -nolazystart option, the plugin.xml file will not be

created.

WAB Utility examples: The simplest use of the WAB script only specifies the war file to be translated:

wab myweb.war

The above will create a myweb.jar file in the directory from which the tool was invoked.

You can specify the target name and location for the WAB JAR using the -o parameter:

wab myweb.war -o /myruntime/eclipse/plugins/myweb.jar

You can add additional libraries to the translation class path using the -classpath parameter:

wab myweb.war -classpath myLib1.jar;myLib2.jar

You can use the -g option to specify compilation with debug information.

WAB Utility parameters: WAB utility invocation has the following form:

wab <war file> [ Options ]

The following table describes the options parameters available to the WAB utility.

Table 19. WAB Utility options parameters

Option Description

<war file> File name of the war file to be transformed into a WAB

file. This must be a Servlet 2.3 or 2.4 compliant war file.

-contextpath <path> Specify the context path for the web application. By

default, the base name of the output file is used for the

context path. For example, the default context path for

inventory.jar is /inventory.

-classpath <classpath> Augment the class path to be used for the JSP file

compilation. The WAB utility automatically includes the

javax.servlet.* packages on the class path.

-o <output file> File name of the resulting WAB file. The default name is

the base <war file> name with .JAR file extension, placed

in the same directory as <war file>.

-includesource When specified, the WAB file will include the original

JSP source files. By default, JSP files are removed from

the WAB, since they are translated to their underlying

servlet classes.

-g When specified, JSP files are compiled with debug

information.

248 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 259: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 19. WAB Utility options parameters (continued)

Option Description

-id <name> Specify the bundle symbolic name. By default, this is the

base name of the output file.

-portlet Option for translating web archives that are also portlets.

-jsf Option for translating web archives that leverage

JavaServer Faces technology.

-jstl Option for translating web archives that leverage JSP

Standard Tag Library.

-nolazystart Option for not adding extension point contribution to

lazily start the web project at deployment time.

-javalevel <Java level> Java compliance level. Valid values are ″14″ and ″15″.

Default is ″14″.

-requirebundle <requirebundle> A comma separated list of bundle symbolic names to be

added to the Require-Bundle header of the manifest file.

Using Lotus Expeditor servers

The concept of Server Runtimes describes run time environments by containing information such as the

run time install directory and JRE. Web projects can have a target run time associated with them. This

allows the tools to modify the project’s build characteristics based on the targeted run time type. This

mechanism also allows the tools to run non-Client Services web projects on a Client Services run time.

Client Services web projects have Client Services 6.1 run times as the targeted run times.

A Client Services run time type is a custom runtime type for the Client Services run time that supports

Web modules for J2EE level 1.3 and 1.4 and EJB modules for J2EE level 1.2 and 1.3. A Client Services

Server is associated with the Client Services run time type. Servers will contain launch specific

information that corresponds to the set of information that can be configured when running a run time

workbench.

There are multiple Client Services run time instances of the Client Services run time type. Each instance

has a Target Definition ID that it corresponds to, in order to calculate which JRE is associated with this

run time. There is at least one instance for each Target Definition, defined automatically by the system as

needed. You are able to create and edit new instances.

Servicing Web Applications

This section provides information on servicing Web Applications.

Web Container Logging

The Web Container will log all messages using the JDK logging. The Lotus Expeditor logger plug-in will

redirect these messages to <USER_HOME>\IBM\RCP\<INSTALL_ID>\<USER_NAME>\logs\rcp.log.*.

The following table shows the mapping between the Web Container log levels and the levels used by

JDK:

Table 20. Web Container log level mapping

Web Container Log Level OSGi Log Level java_util.Level

ERROR ERROR SEVERE

WARNING WARNING WARNING

INFO INFO INFO

DEBUG DEBUG FINE

EVENT DEBUG FINER

Developing applications 249

Page 260: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 20. Web Container log level mapping (continued)

Web Container Log Level OSGi Log Level java_util.Level

ENTRY DEBUG FINER

EXIT DEBUG FINER

Configuring the Web Container Logging: Since the Web Container leverages JDK logging to log all

messages, no additional configuration of the Web Container is necessary. Refer to the Logging chapter in

the documentation Assembling and Deploying Lotus Expeditor Applications for more information on how to

configure the runtime logging framework.

Debugging and testing Web Applications

This section provides information on debugging and testing Web Applications.

Running and debugging using Client Services launcher

To run or debug a Client Services Web Project using Client Services launcher, perform the following

procedure:

1. Bring up the Run or Debug launcher by selecting either Run > Run... or Run > Debug...

2. Select the Client Services configuration type, and click New to create a new Client Services launch

configuration.

3. Select the Plug-ins tab, and ensure the web projects to be tested are selected.

4. Select either Run or Debug to launch.

Running and debugging using ″Run on Server″ style

This section provides information on running and debugging using ″Run on Server″ style.

Running or debugging Client Services Web Projects on the Client Services runtime: To run or debug

a Client Services Web Project on the Client Services runtime, perform the following procedure:

1. Select Window > Open Perspective > Other > J2EE to switch to the J2EE Perspective.

2. From the project Explorer view, select the Client Services web project to be tested.

3. Right click the project, and select Run As > Run on server... (or Debug As > Debug on Server...)

4. Choose a Client Services 6.1 server if one exists and click Next. If one does not exist, define a Client

Services 6.1 server by:

a. Select IBM > Client Services v6.1 as the server type, and click Next.

b. Choose a target definition and/or features/plug-ins, and click Next.5. To test multiple projects, add or remove other projects that are configured on the server.

6. Select Finish to launch.

Run or debug a non-Client Services Web Project on the Client Services runtime: To run or debug a

non-Client Services Web Project on the Client Services runtime, perform the following procedure:

1. Change the project’s runtime to the Client Services runtime from the project’s Properties > Targeted

Runtimes. If the Client Services run time is not displayed or disabled, remove the project facets that

are not supported by the Client Services run time, as noted in this page.

2. Update the project’s manifest file manually to add dependencies to Import-package or Require-Bundle

entries, if the project has dependencies on OSGi bundles or services other than servlet and JSP. Since

the project is not a Client Services Web Project, it does not have the support from Lotus Expeditor

Toolkit to automatically manage the dependencies.

3. Select Window > Open Perspective > Other > J2EE to switch to the J2EE Perspective.

4. From the project Explorer view, select the web project to be tested.

5. Right click the project, and select Run As > Run on server... (or Debug As > Debug on Server...)

250 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 261: Lotus Expeditor: Developing Applications for Lotus Expeditor

6. Choose a Client Services 6.1 server if one exists, and click Next. If one does not exist, define a Client

Services 6.1 server by:

a. Select IBM > Client Services v6.1 as the server type, and click Next.

b. Choose a target definition and/or features/plug-ins, and click Next.7. To test multiple projects, add or remove other projects that are configured on the server.

8. Select Finish to launch.

Running or debugging a Client Services Web Project on a non-Client Services runtime: To run or

debug a Client Services Web Project on a non-Client Services runtime, perform the following procedure:

1. Select Window > Open Perspective > Other > J2EE to switch to the J2EE Perspective.

2. From the project Explorer view, select the web project to be tested.

3. Right click the project and select Run As > Run on server...

4. Choose a non-Client Services server if one exists and click Next. If one does not exist, define a

non-Client Services server by:

a. Choose a server type, and click Next.

b. Specify the server settings depending on the server type selected. This process might involve

multiple setup panels.5. To test multiple projects, add or remove other projects that are configured on the server.

6. Select Finish to launch.

Developing Web Services

The Lotus Expeditor Toolkit extends the Rational Software Development Platform through plug-ins that

enable you to build applications targeting the Lotus Expeditor runtime platform. The Lotus Expeditor

Toolkit Web Services plug-in suite enables you to develop applications that consume and are exposed as

Web Services targeting the OSGi-based Lotus Expeditor runtime platform. For more information on the

Rational Software Development Platform, visit http://www.ibm.com/pvc.

Understanding Web Services

The Lotus Expeditor Toolkit Web Services runtime plug-in suite provides functionality similar to libraries

that implement the Java 2 Micro Edition Web Services Specification (JSR-172). In some cases, very

complex Web services that comply with JAX-RPC may not be fully consumable by JSR-172 Web services.

For cases where the client needs to consume JAX-RPC based services, the Apache Axis 1.3 Web Services

tools provided with Lotus Expeditor Toolkit should be used instead.

To enable you to develop Web Services applications, the Web Services Tools allows you to generate client

code that consumes Web Services as well as exposes OSGi services as Web Services providers.

Note: The Lotus Expeditor Client for Devices does not support exposing OSGi services as Web Services

providers. Lotus Expeditor Client for Devices only supports JSR-172, without dynamic Web

Services clients.

An application that will consume a Web Service needs to identify the service end-point, typically a URL

to a Web Services Description Language (WSDL) document and use the interface to invoke the Web

Services provider. An application that will be exposed as a Web Services provider must implement a Java

interface that defines the Web Service calls.

Technologies

This section provides information on Web Services technologies.

Web Services Description Language (WSDL): A WSDL document provides the description of the Web

Services interface. In Lotus Expeditor Toolkit Web Services terminology, A top-down approach is used to

generate code from a WSDL (typically used for developing Web services clients), whereas a bottom-up

Developing applications 251

Page 262: Lotus Expeditor: Developing Applications for Lotus Expeditor

approach is used to generate a WSDL from code (typically used for developing Web Services

providers).The Lotus Expeditor Toolkit Web Services v 6.1 plug-in supports both the top-down approach

and bottom-up approach.

For more information about WSDL, please visit http://www.w3.org/TR/wsdl.

Simple Object Access Protocol (SOAP): SOAP is the message format of the transaction that takes place

when a Web Services client that communicates with a Web Services provider. The WSDL defines the

restrictions on the format of these messages.

For more information about SOAP please see http://www.w3.org/TR/soap.

JAX-RPC: The Java API for XML-Based Remote Procedure Call (JAX-RPC) enables developers to build

Web Services using XML-based RPC functionality according to the SOAP 1.1 specification.

We have included Apache Axis 1.3 in the runtime to allow clients to consume the JAX-RPC based

services.

Note: We do not support JAX-RPC based providers in the runtime. Also, Lotus Expeditor Toolkit extends

the RAD’s Web Services wizards to allow the generate the JAX-RPC based client that are compliant

with the Lotus Expeditor Runtime.

For more information about JAX-RPC, please visit http://java.sun.com/xml/jaxrpc.

The Web Services Client Programming Model: Similar to the programming model specified in the Web

Services for J2ME specification (JSR-172), the Lotus Expeditor Toolkit provides the following capabilities:

1. A generated stub from the Web Services Description Language (WSDL) description of the service

operation.

The Mobile Web Services Client wizard generates a static client stub class using the WSDL that is

exported from the Web Services provider as its input. The stub is then used to invoke the Web

Services provider.

In addition to the static stub, the Web Services Gateway proxy library (com.ibm.pvcws.osgi), a

component of Lotus Expeditor can be used to generate a dynamic client stub on-the-fly. This dynamic

client stub may be used in place of the static client stub, which hard-codes the SOAP message

definitions and method calls, in order to build Web Services clients dynamically. Other functionality

provided by this proxy library is the ability to provide custom marshallers (serializers) for types that

are incompatible with JSR-172.

Note: Lotus Expeditor Client for Devices supports a JSR-172 implementation only and does not

provide com.ibm.pvcws.osgi.

2. WSDL-defined API.

The WSDL document defines an application programming interface (API) that makes up the complete

Web Services client application. This API must be present on both the server and client side to allow

the endpoints to communicate properly.

3. Instantiation of the stub

The client application uses an instance of the static or dynamic stub to indirectly access the Web

service defined by a given WSDL.

It is imperative that the WSDL definition reflects the actual interface to the Web service at runtime.

The JAX-RPC subset does not perform any version control. Any differences between the defined

WSDL and the instance of the Web Service may produce unpredictable results.

4. Invocation of stub methods that correspond to the implementation of service endpoint operations.

The Web Services client application can use an instance of the stub to set stub properties, including

the service endpoint. The methods generated in the stub are used to call service endpoint operations.

252 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 263: Lotus Expeditor: Developing Applications for Lotus Expeditor

5. Packaging the stub with the client application.

The generated stub is provided in source form. It is used during application development.

Tools

This section provides information on Web Services tools.

Tools for Mobile Web Services development: The Lotus Expeditor Toolkit provides tools for creating

Mobile Web Services client code, as well as code for exposing an OSGi service as a Web services provider.

The tools provided include:

v A Web Services client wizard that includes a wizard to configure security

v A Web Services client security wizard to configure client security

v A Web Services provider wizard to expose OSGi services as Web Services providers

v A Web Services provider security wizard to configure security

v Editors to modify WS-Security configurations

v A Web Services wizard for creating JAX-RPC based clients

Web Services Resource Framework

This section contains information regarding the Web Services Resource Framework.

Lotus Expeditor for Devices does not support WSRF.

Understanding WSRF applications

Web Services Resource Framework (WSRF) defines a resource as a logical entity that is identifiable, and

has zero or more properties, which are expressible in XML infoset. A resource may also have a lifecycle.

A Web Service Resource (WS-Resource) is the combination of a resource and a Web service through which

the resource can be accessed.

WSRF defines a set of specifications for accessing resources using Web services in a stateful manner. For

more information about WS-Resource, please visit http://www.osgi.org.

Technologies: Web Services Resource Framework Specification

The Web Services Resource Framework (WSRF) is a family of specifications introduced in January 2004,

with the intention to provide a way to access stateful resources using a standard set of message exchange

patterns, fronted by web services. The WSRF family specifications include the following:

v WS-Resource

v WS-ResourceProperties

v WS-ResourceLifetime

v WS-BaseFaults

The key concept in WSRF is the WS-Resource, which is composed of a Web service and a stateful resource.

A stateful resource can be the files in a file-system or rows in a relational database, or an encapsulated

object in an OSGi Service. The consumer of the WS-Resource can access this stateful resource using

standard set of message exchange pattern described as operations in the above set of specification. For

example, WS-ResourceProperties specifications define a standard set of message exchanges that allow a

requestor to query or update the resource property values. Similarly, WS-ResourceLifetime specification

standardizes the means by which a WS-Resource can be destroyed; it defines the means by which a

resource may be destroyed after a period of time. WS-BaseFaults provides a standard way of reporting

faults from WS-Resources to requestor.

Developing applications 253

Page 264: Lotus Expeditor: Developing Applications for Lotus Expeditor

WS-Resource: A WS-Resource is the combination of a resource and a Web service through which the

resource can be accessed. WSRF specification defines the pattern by which resources are accessed through

Web services, and the means by which WS-Resources are referenced. Some of the important characteristics

of WS-Resource are as follows:

v A reference to a WS-Resource is represented by an endpoint reference (EPR), or more precisely an XML

element whose type is, or is derived (by extension), from the complexType named

EndpointReferenceType defined by the [WS-Addressing] specification. Such EPRs must reference exactly

one WS-Resource.

v The set of properties of the resource must be expressed using an XML Infoset described by XML

schema. The WS-Resource must support accessing resource properties through message exchanges

defined by the WS-Resource Properties specification [WS-ResourceProperties].

v A WS-Resource may support the message exchanges defined by the WS-Resource Lifetime specification

[WS-ResourceLifetime].

The following figure shows a simple scenario in which three different resources (A, B and C) being

exposed as WS-Resource using a Web service.

1. EndpointReference2. Webservice3. EndpointReference (same as 1)4. wsa:Address referring to the Webservice5. The resourceID referring to Resource "C"

1

4

2

C

A

B5

3

<wsa:EndpointReference><wsa:Address>

http://someOrg.com/aWebService</wsa:Address><wsa:ReferenceProperties>

<tns:resourceID> C </tns:resourceID></wsa:ReferenceProperties></wsa:EndpointReference>

ServiceRequestor

The EndpointReference for the resource “C” is shown below:

<wsa:EndpointReference>

<wsa:Address>http://someOrg.com/aWebService</wsa:Address>

<wsa:ReferenceParameter>

<tns:resourceID> C </tns:resourceID>

</wsa:ReferenceParameter>

</wsa:EndpointReference>

In complex scenarios, there may be additional information in EndpointReference, provided as

ReferenceParameters or MetaData that may be required to clearly identify the associated resource.

WSRF Runtime: WSRF Plug-ins are an implementation of the following set of specifications in the OSGi

environment:

254 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 265: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 21. Specification versions

Specification Number Specification Version

1 WS-Resource http://docs.oasis-open.org/wsrf/wsrf-ws_resource-1.2-spec-cs-01.pdf

2 WS-ResourceLifeTime http://docs.oasis-open.org/wsrf/wsrf-ws_resource_lifetime-1.2-spec-cs-01.pdf

3 WS-ResourceProperties http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-cs-01.pdf

4 WS-BaseFault http://docs.oasis-open.org/wsrf/wsrf-ws_base_faults-1.2-spec-cs-01.pdf

5 WS-Addressing http://www.w3.org/TR/2005/CR-ws-addr-core-20050817

The WSRF implementation provides an environment to host WS-Resources in an OSGi environment.

These WS-Resources by definition can be accessed through web services in a stateful manner. The

programming model supported by the WSRF implementation allows for exposing varied constructs, like

an OSGi Service, a Java Bean, a physical file system, or a database as a WS-Resource.

The WSRF implementation also provides a client runtime environment, where WS-Resource clients and

applications can run and access WS-Resources.

Note: Running Lotus Expeditor with the osgi.resolveMode=strict option, may lead to unpredictable

behavior of the Web Services Resource Framework (WSRF) components.

WSRF tools: The Lotus Expeditor Toolkit provides tools for creating WS-Resource and client code to

access the same. The tools provided include:

v Wizard to expose OSGi services as WS-Resource providers

v Wizard to create client code for accessing WS-Resource hosted on Lotus Expeditor

Note: Running Lotus Expeditor Toolkit with osgi.resolveMode=strict option may lead to unpredictable

behavior of the Web Services Resource Framework (WSRF) tool components.

Creating WS-Resource projects

The WSRF implementation realizes the WS-Resource modeling in OSGi environment with the help of the

following constructs:

v Resource

v Adapter

v Web service

Resource: An OSGi bundle that encapsulates one or more stateful service objects that must be exposed as

a WS-Resource. This service object in the Resource Bundle may be developed to encapsulate some

business logic or be a software façade for a hardware resource. Some examples of a Resource include: a

row of a database, a file system, or hardware components.

Web service: An OSGi bundle that acts as a Web Service facade for the WS-Resource. This Web service

exposes WSRF standard port-types and custom port-types defined by the Resource developer. This

bundle also encapsulates the Message-level authentication/authorization logic.

Adapter: An OSGi bundle, acts as a bridge between the Web Services bundle and the Resource bundle. It

routes the incoming Web Service messages (both the WSRF standard port-types and the custom

Developing applications 255

Page 266: Lotus Expeditor: Developing Applications for Lotus Expeditor

port-types) to the Resource instance addressed by the requestor. Any responses from the resource

(including exceptions) are routed back through the Adapter and the Web Service bundle to the requestor

as normal response or faults. The Adapter bundle is partially generated by the WSRF tool wizards, with

placeholders for the developer to provide implementation to interact with the Resource instances in the

Resource bundle.

Sample WS-Resource on Lotus Expeditor

The following figure illustrates the various components of WS-Resource in an OSGi environment and the

corresponding client components. The client environment need not necessarily be an OSGi environment.

WS-Resource clientapplication

WS-Resource Client Environment WS-Resource Provider Environment

Communication -Application specificproduct

Database -Physical resource

Web service client stub

WSRF4OSGi ClientComponents

WS-Addressing

Web service Clientruntime

Resource Service(OSGi Service)

WS-Resource Adapter

WS-ResourceWeb Service

WSRF4OSGi ClientComponents

WS-Addressing

Web Services ServerRuntime (SOAP Server)

Communication-SOAP over HTTP

OS

GI/N

on

-OS

iE

nviro

nm

en

t

OS

Gi

En

viro

nm

en

t

In the above scenario, the physical resource (a database) is exposed as an OSGi service, and this OSGi

service is in turn exposed as a WS-Resource.

Developing WS-Resource providers: Developing a WS-Resource involves creating the basic OSGi service

that exposes a physical resource as an OSGi service, and creating the Adapter to the resource and the

corresponding Web service through which the resource can be accessed. Some part of the WS-Resource

can be developed using the tools provided by Lotus Expeditor Toolkit. For other development needs, the

developers are required to provide the implementation.

Developing the resource bundle: This step involves development of an OSGi service that exposes a physical

resource such as a database, Java bean or a file system. The developer has to define a service interface

and provide an implementation for this interface (if necessary). For the case of simplicity, it is assumed

that the developer provides an implementation to the service interface. Developers can use the standard

plug-in development wizard to create an OSGi plug-in to expose this interface as an OSGi service.

In the next step, create the Web Service bundle and the Adapter bundle to expose the OSGi service

interface (Resource) as a WS-Resource.

Developing the Web Services bundle and adapter bundle: Lotus Expeditor Toolkit provides wizards to

generate the WS-Resource Adapter and Web service components. The WS-Resource Web service

256 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 267: Lotus Expeditor: Developing Applications for Lotus Expeditor

component is completely generated by the tool, whereas the WS-Resource Adapter component generated

by the tool requires you to provide enhancements/modifications based on specific scenarios.

The WS-Resource Provider Wizard of the Lotus Expeditor Client Lotus Expeditor Toolkit uses the

bottom-up approach to generate the WSDL (and the related Provider/Client code skeletons) from a Java

Interface/code. Perform the following steps to create the Web service OSGi bundle and the related

Adapter bundle for the given Resource bundle:

1. Select File > New > Other.

2. Select Client Services > Mobile Web Services > WS-Resource Provider.

3. From the WS-Resource details page:

v Provide the WS-Resource name (for example, WS-Resource).

v Select the WS-Resource service interface.

v Add the service interface selected in step 2 and the dependent classes to the Resource Classpath

list.

v Select the Web Service Resource Framework (WSRF) specifications that should be implemented:

– By default, WS-Resource property specification is selected. Implementation of this specification is

mandatory for any WS-Resource.v Select Expose service methods to be able to expose the other methods of the OSGi Service Interface

as custom port-type of the WS-Resource, in addition to the standard WSRF port-types.

v To secure the WS-Resource, select Enable Security. Enabling security requires users to update the

generated Java classes and configuration files. Refer to the section “Securing a WS-Resource” on

page 273 for detailed steps.

v Click Next.4. From the WS-Resource properties selection page:

v Select the properties of the WS-Resource that should be exposed.

v You can also define additional properties to the WS-Resource, by selecting the Add property...

button.

– Specify the name of the property.

– Select the property type.

– If the property is an array, select the Array type check box.

– Click OK.v Click Next.

5. The Web service methods selection page is displayed if you chose to expose Web service methods in

Step 3.

v Select the methods that should be exposed as Web service methods.

v Click Next.6. From the project details page.

v Provide the Name and Location for the creation of new projects for the WS-Resource Web Service

and WS-Resource Adapter.

v Click Next.7. From the plug-in details page, provide the following information

v Plug-in name

v Plug-in ID

v Plug-in Version8. Click Finish.

After clicking Finish, the Lotus Expeditor Toolkit creates two projects in the workspace, one each for

WS-Resource adapter and WS-Resource web service.

Developing applications 257

Page 268: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: WS-Resource Provider wizard works on a bottom-up approach for generating a WSDL description

(such as, given the Java Interface a WSDL description is generated). The generated WSDL

description follows non-wrapped style. Hence, the custom port-types (service methods) in a

WS-Resource will not accept Java class/interface with the following constructs, while generating

WS-Resource provider bundles:

v Java interface with methods having more than one parameter

v Java interface with overloaded methods

Note: Currently, the WS-Resource Provider wizard does not provide a facility to specify the multiplicity

of the resource properties. However, the wizard defaults the multiplicity and nillable attributes as

follows:

Table 22.

Data Types minOccurs maxOccurs nillable Description

Primitive types (e.g.,

int)

1 1 false The property can not

be ’null’.

Wrapper types (e.g.,

Integer)

1 1 true The property can be

’null’.

Primitive array types

(e.g., int[])

0 unbounded false The property can be

’null’. If the property

is not ’null’, the

individual array

elements can not be

’null’.

Wrapper array types

(e.g., Integer[])

0 unbounded true The property can be

’null’. If the property

is not ’null’, the

individual array

elements can be

’null’.

Complex types (e.g.,

URI)

1 1 true The property can be

’null’.

Complex array types

(e.g., URI[])

0 unbounded true The property can be

’null’. If the property

is not ’null’, the

individual array

elements can be

’null’.

Similar conventions are followed for the parameters and return types of custom port-types (service

methods) in Web Services.

Note: The generated WS-Resource Provider exposes all the port types of WS-ResourceProperties

specification. The wizard does not provide a facility to deselect portTypes designated as ″optional″

by the specification. Similarly, when you choose to implement the WS-ResourceLifeTime interface,

all portTypes of the WS-ResourceLifeTime specification will be exposed.

Note: The wizard does not support non-English text for property names, resource class/interface name,

project name, package prefix, plug-in name, plug-in ID, plug-in provider name. Entering

non-English text in the wizard fields may result in undesirable behavior.

Creating a WS-Resource client: To generate the client stub, the WS-Resource should have been

deployed and started on the Lotus Expeditor runtime.

258 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 269: Lotus Expeditor: Developing Applications for Lotus Expeditor

To create a Web Service Resource client from the WSDL description of WS-Resource, perform the

following steps:

1. Select File > New > Other.

2. Select Client Services > Mobile Web Services > Create WS-Resource Client.

3. From the WS-Resource details page:

v Enter the location of the WSDL description published by the Web Services provider. You can

provide an HTTP URL.

v To secure access to the WS-Resource, select Enable Security. Enabling security requires users to

update the generated Java classes and configuration files. Refer to the section “Securing a

WS-Resource” on page 273 for detailed steps.

v Click Next.4. From the project details page.

v Provide the Name and Location for the creation of a new project for the WS-Resource client.

v Click Next.5. From the plug-in details page, provide the following information:

v Plug-in name

v ID

v Version6. Click Finish.

After clicking Finish, the Lotus Expeditor Toolkit creates the project in the workspace, for the

WS-Resource client.

Note: To run the WS-Resource Client wizard successfully, the computer that runs the wizard should be

connected to the internet, since the wizard accesses external schemas while generating the client

Java code.

Note: The WSDL description for WSRF Web services follows a non-wrapped style and the WS-Resource

client wizard is customized to generate Java code for WSRF Web services only. Also, using a

different client generation tool (other than the WS-Resource Client wizard) to generate Java code

for WSRF Web services may not generate correct code.

Note: The SOAP messages exchanged between the WS-Resource provider and the WS-resource client

follow a non-wrapped style. Currently, the WS-Addressing implementation is customized to handle

non-wrapped style SOAP messages.

Note: Currently, the wizard does not support non-English text for the project name, package prefix,

plug-in name, plug-in ID, plug-in provider name. Entering non-English text in the wizard fields

may result in undesirable behavior.

Note: You should not modify the generated package or class names of the WS-Resource client bundle.

Supported data types: The current version of the WSRF implementation supports the following data

types as WS-Resource properties, parameters and return types in service methods:

Primitive/Primitive array int, long, float, double, byte, short, boolean

Wrapper/Wrapper array Integer, Float, Long, Double, Byte, Short, Boolean

Developing applications 259

Page 270: Lotus Expeditor: Developing Applications for Lotus Expeditor

Complex types/Complex array java.lang.String

java.net.URI

java.util.Calendar

java.util.Date

javax.xml.namespace.QName

org.w3c.dom.Element

com.ibm.wsaddressing.wsspi.EndpointReference

com.ibm.wsrf.common.duration.Duration

Any Java bean that wraps one or more of the above

types as instance variables

Note: Currently, custom marshaller support is not provided for WSRF Web services.

Note: char, Character, char[], Character[] types are not supported. The org.w3c.dom.Element[] type

is not supported in custom port types (service methods) as parameters and return types. Java

beans containing the org.w3c.dom.Element[] type as a field is not supported. Usage of data types

other than those mentioned above in the table, may lead to unexpected behavior.

Note: EndpointReference (com.ibm.wsaddressing.wsspi.EndpointReference) type requires special

handling at the application level. The WS-Resource Client EndpointReference is handled as

com.ibm.wsrf.common.addressing.EndpointReferenceType. For example, if a custom port type takes

EndpointReference type as a parameter or return type, the corresponding method signature in the

generated WS-Resource Client SOAP stub will have EndpointReferenceType as a parameter or

return type. Similarly, in case of Resource properties of type EndpointReference, the WS-Resource

Client SOAP stub will have EndpointReferenceType as a type (QType for the property) description.

You should send and receive objects of type EndpointReferenceType while invoking methods on

the generated client SOAP stub. You can use the following methods provided by the

com.ibm.wsrf.common.util.EndPointReferenceHelper class to convert objects of one type to another

and vice-versa:

v EndPointReferenceHelper.getEndPointReferenceObject (EndpointReferenceType eprType) –

Returns object of type EndPointReference

v EndPointReferenceHelper. getEndPointReferenceTypeObject(EndpointReference epr) – Returns

object of type EndPointReferenceType

Developing WSRF application logic

This section contains information on developing logic for WSRF applications.

WS-Resource provider application: WS-Resource Web service generated by the toolkit does not require

any changes. On the other hand, WS-Resource Adapter generated by Lotus Expeditor Toolkit requires

you to provide implementation of the business logic in the generated classes.

The tool will generate the following sub-components in the adapter plug-in:

Table 23.

Sub-Component Name Description

<ResourceName>AdapterActivator Bundle activator of WS-Resource Adapter OSGi bundle.

<ResourceName>AdapterImpl Client requests received by WS-Resource Web service are

delegated to this class.

260 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 271: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 23. (continued)

Sub-Component Name Description

<ResourceName>LifeTimeManager This class contains the empty implementations for

managing the lifetime of the WS-resource. Developers

should provide implementation to the methods based on

the scenario.

<ResourceName>PropertyManagerBase This is the base class for <ResourceName>PropertyManager

class bridging the WSRF implementation and

WS-Resource Adapter.

<ResourceName>PropertyManager This class contains empty implementations for managing

the WS-Resource properties. Developers should provide

implementation to the methods based on the scenario.

<ResourceName>ServiceManager This class contains default implementation for the Service

methods.

<ResourceName>AdapterIfc This Interface contains the Service Methods that the

adapter is exposing on behalf of the actual resource.

For example, if the resource name is SampleResource the names of the generated classes would be

SampleResourceLifeTimeManager, SampleResourcePropertyManager, and so on.

You should provide implementation to methods of the following classes:

v <ResourceName>LifeTimeManager

v <ResourceName>PropertyManager

For explaining the steps in making the Resource, Web service and Adapter to work together as

WS-Resource, a simple resource called PrinterResource is considered.

PrinterResource: This resource is developed as an OSGi bundle and has the following service interface

and implementation:

public interface IPrinterService {

String getJobID();

void setJobID(String argJobID);

}

public class PrinterService implements IPrinterService {

private String jobID = null;

public String getJobID() {

return jobID;

}

public void setJobID(String argJobID) {

jobID = argJobID;

}

}

The PrinterService is registered to the OSGi environment through the bundle activator class of

PrinterResource OSGi bundle.

PrinterResourceAdapter: The Adapter is generated using the WS-Resource Provider wizard for the above

resource. You should provide implementation for the methods in the following classes generated by the

wizard:

Developing applications 261

Page 272: Lotus Expeditor: Developing Applications for Lotus Expeditor

PrinterResourceLifeTimeManager

The following code sample shows a sample implementation of getResource, createResource, and

destroyResource methods.

public class PrinterResourceLifeTimeManager {

private BundleContext bundleContext = null;

private IPrinterService printerService = null;

public PrinterResourceLifeTimeManager(BundleContext bundleContext) {

this.bundleContext = bundleContext;

}

public Object getResource(ResourceConfiguration resourceConfiguration)

throws ResourceUnavailableFault, Exception {

ServiceReference ref = bundleContext

.getServiceReference(IPrinterService.class.getName());

printerService = (IPrinterService) bundleContext.getService(ref);

return printerService;

}

public ResourceConfiguration createResource(Element configInfo)

throws ResourceUnavailableFault, ResourceUnknownFault, Exception {

ResourceConfiguration retValue = new ResourceConfiguration();

return retValue;

}

public void destroyResource(ResourceConfiguration resourceConfiguration)

throws ResourceUnavailableFault, ResourceNotDestroyedFault,

Exception {

// Scenario specific logic for destroying resource

}

}

The implementation of createResource is specific to the WS-Resource developed. The

ResourceConfiguration object returned by the method will contain information about the created

resource for the consumption of the client application. The implementation of getResource

returns an instance of the OSGi service. Similarly, the implementation of destroyResource is also

specific to the WS-Resource developed.

PrinterResourcePropertyManager

The following code sample shows a sample implementation of the methods in the

PrinterResourcePropertyManager class:

public class PrinterResourcePropertyManager extends PrinterResourcePropertyManagerBase{

private org.osgi.framework.BundleContext bundleContext;

public PrinterResourcePropertyManager(org.osgi.framework.BundleContext bundleContext) {

super(bundleContext);

this.bundleContext = bundleContext;

}

public void updateJobID(Object resource, Object value)

throws ResourceUnavailableFault,

UnableToModifyResourcePropertyFault,

UpdateResourcePropertiesRequestFailedFault,

InvalidModificationFault,

BaseFault, Exception {

printerresource.IPrinterService resourceRef = (printerresource.IPrinterService) resource;

java.lang.String inValue = (java.lang.String)value;

resourceRef.setJobID(inValue);

}

public Object getJobID(Object resource)

262 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 273: Lotus Expeditor: Developing Applications for Lotus Expeditor

throws ResourceUnavailableFault, Exception {

printerresource.IPrinterService resourceRef = (printerresource.IPrinterService) resource;

return resourceRef.getJobID();

}

public void insertJobID(Object resource, Object value)

throws ResourceUnavailableFault,

UnableToModifyResourcePropertyFault,

InsertResourcePropertiesRequestFailedFault,

InvalidModificationFault,

BaseFault, Exception {

printerresource.IPrinterService resourceRef = (printerresource.IPrinterService) resource;

java.lang.String inValue = (java.lang.String)value;

resourceRef.setJobID(inValue);

}

public void deleteJobID(Object resource)

throws ResourceUnavailableFault,

DeleteResourcePropertiesRequestFailedFault, Exception {

printerresource.IPrinterService resourceRef = (printerresource.IPrinterService) resource;

// Scenario specific logic for deleting resource property

}

}

If the exposed property is of the array type, special handling may be required. For example, if

the jobID is of type String array, the implementation for insertJobID and updateJobID will be as

below:

public void updateJobID(Object resource, Object value)

throws ResourceUnavailableFault,

UnableToModifyResourcePropertyFault,

UpdateResourcePropertiesRequestFailedFault,

InvalidModificationFault,

BaseFault, Exception {

printerresource.IPrinterService resourceRef = (printerresource.IPrinterService) resource;

String[] inValue;

if(value == null){

inValue = null;

}else{

inValue = new String[((Object[])value).length];

System.arraycopy(value, 0, inValue, 0, ((Object[])value).length);

}

resourceRef.setJobID(inValue);

}

public void insertJobID(Object resource, Object value)

throws ResourceUnavailableFault,

UnableToModifyResourcePropertyFault,

InsertResourcePropertiesRequestFailedFault,

InvalidModificationFault,

BaseFault, Exception {

printerresource.IPrinterService resourceRef = (printerresource.IPrinterService) resource;

String[] inValue;

if(value == null){

inValue = null;

}else{

inValue = new String[((Object[])value).length];

System.arraycopy(value, 0, inValue, 0, ((Object[])value).length);

}

}

Developing applications 263

Page 274: Lotus Expeditor: Developing Applications for Lotus Expeditor

In cases where the exposed property is array of primitives such as the int array, they will be

received in the adapter as the corresponding wrapper array (for example, int array will be

received as the Integer array). This wrapper array has to be iterated and the corresponding

primitive array should be constructed.

The following samples explain how the primitive and wrapper arrays are handled.

Consider an example of a resource property that is of the type primitive array, for example int

[]. In the WS-Resource Adapter (in the PropertyManager class), the object received in the

Update/Insert method would be of type Integer[] instead of int[]. This should be handled as

follows:

public void insertIntArray(Object resource, Object value)

throws Exception {

//cast the resource object to proper type

Object[] temp = (Object[])value;

//this would be Object[] and not int[]

int[] arr = new int[temp.length];

for (int i = 0; i < temp.length; i++) {

arr[i] = ((Integer)temp[i]).intValue();

}

//invoke the method on the resource object

}

Similarly, in the case of the GetResourceProperty operation, int[] is handled as follows:

throws Exception {

//cast the resource object to proper type

//int[] arr = get the int[] object from resource object

Integer[] integers = new Integer[arr.length];

for (int i = 0; i < integers.length; i++) {

integers[i] = new Integer(arr[i]);

}

return integers;

}

For handling an array of Java Wrapper array types, such as Boolean[] must be handled as

follows:

public void updateWBooleanArray(Object resource, Object value)

throws Exception {

//cast the resource object to proper type

Boolean[] newVal = new Boolean[((Object[])value).length];

System.arraycopy(value, 0, newVal, 0, ((Object[])value).length);

//invoke the method on the resource object

}

WS-Resource client applications: WS-Resource Client SOAP stubs generated by the toolkit do not

require any modifications. You will have to create the application that delegates the requests to the

generated client SOAP stub to consume the services offered by WS-Resource.

WS-Resource creation operations: Clients can create an instance of WS-Resource by using the

createWSResource() method provided in the WS-Resource. The code sample below shows how clients can

create an instance of a WS-Resource:

264 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 275: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: Clients must save WS-Resource Endpoint Reference for any further communication with this

instance of the WS-Resource.

configInfo: The configInfo is a Node array of Text/Element objects that contains any information that

may be required to instantiate the WS-Resource. For example, in the case of a Database, it might be the

User ID and password information. In the case that WS-Resource does not require any such information,

then configInfo may be null.

WS-Resource LifeTime operations: WS-Resource LifeTime provides the following operations for

managing the lifetime of a WS-Resource:

Setting the termination time of a WS-Resource instance: Client applications can set the TerminationTime for

the WS-Resource by passing a Calendar or Duration Object. WSRF server side runtime framework

destroys the resource at a scheduled time. The termination time can be set by providing a future time, or

by passing a Duration Object (containing the duration of the remaining Time). The code example below

shows how to mark the termination time for the WS-Resource by passing a future time:

String uriString = //Endpoint address (URL string) of the Webservice

EndpointReference addressingEPR = null;

AddressSoap_Stub stubObj = null; //Webservice client stub object, AddressSoap_Stub

is the sample stub obj.

WSAddressingService addressingService = null;

//Create an End Point Rreference for the Webservice

try {

addressingService = new WSAddressingServiceImpl();

addressingEPR = addressingService.createEndpointReference(uriString);

} catch (Exception e) {

//handle exception

}

Node[] configInfo = //Text/Element Nodes representing the configuration Info

Calendar initTermTime = //the termination time client want to set for the WS-Resource

EndpointReference fromEPR = //the from EPR field. This will be null in the case of a non Webservice client.

HandlerList handlerList =//the handlerList Object containing the Handler objects to be used in this request.

//Create an instance of Web service client SOAP stub

stubObj = new AddressSoap_Stub();

//Create Operation Context for this operation

OperationContext operationContext = new OperationContext();

operationContext.setFromEPR(fromEPR); //optional, it need to be set when there is a Resource to

Resource communication

operationContext.setToEPR(addressingEPR);

operationContext.setHandlerList(handlerList); //setting handler list is optional. Required only

if custom messsage handlers are required.

OperationContext.setCurrentThreadsContext (operationContext);

//Invoke create Operation on the SOAP Stub

EndpointReference wsresourceEPR = null;

try {

wsresourceEPR = stubObj.createWSResource(configInfo, initTermTime);

} catch (Exception e1) {

//handle exception

}

Calendar newTerminationTime = //new termination time to be set for this instance of WS-Resource

EndpointReference fromEPR = the from EPR field. This will be null in the case of a non Webservice client

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference returned by WS-Resource as

a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub(); //Sample Webservice Client Stub object

int termTime = 0//future time

Calendar newTerminationTime = Calendar.getInstance();

newTerminationTime.set(Calendar.HOUR, termTime);

try{

opContextObj = OperationContext.getCurrentThreadsContext();

opContextObj.setToEPR(wsresourceEPR);

stubObj.setTerminationTime(newTerminationTime);

}catch(Exception e){

// handle exceptions

}

Developing applications 265

Page 276: Lotus Expeditor: Developing Applications for Lotus Expeditor

//use the below code if you want to setTerminationTime using Duration.

String pattern= "P2Y5M4D";

Duration durationInfo = Duration.parse(pattern));

try{

opContextObj = OperationContext.getCurrentThreadsContext();

opContextObj.setToEPR(wsresourceEPR);

stubObj.setTerminationTime(durationInfo);

}catch(Exception e){

// handle exceptions

}

Destroying the WS-Resource instance: Client applications can explicitly destroy the WS-Resource. On

receiving such a request, the WSRF server side framework removes references to the associated

WS-Resource. The code example below shows how you can explicitly destroy the WS-Resource:

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference returned by

WS-Resource as a result of createWSResource operation

AddressSoap_Stub stub = new AddressSoap_stub(); //Sample Webservice Client Stub object

try{

opContextObj = OperationContext.getCurrentThreadsContext();

opContextObj.setToEPR(wsresourceEPR);

stubObj.destroy();

}catch(Exception e){

// handle exceptions

}

WS-Resource properties operations: This section contains information regarding WS-Resource

properties operations.

Acquiring the value of a resource property: It is assumed that the client has saved the EndpointReference

that was returned to the client as a result of a createWSResource operation. The code example below

shows how you can get the value of a resource property from WS-Resource:

QName propertyQName = // QName of the resource property whose value client is looking for

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference returned

by WS-Resource as a result of createWSResource operation

propertyQName = //value for QName can be populate from generated RPD java file i.e

Address_ResourcePropertyDocument.java

AddressSoap_Stub stubObj = new AddressSoap_stub();

//create an Operation Context for this operation

try{

OperationContext operationContext = OperationContext.getCurrentThreadsContext();

opContextObj.setToEPR(wsresourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

Object[] responseObj = stubObj.getResourceProperty(propertyQName);

}catch(Exception e){

// handle appropriate Exceptions

}

Fetching values of multiple properties: It is assumed that the client has saved the EndpointReference that

was returned to the client as a result of the createWSResource operation. The code example below shows

how you can get the value of multiple resource properties from the WS-Resource using the

GetMultipleResourceProperties operation:

QName []propertyQNames = // QName array of the resource properties whose value client

is looking for

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference returned by

WS-Resource as a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub();

//create an Operation Context for this operation

266 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 277: Lotus Expeditor: Developing Applications for Lotus Expeditor

try{

OperationContext operationContext = OperationContext.getCurrentThreadsContext();

opContextObj.setToEPR(wsresourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

Hashtable ht = stubObj.getMultipleResourceProperties(propertyQNames);

Set enu = ht.keySet();

Iterator itr = enu.iterator();

while(itr.hasNext()){

QName key = (QName)itr.next();

String displayValue = new String();

Object value = ht.get(key);

displayValue = value.toString();

}

}catch(Exception e){

// handle appropriate Exceptions

}

Querying for resource properties information: The WSRF implementation allows clients to query values of

the Resource properties exposed by the WS-Resource. For doing a query, users should provide XPath 1.0

based query expression information. For example, SampleWSResource_ResourcePropertyDocument/CurrentTime. The root of RPD will always be <PID>_ResourcePropertyDocument.

Below is a sample code explaining how to query a WS-Resource:

String expression = //the query expression [e.g //emailed to query emailed Property]

EndpointReference wsresourceEPR =

//Resource Qualified EndpointReference returned by WS-Resource as a

result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_Stub();

try{

opContextObj.setToEPR(wsresourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

Node [] response = stubObj.queryResourceProperties(expression);

} catch(Exception e){

//handle exceptions

}

Deleting the value of a resource property: It is assumed that the client has saved the EndpointReference,

which was returned to the client as a result of the createWSResource operation. In the WSRF

environment, deletion of a resource property does not imply that the values associated with that resource

property are deleted from the actual resource instance. The property will get removed from the Resource

Property Document for that WS-Resource Instance. The responsiblity of deleting the value of the resource

property lies with the adapter Property manager class. It must be noted that the WS-Resource may or

may not allow deletion of a resource property.

Once the property is deleted, the user may no longer be able to get/query the value of that resource

property. To interact again with that property the user must use the insert operation.

It must be noted that delete should not be used for TerminationTime and CurrentTime resource properties.

The code example below illustrates how to delete a resource property in the WS-Resource:

QName deleteQName = // QName of the resource property whose

value has to be deleted, this can be find from generated RPD class

i.e Address_ResourcePropertyDocument

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference

returned by WS-Resource as a result of create WS-Resource operation

AddressSoap_Stub stubObj = new AddressSoap_stub(); // Sample Client Stub Object

try{

Developing applications 267

Page 278: Lotus Expeditor: Developing Applications for Lotus Expeditor

operationContext.getCurrentThreadsContext();

operationContext.setToEPR(wsresourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

stubObj.deleteResourceProperties(deleteQName);

} catch (Exception e){

// handle exceptions

}

Inserting a resource property value: It is assumed that the client has saved the EndpointReference, which

was returned to the client as a result of the createWSResource operation. Inserting a resource property

implies that the property gets inserted in the Resource Property Document of that WS-Resource instance.

If the property already exists in the Resource Property Document, then the insert operation for that

property will fail.

It must be noted that insert should not be used for TerminationTime and CurrentTime resource properties.

The code example below illustrates how to insert a resource property in the WS-Resource:

QName insertQName = // QName of the resource property whose value has to be inserted

Object insertValue = //new value for resource property represented by above QName

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference returned

by WS-Resource as a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub(); // Sample Client Stub Object

InsertRequestType insertRP = new nsertRequestType(insertQName , insertValue);

try{

opContextObj.setToEPR(resourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

stubObj.insertResourceProperties(insertRP);

}catch(Exception ex){

//handle exceptions

}

Note: The InsertResourceProperty operation cannot be invoked without setting a default value for the

property. If you want to insert a property without any value, set the property value to null in the

case of non-primitive type properties. In the case of primitive type properties, set a default value.

Updating a resource property value: It is assumed that the client has saved the EndpointReference, which

was returned to the client as a result of createWSResource operation. Note that the WS-Resource may or

may not allow updates on a resource property.

It must be noted that update should not be used for TerminationTime and CurrentTime resource

properties.

The code example below shows how one can update the value of a resource property in the

WS-Resource:

QName updateQName = // QName of the resource property whose value has to be updated

Object updateValue = //new value for resource property represented by above QName

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference

returned by WS-Resource as a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub(); // Sample Client Stub Object

UpdateRequestType updateRP = new UpdateRequestType (updateQName , updateValue);

try{

opContextObj.setToEPR(resourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

268 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 279: Lotus Expeditor: Developing Applications for Lotus Expeditor

stubObj.updateResourceProperties(updateRP);

}catch(Exception ex){

//handle exceptions

}

Using Set Operation to simultaneously insert update delete resource properties: The SetResourceProperties

operation allows multiple changes to the resource property or properties in the resource property

document through a single request. It is assumed that the client has saved the EndpointReference, which

was returned to the client as a result of createWSResource operation. The Set request will maintain the

order of insert/update/delete provided by the client.

It must be noted that set should not be used for TerminationTime and CurrentTime resource properties.

The code example below shows how you can perform multiple operations through

SetResourceProperties on a resource property:

QName insertQName = // QName of the resource property whose value has to be inserted

Object insertValue = //new value for resource property represented by above QName

QName updateQName = // QName of the resource property whose value has to be updated

Object updateValue = //new value for resource property represented by above QName

QName deleteQName = // QName of the resource property whose value has to be deleted

SetRequestType insertRP = new InsertRequestType(insertQName, insertValue);

SetRequestType updattRP = new UpdateRequestType(updateQName, updateValue);

SetRequestType deleteRP = new DeleteRequestType(deleteQName);

ArrayList aList = new ArrayList();

aList.add(insertRP);

aList.add(updateRP);

aList.add(deleteRP);

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference

returned by WS-Resource as a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub(); // Sample Client Stub Object

try{

SetResourceProperties srp = new SetResourceProperties();

SetRequestType [] srt = new SetRequestType[aList.size()];

for(int i=0; i<aList.size(); i++){

srt[i] = (SetRequestType)aList.get(i);

}

opContextObj.setToEPR(resourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

srp.setSetRequestTypes(srt);

stubObj.setResourceProperties(srp);

}catch(Exception ex){

//handle exceptions

}

Fetching the ResourcePropertyDocument: Users can get the ResourcePropertyDocument for the WS-Resource

instance. Below, is a sample code explaining how you can get the Resource Property Document for the

WS-Resource instance:

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference

returned by WS-Resource as a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub(); // Sample Client Stub Object

try{

opContextObj.setToEPR(wsresourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

Object[] obj = stubObj.getResourcePropertyDocument();

} catch(Exception e){

//handle exceptions

}

Developing applications 269

Page 280: Lotus Expeditor: Developing Applications for Lotus Expeditor

Replacing the ResourcePropertyDocument: The PutResourcePropertyDocument operation helps the

applications to replace the existing resource property document of a WS-Resource. It is assumed that the

client has saved the EndpointReference, which was returned to the client as a result of the

createWSResource operation.

It must be noted that put should not be used for TerminationTime and CurrentTime resource properties.

The code example below shows how one can use the putResourcePropertyDocument functionality:

QName propertyQName1 = // QName of the resource property whose value has to be updated

Object propertyValue1 = //new value for resource property represented by above QName

QName propertyQName2 = // QName of the resource property whose value has to be updated

Object propertyValue2 = //new value for resource property represented by above QName

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference returned

by WS-Resource as a result of createWSResource operation

Address_PropertyMap map = new Address_PropertyMap // sample Property Map Object,

this will be generated by the tool.

map.addPropertyToMap(propertyQName1, propertyValue1);

map.addPropertyToMap(propertyQName2, propertyValue2);

AddressSoap_Stub stubObj = new AddressSoap_stub(); // Sample Client Stub Object

try{

opContextObj.setToEPR(resourceEPR);

OperationContext.setCurrentThreadsContext(opContextObj);

stubObj.putResourcePropertyDocument(map);

} catch(Exception e){

//handle exceptions

}

WS-Resource service method operations: This is a special type of interaction with WS-Resource. In

addition to exposing methods related to various WSRF specifications, the WSRF implementation allows

WS-Resources to also expose service methods. The code example below shows how clients can invoke a

service method echo(int i1) on a WS-Resource:

EndpointReference wsresourceEPR = //Resource Qualified EndpointReference

returned by WS-Resource as a result of createWSResource operation

AddressSoap_Stub stubObj = new AddressSoap_stub();

try{

operationContext.setToEPR(wsresourceEPR);

stubObj.setCurrentOperationContext(operationContext);

int i1 = 100;

int i2 = stubObj.echo(i1);

} catch (Exception e){

// handle exceptions if any

}

Note: The server side exceptions will be received as BaseFault or JAXRPCException at the client

application. To retrieve the exception trace, the following methods of the WSBFUtils class can be

used:

v WSBFUtils.getFaultTrace(Throwable argThrowable)

v WSBFUtils.getFaultTrace(BaseFault argBaseFault)

For example, the exception trace from JAXRPCException can be retrieved as follows:

catch (JAXRPCException e)

{

Throwable throwable = e.getLinkedCause();

String traceStr = WSBFUtils.getFaultTrace(throwable);

..................

}

270 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 281: Lotus Expeditor: Developing Applications for Lotus Expeditor

The exception trace from BaseFault can be retrieved as follows:

catch (BaseFault e)

{

Throwable throwable = e.getLinkedCause();

String traceStr = WSBFUtils.getFaultTrace(throwable);

..................

}

For a detailed explanation on developing WS-Resource and client applications, refer to the IBM

developerWorks article published at http://www.ibm.com/developerworks/lotus/library/expeditor-wsrf.

Packaging and deploying WS-Resource bundles

Web services applications are deployed as OSGi bundles/Eclipse plug-ins. They run in the Lotus

Expeditor runtime platform and require no extra special handling.

Deploying a WS-Resource provider: The WS-Resource provider is comprised of a Resource bundle,

Adapter bundle and the Web service bundle. In order to deploy the WS-Resource provider, launch an

instance of the Lotus Expeditor runtime with the Resource bundle, Adapter bundle and the Web service

bundle installed.

To deploy a Web services provider from the IDE, perform the following procedure:

1. Select Run > Run....

2. Create a new Lotus Expeditor runtime instance if necessary.

3. From the Plug-ins tab, ensure that your Web services provider bundles are checked.

4. Select Run.

5. At the osgi> prompt in the console view, type ss to display a list of all registered bundles and their

associated IDs.

6. From the list, find the bundle ID for your Resource, Adapter and Web service bundles.

7. At the osgi> prompt in the console view, type start <bundle ID>, where <bundle ID> is the bundle

ID for your plug-ins. Please start these three bundles in following order:

a. Resource bundle

b. Adapter bundle

c. Web service bundle8. Once the WS-Resource provider bundles are started, the WSDL for the WS-Resource Web service will

be immediately available for client use.

9. Verify that the Web services provider has started successfully. From a browser, enter the following

URL:

http://<machine>:<port>/ws/pid/<servicepid>?wsdl

Where <machine> is the name of the machine hosting the Web services provider, <port> is the port

used by the Web container, and <servicepid> is the name used to register the Web services provider.

You may look in the WS-Resource Web service Bundle Activator class to know the service PID for the

Web service Component of the WS-Resource.

For example, if the machine hosting the Web service is the local host, the Web container is listening on

port 1477, and the Java interface used to expose the Web service provider is MyWebServiceImpl, the

WSDL URL will be:

http://localhost:1477/ws/pid/MyWebServiceImpl?wsdl

Note: In cases where the WS-Resource Provider is security enabled, you should export Resource, Adapter

and Web Service as Folder type bundles instead of JAR type bundles.

Developing applications 271

Page 282: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: By default, the Web container port is dynamically selected by the Lotus Expeditor runtime. Refer

to the Web Container Configuration section in the Assembling and Deploying Lotus Expeditor

Applications in order to bind the Web container to a static port instead.

Deploying a WS-Resource client: In order to deploy the WS-Resource client, launch an instance of the

Lotus Expeditor runtime with the WS-Resource client bundle installed.

To deploy a Web services provider from the IDE, perform the following procedure:

1. Select Run > Run...

2. Create a new Lotus Expeditor runtime instance if necessary.

3. From the Plug-ins tab, ensure that your WS-Resource client bundle is checked.

4. Select Run.

5. At the osgi> prompt in the console view, type ss to display a list of all registered bundles and their

associated IDs.

6. From the list, find the bundle ID for your WS-Resource client bundle.

7. At the osgi> prompt in the console view, type start <bundle ID>, where <bundle ID> is the bundle

ID for your WS-Resource client bundle.

Note: It is not recommended to deploy a WS-Resource provider and its corresponding WS-Resource

client in the same instance of a Lotus Expeditor Client runtime. To use the WS-Resource client in

any application bundle in order to access a WS-Resource, export WS-Resource client as a Java

library (JAR) and package it along with the bundle, using the following procedure:

1. Export the WS-Resource Client Stub as JAR.

2. Copy the JAR file into the project folder of the bundle (the bundle with which WS-Resource

client should be packaged).

3. If the WS-Resource client is security enabled:

a. Add the following bundle to the Require-Bundle list of the bundle Manifest:

com.ibm.pvcws.wss.4. Edit the bundle Manifest to include the WS-Resource client JAR in Bundle-ClassPath

5. Edit the build configuration of the bundle to include the WS-Resource client JAR while

building the bundle

6. Export the bundle and deploy it on the Lotus Expeditor runtime

Accessing a WS-Resource from Java applications: A WS-Resource deployed on the Lotus Expeditor

runtime can also be accessed through a Java application.

To access a WS-Resource from a Java application, perform the following procedure:

1. Export the WS-Resource Client Stub as JAR and set it to the application class path

2. Set the Java libraries (JARs) corresponding to the following bundles to application classpath.

v com.ibm.pvcws

v com.ibm.pvcws.osgi

v com.ibm.wsaddressing

v com.ibm.wsbf

v com.ibm.wsrf.client

v com.ibm.wsrf.common

v org.eclipse.osgi

v com.ibm.icu

3. If the WS-Resource client is security enabled, additionally set the following in the classpath:

com.ibm.pvcws.wss.

272 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 283: Lotus Expeditor: Developing Applications for Lotus Expeditor

4. If the WS-Resource client is security enabled, copy all the generated folders containing security related

templates/files to the location where Java client application is run.

5. Run the application as a stand-alone Java application.

Securing a WS-Resource

The WSRF implementation currently supports security enablement of a WS-Resource at two levels:

v Enabling security, while generating a WS-Resource: This is achieved by selecting the Enable Security

checkbox while generating providerand client code for the WS-Resource.

v Enabling security, while running a pre-generated secured WS-Resource: Once the provider and client

components have been generated with the security code, you can enable the security at the runtime

with following security configurations:

– sign only

– encrypt only

– sign and encrypt

– authentication only

WSRF does not support the following security configurations in this release:

v signing and authentication

v encryption and authentication

v signing, encryption and authentication

To enable the security, it is necessary that both provider (sever-side) and client (client-side) be enabled

with the same security configuration.

Enabling security for WS-Resource providers: To enable security at server side, you must create the

WS-Resource provider component using the WSRF Provider tool with the Enable security option

checked.

With the exception of the ″authentication only″ security configuration, security configurations do not

require any modification in the generated code. If you want to enable the security configuration as

″authentication only″, you need to write the Custom Authenticator class. Please refer to “Developing

custom authenticators” on page 274 for more details.

To enable the security in the WS-Resource Provider at the runtime, you are required to:

v Create a Configuration Property (VM system property) in the rcpinstall.properties file that has the

format <WS-Resource_Webservice_Bundle_Symbolic_Name>.wsrf.security.type.

v The property will be set to a specific value depending on the required security configuration. The table

below shows the values to be set for the different security configuration.

Value Description

authenticator For security as ‘authentication only’

sign For Security as ‘sign only’

encrypt For security as ‘encrypt only’

sign_encrypt For security as ‘sign and encrypt’

For example, to enable security as ‘authentication only’ in the PrinterResource, if the Web service

component’s bundle symbolic name is printerresource.webservice, then set the Configuration Property

as:

- Dprinterresource.webservice.wsrf.security.type=authenticator

Note: The Configuration Property can be added into the rcpinstall.properties file, located at:

Developing applications 273

Page 284: Lotus Expeditor: Developing Applications for Lotus Expeditor

For Windows:

<home drive>\<home path>\IBM\rcp\<rcp.install.id>\<username>

For Linux:

<home>/IBM/rcp/<rcp.install.id>/<user>

To turn off security, delete the configuration property created for that particular WS-Resource.

Enabling security for WS-Resource clients: Create a WS-Resource’s client using the WS-Resource Client

tool with the Enable security option checked.

Once the client component is generated, it can be enabled with the appropriate security configuration

(same as provider’s security enablement option chosen).

To enable a particular security option, you are required to:

v Create a Configuration Property (VM system property) that has the format <PID>.wsrf.security.type.

v The property will be set to a specific value depending on the required security configuration. The table

below shows the values to be set for the different security configuration.

Value Description

authenticator For security as ‘authentication only’

sign For Security as ‘sign only’

encrypt For security as ‘encrypt only’

sign_encrypt For security as ‘sign and encrypt’

For example, for a WS-Resource configured with security as ‘authentication only’ and PID

‘PrinterResource’, the system property variable should be set as

PrinterResource.wsrf.security.type=authenticator.

For ‘authentication only‘ security configuration, the user ID and password should be provided by the

user as below:

1. When the client code is generated with the ‘Enable Security’ check box selected, a file named

ibm-webservicesclient-bnd.xmi is generated. This can be located in the package

*.security.authenticator.

2. This file will be edited and to provide the user id and password as below:

<basicAuth userid="user1" password="password1"/>

For turning off the security, delete the configuration property created for that particular WS-Resource.

Developing custom authenticators: In cases, when the WS-Resource Provider is generated with the

Enable Security check box selected, the tool generates the custom authenticator with empty

implementation in the WS-Resource Web service bundle.

This authentication can be identified by the name <ResourceName>Authenticator.java, and is available in

<PackagePrefix>.authenticator. For example, if the resource name is PrinterResource and the package

prefix is com.myorg, the authenticator generated can be identified as

com.myorg.authenticator.PrinterResourceAuthenticator.

You will have to provide implementations for the following methods of this class, to authenticate users

and to authorize users to access WS-Resource, Resource properties and the custom portTypes. This is

required if you have chosen the security configuration as ″authentication only″.

274 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 285: Lotus Expeditor: Developing Applications for Lotus Expeditor

public void doAuthenticate(WSRFMessageAutheticatorContext authMessageContext)

throws WSSException {

}

public void doAuthorize(WSRFMessageAutheticatorContext authMessageContext)

throws WSSException {

}

A typical authentication implementation (implementation of the doAuthenticate() method) will involve

getting the user name from the context and authenticating the user against a repository (file, database,

LDAP etc). The implementation should throw a new WSSException if the authentication fails.

A typical authorization implementation (implementation of the doAuthorize() method) will involve

writing authorization code by using WSRF SOAP request’s specific details - such as the operation name,

resource Properties and resource ID . The SOAP request details can be taken from the private methods

present within the <ResourceName>Authenticator.java class. The provider generates these private

methods within the <ResourceName>Authenticator.java class automatically and developers are just

required to consume these methods for the case specific implementation of doAuthorize() method.

Mobile Web Services

This section provides information regarding Mobile Web Services.

Creating Mobile Web Services

This section provides information on Mobile Web Services creation.

Creating Mobile Web Services providers: Any OSGi service can be exposed on the Lotus Expeditor as a

Web Services provider using the Lotus Expeditor Toolkit, provided that the service implements a Java

interface.

To create a Web Services provider from scratch, perform the following procedure:

1. Create a new Client Services project named MyWebServicesProvider:

a. Select File > New > Project.

b. Select Client Services > Client Services Project.

c. Select Next.

d. Type a name for the new project (for example, MyWebServicesProvider).

e. Select Next.

f. Select Next.

g. Select Finish.2. Create the code that will be exposed as a Web services provider:

a. Create a simple Java interface with a method declaration.

b. Create a Java bean class that implements the interface, and then select it in the workspace.

c. Select File > New > Other.

d. Select Client Services > Mobile Web Services > Mobile Web Services Provider.

e. Select the Java interface implemented by the selected file.

f. Select the classes requiring custom marshalling (if any).

g. If you checked Configure Security on the first page, select Next and refer to “Securing Mobile

Web Services” on page 289 for information on how to configure Web services security. Otherwise,

select Finish.

After selecting Finish, the Lotus Expeditor Toolkit will modify the Bundle Activator of the targeted

project with the following changes:

Developing applications 275

Page 286: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Modifies BundleActivator to implement ServiceTrackerCustomizer methods -

addingService(),modifiedService() and removedService() to perform life cycle management in OSGi

runtime

v Adds the exposeService() method

The following is an example of a provider:

/* method called from addingService(ServiceReference arg0)

* exposeService(WebServiceProvider provider) created after exposing as web service

*/

private void exposeService(WebServiceProvider provider) {

Hashtable props = new Hashtable();

props.put(org.osgi.framework.Constants.SERVICE_PID, "MyWebService");

props.put("com.ibm.pvcws.wsdl", "");

context.registerService(complexprovider.ComplexInterface.class

.getName(), new MyWebService(), props);

provider.exportPid("MyWebService");

}

/*(non-Javadoc)

*@see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)

*/

public Object addingService(ServiceReference arg0) {

WebServiceProvider provider = (WebServiceProvider) context.getService(arg0);

registerCustomSerializers();

if (provider != null)

exposeService(provider);

return provider;

}

/*(non-Javadoc)

*@see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference)

*/

public void modifiedService(ServiceReference arg0, Object arg1) {

//DO NOTHING

}

/*(non-Javadoc)

*@see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference)

*/

public void removedService(ServiceReference arg0, Object arg1) {

//DO NOTHING

}

Also, the start() method of the Bundle Activator will be modified to open the serviceTracker for OSGi,

so that the provider bundle waits until the web services runtime starts. In addition, the

registerCustomSerializers () method will be generated inside the Bundle Activator, if custom

marshalling types have been selected from the wizard. This method registers all the custom marshaller

factory classes as an OSGi service.

Both the exposeService() and registerCustomSerializers() needs to be get called from inside of

addingService() in order to have proper life cycle management. In addition, the Servicetracker must be

stopped and closed inside of the BundleActivator stop() method.

The Mobile Web Services Provider wizard also auto generates the full implementation code for custom

marshallers if the Web Services provider needs to handle java.util.Calendar or java.util.HashMap or

java.util.Hashtable. If the Web Services provider needs to handle non-bean classes or types that are

incompatible with JSR-172 (other than the one’s mentioned above), custom marshallers need to be

implemented. Please refer to the section “Custom serialization (marshalling)” on page 283 for more

information.

276 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 287: Lotus Expeditor: Developing Applications for Lotus Expeditor

Lotus Expeditor for Devices does not support running Web Services providers.

Creating Mobile Web Services clients: The Lotus Expeditor Toolkit can be used to create Web Services

client code that calls Web Services providers via a static or dynamic stub. The Lotus Expeditor Toolkit

supports the creation of Web Services clients using the WSDL of the Web Services provider. If the Web

Services client will target a Lotus Expeditor Client Web Services provider, it is best to create and deploy

the Web Services provider first, prior to creating the Web Services client so that its WSDL is available.

Following are the steps to create a Web services client from scratch:

1. Create a new bundle project named MyWebServicesClient:

a. Select File > New > Project.

b. Select Client Services > Client Services Project.

c. Select Next.

d. Type a name for the new project (for example, MyWebServicesClient).

e. Select Next.

f. Select Next.

g. Select Finish.2. Create a new client interface and optional stub:

a. Select File > New > Other.

b. Select Client Services > Mobile Web Services > Mobile Web Services clients.

c. Select Browse to select the source folder or project for your client application.

d. Optionally, enter the package you wish to use for the static stubs or leave it blank to use a default

package instead. Please note that this option will not be enabled if you select the Create Dynamic

Stub check box, as the Web Services runtime component requires that the package name match the

WSDL namespace.

The Lotus Expeditor Client for Devices does not support exposing OSGi services as Web Services

providers. Lotus Expeditor Client for Devices only supports JSR-172. without dynamic Web

Services clients.

Note: If you intend to deploy a Web service client and a Web service provider in the same

runtime, place the Web service client stub in a package that is different from the package of

the Web service provider to prevent a runtime conflict.

e. Enter the URL of the WSDL exposed by the Web Services provider (if known) or use the Browse

button to load the WSDL from any project in the current workspace.

Please note that if the URL is secured with SSL (e.g. HTTPS), you will need to start the Rational

Software Development Platform with the appropriate VM arguments to provide a valid client

certificate. For example, the following VM arguments can be used:

-Djavax.net.ssl.keyStore=<path_to_keystore_file>

-Djavax.net.ssl.keyStoreType=<keystore_type>

-Djavax.net.ssl.keyStorePassword=<keystore_password>

-Djavax.net.ssl.trustStore=<path_to_truststore_file>

-Djavax.net.ssl.trustStoreType=<truststore_type>

-Djavax.net.ssl.trustStorePassword=<truststore_password>

Optionally, select the Create Dynamic Stub check box to use dynamic stubs rather than create

static stubs.

A dynamic stub allows the Web Services client to create and use custom marshallers for WSDL

types that are non-bean classes or are incompatible with JSR-172.

f. Optionally, select the Configure Security check box to configure Web Services Security for the

client.

g. Select Next.

Developing applications 277

Page 288: Lotus Expeditor: Developing Applications for Lotus Expeditor

h. If there are any types in the WSDL that may require custom marshalling, you will be presented

with the option of generating custom marshaller stubs for each type. This will only be true if the

Create Dynamic Stub check box is checked.

For each type selected in the list, two classes will be generated; MarshalFactory and Marshaller.

These classes are implementations of the corresponding classes in the com.ibm.pvcws.osgi plug-in.

Please refer to the section “Custom serialization (marshalling)” on page 283 for information on

how to complete the implementation of custom marshallers.

i. If Configure Security was checked on the first page, select Next and refer to the section “Securing

Mobile Web Services” on page 289 for information on how to configure Web services security.

Otherwise, select Finish.

Note: If you receive an exception with the message “Parsing of the specified WSDL failed”,

followed by an explanation, ensure that the WSDL is accessible through a browser. This

exception could either be the result of a firewall message in HTML-form requiring

authentication, or could be due to an invalid WSDL. Please consult with your administrator.

Lotus Expeditor for Devices does not support dynamic stubs and Web Services security. As a result, any

Web Services clients using dynamic stubs or Web Services security will not work on Lotus Expeditor for

Devices.

Static Mobile Web Services clients: If you generated Web Services client code to use a static stub (i.e., you

did not check the Create Dynamic Stub box), you will see that a *Soap_Stub class was generated. To

invoke the Web services provider, you simply need to instantiate a *Soap_Stub object and then call the

Web services provider methods you wish to exercise. For example:

A method consumeService() will be generated inside the Bundle Activator.

private void consumeService(BundleContext context)throws Exception {

MyWebServiceSoap_Stub stub=new MyWebServiceSoap_Stub();

//TODO: invoke any of the stub methods to consume the service

Invoke your stub methods as follows:

System.out.println("Name=" + stub.getName());

}

Please note that this release of the Lotus Expeditor Toolkit does not support custom marshalling with

static Web Services clients.

Note: The generated stub will contain the URL of the WSDL specified in the tools. However, this is only

ideal for consuming Web services at fixed locations. If you intend to host a Web services client in

the same Lotus Expeditor runtime of the Web services provider, and the Web container is selecting

a port dynamically, you must register the Web services client BundleActivator as an

HttpSettingListener (package com.ibm.pvc.webcontainer.listeners.HttpSettingListener) in

order to obtain the port that the Web container is listening on at startup. Then set the endpoint

address accordingly. Following is a listing of the changes that need to be made on the project

MANIFEST.MF file and the BundleActivator class, including a sample implementation of the

HttpSettingListener interface:

MANIFEST.MF:

Require-Bundle: ..., com.ibm.pvc.sharedbundle

import com.ibm.pvc.webcontainer.listeners.HttpSettingListener;

public class MyBundleActivator

extends implements BundleActivator, HttpSettingListener

{

String endpoint = null;

278 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 289: Lotus Expeditor: Developing Applications for Lotus Expeditor

public void start(BundleContext context) throws Exception

{

/* *********************************************************** */

/* when running a web service client on the same host as a web */

/* service provider, we must change the endpoint so that it */

/* matches the port!! */

/* *********************************************************** */

context.registerService(HttpSettingListener.class.getName(),

this, null);

/* *********************************************************** */

/* create the endpoint URL; please note that you will need to */

/* make some changes to prevent a race condition with the set- */

/* ting of httpPort as the registerService call from above is */

/* asynchronous so it may not be properly set by the time we */

/* execute the line below. */

/* *********************************************************** */

endpoint = "http://localhost:" + httpPort + "/ws/pid/echoSvc";

/* *********************************************************** */

/* if using a static client, use the following code */

/* *********************************************************** */

// change the endpoint to use the dynamic port which is set below

EchoServiceSoap_Stub stub = new EchoServiceSoap_Stub();

stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,

endpoint);

/* *********************************************************** */

/* if using a dynamic client, use the following code */

/* *********************************************************** */

String service = "com.ibm.pvcws.osgi.proxy.WSProxyService";

ServiceReference ref = bundleContext.getServiceReference(service);

if (ref == null)

{

System.err.println("Error: WSProxyService does not “ +

“exist.");

return;

}

WSProxyService wsManImpl =

(WSProxyService)context.getService(ref);

try

{

/* register the wsdl at the new endpoint */

wsManImpl.register(endpoint + "?wsdl");

}

catch (Exception e)

{

e.printStackTrace();

return;

}

}

/**

* Implement the Web Container Listener interfaces */

*/

private static boolean validSetting = false;

private static int httpPort = 0, httpsPort = 0;

private static final String PROPERTY_HTTP_PORT = "http.port";

private static final String PROPERTY_HTTPS_PORT = "https.port";

private static Map settingsMap = new HashMap();

public void settingsAdded(String pid, Dictionary properties)

{

Developing applications 279

Page 290: Lotus Expeditor: Developing Applications for Lotus Expeditor

Map settings = new HashMap();

Enumeration enum = properties.keys();

while (enum.hasMoreElements())

{

String key = (String)enum.nextElement();

settings.put( key, properties.get( key ) );

}

settingsMap.put( pid, settings );

if (!validSetting)

{

scanSettings();

}

}

public void settingsModified(String pid, Dictionary properties)

{

Map settings = (Map)settingsMap.get( pid );

if (settings == null)

{

settings = new HashMap();

}

Enumeration enum = properties.keys();

while (enum.hasMoreElements())

{

String key = (String)enum.nextElement();

settings.put( key, properties.get( key ) );

}

settingsMap.put( pid, settings );

scanSettings();

}

public void settingsRemoved(String pid)

{

settingsMap.remove( pid );

scanSettings();

}

private void scanSettings()

{

boolean found = false;

Iterator iter = settingsMap.keySet().iterator();

while (!found && iter.hasNext())

{

Map settings = (Map)settingsMap.get( (String)iter.next() );

Integer httpPort_ = (Integer)settings.get(

PROPERTY_HTTP_PORT );

if (httpPort_ != null)

{

httpPort = httpPort_.intValue();

validSetting = true;

found = true;

}

Integer httpsPort_ = (Integer)settings.get(

PROPERTY_HTTPS_PORT );

if (httpsPort_ != null)

280 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 291: Lotus Expeditor: Developing Applications for Lotus Expeditor

{

httpsPort = httpsPort_.intValue();

validSetting = true;

found = true;

}

}

if (!found)

{

validSetting = false;

httpPort = 0;

}

}

}

Lotus Expeditor for Devices does not support the use of Web Services providers. As a result, you cannot

host a Web services client in the same Lotus Expeditor for Devices runtime of a Web services provider.

Dynamic Mobile Web Services clients: If you generated Web Services client code to use a dynamic stub (i.e.,

you checked Create Dynamic Stub) you will need to register the WSDL of the Web Services provider

using the Gateway plug-in. In order to do this, use the WSProxyServiceFactory class to get a new instance

of WSProxyService and invoke one of the following methods at runtime:

boolean register(String url);

boolean register(String url, Dictionary properties);

Both methods take the URL of a WSDL resource that describes the Web Services provider. The WSDL will

be retrieved and parsed to determine the end point of the Web Services provider, the names of the

interface to register, and the data structures and methods used by the interface. An automatically

generated ″virtual″ OSGi service will then be registered by the Web Services Gateway-using the class

name of the interface derived from the WSDL-defined operation.

After the OSGi service is registered, it can be retrieved from the OSGi service registry and used just as

any other local OSGi service. The OSGi service will stay registered until the virtual bundle for that

service is stopped or uninstalled. If the unregister() method of WSProxyService is used, the virtual

bundle registering the service will be stopped.

Note: When running a dynamic Web services client and a Web services provider in the same runtime,

there will be two bundles providing the Web service interface (the client and the provider). As a

result, the call to retrieve the OSGi service will return one reference to each. There are two

solutions to this problem. First, you may set a property on the Web services provider

exposeService method in order to differentiate between the two. Second, You may directly access

the dynamic proxy by invoking the runtime APIs.

Following is as an example on how to set this property on the Web services provider side:

private void exposeService(BundleContext context)

{

Hashtable props = new Hashtable();

props.put(org.osgi.framework.Constants.SERVICE_PID,

“MyWebServiceImpl");

props.put("com.ibm.pvcws.wsdl", "");

props.put(“NAME”, “PROVIDER”);

context.registerService(MyWebService.class.getName(),

new MyWebServiceImpl(), props);

WebServiceProvider provider = getProvider(context);

provider.exportPid("MyWebServiceImpl");

}

The Bundle Activator code must implement the ServiceTrackerCustomizer in order to handle the life

cycle management for OSGi. Hence the methods addingService(),modifiedService() and

removedService() must be added to the Bundle Activator code.

Developing applications 281

Page 292: Lotus Expeditor: Developing Applications for Lotus Expeditor

public Object addingService(ServiceReference arg0) {

WSProxyService proxy = (WSProxyService) context.getService(arg0);

//do this if custom marshalling is needed for the clients

registerCustomSerializers();

try{

consumeService();

} catch (Exception e) {}

return proxy;

}

public void modifiedService(ServiceReference arg0, Object arg1) {

//DO NOTHING IN THIS METHOD

}

public void removedService(ServiceReference arg0, Object arg1) {

//DO NOTHING IN THIS METHOD

}

start() must create a service tracker for the WSProxyService and open it.

private String proxyService = WSProxyService.class.getName();

public void start(BundleContext context) throws Exception {

super.start(context);

this.context = context;

proxyTracker = new ServiceTracker(context,proxyService, this);

proxyTracker.open();

}

The registering of the WSDL and dynamic web service invocation code goes into consumeService() or at

the end of addingService() method.

public void consumeService(BundleContext context) throws Exception

{

WSProxyService wsManImpl = WSProxyServiceFactory.newInstance(context, null);

try

{

// NOTE: since by default the web container listens on a random port,

// refer to the section Static Web Services clients for information on

// how to obtain the chosen port programmatically and use that

// information to form the WSDL URL.

wsManImpl.register("http://localhost:8777/ws/pid/MyWebServicesImpl?wsdl);

ServiceTracker tracker = new ServiceTracker(context,

MyWebService.class.getName(), null);

tracker.open();

ServiceReference refs[] = tracker.getServiceReferences();

for (int i=0; i<refs.length; i++)

{

String name = refs[i].getProperty("NAME");

MyWebService stub = (MyWebService)context.getService(refs[i]);

if ((name != null) && (name.equals("PROVIDER")))

{

/* this is a direct call into the service and is more

efficient as it would not execute the web services

stubs

*/

282 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 293: Lotus Expeditor: Developing Applications for Lotus Expeditor

System.out.println("NAME= + stub.getName());

}

else

{

/* this is an indirect call into the service which is

less efficient as it would execute the web services

stubs

*/

System.out.println("NAME= + stub.getName());

}

}

tracker.close();

}

catch (Exception e)

{

e.printStackTrace();

}

The ServiceTracker must be disposed prior to exiting the bundle activator.

public void stop(BundleContext context) throws Exception {

plugin = null;

super.stop(context);

if (tracker != null)

tracker.close();

if (proxyTracker != null)

proxyTracker.close();

}

If the Web Services client needs to handle non-bean classes or types that are incompatible with JSR-172

style Web Services, custom marshallers need to be implemented. Please refer to the section “Custom

serialization (marshalling)” for more information.

Note: Following is an example on how to invoke the runtime API to access the dynamic proxy. This

approach is less complex than the first one. All you are required to do is the following inside the

consumeService method. No Service tracking logic is required.

if (!wsManImpl.register(MyWebService.class,wsdlURL, props)) {

throw new Exception("Unable to consume service " + wsdlURL);

}

MyWebService stub = (MyWebService)wsManImpl.getProxy();

Developing Mobile Web Services logic

This section provides information on Mobile Web Services logic development.

Custom serialization (marshalling): Custom marshalling is required for handling non-bean classes as

well as types that are incompatible with JSR-172. Custom marshalling can be implemented for both Web

Services providers and Web Services clients. The Lotus Expeditor Toolkit v 6.1 does automatically

generate custom marshaller code for Web Services providers and for Web Services clients.

When custom marshalling is required, the developer is responsible for completing the code within the

generated MarshalFactory and Marshaller classes on the Web services client and Web services provider.

However, the Lotus Expeditor Toolkit Web Services will provide complete custom marshalling code

implementation for three non JSR-172 types - Calendar, HashMap and Hashtable.

This section describes the Application Program Interfaces (API) used in the serialization of data structures

that cannot be automatically serialized by the Web Services engine for OSGi.

Developing applications 283

Page 294: Lotus Expeditor: Developing Applications for Lotus Expeditor

The current Web Services engine uses Java reflection and conventions similar to the functionality

described in JSR 101 to automatically generate a WSDL to describe services and to serialize data

structures for wire transmission. However, in order for the conventions to work, the data structures must

have a bean-like structure. Unfortunately, not all data structures have this structure and require specific

logic to be serialized and described.

The serialization API has the following features:

v The programmer does not deal with XML processing

v Only the structures that need special processing need custom marshallers

Using the Lotus Expeditor Toolkit, it is easy to write classes that can automatically be serialized.

However, when working with legacy classes and classes that contain logic, complications arise. Very few

of the standard Java classes lend themselves to automatic serialization. For example, consider the

java.util.Properties class and the java.util.Calendar class. Neither of these two classes follows the

Lotus Expeditor Web Services conventions. Furthermore, there is a standard mapping of the Calendar

class into the XML Schema namespace, so even the namespace mapping conventions do not apply. The

serialization API allows data structures to be introspected.

It has three parts:

v Class name to QName mapping

v Enumeration of the members that make up a class

v Extractions of members from an instance of a class

As it is an introspection API, the programmer does not need to be involved in the generation of XML for

the WSDL or the SOAP messages. In fact, the actual encoding can be changed since none of the encoding

constructs manifest themselves in the API.

Another design feature of the serialization API is that it is only needed for those classes that cannot be

processed using the standard conventions. For example, when the marshaller of the Properties class is

written, it is represented as an array of PropertyEntry objects where PropertyEntry is a class that has two

public members, a key and a value, both of type String. Because PropertyEntry follows the normal

convention for writing serializable data structures it is not necessary to write a custom marshaller for it.

Custom marshallers implement the ClassDescriberMarshalFactory interface and are registered in the

OSGi service registry. The Web services engine dynamically looks up the marshallers and invokes them

when needed. This allows for easy deployment of new marshallers and non-disruptive removal of

unnecessary marshallers.

Lotus Expeditor for Devices does not support custom marshalling.

MarshalFactory: When the Web Services engine needs to map a class to a QName or get a Marshal for a

QName, it relies on the MarshalFactory class for help. The MarshalFactory class consists of two methods:

public interface MarshalFactory {

Class getClassForQName(ClassLoader cl, QName qtype);

Marshal getMarshaller(QName qtype);

}

Marshal: The Marshal interface has only one method and should not be implemented directly. Either a

SimpleMarshal or ComplexMarshal should be implemented instead. Each time a new object needs to be

serialized, the Web Services engine will call MarshalFactory.getMarshaller(). When servicing the call,

the MarshalFactory can create a Marshal object to handle the specific object, or it can reuse an already

created object. The Web Services engine interacts with the two Marshal types in different ways. The

engine selects the appropriate behavior by checking the class of the Marshal returned from

getMarshaller().

284 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 295: Lotus Expeditor: Developing Applications for Lotus Expeditor

ClassDescriberMarshalFactory: The ClassDescriberMarshalFactory is an interface that extends both

MarshalFactory and CustomClassDescriber. It does not add any new methods. Bundles must register

services using the ClassDescriberMarshalFactory in the service registry to provide custom serializers.

Serializers that only register services under the MarshalFactory and CustomClassDescriber interfaces will

be ignored by the web service engine. Examination of the information provided by the

CustomClassDescriber and the MarshalFactory shows that there is some overlap between the information

provided by the two interfaces. It is the responsibility of the implementer to ensure that the information

is consistent.

Examples: This section contains two examples of custom marshallers. The first example shows a

SimpleMarshal for Calendar, and highlights the use of QName mapping to map Calendar to

xsd:dateTime, a mapping defined in JAX-RPC. The second example shows a ComplexMarshal for

Properties, and also illustrates the use of an intermediate class and the use of QName mapping to return

a non imported class.

Calendar example: The serialization of Calendar is illustrated in two parts: the implementation of

CalendarMarshalFactory, and the implementation of CalendarMarshal.

CalendarMarshalFactory

You must register a service of type ClassDescriberMarshalFactory, so that it is the interface that the

CalendarMarshalFactory implements. First, you must setup static member variables to aid in your

processing:

static QName calendarType = new QName(NamespaceConstants.NSURI_SCHEMA_XSD,

"dateTime");

static ClassDescriptor cdCalendar = new ClassDescriptor(calendarType, 1, 1, true);

static ClassDescriptor cdCalendarArray = new ClassDescriptor(calendarType, 1,

Integer.MAX_VALUE, true);

static PartsDescriptor parts = new PartsDescriptor

(new QName[] { new QName("entries") ],

new Class[] { PropertyEntry[].class });

Now you can write the methods that correspond to ClassDescriber:

public boolean canDescribe(Class c) {

if (c.isArray()) c =

c.getComponentType();

return c.equals(Calendar.class);

}

In the canDescribe() method you can describe both Calendar and Calendar[]. Ensure you check for both.

public ClassDescriptor getQType(Class c) {

boolean isArray = false;

if (c.isArray()) {

c = c.getComponentType();

isArray = true;

}

if (c.equals(Calendar.class)) {

return isArray ? cdCalendar :

cdCalendarArray;

}

return null;

}

This checks to see if the class in question is Calendar and returns the precomputed ClassDescriptors if

appropriate. Observe that the only difference between cdCalendar and cdCalendarArray is that the

maxOccurs value is 1 in the non-array case, and MAX_VALUE in the array case.

Developing applications 285

Page 296: Lotus Expeditor: Developing Applications for Lotus Expeditor

public PartsDescriptor getParts(Class c) {

return null;

}

getParts() always returns null since even if c == Calendar.class. The Calendar class is a simple class

and therefore has no parts.

public Class getClassForQName(ClassLoader cl, QName qtype)

{

return calendarType.equals(qtype) ?

Calendar.class : null;

}

This method handles QName mapping. It simply returns the Calendar class if the qtype matches

xsd:dateTime.

static SimpleMarshal calMarshal = new CalendarMarshal();

Marshal getMarshaller(QName qType)

{

return calendarType.equals(qType) ?

calMarshal : null;

}

This is the final method to be implemented. In this method, the system returns a precomputed

SimpleMarshal for Calendar if the qType is xsd:dateTime. The CalendarMarshal has no reusable state, even

if it is used concurrently.

CalendarMarshal

When Calendar is encoded as xsd:dateTime it has no members, so you must use a SimpleMarshal.

public Object deserialize(String value) {

try {

Date date = new SimpleDateFormat().parse(value);

Calendar cal = new GregorianCalendar();

cal.setTime(date);

return cal;

} catch (ParseException e) {

e.printStackTrace();

}

return null;

}

To deserialize a Calendar object, take the given string and use SimpleDateFormat to create a Calendar.

Note that even though the return value is Object, we must return a Calendar since that is the type this

Marshal handles.

public String serialize(Object o)

{

Calendar cal = (Calendar)o;

String date = new SimpleDateFormat().format(cal.getTime());

return date;

}

In the serialize() method we know that o is of type Calendar since that is the type this Marshal

handles. You must convert the string to use SimpleDateFormat() and return the result.

public Object newArray(int size)

{

return new Calendar[size];

}

The final method returns an array of the correct size. The Calendar serializer is ready to register in the

service registry.

286 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 297: Lotus Expeditor: Developing Applications for Lotus Expeditor

Properties example: The serialization of Properties is illustrated in two parts: the implementation of

PropertiesMarshalFactory, and then of PropertyMarshal.

This example covers the serializer for Properties. As explained, the Properties class is serialized using an

intermediate class called PropertyEntry:

public class PropertyEntry {

public String key;

public String value;

}

Because PropertyEntry is a class that is easily serialized, you don’t need to write a serializer for it.

However, since it is an intermediate class, you must return the PropertyEntry.class in the QName

mapping. In addition, since the conventional class name is used for QName mapping, you don’t need a

mapping for Properties. It is easy to get confused because the PropertiesMarshalFactory maps

PropertyEntry, a class it is only using internally, but not Properties, the class it is actually serializing.

Remember from the QName mapping discussion that mapping is used when the QName doesn’t

correspond to the convention or the class isn’t a class that will normally be imported by the virtual

bundle or the service. Properties does not meet either case, but PropertyEntry meets the second case. The

getClassForQName is defined as follows:

static QName propertyEntryQType = DefaultMarshalFactory.defaultGetClassQName

(PropertyEntry.class.getName());

public Class getClassForQName(ClassLoader cl, QName qtype)

{

return qtype.equals

(propertyEntryQType) ?

PropertyEntry.class:null;

}

Because the PropertyMarshalFactory is almost exactly the same as CalendarMarshalFactory, only the

getParts() method is shown. It differs substantially:

static PartsDescriptor parts = new PartsDescriptor(new QName[]

{ new QName("entries") },

new Class[] { PropertyEntry[].class });

public PartsDescriptor getParts(Class c) {

if (c.isArray()) c = c.getComponentType();

if (c.equals(Properties.class)) {

return parts;

}

return null;

}

The Properties class is encoded as a complex type with one member (entries) that is an array of

PropertyEntrys. As a result, the PartsDescriptor for Properties is made up of two arrays of one entry.

The first array has the name of the members, and the second the class of the members. The

PropertiesMarshal implements ComplexMarshal and has the following members:

public Object newArray(int length)

{

return new Properties[length];

}

As with Calendar, this is a simple method that returns an array of the specified size.

public Object newHandle() {

return new Properties();

}

Since Properties has a default constructor and has methods to add to it, it can return an instance of

Properties.

Developing applications 287

Page 298: Lotus Expeditor: Developing Applications for Lotus Expeditor

{

PropertyEntry entries[] = (PropertyEntry[])value;

for(int i = 0; i < entries.length; i++) {

((Properties)handle).put(entries[i].key, entries[i].value);

}

}

As there is only one member for Properties, there is no need to check the index. You must only put the

received entries into the Properties object.

public Object newInstance(Object handle) {

return handle;

}

There is nothing to do in this routine since handle is already a Properties object.

public Object getMember(Object obj, int index) {

Properties props = (Properties)obj;

Vector entries = new Vector();

Enumeration en = props.keys();

while(en.hasMoreElements()) {

PropertyEntry entry = new PropertyEntry();

entry.key = (String)en.nextElement();

entry.value = props.getProperty(entry.key);

entries.add(entry);

}

return entries.toArray(new PropertyEntry[0]);

}

As there is only one member, the index does not need to be checked. Since you are generating the entries

member, you must build a PropertyEntry[] and return it.

public int getMemberCount() {

return 1;

}

There is only one member.

QPart entriesPart = new QPart(new QName("entries"),

DefaultMarshalFactory.defaultGetClassQName(PropertyEntry.class.getName()), 0,

Integer.MAX_VALUE, true, true);

public QPart getPart(int index) {

return entriesPart;

}

Return the QPart that describes the entries member. The first argument of the Qpart constructor is the

standard mapping of the QName. The second says that the array can be an empty array. The third says

that it is an unbounded array. The fourth says it can be null. The fifth indicates whether the QPart needs

to be qualified (always set it to true).

Final steps: Now that the serializers are prepared, you must register them in the service registry so that

they can be used. This is done by registering the serializers in the clients’ and providers’ respective

activator classes. This method can be called either at the beginning of the start or the addingService

methods.

public void registerSerializers {

bc.registerService(

ClassDescriberMarshalFactory.class.getName(),

new PropertyMarshalFactory(),

null);

bc.registerService(

288 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 299: Lotus Expeditor: Developing Applications for Lotus Expeditor

ClassDescriberMarshalFactory.class.getName(),

new CalendarMarshalFactory(),

null);

}

To register the serializers, construct the two factories and register them as ClassDescriberMarshalFactory

services.

Securing Mobile Web Services

This section provides information on securing Mobile Web Services.

Lotus Expeditor for Devices does not support Web Services security. Lotus Expeditor for Desktop does

not support XML encryption feature on the jclDesktop profile because of limitation of crypto library on

the jclDesktop profile. We are planning to add support for encryption on the jclDesktop profile in future

release.

Creating secure Mobile Web Services providers: In order to secure Web Services providers, you must

first create the Web Service provider by referring to “Creating Mobile Web Services providers” on page

275. During the creation process, ensure you check Configure Security. Perform the following procedure

to configure Web services security to secure Web Services providers:

1. Select the Web services name and port from the drop down menu.

2. Configure Web Services Security:

a. Select the Web Services name and port from the drop down menu.

b. Under ’How to create Web Services Security configuration’, select the appropriate choice. For a test

case, select Template configuration, then select the Server type and the Security template from the

drop down menus.

v Use other Lotus Expeditor 6.x configuration

If you browse a folder including the existing WS-Security configurations for the Lotus Expeditor

under the other existing project, you can import the configurations into the working project.

v Import WebSphere Application Server 6.x configuration

If you browse a folder including the existing WS-Security configurations for the WAS 6.0 client,

you can import the configurations into the working project.

v Use template configuration

If you select one client type and one security template, you can use the predefined

configurations in the working project.

The following is a list of client types:

– Lotus Expeditor 6.x

– WebSphere Application Server 6.x

– WebSphere Application Server 5.x

The following is a list of security templates:

– Signing and encryption

– Signing only

– Encryption only

– Basic authentication only

– Signing and basic authentication

– Encryption and basic authentication

– Signing, encryption, and basic authenticationc. Select Finish.

After completing the above procedure, the WS-Security Provider Editor appears. Some files may be

created or modified, as follows:

Developing applications 289

Page 300: Lotus Expeditor: Developing Applications for Lotus Expeditor

v WS-Security-related code is inserted in the file BundleActivator.java under the working project

v The files ibm-webservices-ext.xmi, ibm-webservices-bnd.xmi, serverSample.jks, and wssecurity.xml

are generated in the export directory of the package containing the file BundleActivator.java.

CAUTION: The serverSample.jks is designed for testing only. You should use your own key store file

instead of serverSample.jks for commercial use to avoid security exposure. Anyone who can

read this document can access the serverSample.jks.

CAUTION: The jclDesktop profile cannot read the file serverSample.jks that is created using other

profiles such as J2SE due to the limitation of the jclDesktop profile’s ability to read a

keystore and vice versa. We are planning to remove this limitation in a future release.

At this point, you may re-deploy your Web Services provider with security enabled, but if you want to

change the WS-Security configurations in the working project, you can edit them with the WS-Security

Provider Editor. To understand more details of how to edit the WS-Security configurations, please refer to

“Editing the Mobile Web Services security configuration” on page 293.

Securing pre-existing Mobile Web Services providers: To secure a Web Services provider that already

exists, perform the following procedure:

1. Launch the Web Services provider security configuration wizard:

a. Select File > New > Other. Select Lotus Expeditor Mobile Web Services > Lotus Expeditor Mobile

Web Services Provider Security Configuration.

b. Click Next.

c. Enter the source folder containing the Java source code for the Web Services provider application.

d. Enter the URL of the WSDL exposed by the Web Services provider.

e. Click Next.2. Configure Web Services Security:

a. Select the Web Services name and port from the drop down menu.

b. Under How to create Web Services Security configuration, select the appropriate choice. For a

test case, select Template configuration, then select the Server type and the Security template from

the drop down menus (refer to “Creating secure Mobile Web Services providers” on page 289 for

more information):

v Use other Lotus Expeditor 6.x configuration

v Import WebSphere Application Server 6.x configuration

v Use template configurationc. Select Finish.

Note: The serverSample.jks is designed for testing only. You should use your own key store file instead

of serverSample.jks for commercial use to avoid security exposure. Anyone who can read this

document can access the serverSample.jks.

Note: The jclDesktop profile can’t read serverSample.jks that has been created using other profiles such

as J2SE due to the limitation of the jclDesktop profile’s ability to read a keystore and vice versa.

This limitation will be removed in a future release.

Creating secure Mobile Web services clients: In order to secure Web services clients, refer to “Creating

Mobile Web Services clients” on page 277. Ensure that you check Configure Security. Perform the

following procedure to configure Web services security for a secure Web services client:

1. Select the Web services name and port from the drop down menu.

2. Under ’How to create Web Services Security configuration’, select the appropriate choice. For a test

case, select Template configuration, then select the Client type and the Security template from the

drop down menus.

290 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 301: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Use other Lotus Expeditor 6.x configuration

If you browse a folder including the existing WS-Security configuration for the Lotus Expeditor

under the other existing project, you can import the configurations into the working project.

v Import WebSphere Application Server 6.x configuration

If you browse a folder including the existing WS-Security configurations for the WAS 6.0 client, you

can import the configurations into the working project.

v Convert WCTME 5.x class-based configuration

If you browse a WS-Security configuration java file for WCTME 5.8 or 5.7, you can convert the

configuration for use with the Lotus Expeditor 6.0.

v Use template configuration

If you select one server type and one security template, you can use the predefined configurations

in the working project.

The following is a list of server types:

– Lotus Expeditor 6.x

– WebSphere Application Server 6.x

– WebSphere Application Server 5.x

The following is a list of security templates:

– Signing and encryption

– Signing only

– Encryption only

– Basic authentication only

– Signing and basic authentication

– Encryption and basic authentication

– Signing, encryption, and basic authentication3. Select Finish.

After completing the above procedure, the WS-Security Client Editor appears. Some files may be created

or modified, as follows:

If the Web services client is static and you specified a package in the Mobile Web Services Client

wizard

v The port files ’*.java’ and ’*_Stub.java’ are generated in the specified package. The name of the port

file is taken from the portType in the WSDL file

v WS-Security related code is inserted in ’*_Stub.java’

v The files ibm-webservicesclient-ext.xmi, ibm-webservicesclient-bnd.xmi, clientSample.jks, and

wssecurityclient.xml are generated in the export directory in the specified package

If the Web services client is static and you did not specify a package in the Mobile Web Services

Client wizard

v The port files ’*.java’ and ’*_Stub.java’ are generated in the package specified from the contents of

the WSDL file

v WS-Security-related code is inserted in the file ’*_Stub.java’

v The files ibm-webservicesclient-ext.xmi, ibm-webservicesclient-bnd.xmi, clientSample.jks, and

wssecurityclient.xml are generated in the export directory in the package specified from the WSDL

file

If the Web services client is dynamic

v A port file is generated in the package specified in the WSDL file

v WS-Security-related code is inserted in the file BundleActivator.java under the working project

Developing applications 291

Page 302: Lotus Expeditor: Developing Applications for Lotus Expeditor

v The files ibm-webservicesclient-ext.xmi, ibm-webservicesclient-bnd.xmi, clientSample.jks, and

wssecurityclient.xml are generated in the export directory in the package specified from the WSDL

file

CAUTION: The clientSample.jks is designed for testing purposes only. You should use your own key

store file instead of clientSample.jks for commercial use to avoid security exposure. Anyone

who reads this document can access the clientSampke.jks.

CAUTION: The jclDesktop profile cannot read the file clientSample.jks created using other profiles

such as J2SE due to the limitation of the jclDesktop profile’s ability to read a keystore and

vice versa. This limitation will be removed in a future release.

CAUTION: When you select ’Basic authentication’ as a template, the Mobile Web Services security

configuration declares username: @USERNAME@, password: @USERNAME@ by default. To run the

client properly, you must edit the Mobile Web Services security configuration in order to

modify these default values. Please refer to “Editing the Mobile Web Services security

configuration” on page 293.

Securing pre-existing Mobile Web Services clients: To secure a Web Services client that already exists,

perform the following procedure:

1. Launch the Web Services client security configuration wizard:

a. Select File > New > Other.

b. Select Lotus Expeditor Mobile Web Services > Lotus Expeditor Mobile Web Services Client

Security.

c. Click Next.

d. Enter the source folder containing the Java source code for the Web Services provider application.

e. Enter the URL of the WSDL exposed by the Web Services provider.

f. Click Next.2. Configure Web Services Security:

a. Select the Web Services name and port from the drop down menu.

b. Under How to create Web Services Security configuration, select the appropriate choice. For a

test case, select Template configuration, then select the Client type and the Security template from

the drop down menus (Refer to “Creating secure Mobile Web services clients” on page 290 for

more information):

v Use other Lotus Expeditor 6.x configuration

v Import WebSphere Application Server 6.x configuration

v Convert WCTME 5.x class-based configuration

v Use template configurationc. Click Finish.

CAUTION: The clientSample.jks is designed for testing purposes only. You should use your own key

store file instead of clientSample.jks for commercial use to avoid security exposure. Anyone

who reads this document can access the clientSampke.jks.

CAUTION: The jclDesktop profile cannot read the file clientSample.jks created using other profiles such

as J2SE due to the limitation of the jclDesktop profile’s ability to read a keystore and vice

versa. This limitation will be removed in a future release.

CAUTION: When you select ‘Basic authentication’ as a template, the Mobile Web Services security

configuration declares username: @USERNAME@, password: @PASSWORD@ by default. To run the

292 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 303: Lotus Expeditor: Developing Applications for Lotus Expeditor

client properly, you must edit the Mobile Web Services security configuration in order to

modify these default values. Please refer to “Editing the Mobile Web Services security

configuration.”

Editing the Mobile Web Services security configuration: In order to understand how to edit the Mobile

Web Services security configuration in the working project, this section introduces four typical scenarios.

To avoid confusion, they are called Scenario #1 through Scenario #4.

Note: You cannot edit the Mobile Web Services security configuration under WTP. It is supported on

RSDP and RSA only.

v Scenario #1: Basic Authentication

The request message contains a user name token containing a plaintext password in the Security

header. The receiver checks the user name and password. If no errors are detected, it returns the

response message without any security mechanisms.

v Scenario #2: Basic Authentication with Encryption

The request message contains a user name token containing a plaintext password in the Security

header. The user name token is encrypted using a public key provided out-of-band. The receiver

decrypts the token and checks the user name and password. If no errors are detected, it returns the

response message without any security mechanisms.

v Scenario #3: Sign and Encrypt

The request message contains a body, which is signed and then encrypted. The certificate for signing is

included in the message. The certificate for encryption is provided out-of-band. The receiver decrypts

the body and then verifies the signature. If no errors are detected, it returns the response message

signing and encrypting the message body.

v Scenario #4: Signed Token

The request message contains a body, which is signed. The signature also covers the token used for

signing by means of the STR Dereference Transform. The certificate for signing is included in the

message. The receiver verifies the signature. If no errors are detected, it returns the response message

signing the message body. The signature also covers the token used for signing by means of the STR

Dereference Transform.

Editing a Mobile Web Services security configuration for basic authentication (scenario #1): Before editing the

Mobile Web Services security configuration, this scenario assumes that you selected Use template

configuration under ’How to create Web Services Security configuration’ and Basic authentication only

as a security template. To edit a Mobile Web Services security configuration in this scenario for the Web

Services client, perform the following procedure:

1. Open the WS-Security Client Editor.

2. Expand the Security Request Generator Binding Configuration section of the WS binding tab.

3. Expand the Token Generator section, select the gen_unt item in a list, and select Edit. From the next

menu:

a. Remove the existing User ID (@USERNAME@) and the existing Password (@PASSWORD@).

b. Edit an appropriate User ID and Password.

c. Select OK.4. Save your changes.

You do not need to edit a Mobile Web Services security configuration in this scenario for the Web

Services provider.

Editing a Mobile Web Services security configuration for basic authentication with encryption (scenario #2):

Before editing the Mobile Web Services security configuration, this scenario assumes that you selected

Use template configuration under ’How to create Web Services Security configuration’ and Encryption

Developing applications 293

Page 304: Lotus Expeditor: Developing Applications for Lotus Expeditor

and basic authentication as a security template. To edit the Mobile Web Services security configuration in

this scenario for the Web services client, perform the following procedure:

1. Open the WS-Security Client Editor.

2. Expand the Security Request Generator Binding Configuration of the WS binding tab.

3. Expand the Token Generator section, select the gen_unt item in a list, and select Edit. From the next

menu:

a. Remove the existing User ID (@USERNAME@) and the existing Password (@PASSWORD@).

b. Edit an appropriate User ID and Password.

c. Select OK.4. Expand the Key locators section, select the gen_klocator item in a list, and select Edit. From the next

menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias and Key name for the encryption key.

d. Select OK.5. Expand the Key information section, select the gen_enckeyinfo item in a list, and select Edit. From

the next menu:

a. Select the key name you specified as the Key name in the key locator.

b. Select OK.6. Save your changes.

To edit the Mobile Web Services security configuration in this scenario for the Web services provider,

perform the following procedure:

1. Open the WS-Security Provider Editor.

2. Expand the Request Consumer Binding Configuration Details section of the WS binding tab

3. Expand the Key Locators section, select the con_encklocator item in a list, and select Edit. From the

next menu:

a. Edit the appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit the appropriate Alias, Key pass, and Key name to specify the decryption key.

d. Select OK.4. Save your changes.

Editing a Mobile Web Services security configuration for sign and encrypt (scenario #3): Before editing the

Mobile Web Services security configuration, this scenario assumes that you selected Use template

configuration under ’How to create Web Services Security configuration’ and Signing and Encryption as

a security template. You don’t need to edit a Mobile Web Services security configuration in this scenario

for the Web Services client if you don’t use your own key store. If you want to use your own key store,

perform the following procedure:

1. Open the WS-Security Client Editor.

2. Expand the Security Request Generator Binding Configuration section from the WS binding tab.

3. Expand the Token Generator section, select the gen_dsigtgen item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit the appropriate Alias and Key name to specify the certificate to be inserted into the message.

d. Select OK.

294 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 305: Lotus Expeditor: Developing Applications for Lotus Expeditor

4. Expand the Key locators section, select the gen_klocator item in a list, and select Edit. From the next

menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias, Key pass , and Key name to specify the key used for digital signature.

d. Edit an appropriate Alias, Key pass , and Key name to specify the key used for encryption.

e. Select OK. 5. Expand the Key information section, select the gen_dsigkeyinfo item in a list, and select Edit. From

the next menu:

a. Select the key name you specified as the Key name in the key locator.

b. Select OK. 6. Expand the Key information section, select the gen_enckeyinfo item in a list, and select Edit. From

the next menu::

a. Select the key name you specified as the Key name in the key locator.

b. Select OK. 7. Expand the Security Response Consumer Binding Configuration section from the WS binding tab.

8. Expand the Trust Anchor section, select the dsigtrustanchor item in a list, and select Edit. From the

next menu:

a. Edit appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Select OK. 9. Expand the Key locators section, select the con_encklocator item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Alias, Key pass , and Key name to specify the key used for decryption.

b. Select OK.10. Save your changes.

You don’t need to edit a Mobile Web Services security configuration in this scenario for the Web Services

provider if you don’t use your own key store. If you want to use your own key store, perform the

following procedure:

1. Open the WS-Security Provider Editor.

2. Expand the Request Consumer Binding Configuration Details section from the WS binding tab.

3. Expand the Trust Anchor section, select the dsigtrustanchor item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Select OK. 4. Expand the Key locators section, select the con_encklocator item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias, Key pass, and Key name to specify the key used for decryption.

d. Select OK. 5. Expand the Response Generator Binding Configuration Details section from the WS binding tab.

6. Expand the Token Generator section, select the gen_dsigtgen item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Key store storepass and Key store path.

Developing applications 295

Page 306: Lotus Expeditor: Developing Applications for Lotus Expeditor

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias and Key name to specify the certificate to be inserted into the message.

d. Select OK. 7. Expand the Key locators section, select the gen_klocator item in a list, and select Edit. From the next

menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias, Key pass, and Key name to specify the key used for digital signature.

d. Edit an appropriate Alias, Key pass, and Key name to specify the key used for encryption.

e. Select OK. 8. Expand the Key information section, select the gen_dsigkeyinfo item in a list, and select Edit. From

the next menu:

a. Edit the key name you specified for the digital signature as the Key name in the key locator.

b. Select OK. 9. Expand the Key information section, select the gen_enckeyinfo item in a list, and select Edit:

a. Edit the key name you specified for the encryption as the Key name in the key locator.

b. Select OK.10. Save your changes.

Editing a Mobile Web Services security configuration for signed token (scenario #4): Before editing the Mobile

Web Services security configuration, this scenario assumes that you selected Use template configuration

under ’How to create Web Services Security configuration’ and Signing only as a security template. To

edit a Mobile Web Services security configuration in this scenario for the Web services client, perform the

following procedure:

1. Open the WS-Security Client Editor.

2. Expand the Request Generator Configuration section on the WS extension tab.

3. Expand the Integrity section, select the int_body item in a list, and select Add. From the next menu:

a. Select Add.

b. Select dsigkey as a Message parts keyword.

c. Select OK. 4. Expand the Response Consumer Service Configuration Details section on the WS extension tab.

5. Expand the Required Integrity section, select the reqint_body item in a list, and select Edit. From

the next menu:

a. Select Add.

b. Select dsigkey as a Message parts keyword.

c. Select OK. 6. Expand the Security Request Generator Binding Configuration section on the WS binding tab.

7. Expand the Token Generator section, select the gen_dsigtgen item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias and Key name to specify the certificate to be inserted into the message.

d. Select OK. 8. Expand the Key locators section, select the gen_klocator item in a list, and select Edit. From the next

menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

296 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 307: Lotus Expeditor: Developing Applications for Lotus Expeditor

c. Edit appropriate Alias, Key pass , and Key name to specify the key used for digital signature.

d. Select OK. 9. Expand the Signing Information section.

10. Expand the Part References section under the Signing Information section and select Add. From the

next menu:

a. Input an appropriate Part reference name.

b. Select the integrity name you specified as the Integrity part.

c. Select http://www.w3.org/2000/09/xmldsig#sha1 as a Digest method algorithm.

d. Select OK.11. Expand the Transforms section under the Signing Information section and select Add. From the next

menu:

a. Input an appropriate Name.

b. Select http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform as an Algorithm.

c. Select OK.12. Select Add again. From the next menu:

a. Input an appropriate Name.

b. Select http://www.w3.org/2001/10/xml-exc-c14n# as an Algorithm.

c. Select OK.13. Expand the Security Response Consumer Binding Configuration section on the WS binding tab.

14. Expand the Trust Anchor section, select the dsigtrustanchor item in a list, and select Edit. From the

next menu:

a. Edit appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Select OK.15. Expand the Signing Information section.

16. Expand the Part References section from the Signing Information section and select Add. From the

next menu:

a. Input an appropriate Part reference name.

b. Select the required integrity name you specified as the Required Integrity part.

c. Select http://www.w3.org/2000/09/xmldsig#sha1 as a Digest method algorithm.

d. Select OK.17. Select Add again. From the next menu:

a. Input an appropriate Name.

b. Select http://www.w3.org/2001/10/xml-exc-c14n# as a Algorithm.

c. Select OK.18. Expand the Transforms section under the Signing Information section and select Add. From the next

menu:

a. Input an appropriate Name.

b. Select http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform as a Algorithm.

c. Select OK.19. Save your changes.

To edit a Mobile Web Services security configuration in this scenario for the Web services provider,

perform the following procedure:

1. Open the WS-Security Provider Editor.

Developing applications 297

Page 308: Lotus Expeditor: Developing Applications for Lotus Expeditor

2. Expand the Request Consumer Service Configuration Details section on the WS extension tab.

3. Expand the Required Integrity section, select the reqint_body item in a list, and select Edit. From

the next menu:

a. Select Add.

b. Select dsigkey as a Message parts keyword.

c. Select OK. 4. Expand the Response Generator Service Configuration Details section on the WS extension tab.

5. Expand the Integrity section, select the int_body item in a list, and select Add. From the next menu:

a. Select Add.

b. Select dsigkey as a Message parts keyword.

c. Select OK

6. Expand the Request Consumer Binding Configuration Details on the WS binding tab.

7. Expand the Trust Anchor section and select Edit. From the next menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Select OK. 8. Expand the Signing Information section.

9. Expand the Part References section from the Signing Information section and select Add. From the

next menu:

a. Input an appropriate Part reference name.

b. Select the required integrity name you specified as the Required Integrity part.

c. Select http://www.w3.org/2000/09/xmldsig#sha1 as a Digest method algorithm.

d. Select OK.10. Expand the Transforms section from the Signing Information section and select Add. From the next

menu:

a. Input an appropriate Name.

b. Select http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform as an Algorithm.

c. Select OK.11. Select Add again. From the next menu:

a. Input an appropriate Name.

b. Select http://www.w3.org/2001/10/xml-exc-c14n# as an Algorithm.

c. Select OK.12. Expand the Response Generator Binding Configuration Details section on the WS binding tab.

13. Expand the Token Generator section, select the gen_dsigtgen item in a list, and select Edit. From the

next menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias and Key name to specify the certificate to be inserted into the message.

d. Select OK.14. Expand the Key locators section, select the gen_klocator item in a list, and select Edit. From the next

menu:

a. Edit an appropriate Key store storepass and Key store path.

b. Select JKS or JCEKS as a Key store type.

c. Edit an appropriate Alias, Key pass , and Key name to specify the key used for digital signature.

d. Select OK.

298 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 309: Lotus Expeditor: Developing Applications for Lotus Expeditor

15. Expand the Key information section, select the gen_dsigkeyinfo item in a list, and select Edit. From

the next menu:

a. Edit the key name you specified for the digital signature as the Key name.

b. Select OK.16. Expand the Signing Information section.

17. Expand the Part References section from the Signing Information section and select Add. From the

next menu:

a. Input an appropriate Part reference name.

b. Select the integrity name you specified as the Integrity part.

c. Select http://www.w3.org/2000/09/xmldsig#sha1 as a Digest method algorithm.

d. Select OK.18. Expand the Transforms section from the Signing Information section and select Add. From the next

menu:

a. Input an appropriate Name.

b. Select http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform as a Algorithm.

c. Select OK.19. Select Add again. From the next menu:

a. Input an appropriate Name.

b. Select http://www.w3.org/2001/10/xml-exc-c14n# as a Algorithm.

c. Select OK.20. Save your changes.

Deploying Mobile Web Services

Web services applications are deployed as OSGi bundles / Eclipse plug-ins. They run in the Lotus

Expeditor runtime platform and require no extra special handling.

Note: If you intend to deploy a Web service client and a Web service provider in the same runtime,,two

different mechanisms can be adopted to avoid any runtime conflicts within OSGi.

v Export the service interface package from the Web service provider MANIFEST.MF and import the

same package in the Web service client MANIFEST.MF

v Another option is to place the Web service client stub in a package that is different from the

package of the Web service provider. Please refer to “Creating Mobile Web Services clients” on

page 277 for information on how to provide a different package name.

Note: If your Web service provider or client needs to handle XML control characters, the data must not

be encoded as a string or a runtime exception will occur. To allow your Web service provider or

client to handle XML control characters, you must use a different encoding such as byte[].

Deploying Mobile Web Services providers: In order to deploy a Web Services provider, launch an

instance of the Lotus Expeditor runtime with the Web Services provider plug-in installed.

Following are the steps to deploy a Web services provider from the IDE:

1. From the IDE, run the Web services provider plug-in:

a. Select Run > Run.

b. Create a new Lotus Expeditor instance if necessary.

c. In the Plug-ins tab, ensure that your Web services provider plug-in is checked.

d. Select Run.

e. At the osgi> prompt in the Console view, type ss to display a list of all registered bundles and

their associated IDs. From the list, find the bundle ID for your Web services provider plug-in.

Developing applications 299

Page 310: Lotus Expeditor: Developing Applications for Lotus Expeditor

f. At the osgi> prompt in the Console view, type start <bundle ID>, where <bundle ID> is the

bundle ID for your Web services provider plug-in. This results in a call to the exposeService()

method of the Web services provider, and its WSDL will be immediately available for client use.2. Verify that the Web services provider has started successfully:

From a browser, enter the following URL:

http://<machine>:<port>/ws/pid/<servicepid>?wsdl

where <machine> is the name of the machine hosting the Web services provider, <port> is the port

used by the Web container (see Note below), and <servicepid> is the name used to register the Web

services provider (by default it is the base name of the class that implements the exposed Java

interface).

For example, if the machine hosting the Web service is the local host, the Web container is listening on

port 1477, and the Java interface used to expose the Web service provider is MyWebServiceImp1, the

WSDL URL will be:

http://localhost:1477/ws/pid/MyWebServiceImpl?wsdl

Note: Since by default the Web container port is dynamically selected by the Lotus Expeditor

runtime, refer to the Web Container Configuration section in the documentation Assembling

and Deploying Lotus Expeditor Applications in order to find the chosen port or to bind the Web

container to a static port instead. If the service is deployed in the same runtime environment,

and a dynamic port is preferred, you can refer to the section Static Mobile Web Services clients

to learn how to write a Web services client that can programmatically retrieve the chosen port.

There are two properties you may change in the OSGi service:

v com.ibm.pvcws.wsdl: The value for this property is either an empty String, or a String containing the

actual WSDL (not a URL to the WSDL, as above).

When set as an empty String, it indicates that the service should be exposed as a Web Service, and the

WSDL should be generated dynamically. You can also pass a String containing the WSDL that describes

the Web Service if the WSDL must be of a form that cannot be auto generated.

If you do not use the empty String, the WSDL must have a location attribute. The value of the location

attribute is unimportant since the Gateway will correct the location when it is served to clients.

v org.osgi.framework.Constants.SERVICE_PID: This is an optional String that can be used to change the

service PID URL part of the Web service WSDL. If changed, make sure to pass the same string to the

exportPid invocation within the exposeService method.

Deploying Mobile Web Services clients: In order to deploy a Web Services client, you must ensure that

the client implementation has been completed prior to launching an instance of the Lotus Expeditor

runtime with the Web Services client plug-in installed.

If you generated Web Services client code that is static you must instantiate the generated Soap_Stub

object and then call the methods you wish to exercise. Please refer to the section “Static Mobile Web

Services clients” on page 278 for information on how to complete a static Web Services client.

If you generated Web Services client code that is dynamic or that requires custom marshalling, you will

need to access the Web Service using the Gateway plug-in. Please refer to the sections “Dynamic Mobile

Web Services clients” on page 281 and “Custom serialization (marshalling)” on page 283 for information

on how to complete a dynamic Web Services client.

Once the client code is complete, launch an instance of the Lotus Expeditor runtime with the Web

Services client plug-in installed and ensure that the appropriate code gets executed to invoke the Web

Services provider.

Note: If you get an exception with the message “Parsing of the specified WSDL failed” followed by an

explanation, ensure that the WSDL is accessible through a browser. This exception could either be

300 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 311: Lotus Expeditor: Developing Applications for Lotus Expeditor

the result of a firewall message in HTML-form requiring authentication, or could be due to an

invalid WSDL. Please consult with your administrator.

Note: When deploying a Mobile Web service client for communicating with a Web service provider that

references byte arrays, you may need to differentiate between WSDLs that map byte arrays to

either byte unbounded or to base64Binary. You can set the

javax.xml.rpc.Stub.BYTE_ARRAY_ENCODING property to byteUnbounded or base64Binary depending

on your needs. If the property is not set, the client will encode byte arrays using base64Binary.

For example:

// static client

stub._setProperty(javax.xml.rpc.Stub.BYTE_ARRAY_ENCODING,

javax.xml.rpc.Stub.BYTE_UNBOUNDED);

// dynamic client

Dictionary props = new Hashtable();

props.put(javax.xml.rpc.Stub.BYTE_ARRAY_ENCODING,

javax.xml.rpc.Stub.BYTE_UNBOUNDED);

WSProxyService wsImpl =

(WSProxyService)bundleContext.getService(serviceReference);

if (wsImpl == null) {

System.err.println("Unable to find service Web service proxy");

return;

}

if (!wsImpl.register(wsdl, props)) {

System.err.println("Unable to consume WSDL");

return;

}

Note: When deploying a Mobile Web service client for communicating with a Web service provider

hosted in WebSphere Application Server 5.1 that references Hashtables or HashMaps, you may need

to set the javax.xml.rpc.Stub.KEY_VAL_FULLY_QUALIFIED property to “false” (see the previous Note

for an example). This will allow the proper SOAP decoding of the mentioned types. By default,

this property is not set.

Axis Web Services

The Lotus Expeditor Toolkit can be used to generate the Apache Axis based Web Services client code that

calls the Web Services providers via a static stub. The JAX-RPC (JSR-101) support is enabled using the

Apache Axis 1.3.

Developers who wish to develop JSR-101 based Web Services clients are able to do so using the modified

version of the WTP tools provided with the Lotus Expeditor Toolkit and the Apache Axis 1.3 runtime

bundled in Lotus Expeditor v6.1. The role for using the Apache Axis runtime is strictly for Client-Side

only. Also there is very minimal security supported. If the security is needed, SSL & Basic Authentication

must be used. A minimal support from the WS-Security specifications (User name Token) is provided

when locating the static stub object using the JNDI. You can find more information on Client-Side Axis

support on the Apache Axis web site at http://ws.apache.org/axis/java/client-side-axis.html.

Creating Axis Web Services

This section provides information on creating Axis Web Services.

Creating an Apache Axis based Web Services client: Following are the steps to create Apache Axis

based static client stubs:

1. Create a Client Services project. Please refer to “Creating a Client Services project” on page 19. Or

convert the project to a Client Services Project using Lotus Expeditor Toolkit, if needed:

Developing applications 301

Page 312: Lotus Expeditor: Developing Applications for Lotus Expeditor

a. Select File > New > Project.

b. Select Client Services > Client Services Project.

c. Select Next.

d. Type a name for the new project (for example, MyWebServicesClient).

e. Select Next.

f. Select Next.

g. Select Finish.A Client Services project is generated in your workspace.

2. Select File > New > Other >Web Services > Web Service Client. Click Next.

3. Input the WSDL location in the Service definition filed and select the Java Proxy as the Client type.

4. Select Client Services v6.1 as a Server and the Apache Axis for Client Services as the runtime.

5. Choose the existing Client Services project that you created above as the Client project.

6. Set the slider bar to Develop as the level for client generation. Uncheck Monitor the Web Service, as

this option is not supported at this time.

7. Click Next to select the output Folder and configure the package to namespace mapping, and then

Finish. Or just click Finish to use the defaults.

Typically, a client would perform the following steps to communicate with the remote service:

1. Obtain an instance of the interface stub.

2. Set the endpoint property of the stub to point to the service endpoint of the Web service.

3. Invoke the remote method.

In Lotus Expeditor, there are two ways to access the Web Services client stub from a client application:

1. By directly obtaining an instance of the interface stub.

2. By using the JNDI to lookup an instance of the interface stub.

Directly obtaining an instance of the interface stub: This option is used when the client has all the

information necessary to communicate with the remote service at compile time and does not have to rely

on the accounts to provide any information. It does not provide support for User name and LTPA Token

for SOAP messages. It should be used when no security is required.

No specific steps are needed before obtaining a stub instance using this mechanism. If the stub is

packaged in a different plug-in than the client, the plug-in is required to export the package so the client

can access it.

For example:

EchoServiceService service = new EchoServiceServiceLocator();

//endpoint address

URL endpoint =

new URL(http://localhost/EchoService/services/EchoService);

//get a stub which implements the SDI

EchoService stub = service.getEchoService(endpoint);

// invoke the remote method

stub.echoString("echo: Hello from EchoService");

Obtaining an instance of the interface stub using the JNDI mechanism: Using this option will provide

a full support of our platform which would integrate the stub instance with the Accounts & the Netfaults

framework. It allows the clients to obtain an initialized stub with properties like the endpoint address,

security property for User name Token & LTPA based authentication. These properties can be stored in

302 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 313: Lotus Expeditor: Developing Applications for Lotus Expeditor

user accounts. Now at runtime, the stub instance reads the properties from the accounts to invoke the

Web service. This mechanism is useful when multiple clients need to share the same service interface

object in the Lotus Expeditor runtime.

An example:

InitialContext ic = new InitialContext();

//JNDI lookup for the stub instance

EchoService stub = (EchoService)ic.lookup

("com.ibm.test.EchoService);

To be able to lookup an instance of the interface stub using JNDI, there are some requirements:

v Two extensions must be defined that provide the binding information for WSObjectFactory and the

service interface and account information for the proxy

v An account must be created with information such as Account name, endpoint, authentication type,

and so on

Defining the extensions to register the Service Interface to JNDI provider: The WSObjectFactory is

responsible for providing a pre-initialized instance of web services client stub for Apache Axis in the

Lotus Expeditor runtime. Upon a client lookup of the client stub using JNDI, the JNDI provider will use

the WSObjectFactory to locate the Web service stub based on the extension definition, which in turn will

cause the stub to initialize and be bound into JNDI.

The Lotus Expeditor Toolkit automatically generates the appropriate plugin.xml entries for the stub as a

part of the development process. The stub developer or the deployer will be required to fill in

appropriate values.

The following example shows how to register the service interface with the Wsfactoryobject.

<extension point="com.ibm.pvc.jndi.provider.java.binding">

<binding jndi-name="com.ibm.test.EchoService"

objectFactory-id= "com.ibm.rcp.ws.objectfactory.WSObjectFactory">

</binding>

</extension>

<extension point="com.ibm.rcp.ws.objectfactory.WSfactoryobject">

<WSobject

account-key="account-name"

class="com.ibm.test.EchoService"

jndi-name="com.ibm.test.EchoService">

</WSobject>

</extension>

Where:

v account-key is the name of the account.

v class is the class name of the service interface.

v jndi-name is the name client will use to lookup the stub instance

Setting the account key programmatically: Currently, the account-key is provided declaratively in

plugin.xml. One can also override the account key provided in the plugin.xml file at runtime during the

JNDI lookup as shown below.

For example:

InitialContext ic = new InitialContext();

EchoService stub = (EchoService)ic.lookup

("com.ibm.test.EchoService@account_name);

Where <account_name> is the name of the account.

Developing applications 303

Page 314: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: This feature is not available for the beta release.

Programmatically creating accounts for Apache Axis Web Services clients: One can create an account

programmatically that will be used by Axis. Here is an example that shows an account creation and

setting the values of various account attributes:

AccountsManager manager =

AccountsManagerFactory.getAccountsManager();

Account account =

manager.newAccount(AccountsManager.DEFAULT_ACCOUNT);

account.setName( Echo Service Account);

account.setType( HTTP);

account.setAuthType( HTTP);

account.setProperty( AuthProperties.SERVER,

http://localhost:9082/EchoService/services/EchoService);

//This can be set programmatically or

//If not set, the Accounts framework will prompt at runtime

account.setProperty(Account.USER_NAME, "user1");

account.getLoginContext().setPassword("password");

Where:

v setName sets the name of the account and that becomes the <account_key>. This is required.

v setType is the Type of the account. This must be HTTP and is required. AuthProperties.SERVER allows

you to set the compete endpoint URL of the Web Service. This must be provided and is required.

v setAuthType is the type of the authentication used with this account. Possible values are:

– HTTP - For Basic Authentication

– J2EE-FORM - For LTPA Token (WAS 6.x/WPS 6.x), also referred to as BinaryToken in the

WS-Security specs.

An empty string with no authentication information. Not setting the authType will default to HTTP.

So, the empty string must be set if no authentication is required.

– USERNAME_TOKEN - This is for Basic Authentication at the SOAP level. The User ID and

password are sent inside the SOAP message in plain text. This can only be set in a secondary

account.v AuthProperties.AUTH_SERVER allows you to set the authentication URI from where the LTPA token

can be obtained. In the case of WebSphere Application Server V6, it is /j_security_check. This

property only needs to be set when setting the authType to J2EE-FORM.

When the LTPA Token is expected by the server, the authentication type needs be set to J2EE-FORM in the

account and the authentication server needs to be set as well as shown below.

account.setAuthType(J2EE-FORM);

account.setProperty(AuthProperties.AUTH_SERVER, j_security_check);

When authentication type is set to USERNAME_TOKEN, it is required that the account is tied to a primary

account that has authentication type of HTTP or J2EE-FORM.

account2.setType( "HTTP");

account2.setAuthType( "USERNAME_TOKEN");

//setting the primary account for a account

account2.setProperty(Account.MASTER_PROPS, account.getUID());

Where account is the primary account and account2 is the secondary account for USERNAME_TOKEN.

For more detailed API information, please refer to the Accounts API. Above gives you enough to create

an account that will work with Axis.

Note: Attachments are not supported in SOAP messages.

304 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 315: Lotus Expeditor: Developing Applications for Lotus Expeditor

Developing wired applications

This section provides information on wired application development.

Portlet communication

The Portlet Container provides the capability for portlets to communicate with each other and eclipse

components using the Property Broker component. Portlet communication can be split up into three

categories:

1. Portlet-to-Portlet: This is JSR 168 inter-portlet communication. When an action is invoked on a JSR

168 portlet the Portlet Container determines the target JSR 168 portlet (s) and invokes the

processAction() method of the target JSR 168 portlet(s).

2. Portlet-to-Eclipse: This is the communication between a JSR 168 portlet and an eclipse component.

The eclipse components must have an action handler registered with the Property Broker. When an

action is invoked on a JSR168 portlet the Portlet Container determines the action and fires a

propertyChanged event through the Property Broker. The Property Broker determines the wires and

invokes the action handler of the target eclipse component.

3. Eclipse–to-Portlet: This is the communication between an eclipse component and a JSR 168 portlet.

The eclipse component must have an action handler that registered with the Property Broker. When

an action is invoked on an eclipse component, the component initiates a propertyChanged event

through the Property Broker. The broker determines the wires, and invokes the action handler of the

target JSR 168 portlet.

Defining actions and properties

The first requirement for inter-portlet and portlet-to-eclipse communication is to define the WSDL file

that declares the actions and properties of the portlets or eclipse components with the Property Broker.

The basic WSDL for the property broker is identical to that of Portal. The namespace and bindings should

all be consistent with any WSDL used to define properties and actions on Portal.

The WSDL file should be contributed to the Lotus Expeditor platform using an eclipse extension. This

extension is registered with the broker.

To wire two portlets or a portlet and an eclipse component, perform the following procedure:

1. Select a Client Services Portlet project or Client Services plug-in project you wish to add the WSDL

file to.

2. Right click the Client Services portlet project and select New > Other > XML > WSDL to create a new

WSDL file. Create the new WSDL file in the Web Content directory of the project.

3. Select Next.

4. Enter the name of the Client Services project you wish to add the WSDL file to.

5. Select Next.

6. Set the target namespace to http://www.ibm.com/wps/c2a. Use defaults for all other options.

7. Select Finish.

8. Right click the WSDL file and select Open With > WSDL Editor to edit the new WSDL file. Things to

remember when editing the WSDL file:

v <wsdl:types> elements are registered with the Property Broker and mapped to actions

v <wsdl:message> elements must reference a valid <wsdl:type>

v The name of the <wsdl:portType> element will be used to map the action to the operation

v <wsdl:binding> elements are used to define binding of the action to its input and output

parameters. The <input> and <output> elements are used to link the action to a <wsdl:type>

v The name of the <portlet:action> element is registered with the Property Broker. Wire definitions

should reference this name (see below).9. Add the required actions and properties to the WSDL file and save the WSDL file.

Developing applications 305

Page 316: Lotus Expeditor: Developing Applications for Lotus Expeditor

To register the WSDL file with the Property Broker, perform the following procedure:

1. Select the Client Services Portlet project that contains the WSDL file you want to register with the

Property Broker.

2. Right click the portlet.xml descriptor and select Open With > XML Editor.

3. Add the location of the WSDL as a portlet preference. The preference name must be

com.ibm.portal.propertybroker.wsdllocation, the value of the preference must be a valid location in

the portlet project. An example preference definition would look like this:

<portlet-preferences>

<preference>

<name>com.ibm.portal.propertybroker.wsdllocation</name>

<value>/wsdl/example.wsdl</value>

<read-only>true</read-only>

</preference>

</portlet-preferences>

Wiring portlets

The second requirement for inter-portlet communication or portlet-to-eclipse communication is to define

the wires between the source and target components. Wires can be defined and contributed to the Lotus

Expeditor platform in two ways:

1. In the Portal-managed environment, the wires should be created using the Portlet Wiring Tool. The

wire information will be stored in the Composite Application (CA) XML file and passed down to the

Lotus Expeditor platform through the Composite Application Infrastructure. The wires from the CA

XML file will be translated to a Property Broker wire by the Topology Handler.

2. In the non Portal managed environment, the wire can be defined and contributed using the Property

Broker wire extension point – com.ibm.rcp.propertybroker.PropertyBrokerWire.

To declaratively register the wire definitions with the Property Broker, perform the following procedure:

1. Select the Client Services Portlet project you want to add the wire definitions to.

2. Right click the plugin.xml descriptor file and select Open With > Plug-in Manifest Editor.

3. Select the Extensions tab.

4. Select Add.

5. Locate the com.ibm.rcp.propertybroker.PropertyBrokerWire extension point and select Finish.

6. Update the <wire> element attributes.

7. Save the plugin.xml file

Wire extension examples

The following are sample declarative wire definitions:

Portlet-to-Portlet Wire

<extension id="com.ibm.rcp.portlet.wire"

name="Portlet Wire"

point="com.ibm.rcp.propertybroker.PropertyBrokerWire">

<wire sourceparam=""

title=""

ordinal=""

type="PROPERTY_TO_ACTION"

sourcename="p2psample3_search_text"

targetparam="p2psample3_search_text"

targetentityid="/PortletCommunication/P2PSearchResult Portlet/default"

sourceentityid="/PortletCommunication/P2P QuickSearch/default"

targetname="P2PSearchResultAction"/>

</extension>

Portlet-to-Eclipse Wire

306 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 317: Lotus Expeditor: Developing Applications for Lotus Expeditor

<extension id="com.ibm.pvc.portlet.wire"

name="Portlet Wire"

point="com.ibm.rcp.propertybroker.PropertyBrokerWire">

<wire sourceparam=""

title=""

ordinal=""

type="PROPERTY_TO_ACTION"

sourcename="SearchText"

targetparam="result_text_to_plugin_B"

targetentityid="com.boa.teller.PluginB"

sourceentityid="/Portlet_Basic_Communication/PortletA/default"

targetname="ResultActionToPluginB"/>

</extension>

Eclipse-to-Portlet Wire

<extension id="com.ibm.pvc.portlet.wire"

name="Portlet Wire"

point="com.ibm.rcp.propertybroker.PropertyBrokerWire">

<wire sourceparam=""

title=""

ordinal=""

type="PROPERTY_TO_ACTION"

sourcename="search_text_to_portlet"

targetparam="ResultText"

targetentityid="/Portlet_Communication_E2P_Portlet/PortletB/default"

sourceentityid="com.boa.teller.PluginA"

targetname="ResultAction"/>

</extension>

The required fields are:

v type - type of the wire. For inter-portlet as well as portlet-to-eclipse communication, the type must be

″PROPERTY_TO_ACTION″.

v sourceentityid - the name of the source. If the source is an eclipse component, the value of this field is

the eclipse view ID. If the source is a JSR 168 portlet, the value of this field is the URI of the source

portlet window. The URI is comprised of the context root, portlet name, and portlet window name

v targetentityid - the name of the target. If the target is a JSR 168 portlet, the value of this field is the

URI of the target portlet window. The URI is comprised of the context root, portlet name, and portlet

window name. If the target is an eclipse component, the value of this field is the eclipse view ID.

v targetname - the name of the target action. The value must come from the WSDL of the target portlet,

and it is the name attribute of the <portlet:action> element.

v sourceparam - the name of the source parameter. The value must come from the WSDL of the source

portlet or eclipse component, and it is the name of the <portlet:param> element in the output section.

v targetparam - the name of the target parameter. The value must come from the WSDL of the target

portlet or eclipse component, and it is the name of the <portlet:param> element in the input section.

Using the portlet wiring tool

To create cross-page wires between your portlets, you must use the portlet wiring tool to make your

actions global. From the tool, select Manage Actions, and then select the Global checkbox.

Creating Cooperative Components with the Lotus Expeditor Property

Broker

The client property broker is a broker that allows for declarative properties, actions, and wires to be used

among completely decoupled components. The property broker is responsible for taking changed

properties and distributing the property values to the appropriate actions as defined by the wires that are

registered. The property broker separates itself from a traditional pub/sub in that it is a controlled

pub/sub that is driven by declarative markup. Meaning an XML or another data source defines how the

two components communicate with each – which property change is passed onto which action within the

Developing applications 307

Page 318: Lotus Expeditor: Developing Applications for Lotus Expeditor

component. The second differentiation is the chain effect that can be accomplished by taking input

parameters and posting output parameters. This ability allows for an infinite amount of Property >

Action > Property combinations.

Components that contribute to the broker most likely do not call into the API’s directly, and instead use

the extension point and the declarative WSDL to declare its actions and properties. The preferred model

allows as little knowledge of the broker and its API’s providing a good level of abstraction from the

broker implementation. At most, a component calls into the broker to post a changed property and then

performs an evaluation of the received property changes to complete the action on the changed property.

Lastly, the client side broker was designed after the IBM Portal property broker, but includes a level of

flexibility above and beyond the portal broker. The client broker allows for different kinds of components

to be contributing to the broker; different components as in SWT, AWT, Eclipse commands, OSGI Event

Admin, etc. This allows for currently established actions to participate in broker communications. The

framework allows for new handlers to be defined using an Eclipse extension point; giving the broker

complete adaptability and compatibility with other messaging systems.

Creating your components

Your components can be defined at many levels with the out of the box functionality of the Lotus

Expeditor broker. The broker supports core Eclipse commands that implement the IHandler

(org.eclipse.core.commands.IHandler) interface.

The Eclipse IHandler interface should be used in the case your application can not depend on any

features that require user interface packages. Use this implementation if your product runs in a device

that does not have SWT or AWT available. The property broker has no UI dependencies and can function

on a device with no UI abilities. The IHandler interface provides a method called execute() you must

implement. The PropertyChangeEvent is set as the event trigger and can be accessed by calling

ExecutionEvent.getTrigger(). The following some sample code processes a property broker change event

in an Eclipse IHandler action:

public Object execute(ExecutionEvent event) throws ExecutionException

{

if (event.getTrigger() instanceof PropertyChangeEvent){

final Display display = Display.getDefault();

final PropertyChangeEvent pce = PropertyChangeEvent)event.getTrigger();

...

}

}

The code to publish a property change is relatively straight forward. An SWT component should use the

SWTHelper (com.ibm.rcp.propertybroker.swt.api.SWTHelper) class to publish its properties. This helper

class removes the complexity of identifying the SWT View instance the property came from by having the

caller simply pass in a this pointer to the view. Here is some sample code where a URL is published on

the broker from an SWT based view:

PropertyValue value = PropertyFactory.createPropertyValue(prop, selection);

SWTHelper.changedProperties(new PropertyValue[]{value}, this);

The core broker also has a version of the changedProperties() method where a Java String is passed in

as the owner context of the property change. The string should match the EntityID of the source in the

wire. This is where the property broker does the run time resolution of a specific instances property

change to a specific instances action.

Since the action code is also a single class there is some coding that must be done in order to make sure

the correct view is updated when a property change has occurred. The SWTHelper has methods to assist in

getting the correct ViewPart.

308 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 319: Lotus Expeditor: Developing Applications for Lotus Expeditor

public void runWithEvent(Event event) {

//Make sure the Event is from the Property Broker

if (event instanceof PropertyChangeEvent){

final Display display = Display.getDefault();

final PropertyChangeEvent finalEvent = (PropertyChangeEvent)event;

display.asyncExec(new Runnable() {

public void run( ) {

//Get the wire definition from the event

Wire def = finalEvent.getWireDefinition();

//Our view object type

PreviewView pView = null;

//view for this action.

PreviewView pView =

(PreviewView)SWTHelper.locateView(def.getTargetEntityId());

...

}

Registering your definitions with the broker

Now that you have defined the concrete class that will be called by the broker for a property change, you

must register the action with the broker using the PropertyBrokerDefinitions extension point. This

extension point will register your action and also the input and output parameters of the action. Each

action cannot only receive one input property change, but also post as many output property changes as

needed. This is a key difference from a traditional pub sub. This means when you action is called by the

broker, it simply adds output properties to the passed in PropertyChangeEvent object by calling

addOutputProperty().

The schema definition of the PropertyBrokerDefinitions extension point has three primary fields:

v Class – Optional Java class that will be instantiated by the broker and should implement one of the

supported handler interfaces (Command, SWT, AWT).

v File – The Web Services Definition Language (WSDL) file that defines the action name, input and

output properties.

v Type – The type of action to be registered, for instance COMMAND, SWT_ACTION

– Map Element

- wsdlActionName - The ID of the action in the WSDL.

- actionID - The ID of the action in the Eclipse system.

- class - Optional class implementation for this specific action. If this class is specified, the property

broker will instantiate the object and contain it with the Action definition. The object will then be

called by the appropriate handler.

Working with the Property Broker WSDL file

The WSDL file is a base WSDL implementation with custom bindings defined. Since this WSDL file must

be compatible with the portal WSDL file we use the exact syntax on the client as we do in the Portal

server. This will be a big benefit when we talk about using the declarative wiring in Portal.

The following is a complete sample of a WSDL file where we define a single action, three base parameter

types, one input parameter and two output parameters:

Action name=produceURL

Input Param=URL,

type=tns:BaseURL

Output Param 1=URL From Tree

type=tns:BaseURL

Output Param 2=Progress

Developing applications 309

Page 320: Lotus Expeditor: Developing Applications for Lotus Expeditor

type=tns:Progress

<definitions name="LoadURLInBrowser_Service"

targetNamespace="http://www.ibm.com/wps/c2a"

xmlns="http://schemas.xmlsoap.org/wsdl/"

xmlns:portlet="http://www.ibm.com/wps/c2a"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns:tns="http://www.ibm.com/wps/c2a"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<types>

<xsd:schema targetNamespace="http://www.ibm.com/wps/c2a">

<xsd:simpleType name="BaseURL">

<xsd:restriction base="xsd:string">

</xsd:restriction>

</xsd:simpleType>

<xsd:simpleType name="Progress">

<xsd:restriction base="xsd:string">

</xsd:restriction>

</xsd:simpleType>

</xsd:schema>

</types>

<message name="LoadURLRequest">

<part name="urlFromTree" type="tns:BaseURL"/>

</message>

<message name="OurResponse">

<part name="loadedURL" type="tns:BaseURL"/>

<part name="progress" type="tns:Progress"/>

</message>

<portType name="LoadURL_Service">

<operation name="loadURL_Operation">

<input message="tns:LoadURLRequest"/>

<output message="tns:OurResponse"/>

</operation>

</portType>

<binding name="ManyOutParamsBinding" type="tns:LoadURL_Service">

<portlet:binding/>

<operation name="loadURL_Operation">

<portlet:action name="produceURL"

type="standard"

caption="Load the new URL"

description="Load.a.new.url.in.the.main.window"

actionNameParameter="ACTION_NAME"/>

<input>

<portlet:param name="URL" partname="urlFromTree" caption="url.loader"/>

</input>

<output>

<portlet:param name="URL From Tree" partname="loadedURL" caption="Browser URL"/>

<portlet:param name="Progress" partname="progress" caption="Browser Progress"/>

</output>

</operation>

</binding>

</definitions>

310 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 321: Lotus Expeditor: Developing Applications for Lotus Expeditor

Using the Composite Application Infrastructure

In most cases you should be using Portal to define your wires however if you are creating components

for Lotus Notes® you can use the client side Composite Application Editor to create your applications in

Eclipse and have them deployed to Portal or Domino. Both options are fine and both are completely

compatible. In this section we focus on using the portal admin tools to create an application that will

define pages with our portlets on them and the application is then installed onto the Lotus Expeditor

Client using the Composite Application Portal catalog.

Both tools provide a visual editor to layout your components and then wire them together. This is the

point in the application development where an application aggregator pieces the separate components

together to give them context within a defined solution, and why it is important to create your

components in a completely decoupled fashion where they can be used under different contexts.

Declarative wiring with the Portal Admin tool

Now that you have a client side component that can register its actions you will want to deploy a portlet

that contains the same WSDL file onto your portal server. By having a portlet register the properties and

actions on the portal server you will be able to use the portal wiring tool to define the wires between

your components. This of course is only one option and the focus of this section is to use declarative

wiring in the Composite Application Infrastructure (CAI). CAI gives the client the ability to connect to a

portal and install an application that is defined with the template application model. The wiring

information for the portlet instances is contained within this markup and will allow the CAI client code

to wire the components together declaratively. Another option is to wire your components using the

PropertyBrokerWire extension point. Under the covers the CAI code uses this extension point by

providing dynamic extensions to it.

You can create your portlets with whatever tool you wish. For the basic broker to work on the client the

portlet does not have to really do anything so creating a “stub portlet” by using the samples in Rational

Application Developer you can simply add your WSDL to the portlet and register the actions and

properties. The Lotus Expeditor does however support locally running JSR 168 portlets that can

intercommunicate with any other registered component with the broker. What this means is you can have

an SWT version of your component and/or a portlet version of your component and deploy them to the

client under different contexts. Once your portlet is created and you export your portlet as a WAR file

you simply import the WAR file into your portal server.

When you put the portlet on a page you can now wire the components together using the normal Portal

Wiring tool. The Lotus Expeditor also supports cross page wiring however in order to enable an action

for cross page wiring you need to mark the action as a ‘Global Action’ using the Manage Actions button

on the wiring screen.

From the wiring tool; you simply select the source portlet, the output property, the target page (defaults

to current), the target portlet, the target property and whether or not this wire is public or private.

Specifying a custom owner for your SWT action

The property broker automatically assigns the plug-in ID as the owner of the action by knowing what

plug-in registered the extension. In the rare case where you need to override what the owner is you can

simply map the instance of the view to a new custom defined owner. This gives generic containers like

the JSR 168 container and the Lotus Notes composite application plug-in the ability to override the action

and specify a domain specific owner. In the case of Lotus Notes for instance they use the replication ID of

the database the action is contained in for the owner.

public void addInstanceToOwner(String instance, Object owner);

The addInstanceToOwner() call now maps the specific view instance with a specific new owner. Now,

during runtime resolution of wiring, the correct instance will be called with the proper action and owner

information.

Developing applications 311

Page 322: Lotus Expeditor: Developing Applications for Lotus Expeditor

Developing for serviceability

This section provides information on developing applications for serviceability.

Understanding serviceability

Most application development environments provide APIs to support the creation and logging of

messages. The OSGi framework, Eclipse framework and the 1.4 JDK (JSR47) all provide different systems

for logging messages. Due to this variety of logging and tracing options, in the Lotus Expeditor runtime,

OSGi bundles, Eclipse applications and standard Java components use different methods to record log

messages. Other groups such as the Apache open source group have also created façade APIs to help

abstract their developers from one specific logging implementation. The Apache commons logging APIs,

for example, support applications written to these facades in the Lotus Expeditor runtime, and will be

redirected to the JSR47 logger for formatting and persistence.

The selection of the appropriate logging APIs is an application specific task in the Lotus Expeditor

runtime. In some cases it is quite simple to determine the best candidate for logging APIs, such as an

eclipse application, which will already be reliant on eclipse APIs, in this case the Eclipse logging APIs

would be the most appropriate choice. In the case of a pure OSGi application with no other eclipse

dependency, it may be most appropriate to use the OSGi LogService to continue to support independence

from the Eclipse APIs and allow the pure OSGi application to execute on OSGi frameworks besides the

Lotus Expeditor runtime which is based on the Eclipse implementation of the OSGi runtime. Finally, if

the application has code leveraging the JRE logging APIs there is no reason to attempt to modify the

application to leverage either the Eclipse APIs or the OSGi logging APIs, rather it can log directly to the

much more rich JRE logger and its messages will be federated into the runtime system log via the Lotus

Expeditor core logging framework. While a specific developer or project may have an affinity for one API

or the other, it should be noted that the most feature rich and flexible of these APIs is the JRE

java.util.logging APIs. With that said, it is recommended that all new projects leverage these APIs, and

existing projects consider leveraging the JRE logging APIs in the future if/when their logging architecture

is redesigned.

Note: It is recommended that new applications for devices use Eclipse logging, as JSR 47 logging may

not be supported in future releases of Lotus Expeditor for Devices due to JSR 47 not being a JME

JSR. Existing applications that use JSR 47 or OSGi logging may continue to do so for this release.

Lotus Expeditor works hard to differentiate between the terms logging and tracing. In Lotus Expeditor,

logging is enabled at all times and provides all of the information needed for standard problem

determination of the product, while tracing produces a much more detailed set of information for

advanced diagnostics/problem determination. While logging is enabled at all times for all components,

tracing is not, but can be enabled simply on a component level by the end user or administrator. For

more information on enabling/disabling logging and tracing please refer to the Assembling and Deploying

Lotus Expeditor Applications and the Troubleshooting guide.

Enabling projects for serviceability

Lotus Expeditor Client provides Client Services target definition support to assist in managing project

dependencies and launch configurations. These target definitions simplify the creation and configuration

of application projects for serviceability, enabling you to select the target logging and tracing APIs, and

provide automatic management of the requisite logging and tracing libraries. When enabling a project for

serviceability, you can select any of the Client Services target definitions for your Client Services project.

The following table provides a list of tasks and the appropriate target feature selections for each profile in

a Client Services project.

312 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 323: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 24. Client Services project tasks

Task Target Features

JSR47 logging and tracing No extra target features required since these APIs are

provided in the Base JRE included with Lotus Expeditor

and are made available via the system class path.

Eclipse Logging and Tracing Eclipse Core components.

Note: This target feature is selected by default in all

Lotus Expeditor profiles.

OSGi LogService logging and tracing Eclipse Core components.

Note: This target feature is selected by default in all

Lotus Expeditor profiles. Also note That while there is a

specific target feature called Log Service, this does not be

selected on your project target profile since it is an actual

Implementation of the OSGi LogService interface, not the

interface definitions that are provided in the Eclipse Core

components target feature.

Apache Commons logging and tracing Apache Commons Components

Developing serviceability logic

Lotus Expeditor 6.1 provides a collection of APIs for logging and tracing:

v The JRE Logger provides the J2SE 1.4 java.util.logging APIs and framework for standard J2SE

applications to produce and submit log messages that can then be collected, filtered and persisted all

via pluggable components as defined by the JRE Logger APIs.

v The Eclipse Logger provides the Eclipse logging APIs and a logging framework for Eclipse applications

to produce and submit log messages that can be collected and persisted by the Eclipse logging

framework.

v The OSGi Log Service provides OSGi specified APIs for OSGi applications to produce and submit log

messages that can be collected, filtered, and then provided to LogReader implementations which can

then provide more filtering and then persist the log records if desired.

v Apache Commons Logging APIs provide a façade interface to abstract developers from one specific

implementation of logging. This is an external interface and is used by several components in the open

source Java world.

JSR47 Logging (java.util.logging)

The logging methods are grouped in five main categories:

v There are a set of ″log″ methods that take a log level, a message string, and optionally some

parameters to the message string.

v here are a set of ″logp″ methods (for ″log precise″) that are like the ″log″ methods, but also take an

explicit source class name and method name.

v There are a set of ″logrb″ method (for ″log with resource bundle″) that are like the ″logp″ method, but

also take an explicit resource bundle name for use in localizing the log message.

v There are convenience methods for tracing method entries (the ″entering″ methods), method returns

(the ″exiting″ methods) and throwing exceptions (the ″throwing″ methods).

v Finally, there are a set of convenience methods for use in the very simplest cases, when a developer

simply wants to log a simple string at a given log level. These methods are named after the standard

Level names (″severe″, ″warning″, ″info″, etc.) and take a single argument, a message string.

For the methods that do not take an explicit source name and method name, the Logging framework will

make a ″best effort″ to determine which class and method called into the logging method. However, it is

important to realize that this automatically inferred information may only be approximate (or even

wrong). Virtual machines are allowed to do extensive optimizations when JITing and may entirely

remove stack frames, making it impossible to reliably locate the calling class and method.

Developing applications 313

Page 324: Lotus Expeditor: Developing Applications for Lotus Expeditor

All methods on Logger are multi-thread safe.

The Lotus Expeditor 6.1 logging framework leverages the JSR47 implementation provided with the

runtime JREs (both JRE 1.5 and JCLDesktop). It works directly with java.util.logging.LogRecord objects.

For more detailed information on JRE Logging APIs, please see the Sun Javadoc at http://java.sun.com/j2se/1.4.2/docs/.

JSR47 Tracing (java.util.logging)

Tracing is integrated into the JSR47 logging framework as part of the standard log event message flow.

While some logging systems provide completely different APIs for logging and tracing, JSR47 only

differentiates them by the severity. SEVERE, WARNING and INFO in Lotus Expeditor are considered log

messages, while all other levels CONFIG, FINE, FINER and FINEST are considered trace messages.

OSGi Logging

The LogService interface allows bundle developers to log messages that can be distributed to other

bundles, which in turn can forward the logged entries to a file system, remote system, or some other

destination.

The LogService interface allows the bundle developer to:

v Specify a message and/or exception to be logged.

v Supply a log level representing the severity of the message being logged. This should be one of the

levels defined in the LogService interface but it may be any integer that is interpreted in a user-defined

way.

v Specify the Service associated with the log requests. By obtaining a LogService object from the

Framework service registry, a bundle can start logging messages to the LogService object by calling

one of the LogService methods. A Log Service object can log any message, but it is primarily intended

for reporting events and error conditions.

The LogService interface defines these methods for logging messages:

v log(int, String) – This method logs a simple message at a given log level.

v log(int, String, Throwable) – This method logs a message with an exception at a given log level.

v log(ServiceReference, int, String) – This method logs a message associated with a specific service.

v log(ServiceReference, int, String, Throwable) – This method logs a message with an exception

associated with a specific service.

While it is possible for a bundle to call one of the log methods without providing ServiceReference

object, it is recommended that the caller supply the ServiceReference argument whenever appropriate,

because it provides important context information to the operator in the event of problems.

For more information on the OSGi Logging APIs please see the OSGi_R4_Service_Compendium,

specifically the OSGi Log Service Specification chapter, as well as “OSGi specification” on page 366.

OSGi Tracing

The OSGi LogService definition is similar to the JSR47 logging framework in the sense that it does not

provide separate APIs for tracing; it simply leverages the log event severity as the way to differentiate

between log messages and trace messages. The LogService defines the following levels for log messages –

ERROR, WARNING, and INFO - and defines the level DEBUG for trace messages. All of the logging

method signatures are valid for tracing so the information provided above is valid for OSGi tracing as

well.

Eclipse Logging

For plug-in developers, the Eclipse logging and tracing mechanism consists of just a few objects and

methods. The following code provides a simple example of logging from a plug-in:

314 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 325: Lotus Expeditor: Developing Applications for Lotus Expeditor

import org.eclipse.core.runtime IStatus;

import org.eclipse.core.runtime Status;

import org.eclipse.core.runtime Platform

IStatus status= new Status (IStatus.ERROR,

"Test",

0,

"Testing Eclipse Error Logging",

(Throwable) null);

getDefault().getLog().log(status);

In order to send a message to the Eclipse logging system, a Status object must be constructed and

populated with all required data. Once the Status object is instantiated it is then passed to the Eclipse

logger via the log() method. The handle to the Eclipse log is located via the getLog() method of the

Plugin class (the Plugin class is accessed via the getDefault() method here).

Eclipse Tracing

Eclipse’s tracing mechanism is based on methods from the Eclipse Platform class, inDebugMode() and

getDebugOption(String) and one tracing configuration file called .options located in the plug-in

directory. Details on Eclipse tracing can be found in the online help at PDE Guide > Getting Started >

Basic Plug-in Tutorial > Running a plug-in > Running with tracing.

Once the trace files have been set up appropriately for the plug-in, and tracing has been enabled via the

workbench configuration screens, the following code shows an example of how the tracing setup is used

by the developer:

if ( Platform.inDebugMode() ) {

if ("true".equalsIgnoreCase (Platform.getDebugOption("T2")) {

IStatus status= new Status(IStatus.INFO,

"Test",

0,

"Testing Eclipse Error Logging", (Throwable)null);

getDefault().getLog().log(status);

}

}

The above example begins by checking to see if debugging has been enabled for this plug-in, if it has

been enabled, then the example confirms that trace level ″T2″ is set to ″true″, if and only if these two

checks are true will the Status object be created and logged to the Eclipse logger.

While the above example illustrates the trace check and a log entry created to the Eclipse logger, plug-in

developers often use System.out or System.err to write out trace information. The Eclipse log file is

typically reserved for Error or Warning conditions that occur during application execution.

Apache Commons Logging

The following code example shows a simple programming example for the Apache Commons Logging

APIs.

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

private static final Log apachelog = LogFactory.getLog("Apache");

apachelog.error("Testing the Apache log");

Java.util.logging best practices

The following is a set of best practices for JSR47 usage:

1. Is there a good way to get logger?

The following pattern can be used in each class to obtain a JSR47 logger:

Developing applications 315

Page 326: Lotus Expeditor: Developing Applications for Lotus Expeditor

private static final String CLAZZ_NAME = MyClass.class.getName();

private static final String PKG = MyClass.class.getPackage().getName();

private static final String LOG_RB = PKG + "." + “Messages.properties);

private static Logger _logger = Logger.getLogger(PKG,LOG_RB);

Substitute your class name for MyClass and ensure you have a properties file with the same name as

the leaf node of the package.

Note: If you use this pattern, use caution when later renaming your packages.

2. Why not just use LogManager.getLogger(″com.ibm.rcp.mypackage″);?

java.util.logging.LogManager.getLogger(String name) returns the logger with a matching name if

it already exists. Otherwise it returns null. There is no guarantee that a given logger will exist when

your class gets instantiated since the order of class instantiation is not determinate. Even if it were

currently, the order could change later. Therefore, it is necessary to use the get methods from the

Logger class to ensure that a Logger is returned. Whether you use LogManager or Logger to get a

logger, no more than one instance of a named logger is ever in existence within a VM at any given

time.

Additionally, since it is possible to instantiate a logger at first with no resource bundle and then later

use it with a resource bundle, consistently requesting it by means of the Logger class ensures that the

expected resource bundle will be available. If you use LogManager you will get the logger (if it

exists). However, it must already have an associated resource bundle. There are alternatives, such as

testing to see if the logger has a ResourceBundle already, and if not, using Logger,getLogger(String

name, String resourceBundleName) to fix the situations. Alternatively, you could adopt the

convention of only using the logbr methods of Logger instead.

3. How do I change the log level for my loggers?

The LogManager is initialized from values in the file <workspace>/.config/rcpinstall.properties.

There, you can set the logger level. For example, if you want to see all log entries for your code in

the package com.ibm.rcp.mypackage, add the following string:

com.ibm.rcp.mypackage.level=FINEST

If you want to hear less from other JSR47 loggers, simply change the default values in the

rcpinstall.properties to SEVERE.

4. Where are my logs?

The system log can be found in <workspace>\logs\error-log-0.xml where n is a number 0 (current

log) or 1 log from the last time it was run.

The system trace file can be found in <workspace>\logs\trace-log-0.xml where n is a number 0

(current log) or 1 log from the last time it was run.

5. What is ″guarded logging″ and why do I need it?

″Guarded logging″ is a pattern that checks to see if a log statement will result in output before it is

executed. Since the logger itself makes this check, it may seem redundant to do this for every call.

However, as almost every logging call creates String objects, it is critical. The accumulation of these

Strings causes memory fragmentation and unnecessary garbage collection. Garbage collection, while

beneficial, also produces significant performance loss. To reduce this as much as possible, always

guard logging statements with a severity less than SEVERE. Since SEVERE is always expressed by

the logger, these do not need a guard. Here is an example, given the declarations in FAQ 1.

if(_logger.isLoggable(WARNING)){

_logger.logp(WARNING,CLAZZ_NAME,method,

"warn.unable.to.get.preference",

new Object[]{pid,key});

}

6. What are guidelines for using each logging level?

INFO

Do: Use INFO for events that represent the normal operation of a component, and will be useful in

resolving problems that may occur in other code segments. For example, After verifying that install

operations are complete, the following message is logged from the launcher:

316 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 327: Lotus Expeditor: Developing Applications for Lotus Expeditor

Done with install operations

Don’t: Use INFO for debug information, for tracing program execution, in potentially frequently

repeating events, or to simply confirm an event unless it will be useful in determining the cause of a

problem with a related event.

WARNING

Do: Use WARNING when a problem has occurred that will effect normal operations adversely, but

will not prevent most operations to continue. A good example would be the following message from

provisioning:

Failed to retrieve page file for URL EXPEDITOR.png.

Don’t: Use WARNING if the problem completely or severely eliminates the use of a function, or for

information messages that do not indicate impaired function.

SEVERE

Do: Use SEVERE to indicate an event causing a significant or complete loss of some function. An

example of a SEVERE message is written by the platform plug-in when the

plugin_customization.ini can not be read:

Error loading plugin customization file

Don’t: Use SEVERE if all or most functionality will continue to be available or if the problem is

transient.

7. How tracing accomplished? What about developer-only tracing?

Tracing is off by default. Trace is intended for use by developers, Quality Engineers and Support.

There are three trace levels: FINE, FINER and FINEST.

FINE: Use this level for significant events that explain the flow or state of the system when trying to

understand or debug a problem. These are usually at the level of object creation, catch clauses for

exceptions that do not constitute errors, and so on.

FINER: There is a set of Logger methods that generate messages with a FINER level. These are

entry(...), exit(..), finer(..) and throwing(..).

v Entering and exiting should be used for method entry and exit.

v Finer can be used for any tracing that is more verbose than desired for fine, but is not method

entry/exit or used before throwing an exception.

v Throwing should be used when you are about to throw or re-throw an exception.

FINEST: Finest is usually thought of as developer or debug tracing. This is used during

development, when attempting to learn the behavior of a system at a fine level of detail and when

trying to diagnose difficult problems once the code is released.

Tracing is a valuable tool, both during and after development. There is a common misunderstanding

that there is ″Developer Only″ tracing. Tracing that developers want to be able to turn on and off

should be done using the java.util.logging.Logger API. The level should be FINEST. Such tracing

can be valuable to support when diagnosing a difficult customer problem. Having it available will be

one factor in reducing the support team’s dependence on development. The rule of thumb should

be: If it is valuable now, it may be valuable later. Use Java logging at the FINEST level and you will

have virtually no impact on performance (with proper guarding), and you will create a valuable tool

for someone else. If you use println or printStackTrace you are not tying into the manageable Java

logging framework, and are likely going to create a distraction for someone else.

8. What should I do about Logging Exceptions?

All exceptions should be noted in a logging statement. Normally, this would be at the WARNING or

SEVERE level unless the exception is trivial or being rethrown. Some further guidelines:

v Always provide a specific message for the log entry including the exception. This should explain

the impact of the exception.

v Log the exception, not its message. Unless you set it yourself, you have no guarantee that the

message will be intelligible or even exist.

Developing applications 317

Page 328: Lotus Expeditor: Developing Applications for Lotus Expeditor

v Do not call printStackTrace on the exception. The logger will do this for you, and in a way that

will allow things like autonomics to respond to the exception. .

v If you catch the exception and then throw a new one (frequently the case in well written API) you

should use the caught exception as the cause of the thrown exception. Generally, you should not

log the caught exception in this case, assuming everybody up the stack follows the same

guidelines.

v Sometimes it makes sense to log the exception anyway, even though you are going to throw

another one if you believe this information may be of use to the user. 9. What is an example of logging?

The following two code samples are common logging patterns.

if (_logger.isLoggable(Level.INFO)) {

_logger.logp(Level.INFO, CLAZZ_NAME, "execute", "info.process.reqs");

}

And...

_logger.logp(Level.SEVERE,CLAZZ_NAME,"run","err.rcpapplication.error",

throwable);

10. What is an example of tracing?

The following code examples illustrate tracing.

Tracing example 1:

if (_logger.isLoggable(Level.FINE))

_logger.fine("Setting activities for page

" + _model.getName() + ":");

Tracing example 2:

private static final String CLASSNAME =

CompositeApplicationAdapterServiceImpl.CLASSNAME;

// If you refactor the class name changes

private GUID methodX(URL url, IProgressMonitor pM, boolean overrideCache) {

if (logger.isLoggable(Level.FINER)) {

logger.entering(CLASSNAME, "methodX", url==

null?"null":url.toExternalForm());

}

GUID res = null;

...

}

In this example, only the URL is logged on enter, as the other arguments are not that useful during

debugging; often when an application does not load, it is a problem with a partially corrupted URL

which is partially computed, so it is very useful to see exactly what URL is being passed into the

load call. Also, this is a private method; there are many public methods that do their job by calling

this private method, so it funnels the logging into this method instead of having the URL logged

several times by the public calls.

} finally {

if (logger.isLoggable(Level.FINER)) {

logger.exiting(CLASSNAME, "methodX", res);

}

}

The ″exiting″ call is in a finally clause so that it logs the exit even if the method throws an exception.

It also logs the result being return from this method, which is, again, very useful for debugging

purposes to figure out what, if anything, went wrong.

Tracing example 3:

public void showApplication(URL url, String pageId, IProgressMonitor

progressMonitor)

throws IllegalArgumentException, CompositeApplicationException {

if (logger.isLoggable(Level.FINER)) {

logger.entering(CLASSNAME,

318 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 329: Lotus Expeditor: Developing Applications for Lotus Expeditor

"showApplication(URL,String,IProgressMonitor)",

new Object[] {url, pageId, progressMonitor});

}

} catch (RuntimeException e) {

logger.log(Level.SEVERE,

PortalCaiUIPlugin.getString(

"str.caiuiplugin.calling.applications.update.job.error"), e);

throw new CompositeApplicationException(e);

}

11. Should I cache my logger level?

It may seem tempting to check the level of your logger once during your execution, and then simply

refer to that cached level instead of asking for the level each time you want to guard your calls. This

is not recommended, however, since it can cause your code to not respond to dynamic updates to

logger level configuration such as via the OSGi command prompt.

Migrating applications

Lotus Expeditor Toolkit provides two methods to migrate projects created with previous versions of the

toolkit. The toolkit can migrate Extension Services projects from a WebSphere Studio Device Developer

5.7 workspace, or Client Services 6.0 projects in a workspace created by a Rational SDP 6.0 platform. Both

methods convert projects in the same way. The toolkit sets the JRE and Target Definition for all migrated

projects to default values.

The toolkit tries to migrate the application service from the Target Features in SMF Bundle Developer, to

the latest target definition in the Lotus Expeditor Toolkit. After migrating a project, you may edit/add

target features and change target definitions. To do this, right click on the project and select Properties.

Choose Client Services, then select the Application Profile tab. For more information on this screen,

refer to “Setting Client Services project properties” on page 21.

Automated migration

Lotus Expeditor Toolkit allows you to migrate your Extension Services projects from a WebSphere Studio

Device Developer 5.7 workspace, or Client Services 6.0 projects in workspace created by a Rational SDP

6.0 platform. Web and Embedded Transaction Container projects require that the migration take place in

one of the supported Rational platforms (either RAD or RSA). Upon startup on an existing workspace,

the toolkit detects and automatically converts all workspace projects. Select Yes, when you are prompted

to set the Lotus Expeditor Toolkit configuration.

This modifies your projects without any user interaction. If you would like to preserve your project

format and data, you should back up the workspace prior to opening the Lotus Expeditor Toolkit on the

folder.

Note: During migration, the class path is updated to match current Target Definitions, and the manifest

is updated to match current runtime requirements. The toolkit will update the MANIFEST.MF file if

one exists, creating a backup called MANIFEST.MF.BAK. It will also set the Java Build Path, the JRE,

and Target Definition to default values.

Manual migration

You may choose to import an existing 5.7 Extension Service, or Client Services 6.0 project into a

workspace. Web and Embedded Transaction Container projects require that the migration take place in

one of the supported Rational platforms (either RAD or RSA). If you would like to preserve your existing

project format and data, back up the project directory prior to using the Migration wizard. To migrate,

perform the following procedure:

1. Select File > Import.

2. Select Existing project into workspace.

Developing applications 319

Page 330: Lotus Expeditor: Developing Applications for Lotus Expeditor

If there is no Client Services category, select Show All Wizards to display the Client Services

category.

3. Select either a WebSphere Studio Device Developer 5.7.1 Extension Services web project, or a

WebSphere Everyplace Client 6.0 Client Services web project in the file system, from CVS, or a project

interchange zip file.

4. Select Finish.

Migrating component logic

As the client platform continues to expand and evolve, new capabilities are added to the platform that

may result in other changes to the platform. It is the intent that plug-ins that were written using the

public APIs and extension points will continue to function on the latest version of the client platform.

Application developers may have inadvertently added dependencies on plug-ins that were intended for

internal use only and may require changes in order to continue to function on the latest release.

Compatibility plug-ins provided

Many capabilities provided by WebSphere Everyplace Deployment 6.0 have been updated in this version

of the client platform. The following compatibility plug-ins have been provided to ease migration to the

current client platform. If you had plug-in requirements on com.ibm.eswe.workbench or

com.ibm.icu.icu4j, you should make the following changes in order to improve future compatibility and

migration.

v com.ibm.eswe.workbench

This plug-in provided the user interface for the WebSphere Everyplace Deployment 6.0 platform. Two

extension points, com.ibm.eswe.workbench.WctApplication and

com.ibm.eswe.workbench.WctWebApplication, were provided to enable contributions to the application

launcher. These extension points are still provided, but the plug-in identifier has changed.

If you used these extension points, the Eclipse Plug-in Project or the Client Services projects created

using previous editions of the tools may have added a statement to the plug-in manifest to create a

dependency on this plug-in. Specifically, the com.ibm.eswe.workbench may have been added as a

plug-in dependency.

Corrective action: Remove com.ibm.eswe.workbench from the plug-in dependency list. You may continue

to use the extension points

v com.ibm.icu.icu4j

This plug-in provided additional Unicode capability beyond the capability provided by the Java

standard class libraries. In WebSphere Everyplace Deployment 6.0, this plug-in provided ICU4J v3.2.0

packages. In this release, Eclipse has provided v3.4.5, but in a plug-in named com.ibm.icu.

Plug-ins written to use the ICU4J packages provided by the com.ibm.icu.icu4j plug-in provided by

WED 6.0 may have the plug-in com.ibm.icu.icu4j listed as a plug-in dependency. An implementation

of the com.ibm.icu.icu4j has been provided in this release that re-exports the packages from

com.ibm.icu.

Corrective Action: The preferred method is to switch from a plug-in dependency on com.ibm.icu.icu4j

to do an Import-Package on the packages from com.ibm.icu that you need to use. Alternatively, you

can change the dependency from com.ibm.icu.icu4j to com.ibm.icu.

Plug-ins removed in this release

This release of Lotus Expeditor has made several packaging changes that have resulted in the removal of

the following plug-ins. These plug-ins provided no public APIs nor did they provide any extension

points, and should not have been dependencies for any plug-ins. However, some plug-ins may have

inadvertently added these plug-ins as a dependency. As a result, plug-ins dependent upon the following

plug-ins will no longer work in the client platform without taking corrective action.

v eclipse/plugins/

– com.ibm.pvc.wct.platform.autostart_6.0.0.20050921v rcp/eclipse/plugins/

320 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 331: Lotus Expeditor: Developing Applications for Lotus Expeditor

– com.ibm.esupport.client.SSCRVP_6.0.0.20050921

– com.ibm.esupport.client.SSEPGG_6.0.0.20050921

– com.ibm.esupport.client.SSFKUX_6.0.0.20050921

– com.ibm.esupport.client.SSSKRX_6.0.0.20050921

– com.ibm.eswe.help.appserver_6.0.0.20050921

– com.ibm.eswe.help.webapp_6.0.0.20050921

– com.ibm.eswe.installupdate_6.0.0.20050921

– com.ibm.eswe.uiworkbench.patch_6.0.0.20050921

– com.ibm.osg.service.device_2.3.0.20050921

– com.ibm.osg.service.http_2.1.3.20050921

– com.ibm.osg.service.log_2.2.0.20050921

– com.ibm.osg.service.metatype_1.1.0.20050921

– com.ibm.osg.service.prefs_1.2.0.20050921

– com.ibm.osg.service.useradmin_1.2.0.20050921

– com.ibm.pvc.persistence_1.1.0

– com.ibm.pvc.wct.internal.logredirector_6.0.0.20050921

– com.ibm.pvc.wct.mgmtservice.application_1.0.0.20050921

– com.ibm.pvc.wct.mgmtservice.com.linux.x86_1.0.0.20050921

– com.ibm.pvc.wct.mgmtservice.com.win32.x86_1.0.0.20050921

– com.ibm.pvc.wct.mgmtservice.com_1.0.0.20050921

– com.ibm.pvc.wct.platform.help_6.0.0.20050921

– com.ibm.pvc.wct.platform.provisioning_6.0.0.20050921

– com.ibm.pvc.wct.platform_6.0.0.20050921

– com.ibm.rcp.swt.browser.dom.moz.win32_1.3.0.005

– com.ibm.rcp.swt.browser.moz.win32_1.3.0.005

– com.ibm.rcp.ui.browser.gtk_1.3.0.005

– com.ibm.rcp.ui.browser.win32_1.3.0.005

There are two methods for taking corrective action:

v Removing the dependency

v Adding your own compatibility plug-ins

To remove the dependency, you will need to edit the manifest.mf (or plugin.xml) to remove from the

plug-in dependencies attribute any plug-ins shown above. You will then need to re-deploy the application

with the changes.

To add your own compatibility plug-in to fulfill any plug-in dependencies, you will need to create a new

plug-in in your workspace.

1. Select File > New > Project > Client Services > Client Services Project.

2. Use the plug-in name as the project name, and deselect Create a Java project, then select Next.

3. Fill in any ID, Name, Version or Provider information that you wish to change, then select Finish.

You will then need to deploy the compatibility plug-in with your application plug-ins. You may also use

a standard Eclipse Plug-in Project to create a new compatibility plug-in.

After you have either removed the dependency, or have created a new compatibility plug-in, you may

see compilation errors as a result of missing packages or classes. You will need to use only public APIs.

Developing applications 321

Page 332: Lotus Expeditor: Developing Applications for Lotus Expeditor

Metatype Service changes

WCTME EO 5.8.1 and WebSphere Everyplace Deployment 6.0 contained the OSGi Metatype Provider

service implementation. At this time, OSGi Release 3 did not define a service that enabled access to this

provider. IBM provided its own service implementation to access the Metatype Provider implementation.

It was registered as com.ibm.osg.service.metatype.MetaTypeService, and implemented the service

interface com.ibm.osg.service.metatype.MetaTypeService. This package was provided by the

com.ibm.osg.service.metatype plug-in.

OSGi Release 4 updated the definition of the Metatype Service to include a new service implementation.

This new service implementation is included in plugin org.eclipse.equinox.metatype. The IBM

proprietary instance of the service has been removed.

Corrective Action: Change references from com.ibm.osg.service.metatype.MetaTypeService to

org.osgi.service.metatype.MetaTypeService. Remove any package imports for

com.ibm.osg.service.metatype, or any plug-in dependencies on com.ibm.osg.service.metatype. The

meta data XML schemas have been updated and any existing meta data XML files will need to be

updated to conform to the new schema definitions.

Changes to plug-in startup

There have been significant changes to the framework that enables the startup of plug-ins. The following

corrective actions may need to performed for any application code:

1. The DB2 Everyplace (com.ibm.db2e), DB2 Everyplace ISync (com.ibm.mobileservices.isync), and

Cloudscape (org.apache.derby.core) plug-ins no longer start automatically on platform startup. These

plug-ins now rely upon class access to autostart. Application code that creates an instance of

the javax.sql.DataSource class for each of the database types will not be affected. Application code

that used the java.sql.DriverManager class to obtain a connection, and did not use a Class.forName()

method to load the database driver class, may encounter errors if the plug-ins are not already started.

A java.sql.SQLException: No suitable driver exception will be a typical exception that is

encountered.

If you run into problems where the database plug-ins need to be started, there are two possibilities for

correcting the problem. The preferred recommendation is to update the application code to use the

javax.sql.DataSource object (defined by JDBC 3.0 specification) to access databases. This provides for

portability of application code to Java class libraries following the Java ME Foundation profile. Refer

to “Data access application development best practices” on page 103.

Alterntiavely, you will need to use the lifecycle capabilities provided by the platform to start these

bundles. Refer to Managing lifecycle for more information about adding plug-ins to the lifecycle.

2. In previous releases, plug-ins that did not contain the Eclipse-AutoStart attribute were automatically

started by the platform. These bundles are now automatically started by the default

com.ibm.rcp.platform.personality as legacy plug-ins. It is strongly suggested that any existing

plug-ins be updated to include the Eclipse-LazyStart attribute, and plug-ins that will not activate

due to class access requests be added to the lifecycle of the platform. Refer to Managing lifecycle for

more information about adding plug-ins to the lifecycle.

Migrating OSGi services

ConfigAdmin, Preferences, and UserAdmin store their data in a different format than in previous versions.

A migration tool provides a migration path for previous users of ConfigAdmin, Preferences, and

UserAdmin to migrate their data to the new platform. This migration occurs automatically at install time

and will migrate all old data in the current workspace.

Note that data will only be migrated if the bundle containing the data has a unique bundle symbolic

name. Also, when ConfigAdmin data is migrated to the new ConfigurationAdmin service, the location

property of any Configurations will be set to empty. This allows for the new Configurations to be

mapped to the correct bundle.

322 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 333: Lotus Expeditor: Developing Applications for Lotus Expeditor

Debugging and testing applications

You can use either the Expeditor Server or the Expeditor Toolkit’s Client Services Launcher to run and

debug applications. Typically, the debugging mechanism you have used in the past will be the easiest to

use for debugging plug-ins.

Regardless of the launch mechanism used for debugging, the critical requirements for successful

debugging are access to the source for your applications, and Java class files that contain debugging

information.

Local debugging and testing

There are two methods available for running and debugging applications in a local instance of the Lotus

Expeditor runtime. Both are equally capable of running applications, but they have individual capabilities

which may make one more preferable.

The Client Services Launcher is ideal if you are familiar with Eclipse Plug-in development tools. It is also

recommended if you are developing bundles that are not J2EE projects, as the Client Services launcher

lets you easily select all bundle projects in your workspace.

The Client Services server is ideal if you are familiar with Rational J2EE development tools. It is also

recommended if you are developing non-Client Services EJB or Web projects, as the Client Services server

can easily add them to the list of configured projects to run. Since the server framework coincides with

the existing RAD J2EE tools, it may be more natural to use if you are primarily doing J2EE development,

especially if you are running the project on both Lotus Expeditor and non-Lotus Expeditor runtimes.

Client Services Launcher

The launcher supports the ability to run and debug Client Services projects from your workspace. The

Client Services runtime launch extends the Eclipse runtime workbench launch. It is suggested that you

use the Client Services launcher rather than the Eclipse runtime workbench launcher for running Client

Services projects, since it automatically handles setting other parameters for the Lotus Expeditor runtime.

Perform the following procedure to run or debug a project using the Lotus Expeditor runtime launch:

1. Select either Run > Run... or Run > Debug... to run or debug using the Lotus Expeditor runtime.

2. Select Client Services under configurations, and select the New button to create a new configuration.

Note: If Client Services runtime configurations have already been created, you can directly select one.

3. On the main tab, ensure that the JRE is set to a desired Client Services supported JRE, such as

jclDesktop.

4. By default, the launcher selects all the external plug-ins and features from the default Client Services

target definition. Use the profile tab to change the plug-ins and features selected for this launch

configuration.

You can also control which language support plug-ins are included in the launch by using the

National Language Support check boxes on the Main tab. These allow you to select group 1, group 2,

and group 3 language support. Refer to “IBM language groups” on page 333 for a definition of these

language groups.

5. By default, the launcher selects all your workspace plug-ins and Client Services projects. To change

the project selection, select the Workspace Plug-ins section from the Plug-ins tab.

6. Select either the Run or Debug button to launch the runtime.

© Copyright IBM Corp. 2004, 2006 323

Page 334: Lotus Expeditor: Developing Applications for Lotus Expeditor

Note: If you choose to manually select plug-ins, do not include fragments from Linux in your

Windows environment, or fragments from Windows in your Linux environment. If both

operating system fragment types are included, the platform will not work correctly. To avoid

this problem, use the Profile tab to select your plug-ins.

Note: If your machine is disconnected from the network (Linux only), then you must manually add

the following entry to the /etc/hosts file:

127.0.0.1 <your_machine_hostname>

This allows the Web Container to function correctly when you are disconnected from the

network.

For more information on launch option, refer to the section Running a Plug-in of the PDE Guide.

For more information on debugging, refer to the section Using the Java integrated development

environment > Concepts > Local Debugging of the Developing Java Applications Guide.

Client Services Server

The server supports the ability to run and debug J2EE projects from your workspace, including Client

Services Web projects, Portlet projects, and Client Services Embedded Transaction as well as existing web

projects and EJB projects.

Note: You should be developing in the J2EE or Web perspective when using the server tools to run J2EE

applications.

Creating a server

Perform the following procedure to create a Expeditor Server:

1. Select New > Other... to bring up the New Wizard.

2. Select Server and click Next to bring up the New Server dialog

3. Select IBM > Client Services v6.1 as the server type and select either Next to choose a Target

Definition or Finish to use the default.

4. If modifying the profile, perform your selections on this page then select Finish.

5. A new server will be created with the default name Client Services v6.1 @ localhost and will be

visible from the Servers view.

Editing a server

You can edit a server’s definition by double clicking the server in the Servers view. To modify the server’s

target definition or selected features, navigate to the Profile tab. To modify the advanced features of the

launch, select Advanced on the main tab. For descriptions of the tabs and fields in this dialog, refer to

Running a Plug-in of the PDE Guide.

Adding projects to a server

Projects that are associated with a server are automatically loaded onto the Lotus Expeditor runtime

when it is started.

To view the list of J2EE projects associated with a server, or to modify the projects on the server,

right-click the server in the Servers view and choose Add and Remove Projects... to display the Add and

Remove Projects dialog.

If you are working with one J2EE project that you want to test, you can right-click the project and choose

Run on Server. The wizard adds that project to a new or existing server, and automatically starts the

server.

324 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 335: Lotus Expeditor: Developing Applications for Lotus Expeditor

In order to add a non-J2EE Client Services project to a server, you must go to the advanced editing screen

(refer to “Editing a server” on page 324). You will be able to select Client Services projects from the set of

Workspace plug-ins on the Plug-ins tab.

Starting a server

From the Servers view, right click the server and select Start to run the server using the Lotus Expeditor

runtime. Or, select Debug to debug using the Lotus Expeditor runtime.

Remote debugging and testing

This section describes methods for remote debugging and testing of projects.

In order to debug the Lotus Expeditor platform, you will need to launch it using specific debug options.

You can launch using either a Debug Launch Configuration from the Client Services launcher in the

toolkit, or by using the command line.

To launch a Lotus Expeditor platform using Client Services launch configuration in the toolkit, create a

Launch Configuration as described in “Client Services Launcher” on page 323. Be sure to use the Debug

> Debug... option in step 1.

You can also launch the Lotus Expeditor platform for debugging using the command line. Add the

parameters

-vmargs -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=zzzz

to the Expeditor launch command line, where zzzz is an available port on your system.

In the Eclipse based IDE, select Debug..., then create a new Remote Java Application launch

configuration. Enter the name of any project, and select a Connection Type of Standard (Socket Attach).

For the Connection Properties, you can use localhost as the host (or supply the IP address or host name

for a remote system), and specify the same port number as you specified when launching the Lotus

Expeditor platform.

Debugging and testing applications 325

Page 336: Lotus Expeditor: Developing Applications for Lotus Expeditor

326 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 337: Lotus Expeditor: Developing Applications for Lotus Expeditor

Packaging and deploying applications

This section assumes you have completed some level of code development and are interested in one of

the two situations below:

v You have completed code development and are now prepared to start constructing installation artifacts

to turn over to an administrator or IT team for distribution to client systems.

v You want to run your code in an actual installed instance of the client platform on your local

development system (and not within an instance launched from the workspace)

For information on constructing installation artifacts for distribution, refer to “Packaging applications for

distribution.”

For information on performing quick deployments of plug-ins to local instances for test purposes, refer to

“Deploying projects for local testing” on page 331.

Packaging applications for distribution

Updates to the client platform are provided in the form of features. Features may contain other features,

or a set of related plug-ins. The Update Manager component of the client platform handles the

installation of the features, and a user interface is provided to manage the installed features.

Features may be provided to the Update Manager by connecting to an update site, or by the included

Enterprise Management agent. Update sites organize features for installation. The Update Manager

typically connects to an update site to determine the features that are available for installation.

The Enterprise Management agent enables the client platform to be managed remotely. Administrators

create software distribution jobs that define the artifacts to be installed, and the Enterprise Management

agent handles the installation tasks.

Understanding application lifecycle

Of the three lifecycle extension points, only the lifecycle.application extension point is supported on

devices. In order to utilize lifecycle.application to start bundles, the developer must extend the

extension point com.ibm.rcp.lifecycle.application.startBundles and provide the application id and

bundle id attributes. The application id specifies the application that is associated with this extension,

while the bundle id field specifies the bundle to start when the associated application is started.

Below is an example of the OrderEntry web application making use of lifecycle.application:

<extension point="com.ibm.rcp.lifecycle.application.startBundles">

<application id="com.ibm.rcp.samples.orderentry.webapp.OrderEntryWebApp">

<bundle id="com.ibm.rcp.samples.orderentry.service" />

</application>

</extension>

The OrderEntry plug-in has it’s plug-in name as com.ibm.rcp.samples.orderentry.webapp and it’s

extension id for the extension point com.ibm.eswe.workbench.WctWebApplication is OrderEntryWebApp.

Together, they are used as the application id for the lifecycle plug-in. The attribute bundle id indicates a

bundle that needs to be started for the OrderEntry web application to run correctly.

For an eRCP application, identified by an org.eclipse.ercp.eworkbench.applications extension, an

extension id is not required. Therefore, the application attribute in this extension is used as the

application id for the lifecycle plug-in. Note that only the application id is used. Do not place the plug-in

name of the eRCP application in front of the application id. For example:

© Copyright IBM Corp. 2004, 2006 327

Page 338: Lotus Expeditor: Developing Applications for Lotus Expeditor

<extension point="org.eclipse.ercp.eworkbench.applications">

<application id="MySample.application" name="My Sample">

<views normal="mysample.views.SampleView" />

</application>

</extension>

Only MySample.application should be used as the application id for the lifecycle plug-in

Finally, if a developer wishes a bundle to be started when the workbench starts, the

lifecycle.application extension can associate to the workbench application id,

org.eclipse.ercp.eworkbench.

Understanding methods of installation

There are two mechanisms to install applications via features. The application can either be installed from

each system by using the Update Manager, or by using an enterprise distribution system.

Local installation

To enable local installation, you will need to provide an update site configuration to the platform. If you

provide an installation program, in addition to any other tasks that you perform, you should provide an

update site for the users to use to install your application. The update site could be provided on the

distribution media, or could be created on the hard drive of the system on which you execute the

installation program.

The customers will need to start their client platform, and use the Update Manager to connect to the site,

and install the application.

For more information on update sites, refer to the documentation Plug-in Development Environment Guide

> Getting Started > Update Sites.

Enterprise installation

In addition to a local installation process, you should also consider providing an installation process to

enable enterprise distribution. To enable the enterprise installation, you should clearly identify each file

that should be installed, and the appropriate installation location.

The client platform provides an Enterprise Management Agent that connects to Tivoli® Device Manager

provided by WebSphere Everyplace Device Manager.

Tivoli Device Manager provides for software distribution as well as configuration jobs to be applied to

the client platform. Tivoli Device Manager uses bundles as the distribution artifacts for the Enterprise

Management Agent.

While the Enterprise Management Agent is capable of accepting a distribution at a plug-in or bundle

level, it is strongly recommended that Eclipse update sites packaged as a bundle using the

NativeAppBundle tool be used as the distribution artifact.

The update site provided to an administrator for distribution is the same update site that is built for local

installation. Therefore, developers can create the same artifacts for enterprise installation as they would

create for local installation.

For more information on update sites, refer to the documentation Plug-in Development Environment Guide

> Getting Started > Update Sites.

Understanding the types of install artifacts

For any successful application installation, you need to provide the appropriate set of installation artifacts

from the following:

328 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 339: Lotus Expeditor: Developing Applications for Lotus Expeditor

Installer/Uninstaller

A program to handle installation (and uninstallation of your application) may be needed if you need to

do anything more than provide an update site to allow installation of your application.

Update site

An Update Site is the key mechanism to enable installation of the application.

For more information on update sites, including how to create one, please see the Getting Started >

Update Sites section of the PDE Guide.

Features

A feature is the only level of installable unit that exists. You cannot choose to install only certain plug-ins

from a feature. The Plug-in Development Platform provides wizards for creating Features.

Once the feature project is created, you can make additional updates to the feature definition by editing

the feature.xml file.

Additionally, if a feature has already been created, you can import the feature as a binary project into

your workspace. Select File > Import > External Features to launch the wizard. Enter the name of an

update site to browse, and you can select the features to import.

Importing External Features is useful if you are attempting to create an Update Site, and someone else

has already created the features that need to be installed.

To enable Lotus Expeditor users to use the Scan for Updates action within the Application Management

dialog, you must add an update URL to the feature.xml file. Using the Feature Manifest Editor, on the

Overview tab, right click on the Update URLs entry in the Feature URLs section, then select New >

Update URL. You can then enter the appropriate update site information in the Properties view that is

displayed.

If no update URLs are provided in the feature.xml file, the Scan for Updates action will still be

displayed as an available action, but will not return any update information.

Lotus Expeditor uses the eclipse directory to contain all of the features and plug-ins from Eclipse. The

rcp directory contains the remainder of the features and plug-ins that are part of the client platform. The

shared directory can be used to install features that are to be used by all users on the client system.

Additionally, there is a feature install directory in the workspace associated with each user.

When new versions of features are provided, they will be installed into the same directory as the

previous version. The installation directory for a feature upgrade cannot be changed.

Versions for features are specified using major.minor.service.qualifier. For example, a version of 4.0.1

has a major version of 4, a minor version of 0, and a service version of 1. An equivalent version is a

version that differs first at the service level. A compatible version is a version that differs first at the

minor level. For example, using our version 4.0.1 above, a version of 4.0.2 would be an equivalent

version, since the service value is the first value that changed. A version of 4.1.2 would be a compatible

version, since the minor value is the first value that changed.

The Scan for Updates capability provided as part of the Application Management dialog enables updates

of only equivalent or compatible versions, according to the preferences selected in the Manage >

Preferences > Install/Update dialog. The default value is for Equivalent feature updates.

A feature version that changes at the major level, for example, a version 5.0.0 that would replace our

version 4.0.1, must be installed through the Application > Install mechanism. Scan for Updates will not

show this feature as being available.

Packaging and deploying applications 329

Page 340: Lotus Expeditor: Developing Applications for Lotus Expeditor

For additional information on versioning, refer to the Feature manifest section of the Platform Plug-in

Developer’s Guide, and the Getting Started > Features section of the PDE Guide .

Plug-ins

Plug-ins provide the core logic capability for the application, but they must be grouped into features in

order to be installed via the Update Manager.

If you choose to use a Feature project, or an Update Site project within your workspace, you will need to

provide the plug-ins within the workspace as well. These plug-ins can either be in source form - if you

are responsible for developing the plug-ins - or they can be in binary form - if another person will be

providing these artifacts to you. If another person is providing the artifacts, then you can import these

artifacts as binary plug-ins so that you can use the Feature and Update Site project capabilities. Select File

> Import > External Plug-ins and Fragments to launch the Import Wizard. Once plug-ins exist in

projects within the workspace, you can use the Feature Manifest Editor to add plug-ins to the Feature,

and the Site Manifest Editor to add features to the Update Site.

For more information on plug-ins, refer to the Getting Started > Basic Plug-in Tutorial section of the

PDE Guide

Native libraries

Plug-ins may use the Java Native Interface (JNI) to access native library code. Native libraries are by

convention placed in a fragment specific to an operating system or architecture to the plug-in providing

the Java classes (native libraries can all be placed within a single plug-in). The organization of the

fragment is the following:

directory\fragment.xml

directory\os\<osgi.os>\<osgi.arch>\*.dll or *.so

Where directory is typically <fragment_name>_<fragment_version>

The value of the osgi.os value above is the value corresponding to the value of the Java System property,

osgi.os. The value of the osgi.arch corresponds to the value of the Java System property, osgi.arch.

The osgi.os value is generally based on the os.name property value, although the value of osgi.os may

alias a set of values for os.name. For example, the osgi.os value of win32 is used to represent an os.name

value of Windows 2000.

The osgi.arch value is generally based on the os.arch property value.

For the runtime environment, since it is targeting Windows 2000, Windows XP, and Linux, the values of

osgi.os would be either win32 or linux.

The value for arch will be x86.

As an example, the DB2 Everyplace component requires native libraries. The plug-in id is com.ibm.db2e

and the version is 8.2.0. The native libraries required for Windows reside in a fragment for this plug-in,

com.ibm.db2e.win32_8.2.0. Within this fragment, the directory os\win32\x86 contains the DLLs required

by DB2 Everyplace.

If there is a single native library required by the plug-in, and it is loaded via the System.loadLibrary()

method, then packaging the fragment or plug-in in this organization is sufficient.

If there are multiple native libraries required by the plug-in, and each one is individually loaded by the

System.loadLibrary() method, and the DLLs do not depend on each other or statically or dynamically

load each other, this organization is sufficient.

330 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 341: Lotus Expeditor: Developing Applications for Lotus Expeditor

If there are multiple native libraries required by the plug-in, and there are dependencies between the

libraries such that a System.loadLibrary() method call loads one of the libraries, but that library

statically or dynamically loads the other libraries, then an additional step is required. Because these

directories are not provided on the System PATH or LIBPATH, the operating system is unable to handle the

loading of the shared library. To cause these directories to be added to the system PATH or LIBPATH so that

the operating system can load these libraries, update the rcpinstall.properties file to add the

appropriate plug-in or fragment directory to the library.path.prepend or library.path.append

properties.

As an example, there are multiple native libraries required for DB2 Everyplace. Because these libraries

have dependencies between them, they must be present on the system PATH or LIBPATH. Therefore, the

fragment directory, C:/Program Files/IBM/Lotus/Expeditor/rcp/eclipse/plugins/com.ibm.db2e.win32.x86_8.2.1.20050620/ os/win32/x86, has been added to the library.path.append

property in the rcpinstall.properties file.

Code that behaves differently between operating systems that are aliased to win32, such as Windows 2000

or Windows XP, should be handled within the native libraries, and should not be placed into separate

plug-ins/fragments, or separate osgi.os directories, since changing the operating system name for the

runtime environment will prevent proper loading of components such as DB2 Everyplace or SWT.

Configuration file updates

Most of the changes required when installing an application can be accomplished by providing the

appropriate plug-ins. However, some of the configuration files used by the Lotus Expeditor platform may

need to be updated. Changes to these files can be made either by installation programs, or by using an

Install Handler associated with the application Feature being installed. An Install Handler is invoked at

certain checkpoints within the installation process. During the applicable checkpoints, code provided

within the Install Handler can make the required changes to the configuration files.

Installation instructions

You should make sure that any installation instructions for your application are clearly provided to your

customers. Your customers will need to know, for example, the location of the update site from which to

install the application, any preferences that may need to be updated, how to start your application, and

so on.

Enterprise distribution instructions

You should also consider the needs of enterprises to use an enterprise distribution mechanism to install

the application. Any artifacts that must be installed should be clearly identified. This will allow the

administrator to easily define the necessary steps to distribute your application. You should supply

Eclipse update sites to the enterprise administrator to allow for distribution of your application.

Using Ant tasks to build a deployable bundle

ANT is a scripting framework often used in task automation for Java. It is commonly used to automate

the building of code from source into the resulting binary artifacts.

The Plug-in Development Environment (PDE) provides a framework for building features and plug-ins

using ANT technology. The automated PDE build technology will dynamically create build scripts based

upon the build.properties file associated with a project.

Deploying projects for local testing

In order to run your application plug-ins in a locally installed instance of the client platform, and not an

instance started from the workspace application launcher, you will need to export your plug-ins to the

local file system. The Client Services runtime does not support the Deploy action available through the

project’s pop-up menu. Rather, you must export the project as discussed below.

Packaging and deploying applications 331

Page 342: Lotus Expeditor: Developing Applications for Lotus Expeditor

This section covers how to export your projects to the local file system for local testing. The steps

suggested here provide the quickest route for exporting your projects to the local file system. Please note

the following:

v Using this method to deploy your plug-ins to the local instance does not allow the plug-ins to be

removed through the Application Management menu

v Removing the plug-in requires that you use local system tools to physically remove the directory or

directories that contain the plug-ins

v The preferred method for creating binaries for distribution to others is to create features and/or update

sites (as covered in “Packaging applications for distribution” on page 327).

v The toolkit does not support the ability to right-click a project, and deploy it from the resulting

submenu.

Exporting plug-ins using the PDE

The PDE provides an Export wizard that will allow you to export a Client Services plug-in project to a

local runtime for deployment.

Select File > Export > Deployable Plug-ins and fragments. This wizard will allow you to select multiple

projects for deployment. You will also be able to select different output formats:

v A single ZIP file containing all plug-ins

v Individual JARs for each plug-in for use on an update site

v A directory structure

When using the directory structure option, you should refer to an eclipse directory, such as

<installation_root>/rcp/eclipse. The export process will automatically put your plug-in into the

plug-ins directory.

Notes:

1. While your plug-in may build successfully in the workspace, the Export mechanism runs a

separate compilation of your plug-in. If you have added entries to the Java build path for your

plug-in, you should also make sure that the build.properties file in your plug-in project

contains any required extra JAR files in the jars.extra.classpath property. The

build.properties file can be updated either through the Build Properties Editor or the Bundle

Manifest Editor.

2. If you will be debugging these plug-ins from another IDE, then you should make sure that

you check the Include source code option in the Export Wizard, and that the Compile source

with debug information option is selected in the Build Options available in the Export

Wizard.

332 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 343: Lotus Expeditor: Developing Applications for Lotus Expeditor

Globalizing your application

You can globalize an application that you build on the Lotus Expeditor platform by using the

International Components for Unicode (ICU) technology. ICU4J is a set of Java classes that extend the

capabilities provided by the J2SE class libraries in the areas of Unicode and internationalization support.

The ICU4J classes (at version 3.4.5) are provided in the com.ibm.icu_3.4.5.jar, and enable you to:

v Support multiple locales

v Support bidirectional text layouts

v Create translatable plug-ins

The following Web site provides more information about the icu4j package: http://www-306.ibm.com/software/globalization/icu/index.jsp

Support for multiple locales

A locale represents a geographic place. A user‘s geographic location implies certain preferences for

operating system and application settings, such as language character sets, date, time, and currency

formats, and the direction in which text is displayed.

The default locale for a Lotus Expeditor application is the same as the locale for the operating system of

the machine on which the client is running. If you design your application to support multiple locales,

the user can specify -nl <locale code> as a command line option when starting the client to change the

default locale for the client application running on their machine.

Things to keep in mind when implementing support for multiple locales:

v Call java.util.Locale.getDefault() to get the current locale. If a user supplies the -nl parameter

when starting the client, it resets the default locale value. Calling java.util.Locale.getDefault()

would return the newly specified locale code.

v Use icu4j whenever possible to generate locale-sensitive data dynamically. The ICU4J classes provide

the following objects among others:

– DateFormat

– MeasureFormat

– MessageFormat

– NumberFormatv Do not expect the same behavior you witness in the locale you are developing in to occur in another

locale. For example, ″i″.to UpperCase() does not return ″I″ in the Turkish locale.

v Keep in mind that sort orders vary in each locale. Call com.ibm.icu.text.Collator to compare

international text.

Note: The Javadoc information for the icu4j.jar package is available from the following Web site:

http://oss.software.ibm.com/icu4j/doc/index.html

IBM language groups

IBM identifies the following language groups:

Table 25. Group 1 languages

Locale code Language

de German

© Copyright IBM Corp. 2004, 2006 333

Page 344: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 25. Group 1 languages (continued)

Locale code Language

es Spanish

fr French

it Italian

ja Japanese

ko Korean

pt_BR Portuguese (Brazil)

zh Chinese (Simplified)

zh_TW Chinese (Traditional)

Table 26. Group 2 languages

Locale code Language

ar Arabic

cs Czech

da Danish

el Greek

fi Finnish

hu Hungarian

iw Hebrew

nl Dutch

no Norwegian

pl Polish

pt Portuguese

ru Russian

sv Swedish

tr Turkish

Table 27. Group 3 languages

Locale code Language

be Belorussian

bg Bulgarian

ca Catalan

et Estonian

hi Hindi

hr Croatian

is Icelandic

lt Lithuanian

lv Latvian

mk Macedonian

ro Romanian

sk Slovak

334 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 345: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 27. Group 3 languages (continued)

Locale code Language

sl Slovenian

sq Albanian

sr Serbian

th Thai

uk Ukrainian

Supporting preferred fonts and bidirectional layouts

Each locale has a preferred set of fonts. Display your application text using these fonts whenever possible

to maintain a unified look and feel for the user. Bi-directional (bi-di) support is important for Arabic and

Hebrew.

To support preferred fonts and bi-di:

1. Instead of using a hard-coded font to format the text you display in the application, retrieve the font

that is preferred for a specific locale by calling the org.eclipse.jface.resource.JFaceResources class.

The JFaceResources class provides the following methods for retrieving preferred fonts:

v getBannerFont()

v getDialogFont()

v getHeaderFont()

v getTextFont()

v getViewerFont()2. Test your plug-in in RTL mode to be sure it responds correctly.

Creating translatable plug-ins

Customize your plug-in to display appropriately to an international audience by:

v Separating out all hard-coded text strings that appear in the user interface, in error messages, message

boxes, or titles that display in title bars

v Enabling the date and number objects you use to be formatted based on the user‘s preferred locale

To ensure that a plug-in is translatable, do the following:

1. Define all translatable strings in a .properties file associated with the plug-in. For example, instead

of defining the name of the plug-in in the plugin.xml file, define it in a file called plugin.properties,

which associates the .properties file to the plugin.xml file. For example, define the name of the

plug-in in the plugin.xml file as follows:

<plugin name="%plugin.name"

2. In the plugin.properties file, include the following text to define the %plugin.name keyword:

plugin.name = My Super-useful Plugin

3. Use the Rational Software Development Platform or a similar product to search your source code for

all translatable strings. Replace each string with a keyword and define the keyword in a .properties

with the same name as the file that contained the translatable string.

4. Identify the locale-specific objects in your plug-in, then organize them into categories and store them

in different ResourceBundle objects accordingly. For example, you can store a series of String objects in

a PropertyResourceBundle, which is backed up by a set of properties files, or you can manage all

locale-specific objects using a ListResourceBundle, which is backed up by a class file. Though the

ListResourceBundle object requires you to code and compile a new source file to support any

Globalizing your application 335

Page 346: Lotus Expeditor: Developing Applications for Lotus Expeditor

additional locales, ListResourceBundle objects are useful because unlike properties files, they can store

any type of locale-specific object, not just text objects.

5. Use the standard Java library classes that localize the formatting for numbers, dates, times, and

currencies. None of these object types can be displayed or printed without first being converted to a

String. The formatting classes enable you to use the proper format for the user‘s locale when

converting an object into a String object. For example, if you use the factory methods provided by the

icu4j.jar package NumberFormat class, you can get locale-specific formats for numbers, currencies,

and percentages. The DateFormat class provides predefined formatting styles for dates and times that

are locale-specific and easy to use.

6. Create a plug-in fragment to contain all .properties files associated with a specific language group.

IBM uses the following convention when naming the language fragments:

Language pack fragment containing IBM Group 1 languages =

<plugin id>.nl1_<version>

Language pack fragment containing IBM Group 2 languages =

<plugin id>.nl2_<version>

7. Provide a feature to group the Language packs you are including in your application. Use the

following convention when naming the features:

Language pack feature containing IBM Group 1 languages =

<feature id>.nl1_version

Language pack feature containing IBM Group 2 languages =

<feature id>.nl2_version

Specify any translatable text in the feature.xml file in an associated feature.properties file.

See the eclipse.org Web site for more details on internationalizing a plug-in at http://www.eclipse.org/articles/Article-Internationalization/how2I18n.html.

336 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 347: Lotus Expeditor: Developing Applications for Lotus Expeditor

Securing applications and data

The Lotus Expeditor platform is a secure platform that protects your application data. Single sign-on with

the operating system capabilities are built into the platform by default.

It secures the applications and application data running on the client by doing the following:

v Limiting access to Target Features to only users with valid authentication credentials.

v Protecting user credentials by storing authentication information, such as user names and passwords,

in an encrypted key store.

By default, the client uses the key store provided by IBM’s JCE provider on jclDesktop. This

implementation of the Java Cryptography Extension (JCE) uses a password-based encryption with Triple

DES (Data Encryption Standard) to protect the store’s contents. The key store also provides storage for

database and account-related passwords created using the PBEKey (Password Based Encryption Key)

interface. The location of the platform key store is specified as the value of the keystore.url security

property set in the java.security file. If no value is specified for the keystore.url, the location defaults to

the following directory:

WORKSPACE\.metadata\.plugins\com.ibm.rcp.security.auth\.keystore.jks.J9

where WORKSPACE is the absolute path to the user’s workspace. If no key store exists, a key store is

created when an application calls the login method. The SecurePlatform class provides methods that you

can use to access and log into the platform key store.

You can implement authentication mechanisms in client applications using the following APIs:

v Accounts API -- Recommended. Enables you to store, access, and use properties that are required to

make a connection to, and communicate with, local and remote services, including user passwords,

which it directly accesses using the AccountsLoginContextService. Use the Accounts API to access the

key store and make password changes outside of the login process. The Accounts API also simplifies

HTTP and J2EE-FORM logins to a remote WebSphere Portal server.

v Java Authentication and Authorization Service (JAAS) APIs -- Not recommended. Connects to servers

and manages user information, including validated passwords, which it handles using a Subject object.

Uses login modules to access the key store and retrieve or store passwords as part of the login process.

You can use the existing LoginConfigurations (HTTP or J2EE-FORM) for HTTP and J2EE-FORM logins

to authenticate with remote servers. The challenge of using straight JAAS APIs with the provided login

configurations is that the Subject object must contain specific classes for the login modules to work. If

you use the Accounts API, it handles the Subject object interaction for you, while enabling you to

directly access the Subject and its contents, if necessary.

Accounts framework

The Accounts framework enables you to store, access, and use properties that are required to make a

connection to, and communicate with, a local or remote service.

Some examples of accounts include:

v An HTTP account which is used to connect to a web based service. This account contains a URL for

the location of the service, and a user name and password to log onto the service.

v An Instant Messaging account which is used by an instant messaging client to connect to an IM server,

such as IBM Lotus Sametime. This account includes a server name, and a user name and password to

connect to the instant messaging server. The account could also be used to store user preferences such

as the text people see when the user’s status is “Away.”

© Copyright IBM Corp. 2004, 2006 337

Page 348: Lotus Expeditor: Developing Applications for Lotus Expeditor

An account can store both connection properties, and properties or preferences specific to that connection.

The Accounts API provides a way to get, add, update, remove, and listen for changes to an account. The

component ensures that once user accounts have been created, either manually by a user or automatically

during provisioning, users will only ever have to enter one password to access all of the services for

which they have accounts. The Accounts component also provides a common user interface from which

users can see and change account information and passwords for all of their services.

Adding accounts

The Account class represents an account and all of its data.

An account contains data necessary to connect to a local or remote service. The account class stores data

as key and value pairs. Several keys are defined in this class as public static final Strings. The keys UID,

NAME, DESCRIPTION, and TYPE must be defined for all account objects. (DESCRIPTION is initially set

to an empty String). A random UID is generated for an account object if you do not provide a UID when

you create it. All other required keys depend on the TYPE key defined for the account, but in general, are

optional.

The Account class contains the following two data stores:

v Persistent store – Writes properties to a database, file, or other store when a call to add or update

account is made.

v In memory store – Properties only exist in this class. Stores data that is only relevant for a given user

session without writing it to disk. Useful for securely handling information such as LTPA cookies.

If you do not specify a store when you create the account, the account data is stored in persistent

properties, by default.

With the exception of operations made using the AccountsLoginContextService, changes to the Account

object are not made permanent until you make a call to update or add the account.

To create an account, perform the following steps:

1. Use the AccountsManagerFactory to access a singleton instance of the platform implementation of the

AccountsManager interface.

AccountsManagerFactory.getAccountsManager();

2. Create the account by doing one of the following:

v To add an account object based on the standard Account class to the persistent store, use the

following methods:

addAccount(Account account)

or:

newAccount(java.lang.String id)

where id is either null or set to DEFAULT_ACCOUNT.

v To create an account object based on a custom account class, use the following method:

newAccount(java.lang.String id)

where id identifies the TYPE property of the custom account class that you defined using the

Accounts extension point. If AccountsManager cannot find a class that matches the given TYPE,

then it uses the base Account class to create the new account object.3. Optional: The Account object returned by the AccountsManager contains all the properties of the

account. You can change the properties using the following methods inherited from the

com.ibm.rcp.security.auth.AuthProperties class (There are get methods that correspond to each of

these set methods):

v setName

v setType

338 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 349: Lotus Expeditor: Developing Applications for Lotus Expeditor

v setDescription

v setAuthType

v setProperty

v setProperties

The UID, NAME, DESCRIPTION, and TYPE properties must have values, but other properties are

optional.

Retrieving accounts

You can retrieve an existing account using methods provided by the AccountsManager class.

To retrieve an existing account, perform the following steps:

1. Use the AccountsManagerFactory to access a singleton instance of the platform implementation of the

AccountsManager interface.

AccountsManagerFactory.getAccountsManager();

2. Retrieve a single account by calling one of the following methods:

v getAccount(java.lang.String uid) – Returns an Account object with the given UID from persistent

store.

v getAccountByName(java.lang.String name) – Retrieves the account with the given name or returns

null if no such account exists.3. Retrieve multiple accounts, in a java.util.List object, using one of the following methods:

v getAccounts(java.lang.String field, java.lang.String value) – Returns all accounts that have the

property field and value that matches property value for that account.

v getAccountsByServer(java.lang.String server) – This method does a partial match on HTTP(s) Web

addresses. It first searches for the exact string, and if one or more accounts are found, it returns

those. If no accounts are found, then it breaks down the path of the Web address and tries each

directory separately. For example, if an account has a server name of http://www.ibm.com, a query

String of http://www.ibm.com/lotusnotes returns that account. If you only want exact matches,

call getAccounts(Account.SERVER, <server_name>).

v getAllAccounts() – Returns all of the accounts in the data store, or an empty List if no accounts

have been added.

Updating accounts

You can update existing accounts using methods provided by the AccountsManager class.

When you call the updateAccount method of AccountsManager, you completely replace the existing

account object referenced by the method. Be sure to retrieve the account you want to update and make

changes to it before calling updateAccount().

To update an account, perform the following steps:

1. Use the AccountsManagerFactory to access a singleton instance of the platform implementation of the

AccountsManager interface.

AccountsManagerFactory.getAccountsManager();

2. Retrieve the existing version of the account object you want to change and make the properties

changes.

3. Use one of the following methods to update the account:

v updateAccount(Account) – Updates an existing Account object in persistent store. (completely

replaces existing account object)

v newAccount(java.lang.String id) – Use this method to make changes to an account object and then

change the UID to match that of the existing account.

Securing applications and data 339

Page 350: Lotus Expeditor: Developing Applications for Lotus Expeditor

Listening for account changes

Add an implementation of the AccountChangeListener to listen for changes to existing accounts or for

accounts being created.

Once an Account object is returned from one of the getter methods in AccountsManager, its properties are

not effected by calls made to updateAccount() using another instance of the Account. To keep an Account

instance up to date, add an implementation of AccountChangeListener An AccountEvent is passed to the

listener when a change happens specifying which account has changed, and what type of change took

place. For example, if an account has registered a change listener, the following method is called when an

Account is changed:

accountChanged(AccountEvent event)

To listen for account changes, perform the following steps:

1. Use the AccountsManagerFactory to access a singleton instance of the platform implementation of the

AccountsManager interface.

AccountsManagerFactory.getAccountsManager();

2. Add an AccountChangeListener to the account you want to monitor.

addAccountChangeListener(AccountChangeListener, Account)

3. To find out what change occurred after an event, call getEvent() to retrieve the AccountEvent, which

contains the event details.

4. When you no longer want to monitor an account, remove the listener.

removeAccountChangeListener(AccountChangeListener listener)

Implementing a custom account type

You can extend the Account class using the Accounts extension point.

Every account has an account type. Each account of a given type can either use the base Account class

provided by the API or create and register a class which extends the Account class and provides

additional functionality.

To implement a custom account type, perform the following steps:

1. Extend the Account extension point and define the required attributes.

2. Write a class that extends the Account class and provides the added functionality you want to provide

in the new account.

3. To implement an object of this type, use the newAccount(java.lang.String id) method and pass the

account TYPE as the id parameter.

Managing secure passwords

The Account class provides access to the AccountsLoginContextService. The AccountsLoginContextService

integrates with the Java Authentication and Authorization Service (JAAS) and enables you to get, set and

remove secure account passwords.

The AccountsLoginContextService uses the platform implementation of the Java Keystore to securely

store and encrypt passwords. To add, remove and update passwords the Account must contain a value

for the Account.CREDENTIAL_ID property. A random value is generated when a new Account object is

created. The credential id is an alias to the password and if two or more Accounts share a password, they

must have matching credential ids.

The stage needs to be set just so.

1. Retrieve the account with the password you want to manage.

2. Initialize the service.

340 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 351: Lotus Expeditor: Developing Applications for Lotus Expeditor

account.getLoginContextService()

A call made on this interface uses the information in the Account object, such as user names and Web

addresses along with the password stored in the keystore, if it exists. It does not use the Account

properties from persistent store, which allows the Account object to be modified without affecting

other users of the same account.

3. Manage the password using one of the following methods. These methods communicate directly with

the Key Store, so any changes made are permanent and no call to updateAccount() or addAccount() is

required:

v getPassword() – Gets the password as a String.

v setPassword(String) – Sets a String password.

v removePassword() – Removes the password.

Note: Remove passwords using the remove() method carefully. The service does not check to see if

other accounts share the password before performing the removal. If you call

removeAccount() in the AccountsManager to remove a password, the framework removes

the password only if no other accounts are sharing it.

SSL and accounts

You can also create and SSL connection using accounts. If the Account has an HTTPS URL scheme, it

establishes a connection when login is called on it’s associated LoginContext. The caller of accounts can

then use data in the JAAS subject (returned by the login call) to continue the connection.

Alternatively, after creating an Account with an HTTPS server specified, you can then open a connection

to the HTTPS server using the java.net.URLHandler. The URLHandler will use the data from Accounts to

open an SSL connection to the server.

Login configurations

A login configuration tells the application which LoginModule to use to authenticate users.

A LoginModule describes the interface implemented by authentication technology providers. You do not

need to understand the inner workings of the LoginModule interface to use the modules provided by the

client in your application. However, if you want to write your own login module, refer to the JAAS

LoginModule Developer’s Guide for more information. You can find the Guide at the following Web site:

http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html

The LoginConfigurationProvider tells the application which configuration to use. It implements the

following method:

public AppConfigurationEntry[ ] getAppConfigurationEntry( String configName)

This method returns an array of AppConfigurationEntry objects. An AppConfigurationEntry object

represents a login module. For example, if the configName parameter specifies a configuration that

defines three login modules, the method would return an array of three AppConfigurationEntry objects.

If the provider does not have a configuration for the specified configName, the method returns null and

the system moves to the next configuration provider. If all of the configuration providers return null, a

LoginException is thrown.

LoginModules occassionally need to communicate with the user of the application to obtain

authentication information or to provide status information to the user. LoginModules use a

CallbackHandler to do so. Applications implement the CallbackHandler interface and pass it to the

LoginContext, which forwards it to the LoginModule. By default, Lotus Expeditor Client ships with one

CallbackHandler for use during platform login. The unique identifier of this CallbackHandler is

Securing applications and data 341

Page 352: Lotus Expeditor: Developing Applications for Lotus Expeditor

com.ibm.rcp.security.auth.ui.defaultKSCallbackHandler. This CallbackHandler prompts the user for

information using an org.eclipse.jface.dialog.TitleAreaDialog. If the callback handler is passed one

PasswordCallback parameter, the resulting dialog box contains one field, labeled Password. If the callback

handler is passed two PasswordCallback parameters, the resulting dialog box contains two fields, labeled

Enter password and Confirm password. You can specify the title and image to display in the dialog box

using Eclipse themes.

Logging into the platform

Lotus Expeditor Client uses the Java Authentication and Authorization Service (JAAS) to provide a

configurable and flexible platform login experience.

JAAS is a Java implementation of the standard Pluggable Authentication Module (PAM) framework and

supports user-based authentication, which means it reliably and securely determines who is currently

executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a

servlet, and supports user-based authorization, which means it ensures users have the access control

rights or permissions required to perform the actions they are trying to perform.

For more information about JAAS, refer to http://java.sun.com/products/jaas/overview.html.

The default client personality automatically logs into the platform when a user starts the client. If you are

using a different personality, you can use the SecurePlatform class to log in. The SecurePlatform class

provides methods to access and log into the platform keystore. It uses the KeyStoreLoginModule to

unlock the keystore. The KeyStoreLoginModule is a non-public login module. Before you implement the

login module, you must determine when you want to initialize the platform login. You can code it to

occur at any time during a client session, but the following two times are most commonly used:

v At startup -- Only grants users access to the Workbench if their login is successful. Otherwise, the

platform exits. This method is useful when the applications installed on the client contain default

views that display secure information. For example, if the default application is an e-mail application

that displays the Inbox view when a user first opens the application.

v Lazily -- Login occurs only when access to the platform key store or the JAAS Subject object is

requested. This method is useful when the applications installed on the client do not display secure

information by default. For example, if the default application is a word processing application that

does not display any documents when a user first opens the application.

To log into the client using the default platform login module, perform the following step:

Log into the client using the SecurePlatform class.

import com.ibm.rcp.security.auth.SecurePlatform;

public void doLogin() {

try {

SecurePlatform.getLoginContext().login();

}catch (LoginException e) {

// Login failed... exit platform or take corrective action

}

}

After you log into the client, you can use the Accounts API. You can use the

AccountsLoginContextService provided by the Accounts API to call the PBEKeyReaderModule and

PBEKeyWriterModule classes to read and write passwords to the key store. The PBEKeyReaderModule

and PBEKeyWriterModule are non-public classes.

Logging into remote servers

To log into a remote server, you can implement your own login module and configuration or you can use

one of the JAAS login modules provided by the Lotus Expeditor.

342 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 353: Lotus Expeditor: Developing Applications for Lotus Expeditor

The following login modules are provided by the client:

v HTTP basic authentication

v Form-based authentication

Using HTTP basic authentication

HTTP basic authentication is an authentication method that requires only a user name and password to

authenticate users who are transferring data over the HTTP protocol.

When you implement the HTTP basic authentication login module, the PBEKeyReaderModule reads the

password from the key store. If the credentials are not found in the inputs supplied by the caller, the

login module invokes the callback handlers supplied by the caller to get the user name and password.

The login module persists the passwords it retrieves from the callback handler in a shared list maintained

by the calling account and updates the user name in the AuthProperties object in the subject. The

HTTPBasicLoginModule validates the password and then the PBEKeyWriterModule writes the validated

password to the key store.

To implement HTTP basic authentication, perform the following steps:

1. Create an account or retrieve an existing account.

2. Call account.setProperty() to set the value of each of the following properties:

v SERVER – Complete URL for the server, containing the protocol (HTTP or HTTPS), domain, path,

and optionally, the port.

v USER_NAME – The http user name.

v CREDENTIAL_ID – Alias which references a password in the keystore. If the password does not

already exist, it is created and this value is set as its alias. Accounts sharing the same password

must have the same credential id.

v MASTER_PROPS (Optional) – The UID of another Account. Master properties are useful when two

or more accounts are accessing services that use the same user directory and share more than just

passwords. When account.getLoginContext() is called the “master” account is used to authenticate

instead of the account making the method call. The “slave” account can then access the “master”

account’s authenticated credentials through the Subject and use them to communicate with the

service. If this value is set, only the SERVER property needs to have a value; the login module

retrieves values for the other properties from the Master account.

Note: You do not need to set the value of the AUTH_TYPE property. ″HTTP″ is the default value.

3. Log in using the specified account.

account.getLoginContext().login();

4. Use the following method to extract the user name from the subject:

String username =

((AuthProperties)subject.getPublicCredentials(AuthProperties.class).

toArray()[0]).getProperty(AuthProperties.USER_NAME);

The getSubject() method returns the authenticated Subject which contains a user name and password

as well as an optional LTPA or other token.

Using form-based authentication

The form-based authentication module provided with the client performs form based logins to remote

WebSphere Portal servers.

Form-based authentication is one of the standard authentication mechanisms in the J2EE architecture. It is

an authentication mechanism that uses a custom login form supplied by the application to collect a user

name and password. The user supplies a user name and password. These are passed to the WebSphere

Application Server’s user registry to be matched with information stored there. If the user name and

password supplied fails to match the information stored in the user registry, the login form reappears.

Even if the user manually enters an HTTP request for a resource, she is redirected to the login form. The

Securing applications and data 343

Page 354: Lotus Expeditor: Developing Applications for Lotus Expeditor

user must enter a valid user name and password before she can successfully access any system resources.

If the user name and password succeeds in matching the information stored in the user registry,

authentication is successful.

The form-based authentication login module also supports single sign-on, which means that users only

have to log into the remote server once and can access any services available from that server for which

they have permissions. If Global security is enabled on the WebSphere Application Server and

Lightweight Third-Party Authentication (LTPA) is specified as the authentication mechanism, then when

the user authentication succeeds, the form based authentication login module returns an LTPA token.

When you implement the form-based authentication login module, the PBEKeyReaderModule reads the

password from the key store. If the credentials are not found in the inputs supplied by the caller, the

login module invokes the callback handlers supplied by the caller to get the username and password. The

login module persists the password retrieved from the callback handlers in a shared list maintained by

the calling account and updates the user name in the AuthProperties object in the subject. The

J2EEFormLoginModule validates the password, and then the PBEKeyWriterModule writes the validated

password to the key store. Additionally, this login module adds an object of

com.ibm.rcp.security.auth.SingleSignonToken type, which contains the LTPA token, to the list of private

credentials in the Subject.

To implement form-based authentication, perform the following steps:

1. Create an account or retrieve an existing account.

2. Call account.setProperty() to set the values of each of the following properties:

v SERVER – Complete URL for the server, containing the protocol (HTTP or HTTPS), domain, path,

and optionally, the port.

v USER_NAME – The HTTP user name.

v CREDENTIAL_ID – An alias which references a password in the key store. If the password does

not already exist, it is created and this value is set as its alias. Accounts sharing the same password

must have the same credential id property value.

v AUTH_SERVER -- The URL used for authentication only. This can be a complete URL like the

SERVER value, or it can be a path which is appended to the base domain of the SERVER value.

Callers can just use this property as long as it contains both the context URL and the host name.

v AUTH_TYPE -- Tells JAAS which login configuration to use. This property must be set to

J2EE-FORM. The default value is HTTP.

v MASTER_PROPS: (Optional) – The UID of another Account. Master properties are useful when two

or more accounts are accessing services that use the same user directory and share more than just

passwords. When account.getLoginContext() is called the “master” account is used to authenticate

instead of the account making the method call. The “slave” account can then access the “master”

account’s authenticated credentials through the Subject and use them to communicate with the

service. If this value is set, only the SERVER property needs to have a value; the login module

retrieves values for the other properties from the Master account.3. Log in using the specified account.

account.getLoginContext().login();

4. Use the following method to extract the LTPA token from the Subject:

SingleSignonToken token =

(SingleSignonToken)subject.getPrivateCredentials(SingleSignonToken.class).

toArray()[0];

The getSubject() method returns the authenticated Subject which contains a user name and password,

as well as an optional LTPA or other token.

344 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 355: Lotus Expeditor: Developing Applications for Lotus Expeditor

Using platform single sign-on

Single sign-on (SSO) authenticates users by prompting them for a user name and password a single time.

Enabling platform single sign-on gives users secure access to the platform key store without displaying

additional authentication prompts.

To implement platform single sign-on, perform the following steps:

1. In the plugin_customization.ini file in the com.ibm.rcp.platform.personality.branding plug-in, set the

value of the following preferences to true:

v com.ibm.rcp.security.auth.ui/ssoAllowed – Boolean value. Determines whether or not users have

the option of using single sign-on. You can set this preference value during the client installation or

later using a managed setting. This preference should not be surfaced to users.

v com.ibm.rcp.security.auth.ui/ssoEnable – Boolean value. Determines whether or not users have the

option of turning single sign-on on or off. If set to true, single sign-on can be used. If set to false,

single sign-on is disabled. The value of this preference is relevant only if ssoAllowed is set to true.

For example:

com.ibm.rcp.security.auth/loginEnabled=true

com.ibm.rcp.security.auth.ui/ssoAllowed=true

2. In the plugin_customization.ini file in the com.ibm.rcp.platform.personality.branding plug-in, set the

value of the following preference to SSO-KS:

v com.ibm.rcp.security.auth/loginConfigName

For example:

com.ibm.rcp.security.auth/loginConfigName=SSO-KS

3. Log into the client using the SecurePlatform class.

import com.ibm.rcp.security.auth.SecurePlatform;

public void doLogin() {

try {

SecurePlatform.getLoginContext().login();

}

catch (LoginException e) {

// Login failed... exit platform or take corrective action

}

}

Implementing single sign-on with remote servers

Single sign-on means that users only have to log onto a remote server once and can access any services

available from that server for which they have permissions.

The form-based authentication login module that is provided with the client performs a form based login

against a remote WebSphere Portal server and retrieves a LTPA token. The LTPA token is returned in the

form of a SingleSignonToken object. The SingleSignonToken object has a getSsoTokens() method which

returns an array of org.apache.commons.httpclient.Cookie objects. You can use these cookies to leverage

the LTPA token for authentication. This object also implements the JAAS Refreshable and Destroyable

interfaces, allowing the caller to refresh and destroy the tokens. You can provide your own form-based

login modules which provide SSO tokens for platform consumers by providing your own implementation

of the SingleSignonToken interface.

To implement single sign-on with a remote server, perform the following step:

Do one of the following:

v Implement single sign-on with a remote WebSphere Portal server by implementing form based

authentication.

v Implement single sign-on with another remote server by providing a custom implementation of the

SingleSignonToken interface.

Securing applications and data 345

Page 356: Lotus Expeditor: Developing Applications for Lotus Expeditor

Contributing a login configuration

You can contribute a login configuration to tell the client to use a specific LoginModule when

authenticating users.

Lotus Expeditor Client provides public login modules which you can extend to implement authentication

to remote servers in your application. The login modules provided enable you to log into a remote

WebSphere Portal server. The client supports the following remote server login configurations:

v HTTP -- Uses HTTP basic authentication to authenticate users who are transferring data over the HTTP

protocol.

v J2EE-FORM -- Uses a form based login to log into a remote WebSphere Portal servers. Form-based

authentication is authentication that uses a custom login form supplied by the application to collect a

user name and password.

Lotus Expeditor Client also provides public login modules which you can extend to implement

authentication to the platform key store in your application. The client supports the following platform

login configurations:

v KS – Uses the KeyStoreLoginModule. The KeyStoreLoginModule gets the password used to load the

key store by first checking the shared state for the value associated with the key “SSO_PASSWORD.” If

such a value exists, the login module uses it. If it does not exist, the provided CallbackHandler

prompts the user for a key store password. After it retrieves the password, the module places the key

store password in the platform Subject.

v SSO-KS – Stacks the SSOLoginModule on top of the KeyStoreLoginModule. If single sign-on is enabled,

the login module loads the platform key store, but does not prompt the user for a password. If single

sign-on is disabled, the user experience is the same as it is for the KS configuration. The

SSOLoginModule generates a unique password composed of a set of 128 random bytes. This password

is persistently and securely* stored using the secureWrite() method in the operating system library

component. The password is available to other LoginModules as the value of the “SSO_PASSWORD”

property in the shared state. The key associated with the password is composed of a set of 64 random

bytes, Base64 encoded, and stored as the value of the com.ibm.rcp.security.auth.ui/sk preference.

*Note: The secureWrite() method used to securely store passwords is platform dependent. Single

sign-on on a Linux operating system is not fully secure; the password is only obfuscated.

Administrators must ensure that the workspace is secured such that only appropriate users have read

access.

If you use a platform login configuration other than the two default configurations, you must guarantee

that the configurations meet the following conditions:

v The platform key store must be successfully loaded using a password retrieved from either the

SSO_PASSWORD item in the shared state or from the CallbackHandler. If the platform key store does

not exist, it must be created using the given password.

v The password used to store and load the platform key store must be placed in a private Credential set

in the Platform Subject.

To contribute a login configuration, perform the following steps:

1. Define the login module to use for the application by doing one of the following:

v Use one of the login modules provided by the client.

v Contribute a Login Module using the com.ibm.rcp.security.auth.loginModule extension point.

If you want to write your own login module, refer to the JAAS LoginModule Developer’s Guide for

information about how to write one. You can find the Guide at the following Web site:

http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html

Provide values for the following attributes of the <extension> element:

– point - A fully qualified identifier of the target extension point, which in this case is

″com.ibm.rcp.security.auth.loginModule″.

346 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 357: Lotus Expeditor: Developing Applications for Lotus Expeditor

– id - A required identifier of the extension instance that applications can use to reference it.

– name - An optional name of the extension instance.

In the <loginmodule> element, provide values for the following attributes:

– class - Fully qualified name of the class that implements the javax.security.auth.spi.LoginModule

interface.

– description – Short description of the task performed by this LoginModule.

For example:

<extension

id="keystoreLoginModule"

name="KeyStore LoginModule"

point="com.ibm.rcp.security.auth.loginModule">

<loginModule

class="com.ibm.rcp.internal.security.auth.module.KeyStoreLoginModule"

description="LoginModule for KeyStore"/>

</extension>

2. Contribute a login configuration using the com.ibm.rcp.security.auth.loginConfigurationProvider

extension-point.

Provide values for the following attributes of the <extension> element:

v point - A fully qualified identifier of the target extension point, which in this case is

″com.ibm.rcp.security.auth.loginConfigurationProvider″.

v id - A required identifier of the extension instance that applications can use to reference it.

v name - An optional name of the extension instance.

In the <loginConfigurationProvider> element, provide a value for the following attribute:

v class - Fully qualified name of the class that extends the javax.security.auth.login.Configuration

class.

Optionally, in the <loginConfigurationUrl> element, provide a value for the following attribute:

v url – Location of a configuration file for this loginConfigurationProvider to use.

For example:

<extension

id="ksConfigurationProvider"

name="Default Configuration Provider for KeyStore"

point="com.ibm.rcp.security.auth.loginConfigurationProvider">

<loginConfigurationProvider class="com.ibm.rcp.internal.security.auth.

KSConfigurationProvider"/>

</extension>

3. Instruct the platform to use your custom configuration by setting the value of the AUTH_TYPE

property in the account equal to the login configuration String value you defined in the login

configuration class.

account.setProperty(Account.AUTH_TYPE, "THUMB")

4. Optional: Contribute a callback handler to the platform using the

com.ibm.rcp.security.auth.callbackHandler extension point.

Note: If you do not want to contribute a custom callback handler, you can use the default callback

handler provided by the platform.

Provide values for the following attributes of the <extension> element:

v point - A fully qualified identifier of the target extension point, which in this case is

″com.ibm.rcp.security.auth.callbackHandler″.

v id - A required identifier of the extension instance that applications can use to reference it.

v name - An optional name of the extension instance.

In the <callbackHandler> element, provide a value for the following attribute:

Securing applications and data 347

Page 358: Lotus Expeditor: Developing Applications for Lotus Expeditor

v class - fully qualified name of the class that implements the

javax.security.auth.callback.CallbackHandler interface.

For example:

<extension

id="defaultUsernamePasswordCallbackHandler"

name="Default CallbackHandler for retrieving a username/password

point="com.ibm.rcp.security.auth.callbackHandler">

<callbackHandler

class="foo.auth.dialog.NameAndPasswordLoginDialog"/>

</extension>

5. Use the com.ibm.rcp.security.auth.callbackHandlerMapping extension point to do one of the

following:

v Specify to use a callback handler provided by the client, such as

com.ibm.rcp.security.auth.ui.defaultKSCallbackHandler.

v Specify the custom CallbackHandler you defined in the previous step as the handler that should be

used by your custom configuration.This handler is passed to all LoginModules used by the Configuration.

Provide values for the following attributes of the <extension> element:

v point - A fully qualified identifier of the target extension point, which in this case is

″com.ibm.rcp.security.auth.callbackHandlerMapping″.

v id -- A required identifier of the extension instance that applications can use to reference it.

v name - An optional name of the extension instance.

In the <callbackHandlerMapping> element, provide values for the following attributes:

v configName – name of the Configuration to bind this CallbackHandler to, for example, “KS”,

“SSO-KS”, ″J2EE″, or ″HTTP″.

v callbackHandlerId – the unique identifier of the CallbackHandler to bind to the specified

Configuration.

For example:

<extension id="defaultHttpBasicCallbackHandler"

name="Default CallbackHandler for HTTP-BASIC Login Configuration"

point="com.ibm.rcp.security.auth.callbackHandler">

<callbackHandler class=

"com.ibm.rcp.internal.security.auth.dialog.HttpBasicLoginDialog"/>

</extension>

6. Optional: Instruct the client to use your custom login configuration as the default platform login

configuration by setting the value of following application preference equal to the name of your

configuration:

com.ibm.rcp.security.auth/loginConfigName

348 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 359: Lotus Expeditor: Developing Applications for Lotus Expeditor

Enabling applications for configuration

This section provides information for enabling applications for configuration.

Using preferences

Plug-in preferences are key/value pairs, where the key describes the name of the preference, and the

value is one of several different types, including Boolean, double, float, int, long, and string. The Eclipse

platform provides support for storing plug-in preferences and showing them to the user on pages in the

workbench Preferences dialog box.

Lotus Expeditor extends the Eclipse capabilities by including the Managed Settings framework, which

can control Eclipse settings based on an administrator’s specification.

Creating preference pages

The references to Preferences in this section cover a wide range of information, from user choices on how

to display information, to configuration options needed to connect to enterprises. The client platform

framework provides built-in capabilities to help manage preferences. You may choose to use one or both

of these options, or to construct your own mechanisms.

When you write the code that defines the content of the preference page, follow these formatting rules:

v Use group boxes to separate areas, if you feel that grouping is necessary. Capitalize only the first letter

of the first word of the group box heading.

v Begin each preferences page with a sentence that describes what the user can do.

v Add a colon after field labels.

v Always provide the Restore Defaults and Apply buttons. You can add other command buttons as

necessary

Using the Managed Settings framework

This framework allows an administrator to initialize, and optionally control, settings values in the Eclipse

preference store. They do this by defining policy and preference settings, or any other name and value

pairs, on the back-end system of their choice. Updates run periodically to populate the designated scopes

and qualifiers in the Eclipse preference store with any new settings or settings changes specified by the

administrator. The administrator may also designate a setting as being read-only. If this is the case, any

user changes to the value will be disallowed.

Administrators can use the managed settings framework to populate both the standard Eclipse scopes

and a custom scope called the ManagedSettingScope. You may use either one to access your application’s

settings. However, there are two advantages to using the ManagedSettingsScope:

v The ManagedSettingScope allows you to determine if the administrator has designated a particular

setting as read-only. If so, you can disable any user interface that would allow the user to change it. If

you do not do this, and allow the end user to change the value using the standard Eclipse Scopes, the

Managed Settings framework will revert the change, causing confusion and frustration for the end

user. Also, if there are any plug-ins monitoring settings changes, they will get two events, one for the

users change and one for the managed settings reversion. Not only could this cause flicker in the UI,

but the reversion could come too late to stop an action that the administrator meant to prevent. If you

do use the ManagedSettingScope to set the value, but forget to check first if it was read-only, the change

will be prevented entirely instead of being reverted after the fact. While this does not improve the

end-user experience, it does prevent any side-effects from having two change events, and more

importantly, enforces the administrator’s intent.

© Copyright IBM Corp. 2004, 2006 349

Page 360: Lotus Expeditor: Developing Applications for Lotus Expeditor

v The standard Eclipse preference scopes use text files to store their data, allowing end users to easily

change the values even if there is no UI in the application to do so. If they do edit a read-only value,

the managed settings framework will revert the value in as timely a manner as possible, but there

could be short periods where the administrator’s value is not the one being used. The

ManagedSettingScope obfuscates its data as a deterrent to end-user tampering. If you retrieve the

settings from the ManagedSettingsScope, you will always be getting the administrator value and not

the user value.

The Portlet Container uses the Managed Settings Framework to implement the Portal Policy API on the

client. If you have an existing applications that uses the Portal Policy API to retrieve values from the

Portal Policy Manager, it can use the same code to retrieve Managed Settings from the Eclipse Preference

store.

Creating a managed settings-aware application:

You do not need to know whether a particular setting is managed in order to use the

ManagedSettingsScope to retrieve its value. If the ManagedSettingsScope does not find the setting

internally, it will automatically search the standard Eclipse scopes and return the value of the setting from

there. This also means that you can still set defaults in the standard ways. Designing your application

using the ManagedSettingsScope accommodates settings that are not managed currently, but may be

managed in the future.

Note: If you are using the Portal Managed Client, you can skip Steps 1 and 2. The Portal Managed Client

automatically performs these steps.

1. By default, the first managed settings update occurs asynchronously when the

com.ibm.rcp.managedsettings plug-in starts. If you want to ensure that the managed settings for an

application have been retrieved before the application begins to run, you can call the following

methods in your initial setup sequence. This also has the effect of starting the Managed Settings

plug-in:

if (!ManagedSettings.hasData()){

ManagedSettings.runSynchronousUpdate(false)

}

This method forces a synchronous update because it waits for the update to complete before it

returns. The false parameter indicates that an update should not be run if the update interval has not

expired. Setting this parameter to true forces an update to run even if the update interval has not

expired. A parameter setting of true should rarely be needed and is only provided to support the

retrieval of settings that the application somehow knows are new and that it needs immediately.

2. If you do not do step 1., you must use another method to start the Managed Settings plug-in,

com.ibm.rcp.managedsettings, early in the client startup cycle. One way to do this is to use a life

cycle extension point. See the Eclipse documentation for other ways to start plug-ins. Note that this

plug-in must be started in order for the administrator’s settings to be brought to the client, even if

individual plug-ins in the application are only using the standard Eclipse scopes and are not accessing

the settings through the Managed Settings scope.

3. Publish a list of the settings used by your application, and the scopes and qualifiers you are using to

access them from the Eclipse Preference store, so that administrators know how to specify values for

the settings.

4. When writing user interface code that allows the end user to change the values of settings, check the

read-only status of each setting before enabling the associated control.

For example, to find out if the setting, canSendAttachments, that is accessed through the qualifier,

com.ibm.workplace.messaging, is a read-only setting, use the following code:

ManagedSettingsScope msScope = new ManagedSettingsScope();

IEclipsePreferences messagingSettings =

msScope.getNode(("com.ibm.workplace.messaging");

boolean canSendAttachments =

messagingSettings.get(“canSendAttachments”, false);

350 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 361: Lotus Expeditor: Developing Applications for Lotus Expeditor

boolean canUserChangeValue =

msScope.isReadOnly("com.ibm.workplace.messaging", (“canSendAttachments”);

The false parameter passed to the get method is the default value that is returned if a value is not

found on the client, even in Default Scope.

5. Be careful with caching the value of a setting because it can be refreshed from the back-end system at

any time. If you do cache it, be sure to register a listener to update the cache if it changes.

6. Register an implementation of the org.eclipse.core.runtime.preferences.IEclipsePreferences.

IPreferenceChangeListener listener on any preference nodes that you want to keep track of.

For example:

messagingSettings.addPreferenceChangeListener(listener)

Using the Portal Policy API on the client:

Portal Policy settings that are brought to the client using Managed Settings framework are also accessible

using the Portal Policy API.

To get Policy Settings using the Portal Policy API:

1. Create a portlet. Select File > New > Portlet Project, and then select Basic Portlet as the portlet type.

2. Select view in Content types and modes, and then click Finish.

3. Use the RenderResponse object to retrieve a managed setting by adding the following code to the

doView(RenderRequest request, RenderResponse response) method of the ClientPolicyPortlet class.

For example:

This code retrieves and displays the policy setting key named ″testMS″ in View mode.

com.ibm.test.myportlet is the policy type of the policy setting.

Creating Eclipse Preference Sets with the Policy Type Editor: The Policy Type Editor for Preferences

removes much of the complexity from the process of updating preferences. With the Policy Type Editor

for Preferences, any Portal Managed Client (PMC) client application that requires centrally administrated

preferences only needs to provide the XML Preference Set/Policy Type definition which defines one or

more preferences. This template is then imported to the Policy Type Editor for Preferences. No additional

code is needed.

public void doView(RenderRequest request, RenderResponse response)throws PortletException, IOException {

// Set the MIME type for the render response

response.setContentType(request.getResponseContentType());

javax.naming.Context ctx = new javax.naming.InitialContext();

PolicyManagerService pms = (PolicyManagerService) ctx.lookup("portal:service/policy/PolicyManager");

PolicyManager policyManager = pms.getPolicyManager();

Target target = policyManager.createTarget(new PortletRequestRuleContext((PortletRequest)request));

Object testMS = policyManager.getValueByTarget(target,"com.ibm.test.myportlet","testMS");

testMSStr = (String) testMS;

response.getWriter().println("<b>[testMS]: " + testMSStr + "</b>");

return;

}

Enabling applications for configuration 351

Page 362: Lotus Expeditor: Developing Applications for Lotus Expeditor

As a developer, you are responsible for writing an XML template defining a Preferences Set / Policy Type

to be managed, including a definition of the preferences, appropriate user friendly labels for displaying

the preferences, and any information that the GUI would use to restrict and/or validate data entered for

the preferences.

Working with Preference Sets: Preference Sets are defined in XML descriptor files referred to as templates.

The templates are written using a format that allows preferences to be generically described. The

template must include all information required to render and validate each preference included.

Each preference is defined with sufficient information that the Editor can construct GUI pages that look

and act almost as if written specifically for those data items. In the XML template, the plug-in developer

can:

v Set a name for the Preference Set/Policy Type.

– Provide translated display names for the Policy Type

– Provide translated descriptions for the Policy Typev Create individual preferences within a Policy Type

– Provide translated display names for the preference

– Set the scope

– Set the qualifier

– Set the key

– Optionally, set a default for the preference’s value.

– Set the item’s type, such as ″URL″, “Integer″ or “boolean”. This is used by the GUI to draw to an

appropriate input entry and validate input to meet the requirements of that type.

– Provide a limited set of possible values to select from. These are usually presented in a drop down

list.

– Set whether a value is required to be entered or can be left blank

The Editor looks at each preference, and provides appropriate validation and error messages when the

administrator enters invalid data. The GUI also uses the type to determine what format of input field to

generate. A boolean will get a check box, a string will get an edit field. Once input is provided, it is

validated to ensure the data provided matches the designated type. The complete list of types supported

is:

v string -- a java.lang.String, no restrictions on values

v boolean – defaults to “true” and “false”

v integer -- convertible to a java.lang.Integer

v real -- convertible to a java.lang.Double

v url -- convertible to a valid java.net.URL

Preferences can have additional constraints defined. Constraints set additional limits on the values that

can be entered. The current list of supported constraints is:

v Enumeration -- a restricted list of values to choose from. The GUI will generate a drop down list box

containing only these values.

v Minimum value <min> -- for integer and real types, the value must be equal to or greater than the

minimum

v Minimum length <min> -- for non-numeric types, the minimum number of characters that must be

entered

v Maximum value <max> -- for numeric types, the value must be equal to or less than the maximum

v Maximum length <max> -- for all other types, the maximum number of characters that may be

entered

352 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 363: Lotus Expeditor: Developing Applications for Lotus Expeditor

v BooleanValues -- the value must conform to one of two values determined by the user. The default is

true/false, but any two string values can be set using <trueValue> and <falseValue>

Each Preference Set contains enough information to allow the Editor to dynamically generate appropriate

data entry entities, with translated labels. Many errors in data entry can be caught on the server by

validating the data against the definitions in the Preference. Translated error messages are displayed,

prompting the administrator on how to correct their entries.

Configuration set Document Type Definition:

<?xml version="1.0" encoding="UTF-8"?>

<!ELEMENT preferenceSet (name, default-locale, language*, preference*)>

<!ATTLIST preferenceSet

version CDATA #REQUIRED>

<!ELEMENT preference (value?, constraints?, language* )>

<!ATTLIST preference

scope CDATA #IMPLIED

qualifier CDATA #REQUIRED

key CDATA #REQUIRED

type (boolean | integer | real | string | url ) #REQUIRED

required (yes | no) "no">

<!ELEMENT language (display-name?, description?) >

<!ATTLIST language

locale CDATA #IMPLIED >

<!ELEMENT values (value*)>

<!ELEMENT value (#PCDATA)>

<!ELEMENT constraints (min?, max?, enumeration?, booleanValues? )>

<!ELEMENT enumeration (value*)>

<!ELEMENT booleanValues (trueValue, falseValue) >

<!ELEMENT display-name (#PCDATA)>

<!ELEMENT description (#PCDATA)>

<!ELEMENT max (#PCDATA)>

<!ELEMENT min (#PCDATA)>

<!ELEMENT name (#PCDATA)>

<!ELEMENT trueValue (#PCDATA)>

<!ELEMENT falseValue (#PCDATA)>

<!ELEMENT default-locale (#PCDATA)>

The following table provides additional element and attribute description information for the above

Document Type Definition:

Table 28. Additional Element Descriptions

Element or Attribute Name Description

preferenceSet Root Element for defining a Preference Set

version Version level for the preference set

provider-name Name of company providing the preference set

preference Root Element for each key/value pair definition

default-locale Defines which language to use when the requested

language has no values

Enabling applications for configuration 353

Page 364: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 28. Additional Element Descriptions (continued)

Element or Attribute Name Description

Language Defines display data for a specific language

display-name Localized name used by the GUI as the label for the

input field

description Localized description

scope scope – see Eclipse Preferences Documentation

qualifier Qualifier, typically the plug-in name– see Eclipse

Preferences Documentation

key Key within the qualifier. – see Eclipse Preferences

Documentation

type See descriptions in (ADD LINK TO PREVIOUS

SECTION)

required Forces a default value to be provided. (Blank is not

allowed)

value The default value for an item

constraint, min, max, enumeration See descriptions in (ADD LINK TO PREVIOUS

SECTION)

Preference Set sample template: The following is an example of a Preference Set template:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE preferenceSet SYSTEM "preferenceSet.dtd">

<preferenceSet version="1.0" provider-name="IBM">

<name>TraderPreferences</name>

<default-locale>en</default-locale>

<language locale= "en">

<display-name>Stock Trade Preferences</display-name>

<description>Description of a Sample Preference Set</description>

</language>

<language locale= "ja">

<display-name>JA-Stock Trade Preferences</display-name>

<description>JA-Discription of a Sample Preference Set</description>

</language>

<language locale= "fr">

<display-name>FR-Stock Trade Preferences</display-name>

<description>FR-Description of Sample Preference Set</description>

</language>

<preference scope="instance" qualifier="com.ibm.plugin.preference"

key="UpdateFrequency" type="string" required="yes">

<value>weekly</value>

<constraints>

<enumeration>

<value>never</value>

<value>hourly</value>

<value>daily</value>

<value>weekly</value>

<value>monthly</value>

</enumeration>

</constraints>

<language locale= "en">

<display-name>Update Interval</display-name>

<description>Frequency of automatic report updates.</description>

</language>

<language locale= "ja">

<display-name>JA-Update Interval</display-name>

354 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 365: Lotus Expeditor: Developing Applications for Lotus Expeditor

<description>JA-Frequency of automatic report

updates.</description>

</language>

<language locale= "fr">

<display-name>FR-Update Interval</display-name>

<description>FR-Frequency of automatic report

updates.</description>

</language>

</preference>

<preference scope="" qualifier="com.ibm.plugin.preference"

key="MaximumTransactionAmount" type="integer" required="yes">

<value>200</value>

<constraints>

<min>5</min>

<max>5000</max>

</constraints>

<language locale= "en">

<display-name>Maximum Transaction Amount</display-name>

<description>The maximum dollar amount allowed per

transaction.</description>

</language>

<language locale= "ja">

<display-name>JA-Maximum Transaction Amount</display-name>

<description>JA-The maximum dollar amount allowed per

transaction.</description>

</language>

<language locale= "fr">

<display-name>FR-Maximum Transaction Amount</display-name>

<description>FR-The maximum dollar amount allowed per

transaction.</description>

</language>

</preference>

<preference scope="" qualifier="com.ibm.plugin.preference"

key="RequiredApprovals" type="integer" required="yes">

<value>1</value>

<constraints>

<min>1</min>

<max>8</max>

</constraints>

<language locale= "en">

<display-name>Manager Approval Levels</display-name>

<description>The number of Managers required to

approve. </description>

</language>

<language locale= "ja">

<display-name>JA-Manager Approval Levels</display-name>

<description>JA-The number of Managers required to

approve. </description>

</language>

<language locale= "fr">

<display-name>FR-Manager Approval Level</display-name>

<description>FR-The number of Managers required to

approve.</description>

</language>

</preference>

<preference scope="instance" qualifier="com.ibm.plugin.preference"

key="Division" type="string" required="no">

<value>CompanyAccess</value>

<constraints>

<min>8</min>

<max>20</max>

</constraints>

<language locale= "en">

<display-name>Company Access Code</display-name>

Enabling applications for configuration 355

Page 366: Lotus Expeditor: Developing Applications for Lotus Expeditor

<description>The Company’s Access Code.</description>

</language>

<language locale= "ja">

<display-name>JA-Company Access Code</display-name>

<description>JA-The Company’s Access Code.</description>

</language>

<language locale= "fr">

<display-name>FR-Company Access Code</display-name>

<description>FR-The Company’s Access Code.</description>

</language>

</preference>

<preference scope="instance" qualifier="com.ibm.plugin2.preference"

key="CompURL" type="url" required="no">

<value>http://www.myCompany.com</value>

<language locale= "en">

<display-name>Company Web Site</display-name>

<description>URL of the company web site.</description>

</language>

<language locale= "ja">

<display-name>JA-Company Web Site</display-name>

<description>JA-URL of the company web site.</description>

</language>

<language locale= "fr">

<display-name>FR-Company Web Site</display-name>

<description>FR-URL of the company web site.</description>

</language>

</preference>

<preference scope="instance" qualifier="com.ibm.plugin.preference"

key="AfterHoursAccess" type="boolean" required="no">

<value>no</value>

<constraints>

<booleanValues>

<trueValue>yes</trueValue>

<falseValue>no</falseValue>

</booleanValues>

</constraints>

<language locale= "en">

<display-name>Allow after hours access</display-name>

<description>Allow transations after business

hours.</description>

</language>

<language locale= "ja">

<display-name>JA-Allow after hours access</display-name>

<description>JA-Allow transations after business

hours.</description>

</language>

<language locale= "fr">

<display-name>FR-Allow after hours access</display-name>

<description>FR-Allow transations after business

hours.</description>

</language>

</preference>

<preference scope="instance" qualifier="com.ibm.plugin.preference"

key="MultipleLogon" type="boolean" required="no">

<value>enable</value>

<constraints>

<booleanValues>

<trueValue>enable</trueValue>

<falseValue>disable</falseValue>

</booleanValues>

</constraints>

<language locale= "en">

<display-name>Allow simultaneous logon</display-name>

<description>Allow account to be logged on in multiple

356 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 367: Lotus Expeditor: Developing Applications for Lotus Expeditor

locations.</description>

</language>

<language locale= "ja">

<display-name>JA-Allow simultaneous logon</display-name>

<description>JA-Allow account to be logged on in multiple

locations.</description>

</language>

<language locale= "fr">

<display-name>FR-Allow simultaneous logon</display-name>

<description>FR-Allow account to be logged on in multiple

locations.</description>

</language>

</preference>

<preference scope="instance" qualifier="com.ibm.plugin.preference"

key="AutoLockout" type="boolean" required="no">

<value>0</value>

<constraints>

<booleanValues>

<trueValue>1</trueValue>

<falseValue>0</falseValue>

</booleanValues>

</constraints>

<language locale= "en">

<display-name>Automatic Lockout Enabled</display-name>

<description>Locks account when unusual activity

detected.</description>

</language>

<language locale= "ja">

<display-name>JA-Automatic Lockout Enabled</display-name>

<description>JA-Locks account when unusual activity

detected.</description>

</language>

<language locale= "fr">

<display-name>FR-Automatic Lockout Enabled</display-name>

<description>FR-Locks account when unusual activity

detected.</description>

</language>

</preference>

</preferenceSet>

The following table gives some additional information on how the GUI was created in this sample. It also

provides information on the sample’s data validation settings.

Table 29. Additional Sample Information

Title of Preference Preference Qualifier/Key Rule Details

Update Interval instance/com.ibm.plugin.preference/

UpdateFrequency

The GUI utilizes a drop down

selection box. This preference’s

value is restricted to one of an

enumerated set of valid values

that were defined in the template.

Maximum Transaction Value instance/ com.ibm.plugin.preference/

MaximumTransactionAmount

An entry field is used, but the

data must be an integer between 5

and 5000.

Manager Approval Levels com.ibm.plugin.preference/RequiredApprovals

An entry field is used, but the

data must be an integer between 1

and 8. This item could also have

been implemented with an

enumerated set of valid values

and a drop down box would be

created.

Enabling applications for configuration 357

Page 368: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 29. Additional Sample Information (continued)

Title of Preference Preference Qualifier/Key Rule Details

Company Access Code com.ibm.plugin2.preference/ Division This entry field may be left blank,

or a string value of between 8 and

20 characters in length can be

entered.

Company Web Site instance/com.ibm.plugin2.preference/CompURL

A URL must be entered.

Allow after hours access com.ibm.plugin.preference/

AfterHoursAccess

A check box where the underlying

value is “yes” or “no”.

Allow simultaneous logon instance/ com.ibm.plugin.preference/

MultipleLogon

A check box where the underlying

value is “enable” or “disable”.

Automatic Lockout Enabled instance/ com.ibm.plugin.preference/

AutoLockout

A check box where the underlying

value is “0” or “1”.

Testing Preference Set definitions: Developers creating new Preference Sets should thoroughly test them

before deploying them to a production environment. This should include verifying each preference is

tested to assure that changes on the server are applied on the client. This can only be done with an

end-to-end test:

v Verifying the template has the correct preference name. The smallest error in the name of the

preferences will result in the preference not being recognized by the client.

v Verify that all values, or at least a representative sample of values, for each preference is tested and

produces the correct client behavior.

v Verify that the correct behavior occurs on the client when the Policy Type is loaded and no subPolicies

have been created.

Understanding preference options

Preferences provide the ability for applications to be configured and managed using one of the provided

management systems, and eliminate the need to change source code or plug-in contents to change

application parameters. While there are several preference models, developers are strongly encouraged to

use the Eclipse preference model, either directly, or through the Managed Settings provider.

Eclipse preferences

The Eclipse framework provides an extensible preference store that permits preference information to be

stored at various levels. Preference information is stored as key value pairs. Preference pages are

generally provided to set or update the preference information stored within the system. Information

stored within the Eclipse preference framework will usually be related to display or operating

characteristics that the user may change to suit his choices. Eclipse-based preferences are not connected to

the enterprise management system. Refer to the Platform Plug-in Developer’s Guide for more information on

using Eclipse preferences.

Configuration admin

The OSGi core framework also provides a configuration management capability known as Configuration

Admin. Configuration Admin provides capabilities to store preference or configuration information based

on key value pairs.

Developers should consider using the OSGi Configuration admin service only if their bundle must also

run in a non-Eclipse OSGi environment. Otherwise, developers are strongly encouraged to use the Eclipse

preferences model.

Applications that use Configuration Admin to store information will need to implement the

ManagedService interface. By implementing this interface, the application will be notified when

configuration information changes. Applications that use Configuration Admin to store configuration and

358 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 369: Lotus Expeditor: Developing Applications for Lotus Expeditor

preference information can also use the Metatype service to provide a metadata description of the

information. The metadata can describe the parameter types, default values, and validation logic to be

applied for each parameter.

If Configuration Admin is used to store configuration information, system administrators can query and

update configuration values via the Enterprise Management Agent.

If configuration information is stored using Configuration Admin, preference pages can be used to

provide a user interface to view and modify preferences. The Lotus Expeditor platform provides classes

to assist in using preference pages to interact with Configuration Admin.

The com.ibm.eswe.preferences.ConfigAdminPreferencePage has subclassed the

org.eclipse.jface.preference.FieldEditorPreferencePage to provide preference pages for configuration

information stored within Configuration Admin. The ConfigAdminPreferencePage creates a

ConfigAdminPreferenceStore, that uses Configuration Admin and Metatype services to obtain the required

data to automatically build the preference page.

To use the ConfigAdminPreferencePage, you will need to create your own subclass of the

ConfigAdminPreferencePage, and supply the Bundle and Persistent ID for the properties that you intend

to display. Within your subclass, you can also affect the set of properties displayed, as well as add your

own validation logic to the page. You will also need to define a preference page via the standard Eclipse

extension point for preference pages, and supply the appropriate metadata files (i.e. METADATA.XML,

METADATA.properties). Refer to “Using the Meta Type Service” on page 362 for more information . The

METADATA.XML and METADATA.properties files are loaded from either the plug-in files or from the plug-in’s

class path. The METADATA.* files must be placed within the META-INF directory of either the project or the

src directory for the project

The ConfigAdminPreferencePage supports only scalar metatype definitions for non-factory PIDs. Integer,

String, and Boolean fields are handled by default. You will need to provide implementations for

FieldEditors for types such as Byte, Char, Long, Float, Double, BigDecimal and BigInteger

Refer to the Javadoc information for the com.ibm.eswe.preference package for more information.

OSGi preference service

The OSGi Preference Service defines a preferences model for OSGi Services. The OSGi Preferences model

enables services to maintain their own preferences information, but the information is not available to

other services or bundles, unless access is provided by the service itself. Developers should consider

using the OSGi Preferences Service for preference information only if their bundle must also run in a

non-Eclipse OSGi environment. Otherwise, developers are strongly encouraged to use the Eclipse

preferences model. For more information, refer to the OSGi R4 Specification.

Using the XML parser services

Applications requiring use of XML Parsers should use the XML Parser Service interface. By using the

XML Parser Service interface, applications are able to dynamically select the parser at runtime, and are

notified of parser service events by the XML Parser Service. However, to use the XML Parser service, you

must modify existing applications.

Applications can use the standard JAXP calls without using the service interfaces. The APIs providing the

parser factories use the underlying service interfaces. In this situation, applications will not be able to

dynamically choose their parser at runtime, and they will not receive event notifications if parser services

are removed. Applications might receive javax.xml.parsers.FactoryConfigurationError if parser actions

are attempted and no parsers exist.

Typical usage of a SAX Parser involves obtaining a reference to the SAX Parser Factory, and then

obtaining a new parser:

Enabling applications for configuration 359

Page 370: Lotus Expeditor: Developing Applications for Lotus Expeditor

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

The following example shows how you can obtain a reference to the SAX Parser Factory using XML

Parser Services:

ServiceReference ref =

context.getServiceReference(SAXParserFactory.class.getName() );

SAXParserFactory factory = context.getService( ref );

SAXParser parser = factory.newSAXParser();

It is not necessary to issue the newInstance call once the factory reference is obtained.

Similarly, when using the DocumentBuilderFactory, the typical sequence using JAXP is:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();

The following example shows how you use the DocumentBuilderFactory using the XML Parser Service.

ServiceReference ref =

context.getServiceReference( DocumentBuilderFactory.class.getName() );

DocumentBuilderFactory factory = context.getService( ref );

DocumentBuilder builder = factory.newDocumentBuilder();

It is not necessary to issue the newInstance call once the factory reference is obtained.

SAX interfaces permit setting properties on the SAXParser object. Since MicroXML does not support

validation, attempting to set the validation property on MicroXML will result in a

org.xml.sax.SAXNotSupportedException being thrown. If your code is not specific to either parser, then

you should be prepared to receive exceptions when attempting to set features, and handle them

appropriately.

Attempts to set other features can result in exceptions if different parser implementations have been

plugged in. If specific parser attributes are required, you can specify them when requesting the parser

factory service.

It is possible to perform validation of XML using DTD or XSD when the XML resources are loaded from

a plug-in. Because the resource is loaded from a plug-in, you need to provide indication of the location of

the DTD file. Create an InputSource object for the XML document that requires parsing. Use the

Bundle.getEntry() or Bundle.getResource() method to obtain a URL or load the resource from a stream.

Set the System ID for the InputSource to the URL used to load the file. By using this process, you do not

need to create an EntityResolver instance to locate the DTD.

Use the following approach to permit DTD or Schema validation against files contained within bundles:

1. Set up an InputSource to specify the stream and the desired URL.

2. Do not use only an input stream, because an attempt to find a DTD or Schema file will result in

unexpected URLs.ServiceReference ref =

context.getServiceReference(SAXParserFactory.class.getName() );

SAXParserFactory factory = context.getService( ref );

SAXParser parser = factory.newSAXParser();

XMLReader xmlReader = parser.getXMLReader();

xmlReader.setContentHandler(this);

xmlReader.setErrorHandler(this);

xmlReader.setFeature("http://xml.org/sax/features/namespaces", true);

xmlReader.setFeature("http://xml.org/sax/features/validation", true);

xmlReader.setFeature("http://apache.org/xml/features/validation/schema",

true );

360 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 371: Lotus Expeditor: Developing Applications for Lotus Expeditor

URL url = getClass().getResource(uri);

java.io.InputStream is = url.openStream();

[1] InputSource input = new InputSource(is);

[2] input.setSystemId( url.toExternalForm() );

xmlReader.parse(input);

Locating the Web Container ports using the HttpSettingListener

Service

Applications running on Lotus Expeditor 6.1 runtime can use the HttpSettingListener service to receive

notification of the Web Container configuration. The Web Container configuration consists of settings

such as the port and host address that the Web Container is listening on.

To use the HttpSettingListener service, application developers must perform the following steps:

1. Update the application manifest to include a dependency on the com.ibm.pvc.webcontainer.listeners

package (Optionally, the application manifest can be updated to require the

com.ibm.pvc.sharedbundle plug-in)

2. Add a Java class to the application project that implements the HttpSettingListener interface.

The following example shows what the listener class would look like:

public class MyListener implements HttpSettingListener {

/* (non-Javadoc)

* @see com.ibm.pvc.webcontainer.listeners.HttpSettingListener#settingsAdded

(java.lang.String, java.util.Dictionary)

*/

public void settingsAdded(String pid, Dictionary properties) {

//TODO – developer needs to implement this method

}

/* (non-Javadoc)

* @see com.ibm.pvc.webcontainer.listeners.HttpSettingListener#settingsModified

(java.lang.String, java.util.Dictionary)

*/

public void settingsModified(String pid, Dictionary properties) {

//TODO – developer needs to implement this method

}

/* (non-Javadoc)

* @see com.ibm.pvc.webcontainer.listeners.HttpSettingListener#settingsRemoved

(java.lang.String)

*/

public void settingsRemoved(String pid) {

//TODO – developer needs to implement this method

}

}

3. Register the application as an HttpSettingListener . The class registering the HttpSettingListener

service must have access to the application’s bundle context object. The following example shows how

to register the application as an HttpSettingListener service in the bundle activator of the

application:

public void start(BundleContext context) throws Exception {

context.registerService(HttpSettingListener.class.getName(),

new MyListener(),

null);

}

Upon activation, the Web Container will send notifications to all the HttpSettingListener service

implementations registered with it. The service implementation will be notified of additions or changes to

the listener configuration (settingsModified() method is invoked).

The following example shows processing of the settings Dictionary passed on the service call:

Enabling applications for configuration 361

Page 372: Lotus Expeditor: Developing Applications for Lotus Expeditor

public void settingsModified(String pid, Dictionary properties)

throws Exception {

String hostName = null;

int portNumber = -1;

String scheme = (String)settings.get( HttpSettingListener.SCHEME );

if (HttpSettingListener.SCHEME_HTTP.equals( scheme )) {

Object iPort = settings.get( HttpSettingListener.HTTP_PORT );

if (iPort instanceof Integer[]) {

portNumber = ((Integer[])iPort)[0].intValue();

} else {

portNumber = ((Integer)iPort).intValue();

}

String sHost = (String)

settings.get( HttpSettingListener.ADDRESS );

if (HttpSettingListener.ALL_ADDRESSES.equals( sHost )) {

hostName = "localhost";

} else {

hostName = sHost;

}

}

}

Note: The settingsAdded() and settingsRemoved() methods are deprecated.

Using the Meta Type Service

The OSGi Configuration Admin Service allows bundles to persistently store their configurations. The

OSGi Meta Type Specification allows for a programmatic description of a bundle’s metadata. The OSGi

MetaType Service ties those two pieces together and enables an administrative bundle to dynamically

discover what another bundle’s configuration looks like and make changes to it. For example, the

configuration screens for the LogService, HttpService, and WebContainer. Likewise, the Configuration

Admin Preferences pages use Configuration Admin and the Meta Type Service to automatically build

preference pages based on the configuration information.

The MetaType Service acts as a middle-man between an administrative bundle and a configurable bundle.

The admin bundle may ask the MetaType Service for a MetaType Provider for a given bundle object. The

MetaType Provider can then be queried to discover the Object Class Definitions and Attribute Definitions

contained within.

For this scheme to work, configurable bundles must provide a way for the MetaType Service to discover

the bundle’s configuration information. Each configurable bundle must have a METADATA.XML file in

the /META-INF directory of their plug-in/bundle. This METADATA.XML file contains a description of the

configuration in XML format and is packaged in the bundle’s JAR file.

This file describes the data in a format defined by METADATA.DTD. Within the METADATA.XML file is a list of

all supported Locales. An additional set of files, METADATA_<locale>.properties should contain the

translatable strings for a locale in key=value format. The METADATA.XML file contains strings for the default

language only, which are used by default if the properties file for the desired locale can not be found.

The Meta Type Service is registered with OSGi under the class name

org.osgi.service.metatype.MetaTypeService and provides a way to define and retrieve

org.osgi.service.metatype.MetaTypeProvider objects for an OSGi bundle. For more information on the

package org.osgi.service.metatype see the OSGi Release 4 specification. The MetaTypeProvider data for

each bundle is stored as a bundle resource at /META-INF/METADATA.XML.

362 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 373: Lotus Expeditor: Developing Applications for Lotus Expeditor

The Meta Type data stored in /META-INF/METADATA.XML is used to define information on how to configure

a bundle using the OSGi service org.osgi.service.cm.ConfigurationAdmin. For example, the Managed

Service PIDs, the Managed Service Factory PIDs, and the Attributes associated are defined in the

METADATA.XML file.

Enabling applications for configuration 363

Page 374: Lotus Expeditor: Developing Applications for Lotus Expeditor

364 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 375: Lotus Expeditor: Developing Applications for Lotus Expeditor

Reference information

This section provides additional reference information for Lotus Expeditor.

Lotus Expeditor top level menus

The Lotus Expeditor platform defines a set of default menu items. This section provides the identifiers

that are required to be used for either of the following cases:

v You want to add additional menu items in a specific location to one of the pre-existing menus

v You want to define activities to allow you to group menu items within an activity group.

The Top Level Menu Items as shown in the table below are defined by Lotus Expeditor.

Table 30. Top level menus

Menu Name Menu ID

File file

View com.ibm.rcp.ui.viewmenu

Help help

File menu

The menu items, markers, and separators defined for the File menu are defined in the following table.

Table 31. File menu

Menu Item Sub-menu Item Menu ID

Close com.ibm.rcp.ui.filemenu.close

separator

Application > applications

Reset

group marker

group marker

Install

Application Management

Preferences... preferences

separator

Close All closeAllTabs

Exit quit

View menu

The menu items, markers, and separators defined for the View menu are defined in the following table.

Table 32. View menu

Menu Item Sub-menu Items Menu ID

Toolbar >

© Copyright IBM Corp. 2004, 2006 365

Page 376: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 32. View menu (continued)

Menu Item Sub-menu Items Menu ID

Show > com.ibm.rcp.ui.showmenu

side bar com.ibm.rcp.ui.sidebar

Banner show_banner

Help menu

The menu items, markers, and separators defined for the Help menu are defined in the following table:

Table 33. Help menu

Menu Item Menu ID

Help Contents helpContents

Support com.ibm.esupport.client.Browser

About <product name>... about

OSGi

This section provides OSGi information.

OSGi specification

One activity of the OSGi Alliance was to define a Java framework that:

v Enables multiple applications to coexist within a single VM

v Manages the life cycle of components within the framework

v Specifies a set of required and optional services on the platform

Lotus Expeditor is built on the Eclipse Rich Client Platform, which includes an OSGi framework. The

framework is based upon the OSGi Service Platform Release 4 specification with additional extensions

provided by the Eclipse 3.2.1 implementation of the OSGi framework. Application developers partition

applications into services and other resources. Services and resources are packaged into bundles, which

are files that serve as the delivery unit for applications. Bundles have manifests with special headers that

enable you to share classes and services at the package level. Within the Eclipse based platforms, all

plug-ins are OSGi bundles, so you can think of the terms plug-in and bundle as being interchangeable.

The OSGi R4 Specifications can be obtained from the OSGI Alliance website at http://www.osgi.org.

Working with OSGi bundles

OSGi™ bundles consist of a JAR file that contains Java classes, resources, and a manifest file. Bundles can

register services for other bundles to use, use services registered by other bundles, export Java packages

for other bundles to use, and import Java packages from other bundles.

Creating OSGi bundles

This section describes how to create an OSGi bundle. For more detailed information about writing

bundles, refer to the OSGi Service Platform Release 4.

Bundles: A bundle is the smallest unit of management for the Framework. Bundles are Java Archive

(JAR) files with a manifest that contains special headers. These headers describe the bundle to the OSGi

framework and list the bundle’s dependencies, such as the packages and services required by the bundle.

Bundles can register services with the OSGi framework that other bundles can use.

366 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 377: Lotus Expeditor: Developing Applications for Lotus Expeditor

The descriptive information in the manifest file differentiates bundles from other JAR files. Non-bundle

JAR files often keep very little information in the manifest file. However, a bundle’s manifest file usually

contains descriptive information, such as the bundle’s name and version, and a list of the packages and

services it requires.

Bundle life cycle: The framework manages the life cycle of bundles. As you install and run a bundle, it

goes through various states. The possible states of a bundle are:

v INSTALLED - the bundle has been installed, but all of the bundle’s dependencies have not been met. The

bundle requires packages that have not been exported by any currently installed bundle.

v RESOLVED - the bundle is installed, and its dependencies have been met, but it is not running. If a

bundle is started and all of the bundle’s dependencies are met, the bundle skips this state.

v STARTING - a temporary state that the bundle goes through while the bundle is starting.

v ACTIVE - the bundle is running.

v STOPPING - a temporary state that the bundle goes through while the bundle is stopping.

v UNINSTALLED - the bundle no longer exists in the framework.

Conventions for creating bundles: When you create bundles, use the following conventions:

v Clean up objects and threads properly during your stop method. The framework does not terminate

lingering threads.

v Return promptly from BundleActivator start() and stop() methods. These methods are invoked

synchronously by the framework. Delays in returning from these methods will affect the ability of the

framework to process other bundle actions. It is recommended that substantial activities be handed off

to another thread for processing, or be delayed until first service invocation.

v Return promptly from Framework and Bundle Listeners events. These event methods are invoked by

the framework. Delays in returning from these methods may adversely affect performance of the

framework.

v Allow for service life cycle events. The OSGi framework provides the ability to dynamically install and

remove bundles. As a result, it is possible in some frameworks that services may not always be

present. A service is only present when the bundle that registered the service is available. See “Getting

and un-getting services from the OSGi Framework” on page 370 for conventions to solve this problem.

Creating manifest files: Each bundle must contain either a manifest file. The bundle’s manifest file

contains data that the framework needs to correctly install and activate the bundle. Legacy Eclipse

bundles can provide some manifest information in their plugin.xml files, but META-INF/MANIFEST.MF

files are the recommended files for Manifest information.

Note: A plugin.xml may contain similar information, however, a plugin.xml also contains extensions and

extension points.

If a bundle contains only a plugin.xml, the Eclipse platform will generate a MANIFEST.MF equivalent when

the platform starts. When you specify data in a manifest file, you must use the headers that were defined

by the OSGi™ specification. You can use user-defined headers; however, the framework ignores any

headers that it does not understand. Refer to the OSGi Service Platform Release 4 specification for more

information about the OSGi Manifest file format and syntax.

The MANIFEST.MF file is located in the META-INF directory of your bundle project. The plugin.xml file, if

present, should be under the root directory.

The following headers are defined in the OSGi Service Release 4 specification and by the Eclipse 3.2.x

extensions to the OSGi framework.

v Import-Package

Reference information 367

Page 378: Lotus Expeditor: Developing Applications for Lotus Expeditor

Use this header to specify the names of any package that you want your bundle to import from the

runtime. If you do not specify the package your bundle needs in this header, you may get a

NoClassDefFound exception when the bundle loads.

Note: You must also specify the package you want to import (using Import-Package) in the

Export-Package header of the bundle that contains the package.

v Export-Package

Use this header to specify the name of any package that you want your bundle to export to the

runtime. If you do not specify the packages needed by other bundles in this header, the dependent

bundles may not resolve.

v Require-Bundle

Use this header to specify the specific bundles that provides packages you use in your bundle. If you

do not specify the bundle which provides the packages you need, you may get a NoClassDefFound

exception when the bundle loads.

v Bundle-Activator

Use this header to specify the fully-qualified name of the BundleActivator class.

A bundle designates a special class to act as a Bundle Activator. The Framework must instantiate this

class and invoke the start and stop methods to start or stop the bundle as needed. The bundle’s

implementation of the BundleActivator Interface enables the bundle to initialize a task, such as

registering services, when the bundle starts and to perform clean-up operations when the bundle stops.

The org.eclipse.core.runtime.Plugin class implements the org.osgi.framework.BundleActivator

interface. When creating Client Services projects, a subclass of Plugin will be created and will become

the BundleActivator for the plug-in.

You may define your own class to implement the org.osgi.framework.BundleActivator interface.

You can specify this header in the Class field on the Overview Page of the Bundle Manifest Editor.

v Bundle-SymbolicName

The Bundle-SymbolicName manifest header can be used to identify a bundle. The Bundle Symbolic

Name and Bundle Version allow for a bundle to be uniquely identified in the Framework. It does not

replace the need for a Bundle-Name manifest header, which provides a human readable name for a

bundle.

You can specify this header in the ID field on the Overview Page of the Bundle Manifest Editor.

Refer to the OSGi Service Platform Release 4 for descriptions of other bundle headers, such as the

following, which provide bundle description information:

v Bundle-Name

v Bundle-Description

v Bundle-Copyright

v Bundle-Vendor

v Bundle-Version

v Bundle-DocUrl

v Bundle-ContactAddress

v Bundle-Fragment

Packages: Bundles can use code that is defined within other bundles by declaring the packages as

imported packages in the manifest file. Although you can create a bundle that does not rely on any

classes other than the Java base packages, most bundles import code from other bundles or the base

runtime class path.

You must import any class that you use within a bundle that is not defined in the bundle or that is not a

base Java class, meaning classes within packages that begin with java.. To import another class, include

368 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 379: Lotus Expeditor: Developing Applications for Lotus Expeditor

an import clause for the class’s package in the bundle’s manifest. You can explicitly import only whole

packages; individual classes cannot be explicitly imported.

A bundle can make the classes the bundle defines available to other bundles by exporting packages. To

enable other bundles to access a particular package, include an export clause for the package in the

manifest of the bundle that contains the package.

Understanding services

In the OSGi environment, bundles are built around a set of cooperating services that are available from a

shared service registry. The service interface defines the OSGi service, which is implemented as a service

object.

Services decouple the provider from the service user. The only code a service provider and a service user

share is the service definition. You can use Java interfaces to define services. Any class that implements

this interface can provide the service.

Bundles that use services that are not provided by the bundle can notify the framework by including an

Import-Service header in the bundle manifest. However, this is not required. When code within a bundle

requests a provider of the service from the framework, the bundle imports the service at runtime.

A bundle that provides services can also include an Export-Service header in its manifest. When code

within a bundle makes a provider available to the framework, the bundle exports the service at runtime.

Registering and unregistering a service with the OSGi Framework: The framework passes a

BundleContext object to your bundle when it invokes your BundleActivator’s start method. Your bundle

can use the BundleContext object to interact with the framework by calling the methods of the

BundleContext object. One method that your bundle can call is registerService, which uses a service

object and an interface name to register a service with the framework’s service registry.

The recommended approach for using services is to provide all interface and object classes referred to in

the service definition in a bundle separate from the service implementation. The service implementation

bundle then imports the packages from the defining bundle, and exports no packages of its own.

Therefore in a typical service usage, there are three bundles involved – a service interface bundle, the

service implementation, and the service consumer.

In the following example, three bundles are created:

v InterfaceBundle

v ServiceImplBundle

v ServiceConsumerBundle

Interface Bundle

The InterfaceBundle exports the com.ibm.osg.example.mtservice package that contains the

com.ibm.osg.example.mtservice.MyTestService interface. The InterfaceBundle adds an Export-Package:

com.ibm.osg.example.mtservice to its MANIFEST.MF file. Since this bundle has no initialization or startup

needs, no BundleActivator is required for this bundle. This interface defines a service than can print a

message:

package com.ibm.osg.example.mtservice;

public interface MyTestService {

// One method is provided by the service.

// This method will simply print

// the message to standard out.

public void printMessage(String message);

}

Service Implementation Bundle

Reference information 369

Page 380: Lotus Expeditor: Developing Applications for Lotus Expeditor

The ServiceImplBundle provides an implementation of the MyTestService (Other bundles could provide

alternative implementations). The ServiceImplBundle exports no packages, but does contain an

Import-Package: com.ibm.osg.example.mtservice in its MANIFEST.MF file so that it can have access to the

MyTestService interface.

The following class provides the implementation for our service. In the following example, a service

called com.ibm.osg.example.mtservice.MyTestService registers with the framework. This implementation

of the service prints the message to the standard output. Generally, packages containing service

implementation classes should not be exported to other bundles.

package com.ibm.osg.example.mytestservice;

public class MyTestService implements com.ibm.osg.example.mtservice.MyTestService{

public void printMessage(String message){

System.out.println("MyTestService - " + message);

}

}

The following BundleActivator class registers the com.ibm.osg.example.mtservice.MyTestService service

with the framework.

package com.ibm.osg.example.mytestservice;

import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceRegistration;

public class MyBundleActivator implements BundleActivator {

ServiceRegistration registration;

/*Create a new instance of the TestService

and then use the BundleContext object to

register it.

Store the registration object

to use to unregister the service when the

bundle is

stopped by the framework.

*/

public void start(BundleContext context)

{

MyTestService testservice = new MyTestService();

if( registration == null ){

registration =

context.registerService(

"com.ibm.osg.example.mtservice.MyTestService",

testservice,

null);

}

}

public void stop(BundleContext context) {

if ( registration != null ){

registration.unregister();

}

registration=null;

}

}

The ServiceConsumer bundle, like the ServiceImplBundle, must contain an Import-Package:

com.ibm.osg.example.mtservice in its MANIFEST.MF file. It may optionally contain an Import-Service:

com.ibm.osg.example.mtservice.MyTestService. This is recommended as the tools will use this to ensure

the framework has the proper prerequisites, but this is not required. See the section “Getting and

un-getting services from the OSGi Framework” for an example of the ServiceConsumer bundle.

Getting and un-getting services from the OSGi Framework: Bundles register and unregister services.

Bundles that depend on services must account for the possibility that the requested service might not be

370 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 381: Lotus Expeditor: Developing Applications for Lotus Expeditor

available. The service can register or unregister with the framework at any time. You can use a

ServiceTracker to enable your bundles to query or listen for service registrations and to react

accordingly.

package com.ibm.osg.example.mygetservice;

import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;

import org.osgi.util.tracker.ServiceTracker;

import com.ibm.osg.example.mtservice.MyTestService;

public class MyBundleActivator

implements BundleActivator, Runnable

{

private boolean done=false;

private ServiceTracker testServiceTracker;

// Bundle Activator Start Method

public void start(BundleContext context)

{

/* Here we initialize and open our ServiceTracker.

It will track any service registering under

the "com.ibm.osg.example.mtservice.MyTestService"

interface.

*/

testServiceTracker =

new ServiceTracker(context,

"com.ibm.osg.example.mtservice.MyTestService",

null);

testServiceTracker.open();

// Here we start a thread that will continue

// to use our service until

// the bundle is stopped.

Thread t = new Thread(this);

t.setName("mygetservice thread");

t.start();

}

/*Bundle Activator Stop Method -- here we stop

the thread and close the

ServiceTracker*/

public void stop(BundleContext context)

{

done=true;

testServiceTracker.close();

}

//Here is a method that uses the service

//we are tracking. First we get

//the service

//from the tracker, then we call its printMessage

//method.

public void useService(String message){

MyTestService testService = (MyTestService)

testServiceTracker.getService();

if( testService != null )

{

// If the service is available then use it.

testService.printMessage(message);

}

else{

// If the service is not available then perform an acceptable action.

Reference information 371

Page 382: Lotus Expeditor: Developing Applications for Lotus Expeditor

// Here we just print the message to standard out and indicate the service

// was not available.

System.out.println("No MyTestService available - " + message);

}

}

// Simply continues to use the test service

// every second until the done flag is set.

public void run(){

int i = 0;

done = false;

while (!done) {

useService("message from test " + i++);

try{

Thread.sleep(1000);

}

catch( InterruptedException ie ){

}

}

}

}

For an example that uses ServiceTrackers and getting services, refer to the Service Tracker example in

the Samples Gallery > Technology Samples > Lotus Expeditor > OSGi section.

Lotus Expeditor Toolkit

This section provides reference information for using the Lotus Expeditor Toolkit.

Wizards

The Lotus Expeditor Toolkit provides a variety of wizards:

New Client Services Project Wizard

Use this wizard to create a new Client Services project. This wizard can be accessed as follows:

1. Select File > New > Project. The new project wizard displays.

2. Expand the Client Services folder and select Client Services Project.

Refer to the following tables for a description of the options and their default values.

Table 34. Client Services Project page

Option Description Default value

Project name Enter a name for your new Client Services Project. None

Create a Java project Select this if the project will contain Java code. Deselect this

if the project will only contain non-Java resources.

Selected to create a

Java project.

Source Folder Name Folder name for Java source files. src

Output Folder Name Folder name for Java class files. bin

372 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 383: Lotus Expeditor: Developing Applications for Lotus Expeditor

This is followed by the Client Services Content page:

Table 35. Client Services Content page

Option Description Default Value

Plug-in ID This is a unique bundle symbolic name. It is suggested that

you update this from the default value. The bundle name

should be a unique URI, following the Java package naming

conventions.

The project name is

used as the default

value.

Plug-in Version The bundle version. The version is in the form of major,

minor, and micro numbers, separated by ‘.’.

1.0.0

Plug-in Name A descriptive bundle name. The default name is

constructed by

appending “Bundle” to

the project name.

Plug-in Provider A description of the bundle provider. None

Class path The class path for the project None

Generate an activator, a

Java class that controls the

plug-in’s life cycle

Selecting this will generate an activator that controls the

plug-in’s life cycle.

Selected

This plug-in will contribute

to the Rich Client Platform

Select this option if you intend for the bundle plug-in to

contribute to the UI.

Selected

Auto-Management

Preference

Select this option to specify whether the application will

search for dependencies based on Required-Bunlde or

Import-Package.

Import-Package

This is followed by the Target Profile page:

Table 36. Target profile options

Option Description Default value

Target Select from the list the Target Definition this Client Services

Project will target. You can change your selection later in the

Client Services property page.

Default Target

Target Definition Features Check the Target Definition Features that your Client

Services Project will require. You can change your selection

later in the Client Services property page. Grey entries are

required by the Target Definition and cannot be un-checked.

The required features

for the selected Target

Definition.

New Client Services Fragment Project Wizard

Use this wizard to create a new Client Services fragment project. This wizard can be accessed as follows:

1. Select File > New > Project. The new project wizard displays.

2. Expand the Client Services folder and select Client Services Fragment Project.

Refer to the following tables for a description of the options and their default values.

Table 37. Client Services Fragment Project page

Option Description Default value

Project name Enter a name for your new Client Services fragment project. None

Reference information 373

Page 384: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 37. Client Services Fragment Project page (continued)

Option Description Default value

Project Contents You may deselect ″Use default″ and click Browse to select a

file system location for your new Client Services Fragment

Project.

The ″Use default

location″ creates the

project in your current

workspace

Create a Java project Select this if the project will contain Java code. Deselect this

if the project will only contain non-Java resources.

Selected to create a

Java project.

Source Folder Name Folder name for Java source files. src

Output Folder Name Folder name for Java class files. bin

This is followed by the Fragment Content page:

Table 38. Fragment Content page

Option Description Default Value

Fragment ID This is a unique bundle symbolic name. It is suggested that

you update this from the default value. The bundle name

should be a unique URI, following the Java package naming

conventions.

The project name is

used as the default

value.

Fragment Version The fragment version. The version is in the form of major,

minor, and micro numbers, separated by ‘.’.

1.0.0

Fragment Name A descriptive bundle name. The default name is

constructed by

appending “Fragment”

to the project name.

Fragment Provider A description of the fragment provider. None

Class path The name of the JAR file in which the project’s built contents

will be placed.

The project name is

used as the JAR file

based name.

Plug-in ID Specify the ID, version, and optional version match rule for

the parent bundle that this fragment contributes to. You may

use the Browse button to select a parent from a dialog of

other bundles in the target platform.

None

Minimum Version The minimum version of the host plug-in Host plug-in’s

minimum version

Maximum Version The maximum version of the host plug-in Host plug-in’s

minimum version

Search for dependencies

automatically upon

resource changes

Select this option to enable the tools to search for package

dependencies whenever the user modifies referenced files.

When this option is deselected, the tooling will not search for

any unresolved or unused dependencies in your project.

Selected

Attempt to automatically

resolve Manifest

dependencies

Select this option to enable the tools to automatically manage

the package dependency information in the manifest file.

Package dependencies in your project’s Java code will

automatically be reflected through proper updates to the

manifest file. When this option is deselected, package

dependencies that are not properly reflected in the manifest

are flagged with problem markers, along with quick fixes to

resolve the problems.

Selected

374 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 385: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 38. Fragment Content page (continued)

Option Description Default Value

Give preference to

Require-Bundle

Require-Bundle will be used to automatically resolve a

package dependency in cases where either Require-Bundle or

Import-Package can be used.

Not selected

Give preference to

Import-Package

Import-Package will be used to automatically resolve a

package dependency in cases where either Require-Bundle or

Import-Package can be used.

Selected

This is followed by the Target Definition page:

Table 39. Target definition options

Option Description Default value

Target Definition Select from the list the Target Definition this Client Services

Project will target. You can change your selection later in the

Client Services property page.

Default Target

Target Definition features Check the Target features that your Client Services Project

will require. You can change your selection later in the Client

Services property page. Grey entries are required by the

Target Profile and cannot be unchecked.

The ″Core OSGi

Interfaces″ Target

Feature is required by

all Target Definitions.

Convert Project to Client Services Project Wizard

Use this wizard to convert a Java or Plug-in project to a Client Services project. This wizard can be

accessed as follows:

1. Select File > New > Other. The new wizard displays.

2. Expand the Client Services folder and select Convert Project to Client Services Project.

Table 40. Convert Existing Project Page

Option Description Default Value

Available projects Select the project to be converted. None

Copy project before

conversion

This option will copy the project before conversion. The

user is required to provide the name of the new convert

project if this option is selected.

Not selected

This is followed by the Target Definition page:

Table 41. Target Definition options

Option Description Default value

Target Select the target for this application from the list of Targets.

You can change your selection later in the Client Services

property page.

Default Target

Target Definition Features Check the target features that your Client Services Project

will require. You can change your selection later in the Client

Services property page. Grey entries are required by the

Target Definition and cannot be unchecked.

The ″Core OSGi

Interfaces″ Target

Feature is required by

all Target Definitions.

Reference information 375

Page 386: Lotus Expeditor: Developing Applications for Lotus Expeditor

Client Services Project Properties page

Use this properties page to update the properties of a Client Services Project. Both Target Definition

selections and project options can be updated. To access this page, right click on the project in the

Package Explorer view, select Properties, and then select Client Services.

Table 42. Target Definition tab

Option Description Default Value

Target Definition Select a Target definition this Client

Services project will target.

None

Target Definition Features Select the Target Features that the

project requires.

The “Core OSGi Interfaces” Target

Feature is required by all Target

Definitions.

Table 43. Options tab

Option Description Default Value

Search for dependencies

automatically upon resource changes

Select this option to enable the tools

to search for package dependencies

whenever the user modifies source

files. When this option is deselected,

the tooling will not search for any

unresolved or unused dependencies

in your project.

Selected

Attempt to automatically resolve

Manifest dependencies

Select this option to enable the tools

to automatically manage the package

dependency information in the

manifest file. Package dependencies

in your project’s Java code will

automatically be reflected through

proper updates to the manifest file.

When this option is deselected,

package dependencies that are not

properly reflected in the manifest are

flagged with problem markers, along

with quick fixes to resolve the

problems.

Selected

Give preference to Require-Bundle Require-Bundle will be used to

automatically resolve a package

dependency in cases where either

Require-Bundle or Import-Package

can be used.

Not selected

Give preference to Import-Package Import-Package will be used to

automatically resolve a package

dependency in cases where either

Require-Bundle or Import-Package

can be used.

Selected by default for projects that

are not contributing to the Rich

Client Platform.

Dialogs

The Lotus Expeditor Toolkit includes the following dialogs:

Client Services Launch Configuration dialog

The Lotus Expeditor Toolkit supports launching a local instance of the Lotus Expeditor runtime. This

supports the ability to both run and debug Client Services projects from your workspace. The Lotus

Expeditor runtime launch extends the Eclipse run-time workbench launch. It is suggested that you use

376 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 387: Lotus Expeditor: Developing Applications for Lotus Expeditor

the Lotus Expeditor launcher for running Client Services projects, since it automatically handles setting

up the proper native library environment for the Lotus Expeditor runtime.

Perform the following procedure to run or debug a project using the Lotus Expeditor runtime launch:

1. Select Run > Run... to run under the Lotus Expeditor runtime, or select Run > Debug... to debug

under the Lotus Expeditor runtime.

2. Select Client Services under configurations, and click New to create a new configuration.

Note: If Lotus Expeditor runtime configurations have already been created, you can directly select

one.

3. On the arguments tab, insure that the JRE selected is the jclDesktop.

4. By default, the launcher selects all the plug-ins/features from the Client Services default target

definition. To change the plug-ins/features in your Client services instance, please go to the Profile

tab.

5. Click either the Run or Debug button to launch the runtime.

Refer to the Running a Plug-in section of the PDE Guide for further information on launch options.

Debugging a remote Client Services runtime: To debug a Client Services runtime that has been started

through other means than the Client Services runtime launcher, refer to “Remote debugging and testing”

on page 325.

Lotus Expeditor Toolkit Preference Dialog

To access and set preferences for the Lotus Expeditor, select Window > Preferences > Client Services.

Refer to the following tables for a description of the options and their default values of the resulting

dialog screens:

Auto-Management Preferences

Table 44. Auto-Management Preferences

Option Description Default Value

Search for dependencies

automatically upon resource changes

Select this option to enable the tools

to search for package dependencies

whenever the user modifies source

files. When this option is deselected,

the tooling will not search for any

unresolved or unused dependencies

in your project.

Selected

Attempt to automatically resolve

Manifest dependencies

Select this option to enable the tools

to automatically manage the package

dependency information in the

manifest file. Package dependencies

in your project’s Java code will

automatically be reflected through

proper updates to the manifest file.

When this option is deselected,

package dependencies that are not

properly reflected in the manifest are

flagged with problem markers, along

with quick fixes to resolve the

problems.

Selected

Reference information 377

Page 388: Lotus Expeditor: Developing Applications for Lotus Expeditor

Table 44. Auto-Management Preferences (continued)

Option Description Default Value

Give preference to Require-Bundle Require-Bundle will be used to

automatically resolve a package

dependency in cases where either

Require-Bundle or Import-Package

can be used.

Not selected

Give preference to Import-Package Import-Package will be used to

automatically resolve a package

dependency in cases where either

Require-Bundle or Import-Package

can be used.

Selected by default for projects that

are not contributing to the Rich

Client Platform.

Default Target Selection

Use the drop-down list to choose the default Target Definition. This means that when creating a new

Client Services project or a new Client Services launch configuration, the default Target Definition

selection will be obtained from this setting.

Show plug-in objects in editors and dialogs using...

v Identifiers

This selection displays the plug-ins and features objects using their given ID attribute. A plug-in or

feature will always have an ID value associated with them. This is not the case with the NAME.

v Presentation names

This selection displays the plug-ins and features objects using their given NAME attribute.

Tag library

The following tag library is provided by the platform to assist in web and portlet application

development.

Aggregation tag library

The following tags are supported in the Aggregation Tag Library:

v init

Description - This tag initializes the portlet framework and must be used in the beginning of the JSP. All

other tags described in this section are only valid in the body of this tag, therefore the init tag usually

encloses the whole body of a JSP. In case the current URL contains an action flag, the action method of

the corresponding portlet is called.

Attributes

– portletURLPrefix="<any string>" (mandatory) This url defines the prefix used for PortletURLs.

Portlet URLs are created either by the state tag or within a portlet’s render method (which is called

by using the insert tag).

– portletURLSuffix="<any string>" (optional) This url defines the suffix used for PortletURLs. Portlet

URLs are created either by the state tag or within a portlet’s render method (which is called by

using the insert tag).

– portletURLQueryParams="<any string>" (optional) This url defines the query parameters used for

PortletURLs. Portlet URLs are created either by the state tag or within a portlet’s render method

(which is called by using the insert tag).

Sub-Tag - state, insert

Tag Library URI - http://ibm.com/portlet/aggregation

v state

378 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 389: Lotus Expeditor: Developing Applications for Lotus Expeditor

Description - This tag creates a URL pointing to the given portlet using the given state. This URL can

either be placed into a variable specified by the var attribute, or be written directly to the output

stream. This tag is especially useful to create URLs for HTML buttons, images, and so forth. When the

URL is invoked, the state changes defined in the URL will be applied to the given portlet.

Attributes

– url="<context>/<portlet-name>" (mandatory) Identifies the portlet for this tag by using the context

and portlet-name to address the portlet.

– windowId="<any string>" (optional) Defines the window ID for the portlet URL created by this tag.

– var="<any string>" (optional) If defined, the URL is not written to the output stream but rather

written into a variable with the given scope and name.

– scope="page|request|session|application" (optional; Default:page) Only valid if var is being used.

If defined the URL is not written to the output stream but rather a variable is created in the given

scope with the given name.

– portletMode="view|help|edit|<custom>" This attribute sets the portlet mode.

– portletWindowState="maximized|minimized|normal|<custom>" This attribute sets the window state.

– action="true/false" (optional; default:false) This attribute defines whether this is an action URL or

not.

Parent-Tag - init

Sub-Tag - urlParam

Tag Library URI - http://ibm.com/portlet/aggregation

v urlParam

Description - This tag calls the render method of the portlet and retrieves the content as well as the title.

The content and title of the specified portlet can optionally be placed into variables using the

contentVar and titleVar attributes.

Attributes

– url="<context>/<portlet-name>" (mandatory) Identifies the portlet for this tag by using the context

and portlet-name to address the portlet.

– windowId="<any string>" (optional) Defines the window ID of the portlet.

– contentVar="<any string>" (optional) If defined the portlet’s content is not written to the output

stream but rather written into a variable with the given scope and name.

– contentScope="page|request|session|application" (optional - Default:page) Only valid if

contentVar is being used. If defined, the portlet’s content is not written to the output stream but

rather written into a variable with the given scope and name.

– titleVar="<any string>" (optional) If defined, the portlet’s title is written into a variable with the

given scope and name. In case it is not defined, the title be disregarded and not written to the

output stream.

– titleScope="page|request|session|application" (optional - Default:page) Only valid if titleVar is

being used. If defined the portlet’s title is not written to the output stream but written into a

variable with the given scope and name.

Parent-Tag - init

Tag Library URI - http://ibm.com/portlet/aggregation

v initBranding

Description - This tag provides the branding theme information to the portlet aggregator page. The

theme includes: a stylesheet, the title bar images, the title bar background color and the content

background color.

Attributes - None.

Parent-Tag - None.

Tag Library URI - http://ibm.com/portlet/aggregation

v initUrlPrefix

Reference information 379

Page 390: Lotus Expeditor: Developing Applications for Lotus Expeditor

Description - This tag provides the URL prefix information for all portlet URLs, including the render

and action URLs. The URL prefix includes the server address and the port number.

Attributes - None.

Parent-Tag - None.

Tag Library URI - http://ibm.com/portlet/aggregation

Message reference

This section provides message reference information.

Web Container messages

The following is a list of the application server messages that you might encounter when using the Web

Container, and the appropriate user responses.

SRVE0016E: Illegal Argument Exception: Invalid header format

Problem User response

Attempting to output a buffer of size less than 0. Only write buffers of size of 0 or greater.

SRVE0014E: Uncaught service() exception root cause {0}: {1}

Problem User response

Uncaught exception thrown in servlet service method. Varies by root cause.

SRVE0015E: Failure to initialize Web application {0}

Problem User response

Could not initialize the web application specified in the

message. Check the error log for more details.

Look in the error log to determine the root cause of this

problem.

SRVE0016E: Illegal Argument Exception: Invalid header format

Problem User response

Invalid format found for a request header. Check client header creation.

SRVE0021I: Servlet unloaded: {0}

Problem User response

The specified servlet has been unloaded after the destroy

method has been called.

none.

SRVE0031E: Illegal Argument Exception: {0} is not a directory.

Problem User response

The specified path is not a directory. Make sure the directory exists or that you are requesting

the right directory.

380 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 391: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0035E: WebAppSecurityCollaborator

Problem User response

WebAppSecurityCollaborator Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0041E: Illegal Argument Exception: Bootstrap file not found

Problem User response

This is an internal system error and is probably caused

by an earlier failure.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

RVE0042E: Illegal Argument Exception: Invalid content length

Problem User response

This is an internal system error and is probably caused

by an earlier failure.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0053E: Illegal Argument Exception: Invalid date format

Problem User response

Invalid date format. Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0055I: Servlet wait for destroy time-out has expired, destroy will be forced: {0}

Problem User response

Servlet is being destroyed after wait has timed out. none.

SRVE0056E: Illegal Argument Exception: Unsupported flag

Problem User response

This is an internal system error and is probably caused

by an earlier failure.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0058E: Did not realize destroy() exception thrown by servlet {0}: {1}

Problem User response

Could not destroy specified servlet. Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

Reference information 381

Page 392: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0060E: Unable to bind host name [{0}] to servletHost [{1}]

Problem User response

Could not bind the specified host name to the specified

servlet host.

Make sure the host name has been specified correctly

and that the servlet host has been specified in

virtualhosts.xml.

SRVE0061E: Illegal Argument Exception: Invalid directory specified: {0}

Problem User response

The specified directory is invalid. Check directory specification for errors.

SRVE0066I: Waiting for servlet to finish servicing requests: {0}

Problem User response

Servlet is still handling the request. Waiting for request

to complete before calling destroy.

none.

SRVE0068E: Uncaught exception thrown in one of the service methods of the servlet: {0}. Exception

thrown : {1}

Problem User response

Uncaught exception thrown in one of the service

methods of the servlet.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0070E: Error initializing for next request

Problem User response

Internal web container error. Gather server logs and contact IBM service.

SRVE0080E: Invalid content length

Problem User response

Internal server error. Gather logs and contact IBM service.

SRVE0086E: Illegal Argument Exception: Missing resource bootstrap properties

Problem User response

Internal server error. Gather logs and contact IBM service

SRVE0097I: Servlet unload initiated: {0}

Problem User response

The specified servlet is being unloaded from service. None

SRVE0100E: Did not realize init() exception thrown by servlet {0}: {1}

Problem User response

Could not initialize the specified servlet. Make sure the servlet class file is available on the

application classpath.

382 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 393: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0103E: Illegal Argument Exception: ScriptName must be the first part of the URI

Problem User response

This is an internal system error and is probably caused

by an earlier failure.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0105E: An exception occurred in Session.releaseSession()

Problem User response

Problem releasing a session. Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0108E: Illegal Argument Exception: Missing flag value

Problem User response

Missing flag value. Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0109E: Illegal Argument Exception: Invalid ObjectPool instantiated.

Problem User response

This is an internal system error and is probably caused

by an earlier failure.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0115E: Error occurred while invoking error reporter {0}

Problem User response

Problem invoking the specified error reporter. Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0120E: IO Error {0}

Problem User response

IO error encountered. Varies depending on reported root cause.

SRVE0121E: Illegal Argument Exception: Trying to write less than 0 bytes

Problem User response

Attempting to output a buffer of size less than 0. Only write buffers of size of 0 or greater.

Reference information 383

Page 394: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0126E: Invalidation Exception: {0} was created

Problem User response

This is an internal system error and is probably caused

by an earlier failure.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0133E: An error occurred while parsing parameters. {0}

Problem User response

Problem encountered parsing servlet parameters. Check parameter definitions in the web.xml file.

SRVE0138E: postInvoke Security Exception

Problem User response

Security problem encountered during request processing. Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0139E: Exception in Security preInvoke {0}

Problem User response

Security problem encountered during request processing. Varies with root cause.

SRVE0140E: Could not instantiate the security collaborator {0}

Problem User response

Internal server error. Gather logs and contact IBM service.

SRVE0155E: Failed to load encoding.properties file {0}

Problem User response

Could not load the specified file. Ensure the specified file exists.

SRVE0156E: Failed to load converter.properties file {0}

Problem User response

Could not load the specified file. Ensure the specified file exists.

SRVE0157E: setBufferSize() called after first write to Output Stream/Writer

Problem User response

An attempt was made to set the response buffer size

after the response was already committed.

Remove the setBufferSize() call or move it to a position

before the response commit.

384 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 395: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0160E: Exception while rolling back UserTransaction: {0}

Problem User response

Problem encountered rolling back the specified user

transaction.

Examine the server logs in order to determine the root

cause of the problem. If there are no related messages or

they do not help to resolve the problem, please contact

IBM Support.

SRVE0161I: IBM WebSphere Application Server - Web Container. Copyright IBM Corp. 1998-2006

Problem User response

Application server identifier. None

SRVE0162I: Servlet Specification Level: 2.4

Problem User response

The servlet specification level supported by the

application server.

None

SRVE0163I: Supported JSP Specification Level: 2.0

Problem User response

The JSP specification level supported by the application

server.

None

SRVE0164E: Web Application {0} uses the context root {1}, which is already in use by Web Application

{2}. Web Application {3} will not be loaded.

Problem User response

Two web applications on the same virtual host share the

same context root.

Either change the context root of one of the web

applications or move one to a different virtual host.

SRVE0169I: Loading Web Module: {0}.

Problem User response

WebModule is starting and being made available for

service.

None

SRVE0180I: [{0}] [{1}] [Servlet.LOG]: {2}

Problem User response

Informational message {2} logged via ServletContext.log

from application {0} with context root {1}.

None

SRVE0181I: [{0}] [{1}] [Servlet.LOG]: {2}: {3}

Problem User response

Informational message {2} logged via ServletContext.log

from application {0} with context root {1} and stack trace

{3}.

None

Reference information 385

Page 396: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0185E: An error has occurred while processing request:

Problem User response

Exception that occurred when processing the request. Review the message to determine the root cause of the

problem.

SRVE0186E: Can’t set buffer size after data has been written to stream

Problem User response

Some data has already been written to the stream, and

hence the buffer size can no longer be controlled

Either set the buffer size before writing data or reset the

buffer before setting the size.

SRVE0187E: Check your classpath to ensure that all classes required by the servlet are present.

Problem User response

A required class was not found Make sure your classpath reflects all the classes you may

be accessing

SRVE0188E: Class {0} does not implement servlet

Problem User response

The class mentioned needs to implement

javax.servlet.Servlet or extend one of

javax.servlet.GenericServlet or

javax.servlet.http.HttpServlet

The class mentioned needs to implement

javax.servlet.Servlet or extend one of

javax.servlet.GenericServlet or

javax.servlet.http.HttpServlet

SRVE0189E: Error occurred while finishing request

Problem User response

This is an error that occurs when the request was being

completed. This could have happened because of a

communication error within the Application Server but

should not have affect the processing of the request.

None

SRVE0190E: File not found: {0}

Problem User response

The mentioned file was not found. Ensure that the mentioned file is in place.

SRVE0194E: Illegal from included servlet

Problem User response

The attempted operation cannot be performed in an

included servlet/JSP (Refer to the Servlet specification)

None

SRVE0196E: Missing required initialization parameter: {0}

Problem User response

The parameter with the mentioned name has no value.

This is a required parameter.

Please supply a value to the mentioned parameter.

386 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 397: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0199E: OutputStream already obtained

Problem User response

Application requested a PrintWriter after the

ServletResponse OutputStream had already been

obtained.

Review application to determine if both PrintWriter and

OuputStream were obtained.

SRVE0200E: Servlet [{0}]: Could not find required class - {1}

Problem User response

Servlet could not find a required class needed to service

the request.

None

SRVE0201E: Servlet [{0}]: not a servlet class

Problem User response

The class mentioned needs to implement

javax.servlet.Servlet or extend one of

javax.servlet.GenericServlet or

javax.servlet.http.HttpServlet

The class mentioned needs to implement

javax.servlet.Servlet or extend one of

javax.servlet.GenericServlet or

javax.servlet.http.HttpServlet

v

SRVE0202E: Servlet [{0}]: {1} was found, but is corrupt:

Problem User response

The servlet class was found to be corrupted Please re-compile the class and try again.

SRVE0203E: Servlet [{0}]: {1} was found, but is missing another required class.

Problem User response

A required class was not found Make sure all required classes are placed in the

folders/Jars representing the classpath

SRVE0204E: The host {0} has not been defined

Problem User response

The virtual host was not found Please check the virtual host configuration in the

virtualhosts.xml file, or through the admin console

SRVE0205E: The host {0} on port {1} has not been defined

Problem User response

Unable to locate Virtual Host defined to handle this

request URI.

None

SRVE0206E: This error typically implies that the servlet was originally compiled with classes which

cannot be located by the server

Problem User response

None Please recompile the servlet with all required

components placed in the class path.

Reference information 387

Page 398: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0207E: Uncaught initialization exception thrown by servlet

Problem User response

The target threw an exception during initialization that

was not caught by the user code.

Please account for the exception in target code.

SRVE0208E: Unsupported conversion

Problem User response

The code tried to do an illegal conversion of a header

value. For example, from int to Data, when such a

conversion is not possible

None

SRVE0209E: Writer already obtained

Problem User response

The writer for this response has already been obtained.

Please use the existing writer

Review application to determine if both PrintWriter and

OuputStream were obtained.

SRVE0210I: This problem can be debugged by recompiling the servlet using only the classes in the

application’s runtime classpath

Problem User response

None None

SRVE0213E: class not found

Problem User response

Internal exception. Contact WebSphere Support for further assistance.

SRVE0214E: invalid count

Problem User response

Internal exception. Contact WebSphere Support for further assistance.

SRVE0215E: non-HTTP request or response

Problem User response

The servlet chain that has been defined can only handle

HTTP requests.

None

SRVE0216E: post body contains less bytes than specified by content-length

Problem User response

The incoming request may be corrupted. None

SRVE0217E: {0} is not a valid class

Problem User response

This error occurred when the webcontainer tried to load

an internal implementation class.

Check to make sure the original WAS classpath has not

been modified.

388 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 399: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0218E: Forbidden: Web Security Exception

Problem User response

The request tried to access a forbidden resource. Please make sure the requesting entity has the required

privileges.

SRVE0219I: No Error to Report

Problem User response

DefaultErrorReport was invoked but no error was found. Review application to determine cause of problem.

SRVE0220I: Wrapped Error-

Problem User response

Error that caused the problem. None

SRVE0221E: Serving contents of JSP files is not allowed

Problem User response

Cannot serve the contents of a JSP file None

SRVE0223I: StackTrace

Problem User response

None None

SRVE0224I: Target Servlet:

Problem User response

None None

SRVE0225I: Root Error-

Problem User response

None None

SRVE0227I: 1. Check that the class resides in the proper package directory.

Problem User response

Package name of resource does not match the compiled

class file’s package.

None

SRVE0228I: 2. Check that the classname has been defined in the server using the proper case and fully

qualified package.

Problem User response

None None

Reference information 389

Page 400: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0229I: 3. Check that the class was transferred to the filesystem using a binary transfer mode.

Problem User response

None None

SRVE0230I: 4. Check that the class was compiled using the proper case (as defined in the class

definition).

Problem User response

None None

SRVE0231E: 5. Check that the class file was not renamed after it was compiled.

Problem User response

None None

SRVE0233E: Error Report

Problem User response

None None

SRVE0234I: Application classpath=[{0}]

Problem User response

None None

SRVE0235E: [{0}] reported an error

Problem User response

See reported error None

SRVE0236E: Error occurred while invoking initialization collaborator on starting() call

Problem User response

Problem User response

Check the FFDC logs for more details on the error Check the FFDC logs for more details on the error

SRVE0237E: Error occurred while invoking initialization collaborator on started() call

Problem User response

Check the FFDC logs for more details on the error Check the FFDC logs for more details on the error

SRVE0238E: Resource paths should have a leading slash

Problem User response

None Please supply a leading slash before the path and try

again.

390 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 401: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0239I: Extension Factory [{0}] was registered successfully.

Problem User response

None None

SRVE0240I: Extension Factory [{0}] has been associated with patterns [{1}].

Problem User response

None None

SRVE0241I: Using [{0}] as the server root in getTempDirectory().

Problem User response

None None

SRVE0242I: [{2}] [{1}] [{0}]: Initialization successful.

Problem User response

The init() method of the target resource executed

successfully and the target has been places into service.

None

SRVE0243I: Reaper thread interval: [{0}] and inactive limit:[{1}] started.

Problem User response

None None

SRVE0244I: Reaper thread unloading servlet: [{0}].

Problem User response

The reaper thread removes servlets that have been

inactive for longer than the reaper inactive limit.

None

SRVE0245I: Reaper thread removing mapping: [{0}] for servlet: [{0}].

Problem User response

The reaper thread removes the mappings for jsps and

other extensions that have been inactive longer the the

reaper inactive limit.

None

SRVE0246I: Reaper thread destroying servlet: [{0}].

Problem User response

None None

SRVE0247E: Error during reaper thread execution.

Problem User response

Exception occurred in the reaper thread processing. Reaper processing is just a form of garbage collection.

Reference information 391

Page 402: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0248I: Requests are currently being processed. Waiting up to 60 seconds before forcing filter

destroy.

Problem User response

None None

SRVE0249W: Application {0} has requested SyncToOSThread, but the server is not enabled for

SyncToOSThread

Problem User response

SyncToOSThread synchronizes the J2EE role identity to

the OS thread, meaning that the OS thread identity is

made equal to the J2EE role identity for the duration of

the request. This message indicates that while an

application has been configured to utilize

SyncToOSThread functionality, the server it is installed

into is not configured to support SyncToOSThread

capabilities.

If SyncToOSThread capabilities are desired for the server

in question, please refer to the InfoCenter for a

description as to how to enable SyncToOSThread for a

server.

SRVE0250I: Web Module {0} has been bound to {1}.

Problem User response

The specified web module has been associated to the

virtualhost mentioned, and can be accessed through any

of the host/port combinations for that virtualhost.

None

SRVE0251W: The threadpool configured under the webcontainer is not being used.

Problem User response

There exists a ThreadPool configuration under the

webcontainer. Any changes made to this configuration

item will not result in changes in the system.

None

SRVE0252W: Transports and Chains have been detected! The transports have been changed to use a

new model. Please use the migration utilities to migrate the transports to the new model. The

threadpool configuration under the webcontainer will not be used with these transports.

Problem User response

Transports have been changed to use Channel Chains.

Please refer to the Infocenter to review information on

Channel Chains, and how to migrate the existing

transports to be channel chain based. The thread pool

configuration under the webcontainer will not be used to

these transports.

Use the migration utilities to migrate your configuration

model from the transports to the new channel chains.

SRVE0253I: [{2}] [{1}] [{0}]: Destroy successful.

Problem User response

The destroy() method of the target resource executed

successfully and the target has been removed from

service.

None

392 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 403: Lotus Expeditor: Developing Applications for Lotus Expeditor

SRVE0254E: Failed to set request character encoding: [{0}].

Problem User response

Invalid request encoding specified on the request. Review logs to determine whether the specified encoding

is a valid encoding.

SRVE0255E: A WebGroup/Virtual Host to handle {0} has not been defined.

Problem User response

Could not find a web group (web module) or virtual

host to handle the request.

Be sure the web group and virtual host is defined and

deployed.

SRVE0256E: WebContainer has not been initialized.

Problem User response

WebContainer is not initialized until an application has

been installed.

None

Reference information 393

Page 404: Lotus Expeditor: Developing Applications for Lotus Expeditor

394 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 405: Lotus Expeditor: Developing Applications for Lotus Expeditor

Appendix. Notices

This information was developed for products and services offered in the U.S.A. IBM might not offer the

products, services, or features discussed in this document in other countries. Consult your local IBM

representative for information on the products and services currently available in your area. Any

reference to an IBM product, program, or service is not intended to state or imply that only that IBM

product, program, or service may be used. Any functionally equivalent product, program, or service that

does not infringe any IBM intellectual property right may be used instead. However, it is the user’s

responsibility to evaluate and verify the operation of any non-IBM product, program, or service.

IBM might have patents or pending patent applications covering subject matter in this document. The

furnishing of this document does not give you any license to these patents. You can send license

inquiries, in writing, to:

IBM Director of Licensing

IBM Corporation

North Castle Drive

Armonk, NY 10504-1785

U.S.A.

For license inquiries regarding double-byte (DBCS) information, contact the IBM Intellectual Property

Department in your country or send inquiries, in writing, to:

IBM World Trade Asia Corporation Licensing

2-31 Roppongi 3-chome, Minato-ku

Tokyo 106, Japan

The following paragraph does not apply to the United Kingdom or any other country where such

provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION

PROVIDES THIS PUBLICATION “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS

OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF

NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some

states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this

statement may not apply to you.

This information could include technical inaccuracies or typographical errors. Changes are periodically

made to the information herein; these changes will be incorporated in new editions of the information.

IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this

information at any time without notice.

Any references in this information to non-IBM Web sites are provided for convenience only and do not in

any manner serve as an endorsement of those Web sites. The materials at those Web sites are not part of

the materials for this IBM product and use of those Web sites is at your own risk.

IBM may use or distribute any of the information you supply in any way it believes appropriate without

incurring any obligation to you.

Licensees of this program who wish to have information about it for the purpose of enabling: (i) the

exchange of information between independently created programs and other programs (including this

one) and (ii) the mutual use of the information which has been exchanged, should contact:

IBM Corporation

Intellectual Property Law

© Copyright IBM Corp. 2004, 2006 395

Page 406: Lotus Expeditor: Developing Applications for Lotus Expeditor

Department LZMS

11501 Burnet Road

Austin, TX 78758-3400

U.S.A.

Such information may be available, subject to appropriate terms and conditions, including in some cases,

payment of a fee.

The licensed program described in this document and all licensed material available for it are provided

by IBM under terms of the IBM Customer Agreement, IBM International Program License Agreement, or

any equivalent agreement between us.

Any performance data contained herein was determined in a controlled environment. Therefore, the

results obtained in other operating environments may vary significantly. Some measurements may have

been made on development-level systems and there is no guarantee that these measurements will be the

same on generally available systems. Furthermore, some measurement may have been estimated through

extrapolation. Actual results may vary. Users of this document should verify the applicable data for their

specific environment.

Information concerning non-IBM products was obtained from the suppliers of those products, their

published announcements or other publicly available sources. IBM has not tested those products and

cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM

products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of

those products.

All statements regarding IBM’s future direction or intent are subject to change or withdrawal without

notice, and represent goals and objectives only.

All IBM prices shown are IBM’s suggested retail prices, are current and are subject to change without

notice. Dealer prices may vary.

This information is for planning purposes only. The information herein is subject to change before the

products described become available.

This information contains examples of data and reports used in daily business operations. To illustrate

them as completely as possible, the examples include the names of individuals, companies, brands, and

products. All of these names are fictitious and any similarity to the names and addresses used by an

actual business enterprise is entirely coincidental.

COPYRIGHT LICENSE:

This information contains sample application programs in source language, which illustrate programming

techniques on various operating platforms. You may copy, modify, and distribute these sample programs

in any form without payment to IBM, for the purposes of developing, using, marketing or distributing

application programs conforming to the application programming interface for the operating platform for

which the sample programs are written. These examples have not been thoroughly tested under all

conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these

programs. You may copy, modify, and distribute these sample programs in any form without payment to

IBM for the purposes of developing, using, marketing, or distributing application programs conforming

to IBM’s application programming interfaces.

You may copy, modify, and distribute these sample programs in any form without payment to IBM for

the purposes of developing, using, marketing, or distributing application programs conforming to IBM’s

application programming interfaces.

396 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 407: Lotus Expeditor: Developing Applications for Lotus Expeditor

Each copy or any portion of these sample programs or any derivative work, must include a copyright

notice as follows:

© (your company name) 2004, 2006. Portions of this code are derived from IBM Corp. Sample Programs.

© Copyright IBM Corp. 2004, 2006 All rights reserved.

If you are viewing this information softcopy, the photographs and color illustrations may not appear.

Trademarks

The following terms are trademarks or registered trademarks of International Business Machines

Corporation in the United States, or other countries, or both:

Everyplace

IBM

IBM logo

Lotus

Rational

Rational Suite

WebSphere

Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other

countries, or both.

UNIX is a registered trademark of The Open Group in the United States and other countries.

Linux is a registered trademark of Linux Torvalds in the United States, other countries, or both.

Microsoft and Windows are trademarks of Microsoft Corporation in the United States, other countries, or

both.

Other company, product or service names may be trademarks or service marks of others.

Appendix. Notices 397

Page 408: Lotus Expeditor: Developing Applications for Lotus Expeditor

398 Lotus Expeditor: Developing Applications for Lotus Expeditor

Page 409: Lotus Expeditor: Developing Applications for Lotus Expeditor
Page 410: Lotus Expeditor: Developing Applications for Lotus Expeditor

����

Printed in USA