+ All Categories
Home > Documents > Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Date post: 03-Feb-2022
Category:
Upload: others
View: 7 times
Download: 0 times
Share this document with a friend
552
Lotus® Expeditor Developing Applications for Lotus Expeditor 6.1.x
Transcript
Page 1: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Lotus® Expeditor

Developing Applications for Lotus Expeditor 6.1.x

���

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

Lotus® Expeditor

Developing Applications for Lotus Expeditor 6.1.x

���

Page 4: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Note

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

Fifth Edition (January 2008)

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

modifications until otherwise indicated in new editions.

© Copyright International Business Machines Corporation 2004, 2008. 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 6.1

Contents

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

What’s new in Lotus Expeditor 6.1.1 . . . . . . 2

Lotus Expeditor Toolkit 6.1.1 . . . . . . . . 2

Lotus Expeditor Client for Desktop 6.1.1 . . . . 3

Lotus Expeditor Client for Devices 6.1.1 . . . . 5

What’s new in Lotus Expeditor 6.1.2 . . . . . . 5

Lotus Expeditor Toolkit 6.1.2 . . . . . . . . 5

Lotus Expeditor Client for Desktop 6.1.2 . . . . 6

Lotus Expeditor Client for Devices 6.1.2 . . . . 8

Overview of the managed client platform . . . . . 8

Managed client services . . . . . . . . . . 8

Access services . . . . . . . . . . . . 9

Interaction services . . . . . . . . . . . 11

Lotus Expeditor Client for Desktop . . . . 11

Lotus Expeditor Client for Devices . . . . 12

Platform management . . . . . . . . . . 12

Using the Lotus Expeditor Toolkit . . . . . . . 12

Getting started with the Lotus Expeditor Toolkit 13

Lotus Expeditor Toolkit overview . . . . . 13

Supported platforms and prerequisite software 13

Limitations when using Lotus Expeditor

Toolkit on Eclipse + WTP . . . . . . . 14

Understanding the development platforms . . 14

Setting up the Lotus Expeditor Toolkit . . . 15

Setup for Desktop development . . . . 15

Setup for Device development . . . . . 15

Creating a sample Client Services project . . 15

Running your project on development

runtimes . . . . . . . . . . . . 15

Setting Toolkit preferences . . . . . . . 16

Turning on build automatically . . . . . . 18

Concepts . . . . . . . . . . . . . 18

Client Services Project . . . . . . . . 18

Managing Client Services project

dependencies . . . . . . . . . . . . 18

Target Definitions . . . . . . . . . 18

Target features . . . . . . . . . . 22

Non-profiled Features . . . . . . . . 22

Automatic management of manifest

package dependencies . . . . . . . . 22

Configuring the Client Services launcher . . 23

Installing the IBM Desktop Runtime

Environment for the Lotus Expeditor Toolkit . 23

Using the Lotus Expeditor Toolkit with Lotus

Sametime . . . . . . . . . . . . . . 24

Configuring for Lotus Sametime . . . . . 24

Configuring for Lotus Expeditor with

Embedded Sametime . . . . . . . . . 25

Launching . . . . . . . . . . . . . 26

Using the Lotus Expeditor Toolkit with Lotus

Notes 8.0 or 8.0.1 . . . . . . . . . . . 26

Configuring for Lotus Notes 8.0 . . . . . 26

Configuring for Lotus Notes 8.0 or 8.0.1 . . . 27

Launching . . . . . . . . . . . . . 27

Selecting and configuring test environments . . 28

Enabling a test environment to display in the

configuration wizard using a Lotus Expeditor

extension point . . . . . . . . . . . 28

Setting up a test environment for

configuration using the extension point

mechanism . . . . . . . . . . . 28

Selecting and configuring test environments

using the Lotus Expeditor Configuration

Wizard . . . . . . . . . . . . . . 29

Using the configuration wizard on startup

to select and configure a test environment . 29

Launching the configuration wizard from

the IDE to select and configure a test

environment . . . . . . . . . . . 29

Setting the configuration wizard to not run

automatically . . . . . . . . . . . 29

Creating and using Client Services applications 30

Creating a Client Services project . . . . . 30

Creating a Client Services fragment project . . 30

Converting a Java project into a Client

Services project . . . . . . . . . . . 31

Importing a Client Services project . . . . 31

Exporting a Client Services project . . . . . 32

Updating an imported Client Services project’s

JRE System Library . . . . . . . . . . 32

Updating the buildpath and classpath for

converted Client Services projects . . . . . 32

Setting Client Services project properties . . . 32

Launching Client Services launch

configurations from the manifest editor . . . 33

Using the samples . . . . . . . . . . . . 33

Installing samples using the Rational Software

Development Platform (RSDP) . . . . . . . 33

Installing samples using Eclipse (without RSDP) 34

Accounts sample . . . . . . . . . . 35

Setup instructions . . . . . . . . . 35

Running the sample . . . . . . . . 36

Troubleshooting . . . . . . . . . . 36

Branding sample . . . . . . . . . . 37

Setup instructions . . . . . . . . . 37

Running the sample . . . . . . . . 38

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

Composite Application sample . . . . . . 39

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

Running the sample – Portlet to Portlet

Communication . . . . . . . . . . 40

Running the sample – Portlet to SWT

Communication . . . . . . . . . . 40

Running the sample – SWT to Portlet

Communication . . . . . . . . . . 40

Running the sample – Browser . . . . . 41

Running the sample – Double Browser . . 41

Running the sample – Cross Page Wire . . 41

Troubleshooting . . . . . . . . . . 42

DB2 Everyplace sample . . . . . . . . 42

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

© Copyright IBM Corp. 2004, 2008 iii

[[[[[[[[

[[

[ [ [ [ [ [ [

Page 6: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

Derby sample . . . . . . . . . . . 44

Setup instructions . . . . . . . . . 44

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

Echo sample . . . . . . . . . . . . 45

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

Echo Secure sample . . . . . . . . . 48

Setup instructions . . . . . . . . . 49

Eclipse Preferences sample . . . . . . . 50

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

Running the sample . . . . . . . . 50

Embedded Browser sample . . . . . . . 51

Setup instructions . . . . . . . . . 51

Running the sample . . . . . . . . 52

Troubleshooting . . . . . . . . . . 52

Embedded Transaction Container sample . . 52

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

eRCP E-mail sample . . . . . . . . . 54

Setup instructions . . . . . . . . . 54

eSWT Demo sample . . . . . . . . . 55

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

ISync sample . . . . . . . . . . . . 56

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

Accounts enablement . . . . . . . . 60

Troubleshooting . . . . . . . . . . 60

JMS with Lotus Expeditor micro broker

provider sample . . . . . . . . . . . 62

Setup instructions . . . . . . . . . 62

Option A: Using the in-memory-based

micro broker instance . . . . . . . . 63

Option B: Using the file-persistence-based

micro broker instance . . . . . . . . 63

JMS with MQe Provider sample . . . . . 64

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

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

JNDI sample . . . . . . . . . . . . 67

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

Troubleshooting . . . . . . . . . . 68

Log and Log Reader sample . . . . . . . 69

Setup instructions . . . . . . . . . 69

Troubleshooting . . . . . . . . . . 70

Mobile Adjuster sample . . . . . . . . 70

Setup instructions . . . . . . . . . 71

MQ Everyplace sample . . . . . . . . 71

Setup instructions . . . . . . . . . 72

Troubleshooting . . . . . . . . . . 73

Network Status sample . . . . . . . . 74

Setup instructions . . . . . . . . . 74

Running the sample . . . . . . . . 74

Troubleshooting . . . . . . . . . . 75

Order Entry sample . . . . . . . . . 75

Setup instructions . . . . . . . . . 76

Order Entry Rich Client sample . . . . 76

Order Entry Web Application sample . . . 77

OSGi Preferences Service sample . . . . . 78

Setup instructions . . . . . . . . . 79

Pizza JSP sample . . . . . . . . . . 80

Setup instructions . . . . . . . . . 80

Portlet Communication sample . . . . . . 81

Setup instructions . . . . . . . . . 81

Rich Application sample . . . . . . . . 82

Setup instructions . . . . . . . . . 82

Troubleshooting . . . . . . . . . . 83

Rich Text Editor sample . . . . . . . . 83

Setup instructions . . . . . . . . . 84

Secured Web Application sample . . . . . 84

Setup instructions . . . . . . . . . 84

Running the sample . . . . . . . . 85

Service Tracker sample . . . . . . . . 86

Setup instructions . . . . . . . . . 86

Simple Portlet sample . . . . . . . . . 88

Setup instructions . . . . . . . . . 88

Simple Portlet Viewer sample . . . . . . 89

Setup instructions . . . . . . . . . 89

Property Broker sample . . . . . . . . 90

Setup instructions . . . . . . . . . 90

Running the sample . . . . . . . . 91

Troubleshooting . . . . . . . . . . 91

Web Application sample . . . . . . . . 91

Setup instructions . . . . . . . . . 91

Web Application Log sample . . . . . . 92

Setup instructions . . . . . . . . . 92

Portlet Aggregation Web Page sample . . . 93

Setup instructions . . . . . . . . . 93

Troubleshooting . . . . . . . . . . 94

XML Parser sample . . . . . . . . . . 95

Setup instructions . . . . . . . . . 95

Developing applications . . . . . . . 97

Application models . . . . . . . . . . . . 97

Application design considerations . . . . . . . 97

End-to-End applications . . . . . . . . . 97

Topology . . . . . . . . . . . . . . 99

Business logic . . . . . . . . . . . . 99

Persistence . . . . . . . . . . . . . 100

Messaging . . . . . . . . . . . . . 100

Management . . . . . . . . . . . . 101

Serviceability . . . . . . . . . . . . 101

Interaction . . . . . . . . . . . . . 101

Cross platform APIs . . . . . . . . . . 101

Packaging . . . . . . . . . . . . . 102

Components . . . . . . . . . . . . 102

Fragments . . . . . . . . . . . . 103

Features . . . . . . . . . . . . . 103

Class loading . . . . . . . . . . . . 104

Developing with the jclDesktop JRE . . . . . . 107

Understanding the jclDesktop JRE . . . . . 107

Developing with jclDesktop Unique

Components . . . . . . . . . . . . . 108

J9 JCE Provider Details . . . . . . . . 109

J9 JSSE and Provider Details . . . . . . 110

Using the IBM JNDI LDAP Provider . . . . 111

Creating an Initial Context . . . . . . 111

Binding to a Server / SASL Support . . . 111

Advanced Topics . . . . . . . . . 113

Developing the application user interface . . . . 116

Understanding the user interface . . . . . . 116

Eclipse . . . . . . . . . . . . . 117

UI toolkits . . . . . . . . . . . . 117

Visual Editor for Java . . . . . . . . . 118

User interaction in the Lotus Expeditor . . . 118

User interface organization . . . . . . . 118

iv Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [

Page 7: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Title bar . . . . . . . . . . . . 119

Menu bar . . . . . . . . . . . . 119

Banner bar . . . . . . . . . . . 119

Data area . . . . . . . . . . . . 119

Coolbar/Toolbar . . . . . . . . . 119

Status bar . . . . . . . . . . . 119

Sidebar . . . . . . . . . . . . 119

Application Launcher . . . . . . . 120

Using widgets on devices . . . . . . . 120

Functional partitioning . . . . . . . 120

Device normalization . . . . . . . . 120

Mobile extensions widgets . . . . . . 121

eSWT programming tips . . . . . . 123

Using the Restricted Workbench . . . . . . 123

Applicability and benefits . . . . . . . 124

Using ILockdownService . . . . . . . 124

Acquiring the ILockdownService . . . . 124

Using the ILockdownService to remove

the window title trim . . . . . . . . 125

Using the ILockdownService to lock the

window . . . . . . . . . . . . 125

Using the ILockdownService to exit the

Restricted Workbench and logoff the OS . 125

Using personalities . . . . . . . . . . 125

Creating a personality . . . . . . . . 125

Creating a personality from scratch . . . 125

Extending an existing personality . . . 126

Lifecycle events . . . . . . . . . . 127

Creating a global toolbar . . . . . . . 127

Contributing to the sidebar . . . . . . . 128

“shelfViews” Programming Model . . . 128

Contributing to the shelfViews extension

point . . . . . . . . . . . . . 128

Developing composite applications . . . . . . 129

Understanding composite applications . . . . 129

Building composite applications using Portal UI 129

Building a composite application

programmatically in Eclipse . . . . . . . 130

Accessing topology meta data . . . . . . . 131

Sample composite application project . . . . 133

Creating an SWT view component . . . . 134

Creating a dummy portlet . . . . . . 136

Enhancing the sample by adding a portlet

component . . . . . . . . . . . . 137

Defining the Rich Client properties on the

Portal UI . . . . . . . . . . . . . 138

Creating multiple SWT components in an

Eclipse plugin . . . . . . . . . . . . 139

Displaying multiple pages in one tab . . . . 141

Creating a custom navigator for composite

applications, for 6.1.1 . . . . . . . . . . 141

Creating a custom navigator for composite

applications, for 6.1.2 . . . . . . . . . . 153

Built-in properties for Eclipse Components . . 164

Exploring more advanced functionality of

composite applications . . . . . . . . . 165

Developing composite application logic . . . 166

Developing data access applications . . . . . . 167

Understanding embedded database

development . . . . . . . . . . . . 167

Databases . . . . . . . . . . . . 167

Embedded databases . . . . . . . . 168

DB2 Everyplace and Apache Derby

comparison . . . . . . . . . . . 168

Deployment and synchronization . . . . . 169

Security considerations . . . . . . . 170

Database lifecycle management . . . . . 171

Enabling projects for data access application

development . . . . . . . . . . . . 171

Client Services target definition features . . 171

Developing database logic . . . . . . . . 172

Data access application development best

practices . . . . . . . . . . . . . 172

Database Lifecycle Management . . . . . 173

Accessing a defined managed datasource 173

Monitoring operations on a managed

datasource . . . . . . . . . . . 173

Accessing the default managed datasource 174

Apache Derby . . . . . . . . . . . 174

Developing Embedded Transaction applications 174

Understanding the Embedded Transaction

Container . . . . . . . . . . . . . . 175

Concepts . . . . . . . . . . . . . 176

EJB Container . . . . . . . . . . 176

Home Interfaces . . . . . . . . . 176

Finder Methods . . . . . . . . . 176

Component interfaces . . . . . . . 176

Transaction management . . . . . . 177

Container managed transactions . . . . 177

Programmatic transaction management 177

DataSource/TxnDataSource . . . . . 177

Container managed relationships . . . . 177

Creating Embedded Transaction projects . . . 178

Using a Client Services Embedded

Transaction project versus an EJB project . . 178

Creating a Client Services Embedded

Transaction project . . . . . . . . . 178

Converting an EJB project to a Client Services

Embedded Transaction project . . . . . . 179

Embedded Transaction Container preferences 179

Developing Embedded Transaction Container

logic . . . . . . . . . . . . . . . 180

Implementing finder methods . . . . . . 180

Configuring and using data sources . . . . 182

Creating and binding DataSource

instances . . . . . . . . . . . . 182

Locating and connecting to a DataSource 183

Locating EJBs . . . . . . . . . . . 183

Finding EJB homes . . . . . . . . 183

Conserving JDBC resources . . . . . . . 183

Working with user managed transactions . . 184

Advanced topics . . . . . . . . . 184

Providing custom bundle activation . . . . 184

Creating Session and Entity Beans . . . . 185

Creating a Container Managed Persistence

(CMP) bean . . . . . . . . . . . 185

Creating EJB CMP 1.1 beans . . . . . 187

Creating a stateless session bean . . . . 187

Creating a Bean Managed Persistence

(BMP) bean . . . . . . . . . . . 188

Implementing container-managed

relationships . . . . . . . . . . . . 189

Contents v

[[[[[[[[

Page 8: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Customizing for target data base (DB2e and

Derby) . . . . . . . . . . . . . 190

Packaging and deploying Embedded

Transaction applications . . . . . . . . . 190

Invoking deployment . . . . . . . . . 190

Embedded Transaction Deployment

Descriptor . . . . . . . . . . . . 190

Embedded Transaction Deployment Editor 191

Debugging and testing Embedded Transaction

applications . . . . . . . . . . . . . 194

Enabling logging and tracing with the

Embedded Transaction Container . . . . . 194

Run or debug Client Services Embedded

Transaction Container projects using the

Client Services launcher . . . . . . . . 194

Run or debug a Client Services Embedded

Transaction Container project on the Lotus

Expeditor runtime . . . . . . . . . . 195

Run or debug a non-Client Services EJB

project on the Lotus Expeditor runtime . . . 195

Run or debug a Client Services Embedded

Transaction Container project on a non-Lotus

Expeditor runtime . . . . . . . . . . 196

Setting breakpoints on generated code . . . 196

Developing Lotus Sametime applications . . . . 196

Understanding Lotus Sametime application

development . . . . . . . . . . . . 196

Enabling projects for Lotus Sametime

application development . . . . . . . . 197

Client Services target profile features . . . 197

Developing Lotus Sametime logic . . . . . 198

Developing management applications . . . . . 198

Developing applications to drive the Enterprise

Management Agent . . . . . . . . . . 198

Accessing the OSGiAgentService object . . . 198

Developing Enterprise Management Agent

SyncML tree extensions . . . . . . . . . 199

SyncML tree extensions overview . . . . 199

Creating an Extension to the SyncML Tree 199

Creating an Extension to register the

command for Exec Leaf . . . . . . . . 200

Developing update manager applications . . . 200

Developing messaging applications . . . . . . 201

Understanding messaging applications . . . . 201

Publish and subscribe messaging . . . . . 201

Topics and hierarchical topic names . . . 202

Publication and subscription messages 205

Point-to-point messaging . . . . . . . 207

Messaging protocols . . . . . . . . . 208

MQTT . . . . . . . . . . . . . . 209

Quality of Service . . . . . . . . . 209

Clean session . . . . . . . . . . 210

WebSphere MQ Everyplace . . . . . . . 211

Lotus Expeditor micro broker . . . . . . 211

Scenarios and applications . . . . . . 212

Understanding the micro broker

components . . . . . . . . . . . 213

Prerequisites . . . . . . . . . . . 215

Micro broker topologies . . . . . . . 215

Environments . . . . . . . . . . 217

WebSphere MQ Everyplace and micro broker

comparison . . . . . . . . . . . . 218

Enabling projects for messaging . . . . . . 218

Client Services target definition features . . 218

Developing messaging application logic . . . 219

MQ Telemetry Transport . . . . . . . 219

Developing network aware applications . . . . 219

Understanding network aware applications . . 219

Enabling network aware applications . . . . 220

Developing network aware application logic . . 220

Component registration . . . . . . . . 220

Creating and configuring handlers . . . . 222

Adding and configuring customized handlers 223

Using the NetStatus API to detect the real

network status . . . . . . . . . . . 224

Using enhanced HttpClient . . . . . . . 224

Monitoring remote resources . . . . . . 224

Using the notification and check models . . 226

Notification model . . . . . . . . 226

Check model . . . . . . . . . . 226

Configuring the proxy settings for Lotus

Expeditor . . . . . . . . . . . . . 226

Developing Portlet applications . . . . . . . 228

Understanding Portlet applications . . . . . 228

URL Addressability . . . . . . . . . 229

Portlet API and Type support . . . . . . 230

Unsupported features . . . . . . . . 230

Using the Portlet Aggregation Tag Library 231

Creating Portlet projects . . . . . . . . . 231

Creating a Client Services Portlet project . . 232

Converting a Java EE Portlet project to a

Client Services Portlet project . . . . . . 232

Importing Client Services Portlet projects . . 233

Adding a Portlet to a Client Services Portlet

project . . . . . . . . . . . . . . 233

Developing Portlet application logic . . . . . 233

Aggregating Portlets to JSPs . . . . . . 233

Securing Portlet application resources . . . 234

Transport level security (HTTPS) . . . . 234

Programmatic security . . . . . . . 235

Customized Portlet Modes Support . . . . 235

Debugging and testing Client Services Portlet

applications . . . . . . . . . . . . . 236

Debugging and testing Client Services Portlet

projects on a test environment . . . . . . 236

Debugging and testing Client Services Portlet

projects on non-Lotus Expeditor runtimes . . 236

Developing Rich Client applications . . . . . . 236

Creating a simple Rich Client Platform

application . . . . . . . . . . . . . 237

Creating a simple Rich Client Application for

devices . . . . . . . . . . . . . . 239

Creating a Rich GUI application for devices 239

Setup . . . . . . . . . . . . . 239

Creating the basic parts of a Rich GUI

application . . . . . . . . . . . 239

Using the eRCP templates to create a Rich

GUI application . . . . . . . . . 241

Running your application on the

development runtime . . . . . . . . 241

vi Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[ [

[ [ [

Page 9: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Creating an eRCP workbench application

from an existing project . . . . . . . . 242

Deploying an eRCP workbench application 243

Installing an eRCP workbench application 244

Running an eRCP eWorkbench application 244

Managing an eRCP eWorkbench application 244

Extending the capabilities of your application 245

Customizing the user interface . . . . . 245

Using themes . . . . . . . . . . 245

Custom widgets . . . . . . . . . 251

Using SWidgets . . . . . . . . . . 280

Managing contributions to the user interface 280

Accessing SWidgets and JFaceEX objects . . 281

Adding and contributing menus . . . . . 282

Menu contributions . . . . . . . . 282

Creating a top-level menu . . . . . . 283

Creating views . . . . . . . . . . . 284

Applying Capitalization and punctuation

guidelines . . . . . . . . . . . . 284

Creating helpful messages . . . . . . . 285

Critical . . . . . . . . . . . . 285

Warning . . . . . . . . . . . . 285

Understanding threading . . . . . . . 285

Customizing existing applications . . . . . 286

Activities . . . . . . . . . . . . . 287

Using activities . . . . . . . . . . 287

Integrating existing RCP applications into Lotus

Expeditor . . . . . . . . . . . . . . 288

Developing with user interface widgets . . . 288

Adding spell checking to applications . . . 288

Using dictionaries supported by a given

locale . . . . . . . . . . . . . 289

Using dictionaries supported by the

platform default locale . . . . . . . 289

Using given dictionaries . . . . . . . 289

Using given dictionaries and a customized

user dictionary . . . . . . . . . . 289

Using the getSuggestions string . . . . 290

User dictionary manager . . . . . . 290

Contributing custom spell checking

services . . . . . . . . . . . . 292

Implementing an embedded Web browser 300

Creating an embedded browser . . . . 301

Enhancing an embedded browser view 302

Setting browser preferences . . . . . . 303

Using the Rich Text Editor . . . . . . . 311

Creating a custom Rich Text Editor . . . 311

Using and controlling the custom Rich

Text Editor . . . . . . . . . . . 312

Accessing a Web address with the integrated

browser application . . . . . . . . . 313

Customizing the integrated browser

application with Eclipse preferences . . . 314

Using the Portlet Viewer . . . . . . . 315

Portlet Viewer extension examples . . . 315

Using the Portlet Viewer with WSRP

portlets . . . . . . . . . . . . 315

Widgets for devices . . . . . . . . . 316

Creating help for the application . . . . . . 316

Developing synchronization applications . . . . 316

SyncML . . . . . . . . . . . . . . 317

Understanding SyncML development . . . 317

Technology overview . . . . . . . . 317

SyncML4J common . . . . . . . . 318

SyncML4J data synchronization . . . . 318

SyncML4J device management . . . . 318

Enabling projects for SyncML development 319

Client Services target definition

components . . . . . . . . . . . 319

SyncManager . . . . . . . . . . . . 319

Understanding the SyncManager . . . . . 319

Enabling projects for the SyncManager . . . 319

SyncService extension point . . . . . 320

TypeService extension point . . . . . 320

SchedulerService extension point . . . . 321

Developing SyncManager application logic 322

Developing Web applications . . . . . . . . 325

Understanding Web Applications . . . . . . 325

Creating Web Application projects . . . . . 326

Using a Client Services Web project versus a

Dynamic Web project . . . . . . . . . 326

Creating a Client Services Web project . . . 327

Converting a Dynamic Web project to a

Client Services Web project . . . . . . . 328

Developing Web Application logic . . . . . 329

Accessing Web application resources . . . 329

Accessing resources packaged in JAR

bundles . . . . . . . . . . . . 329

Registering and accessing static Web

application resources in Lotus Expeditor . 329

Using JSP Standard Tag Libraries . . . . . 330

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

Using the IBM JavaServer Faces (JSF)

Extension or the JavaServer Faces Widget

Library (JWL) . . . . . . . . . . 331

Using the JavaServer Faces Widget Library

(JWL) without the default faces

configuration . . . . . . . . . . 331

Using the Sun JSF Reference

Implementation . . . . . . . . . 332

Struts development . . . . . . . . . 332

Securing Web Application resources . . . . 333

Configuring a Web Application . . . . 333

Supported authentication mechanisms . . 334

Using the User Admin Service to create

users and roles . . . . . . . . . . 334

Using Internet Explorer 7 to access a

secured Web application . . . . . . . 335

Exporting Web Application bundles . . . . 336

WAB Utility . . . . . . . . . . . . 336

WAB Utility installation . . . . . . . 336

WAB Utility usage and parameters . . . 337

Using Lotus Expeditor servers . . . . . . 338

Dynamic JSP support . . . . . . . . . 339

Configuring web projects for incremental JSP

translation . . . . . . . . . . . . 339

Servicing Web Applications . . . . . . . . 340

Web Container Logging . . . . . . . . 340

Configuring the Web Container Logging 340

Debugging and testing Web Applications . . . 340

Running and debugging using Client

Services launcher . . . . . . . . . . 340

Contents vii

[[

[ [ [

Page 10: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Running and debugging using ″Run on

Server″ style . . . . . . . . . . . . 340

Running or debugging Client Services

Web Projects on the Client Services

runtime . . . . . . . . . . . . 340

Run or debug a non-Client Services Web

Project on the Client Services runtime . . 341

Running or debugging a Client Services

Web Project on a non-Client Services

runtime . . . . . . . . . . . . 341

Developing Web Services . . . . . . . . . 341

Understanding Web Services . . . . . . . 342

Technologies . . . . . . . . . . . . 342

Web Services Description Language

(WSDL) . . . . . . . . . . . . 342

Simple Object Access Protocol (SOAP) . . 342

JAX-RPC . . . . . . . . . . . . 342

The Web Services Client Programming

Model . . . . . . . . . . . . . 342

Tools . . . . . . . . . . . . . . 343

Tools for Mobile Web Services

development . . . . . . . . . . 343

Web Services Resource Framework . . . . . 343

Understanding WSRF applications . . . . 343

Technologies . . . . . . . . . . . 344

WS-Resource . . . . . . . . . . 344

WSRF Runtime . . . . . . . . . . 345

WSRF tools . . . . . . . . . . . 346

Creating WS-Resource projects . . . . . 346

Developing WS-Resource providers . . . 347

Creating a WS-Resource client for 6.1.1 352

Creating a WS-Resource client for 6.1.2 353

Supported data types . . . . . . . . 354

Developing WSRF application logic . . . . 355

WS-Resource provider application for 6.1.1 355

WS-Resource provider application for 6.1.2 359

WS-Resource client applications . . . . 363

WS-Resource creation operations . . . . 363

WS-Resource LifeTime operations . . . 364

WS-Resource properties operations . . . 365

WS-Resource service method operations 369

Understanding interactions among

WS-Resources . . . . . . . . . . 370

Packaging and deploying WS-Resource

bundles . . . . . . . . . . . . . 370

Deploying a WS-Resource provider . . . 370

Deploying a WS-Resource client . . . . 371

Accessing a WS-Resource from Java

applications . . . . . . . . . . . 372

Deploying a WS-Resource Client with an

application bundle . . . . . . . . 372

Securing a WS-Resource for 6.1.1 . . . . . 373

Enabling security for WS-Resource

providers . . . . . . . . . . . . 373

Enabling security for WS-Resource clients 374

Developing custom authenticators . . . 375

Securing a WS-Resource for 6.1.2 . . . . . 375

Securing a WS-Resource with Web service

security . . . . . . . . . . . . 376

Creating WS-Resources with Web

container security . . . . . . . . . 379

Mobile Web Services . . . . . . . . . . 381

Creating Mobile Web Services . . . . . . 381

Creating Mobile Web Services providers 381

Creating Mobile Web Services clients . . 386

Developing Mobile Web Services logic . . . 393

Custom serialization (marshalling) . . . 393

Securing Mobile Web Services . . . . . . 399

Creating secure Mobile Web Services

providers . . . . . . . . . . . . 399

Securing pre-existing Mobile Web Services

providers . . . . . . . . . . . . 400

Developing custom authenticators or

custom authorizers for Web Services

providers . . . . . . . . . . . . 400

Creating secure Mobile Web services

clients . . . . . . . . . . . . . 405

Securing pre-existing Mobile Web Services

clients . . . . . . . . . . . . . 407

Developing custom callback handlers for

Mobile Web Services clients . . . . . 407

Editing the Mobile Web Services security

configuration . . . . . . . . . . 410

Deploying Mobile Web Services . . . . . 418

Deploying Mobile Web Services providers 418

Deploying Mobile Web Services clients 419

Axis Web Services . . . . . . . . . . . 420

Creating Axis Web Services Clients . . . . 420

Creating an Apache Axis based Web

Services client . . . . . . . . . . 420

Directly obtaining an instance of the

interface stub . . . . . . . . . . 421

Obtaining an instance of the interface stub

using the JNDI mechanism . . . . . . 422

Defining the extensions to register the

Service Interface to JNDI provider . . . 422

Using the Accounts tool to create accounts

for Apache Axis Web services clients . . 422

Programmatically creating accounts for

Apache Axis Web Services clients . . . . 426

Developing wired applications . . . . . . . 427

Portlet communication . . . . . . . . . 427

Defining actions and properties . . . . . 427

Wiring portlets . . . . . . . . . . . 428

Wire extension examples . . . . . . . 429

Using the portlet wiring tool . . . . . . 430

Property Broker Editor . . . . . . . . 430

Creating Cooperative Components with the

Lotus Expeditor Property Broker . . . . . . 431

Creating your components . . . . . . . 431

Registering your definitions with the broker 432

Working with the Property Broker WSDL file 433

Using the Composite Application

Infrastructure . . . . . . . . . . . 434

Declarative wiring with the Portal Admin

tool . . . . . . . . . . . . . . . 434

Specifying a custom owner for your SWT

action . . . . . . . . . . . . . . 434

Developing for serviceability . . . . . . . . 435

Understanding serviceability . . . . . . . 435

Enabling projects for serviceability . . . . . 435

Developing serviceability logic . . . . . . 436

viii Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[

[[[

[[[[[[[[

Page 11: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

OSGi Logging . . . . . . . . . . . 437

OSGi Tracing . . . . . . . . . . . 437

Eclipse Logging . . . . . . . . . . 438

Eclipse Tracing . . . . . . . . . . . 438

Apache Commons Logging . . . . . . . 438

Java.util.logging best practices . . . . . . 438

Migrating applications . . . . . . . . . . 442

Automated migration . . . . . . . . . 442

Manual migration . . . . . . . . . . . 442

Migrating component logic . . . . . . . . 443

Compatibility plug-ins provided . . . . . 443

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

Metatype Service changes . . . . . . . 445

Changes to plug-in startup . . . . . . . 445

Migrating OSGi services . . . . . . . . . 445

Migrating Portlet applications . . . . . . . 446

Migrating Device applications using the setup

file . . . . . . . . . . . . . . . . 446

Running WebSphere Everyplace Deployment 6.0

Web Services applications on Lotus Expeditor . 446

Debugging and testing applications 449

Local debugging and testing . . . . . . . . 449

Client Services Launcher . . . . . . . . 449

Client Services Server . . . . . . . . . 450

Creating a server . . . . . . . . . . 450

Editing a server . . . . . . . . . . 450

Adding projects to a server . . . . . . . 450

Starting a server . . . . . . . . . . 451

Remote debugging and testing . . . . . . . 451

Remote debugging and testing on devices . . . . 452

Preparing debugging connection . . . . . . 452

Installing debugging tools . . . . . . . . 453

Setting Up the Lotus Expeditor Configuration 453

Testing on devices . . . . . . . . . . . 454

Packaging and deploying applications 455

Packaging applications for distribution . . . . . 455

Understanding the application lifecycle . . . . 455

Understanding methods of installation . . . . 456

Local installation . . . . . . . . . . 456

Enterprise installation . . . . . . . . 456

Understanding the types of install artifacts . . 456

Installer/Uninstaller . . . . . . . . . 457

Update site . . . . . . . . . . . . 457

Features . . . . . . . . . . . . . 457

Plug-ins . . . . . . . . . . . . . 458

Native libraries . . . . . . . . . . . 458

Configuration file updates . . . . . . . 459

Installation instructions . . . . . . . . 459

Enterprise distribution instructions . . . . 459

Using Ant tasks to build a deployable bundle 459

Deploying projects for local testing . . . . . . 459

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

Deploying plug-ins to devices . . . . . . . . 460

Globalizing your application . . . . . 461

Support for multiple locales . . . . . . . . 461

IBM language groups . . . . . . . . . . . 461

Supporting preferred fonts and bidirectional

layouts . . . . . . . . . . . . . . . 463

Creating translatable plug-ins . . . . . . . . 463

Securing applications and data . . . . 465

Accounts framework . . . . . . . . . . . 465

Adding accounts . . . . . . . . . . . 466

Accounts UI . . . . . . . . . . . . . 467

Restricting the editing and visibility of an

Account in the Accounts UI . . . . . . 467

Retrieving accounts . . . . . . . . . . 467

Updating accounts . . . . . . . . . . 468

Listening for account changes . . . . . . . 468

Implementing a custom account type . . . . 469

Managing secure passwords . . . . . . . 469

Authentication and accounts . . . . . . . 470

Accounts and platform login . . . . . . . 470

Login configurations . . . . . . . . . . . 470

Logging into the platform . . . . . . . . 471

Logging into remote servers . . . . . . . 472

Using HTTP basic authentication . . . . . 472

Using form-based authentication . . . . . 473

Using SPNEGO authentication with Tivoli

Access Manager . . . . . . . . . . 474

Considerations for connecting to remote

servers using Web Services . . . . . . . 475

Considerations for accessing TAM and

Siteminder protected resources from an

application . . . . . . . . . . . . 476

Using platform single sign-on . . . . . . . 476

Implementing single sign-on with remote

servers . . . . . . . . . . . . . . 477

Contributing a login configuration . . . . . 477

Using TrustManager and KeyManager . . . . . 479

Implementing TrustManager and KeyManager

in Lotus Expeditor . . . . . . . . . . 480

Hooking in the customized TrustManager 480

Lotus Expeditor support of the

customized TrustManager . . . . . . 480

Developer responsibilities for using the

customized TrustManager . . . . . . 481

Hooking in the customized KeyManager . . 483

Lotus Expeditor support of the

customized KeyManager . . . . . . 483

Developer responsibilities for using the

customized KeyManager . . . . . . 484

Wiring the customized TrustManager/KeyManager with the HTTPS connection

(SSL) 2.1.1 . . . . . . . . . . . . 485

Enabling applications for

configuration . . . . . . . . . . . 487

Using preferences . . . . . . . . . . . . 487

Creating preference pages . . . . . . . . 487

Using the Managed Settings framework . . 487

Creating a managed settings-aware

application . . . . . . . . . . . 488

Using the Portal Policy API on the client 489

Contents ix

[[

[ [ [ [ [

[ [

Page 12: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Creating Eclipse Preference Sets with the

Policy Type Editor . . . . . . . . . 489

Understanding preference options . . . . . 496

Eclipse preferences . . . . . . . . . 496

Configuration admin . . . . . . . . . 496

OSGi preference service . . . . . . . . 497

Using the XML parser services . . . . . . . 497

Locating the Web Container ports using the

HttpSettingListener Service . . . . . . . . . 499

Using the Meta Type Service . . . . . . . . 500

Best Practices for file storage with the Lotus

Expeditor platform . . . . . . . . . . . 501

Reference information . . . . . . . 503

Lotus Expeditor top level menus . . . . . . . 503

File menu . . . . . . . . . . . . . 503

View menu . . . . . . . . . . . . . 504

Help menu . . . . . . . . . . . . . 504

OSGi specific information . . . . . . . . . 504

OSGi specification . . . . . . . . . . . 504

Working with OSGi bundles . . . . . . . 505

Creating OSGi bundles . . . . . . . . 505

Bundles . . . . . . . . . . . . 505

Conventions for creating bundles . . . . 505

Creating manifest files . . . . . . . 506

Packages . . . . . . . . . . . . 507

Understanding services . . . . . . . . 507

Registering and unregistering a service

with the OSGi Framework . . . . . . 507

Getting and un-getting services from the

OSGi Framework . . . . . . . . . 509

Lotus Expeditor Toolkit . . . . . . . . . . 510

Wizards . . . . . . . . . . . . . . 510

New Client Services Project Wizard . . . . 510

New Client Services Fragment Project Wizard 512

Convert Project to Client Services Project

Wizard . . . . . . . . . . . . . 514

Client Services Project Properties page . . . 514

Dialogs . . . . . . . . . . . . . . 516

Client Services Launch Configuration dialog 516

Debugging a remote Client Services

runtime . . . . . . . . . . . . 516

Lotus Expeditor Toolkit Preference Dialog 516

Tag library . . . . . . . . . . . . . . 518

Aggregation tag library . . . . . . . . . 518

Message reference . . . . . . . . . . . . 520

Web Container messages . . . . . . . . 520

Appendix. Notices . . . . . . . . . 535

Trademarks . . . . . . . . . . . . . . 537

x Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 13: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 (Java EE) 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.

With Lotus Expeditor Client for Desktop, Portal administrators can use WebSphere® Portal Server to

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

administrator.

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

Portal Server *

* Optional

© Copyright IBM Corp. 2004, 2008 1

Page 14: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

following operating systems:

v Microsoft® Windows® Vista

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 4 and 5

v RedHat EL 5.0 and 5.1 WS with GTK support

v SUSE Linux® Enterprise Desktop (SLED) 10 SP1

v Microsoft Windows 2000 Service Pack 4

Note: Support has been withdrawn for Novell Linux Desktop 9 (NLD9).

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 Edition)

v Windows Mobile 2003 SE (PocketPC and Phone Edition)

v Windows CE Professional 5.0

v Nokia E90

Note: The support for the Nokia E90 is provided as early release code for internal evaluation and

testing. The support for the Nokia E90 may not be used for productive purposes.

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 6.1.1

This section describes what’s new in Lotus Expeditor 6.1.1.

Lotus Expeditor Toolkit 6.1.1

The Lotus Expeditor Toolkit 6.1.1 provides new application development functions over the previous

release, Lotus Expeditor Toolkit 6.1. Here are the highlights of these new application development

functions:

New Toolkit Platforms

v Microsoft Windows Vista

v RedHat EL 4.0 WS with GTK support - Update 4

v RedHat EL 5.0 WS with GTK support

v SUSE Linux Enterprise Desktop (SLED) 10

Eclipse Integrated Development Environment (IDE) 3.2.2

The 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) 3.2.2.

Lotus Notes® 8.0 Application Development

A new target definition for Lotus Notes 8.0 enables application developers to easily set up their

development environment to compile, run and debug applications developed for Lotus Notes 8.0,

including the use of Lotus Expeditor services that ship with Lotus Notes 8.0.

2 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 15: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In addition, Lotus Expeditor 6.1.2 supports Lotus Notes 8.0.1 development.

Sametime® Application Development

Two new target definitions for Lotus Sametime are provided in 6.1.1. The first new target

definition for Lotus Sametime Connect enables application developers to easily set up their

development environment to compile, run and debug applications developed for Sametime 7.5.1,

including the Lotus Expeditor services that ship with these Sametime releases.

The second new Lotus Sametime target definition for Lotus Expeditor with Lotus Sametime

components enables application developers to now develop Lotus Expeditor applications that

include Lotus Sametime 7.5.1 functionality.

Device Application Development

The toolkit enables application developers to remotely deploy, launch and debug their

applications on devices.

Java Web Start

The toolkit enables you to package and launch applications by using Java Web Start.

Portlet “Wiring”

In order to wire portlets for use on the client, portlets must expose their properties and actions

through a Web Services Description Language (WSDL) file. Currently the only means of creating

a WSDL file with the toolkit is by using a text or XML editor. This is a difficult and error prone

process. A new WSDL editor provides a simple, graphical editor for creating WSDL for the client.

Selective Install

The toolkit now allows application developers to selectively install one or more of the following

tools components into their IDE:

1. Lotus Expeditor Toolkit

2. Lotus Expeditor Development Runtimes

3. Lotus Expeditor Development Runtimes J9 VM (or jclDesktop).

Web Services

Instructions have been provided on using the Web Service Security tools to configure LTPA token

support for improving interoperability with WebSphere Application Server (WAS). In addition,

instructions have been provided on using these tools to expose the authentication/authorization

mechanism used by client applications to consume Web Services.

Lotus Expeditor Client for Desktop 6.1.1

The Lotus Expeditor Client for Desktop 6.1.1 provides new application functions over the previous

release, Lotus Expeditor Client for Desktop 6.1. Here are the highlights of these new application

functions:

New Desktop Platforms

v Microsoft Windows Vista

v RedHat EL 4.0 WS with GTK support - Update 4

v RedHat EL 5.0 WS with GTK support

v SUSE Linux Enterprise Desktop (SLED) 10

Note: Support has been withdrawn for Novell Linux Desktop 9 (NLD9).

Eclipse Rich Client Platform (RCP) 3.2.2

The client platform includes the Eclipse Rich Client Platform 3.2.2.

Mozilla

This release supports the Mozilla browser 1.8 on Linux clients.

Point-to-Point Messaging

Currently, MQ Everyplace® (MQe) provides point-to-point messaging for the Java Message

Product overview 3

[

Page 16: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Service (JMS) API. In this release, the Micro Broker also provides point-to-point messaging for the

JMS API. Micro Broker supports offline messaging for mobile end-users and all messaging types

defined for JMS.

JavaServer Faces Widget Library (JWL) and Extensions Support

JWL is a JavaServer Faces (JSF) and JavaScript-based widget library that augments JSP and HTML

pages with a rich set of input, output and navigation components. JWL also includes support for

AJAX-based page interactions so pages can include more complex components and interact with

the Web Server without requiring a full redraw of the page for each interaction.

Synchronizable and Serializable Portal API’s

Application developers can use the Synchronizable and Serializable Portal APIs to develop offline

composite applications.

Derby 10.2

This release updates Cloudscape™ to Derby 10.2 to support new database functions encompassing

tools, security, administration, JDBC, and SQL. Examples include support of XML datatypes and

operators for storing and querying XML data, JDBC 4.0 drivers, and re-encrypting encrypted

databases. For a complete list of new features, go to the Apache Derby web site at

http://db.apache.org/derby/releases/release-10.2.2.0.html.

DB2® Everyplace

This release updates DB2 Everyplace to version 9.1.1 to support new database features:

v Performance improvement

v Retrieve index information through CLI and JDBC interfaces

v Strong encryption support – 3DES or AES

v Support SUSE Linux 9/p-series

v Support new versions of client platform operating systems:

– Symbian 9 Support

– MS Vista Supportv Larger BLOB synchronization

– Support all data sources, including DB2, Informix®, Oracle and MS SQL Server.

– Enlarge size limitation from 32KB to 4MB

User Interface Extensions

This release extends the JFaceEX API to support animation effects (e.g. growing/sliding

windows).

Composite Application Extensions

This release provides new API’s to create a Job to update all composite applications currently

installed on the client and create a Job to load a specified list of composite applications.

Property Broker Extensions

Application developers can create actions that are registered dynamically at runtime. The

registration may be tied to a specific perspective or view part – meaning the Action will be

registered with the property broker when the page/view becomes visible.

A property change may occur on a property before the wire or action has been fully initialized.

This results in the target component not getting the “default” value of an exposed property. An

application developer can identify the default value for a property and any wired actions that

should receive the “current” value whenever the wire or action is enabled.

Web Services

Web Services now expose the authentication/authorization mechanism used by client applications

to consume Web Services.

4 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 17: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Login Enhancements

The Accounts API now supports Siteminder and Tivoli® Access Manager (TAM) logins to a

remote WebSphere Portal server.

Lotus Sametime

This release provides the embedded version of Lotus Sametime as part of the desktop product

installation update site. Embedded Sametime can be installed into Lotus Expeditor to provide

instant messaging capabilities using the Lotus Expeditor sidebar.

Lotus Expeditor Client for Devices 6.1.1

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

release, Lotus Expeditor Client for Devices 6.1. Here are the highlights of these new application features:

New Device Platforms

v Windows CE Professional 5.0

v Nokia E90

Note: The support for the Nokia E90 is provided as early release code for internal evaluation

and testing. The support for the Nokia E90 may not be used for productive purposes.

Point-to-Point Messaging

Please read the description in “Lotus Expeditor Client for Desktop 6.1.1” on page 3.

DB2 Everyplace

Please read the description in “Lotus Expeditor Client for Desktop 6.1.1” on page 3.

Security

This release supports the Java Secure Socket Extension (JSSE) and Java Cryptography Extension

(JCE) API’s. This release also supports Web Services security and the declarative Java EE security

model for Web applications. Previously, both of these functions were only supported by the

desktop client.

javax.sound Feature

The javax.sound feature is an audio library provided by Lotus Expeditor. It provides a set of

simple API for playing audio files that includes start, pause, stop, and setting position within a

sound file. All the functions are easily utilized in Lotus Expeditor applications. Currently, the

only supported audio file format is WAV, with signed PCM encoding. The provided API is a

subset of Sun Java SE javax.sound.sampled. Only the audio playing related functions are

supported. By using this standard interface, developers can benefit from increased compatibility

between different environments.

What’s new in Lotus Expeditor 6.1.2

This section describes what’s new in Lotus Expeditor 6.1.2.

Lotus Expeditor Toolkit 6.1.2

The Lotus Expeditor Toolkit 6.1.2 provides new application development functions over the previous

release, Lotus Expeditor Toolkit 6.1.1. Here are the highlights of these new application development

functions:

New Toolkit Platforms

v Redhat EL 4.0 Update 5

v Redhat EL 5.1

v Suse Enterprise Linux SP1

Target Definitions

The ’Default’ and ’Default With Embedded Sametime’ target definitions have been updated to

take advantage of a new option to set the default status of optional plug-ins or features.

Product overview 5

[

[

[

[[[

[

[

[

[

[[[

Page 18: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In 6.1.1, all optional features were selected by default in the Client Services Launch Configuration

wizard. In 6.1.2, only the features that are launched by the stand-alone Lotus Expeditor Runtime

Client are selected by default. This means that the Lotus Expeditor Client, when launched using

the toolkit, has an identical set of features as when it launched stand-alone. Samples such as the

Order Entry Sample are no longer launched by default. You can choose to select any features for

launch individually through the launch wizard.

Features that were selected by default in the launch wizard in previous releases include:

v All Dictionaries except English (United States)

v Enterprise Management Agent Servlet

v Integrated Browser Application Component

v JavaServer Faces Widget Library (JWL)

v Order Entry Sample

v Web Application Compatibility

v Web Services Resource Framework

In 6.1.2, you can choose to select any of them individually.

Support for Incremental JSP build

In previous releases, all JSPs were translated each time a web project was run or exported. This

release provides an option to only translate JSPs whose content has changed.

eRCP Application templates

PDE-style templates have been added in this release which can be used to generate basic eRCP

Device applications and eRCP e-Mail applications. These templates provide a jump start on

application programming for Lotus Expeditor devices.

Windows Mobile v6.0 Device Support

This release adds support for Windows Mobile V6.0.

Support for compliant Web Services Fault Handling

Mobile Web Services support was enhanced to support Web Services with custom faults. The

provider wizard now can expose Java interfaces with service specific exceptions as a Web Service

and generate WSDL schemas with WSDL Fault elements. The Client wizard was enhanced to

consume these generated WSDL files.

WSRF The version of WSRF that is included in this release is V1.2.1.

Lotus Expeditor Client for Desktop 6.1.2

The Lotus Expeditor Client for Desktop 6.1.2 provides new application functions over the previous

release, Lotus Expeditor Client for Desktop 6.1.1. Here are the highlights of these new application

functions:

New Desktop Platforms

v Redhat EL 4.0 Update 4 and 5

v Redhat EL 5.1

v Suse Enterprise Linux SP1

v Microsoft Windows Vista

v Citrix v 4.5

Composite Application Editor (CAE)

The Composite Application Editor (CAE) provides the tooling necessary for developers and

business users to construct composite applications for Lotus Notes from existing components.

CAE runs on the client platform in conjunction with a portal server. In Lotus Expeditor 6.1.2,

CAE is now packaged directly with the Lotus Expeditor runtime. This allows Lotus Expeditor

6 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[

[

[

[

[

[

[

[

[

[

[[[

[[[[

[[

[[[[[

[[

[

[[[

[

[

[

[

[

[

[[[[[

Page 19: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

users to construct composite applications in the same manner that a Lotus Notes user can. In the

initial release, applications built with CAE must be deployed using a portal server to a portal

managed client.

Windows Citrix Terminal Server Support

The Lotus Expeditor Client for Desktop is now supported on the Windows Citrix Terminal Server.

WebSphere Channel Framework

The Lotus Expeditor 6.1.2 Web Container now supports the WebSphere Channel Framework. The

Channel Framework provides common networking services, protocols and I/O operations for the

WebSphere Application Server and other exploiting products. More importantly, the Channel

Framework offers tremendous performance advantages over the existing legacy transport

component used by the Lotus Expeditor Web Container. While the transport is lightweight and

suitable for device and desktop platforms, it cannot support tens of thousands of connections at

the same time. The Channel Framework will give Lotus Expeditor / LWI the ability to host web

applications, such as IBM Director, that provide monitoring support for tens of thousands of

endpoints.

Lotus Expeditor micro broker buffered JMS client

This allows micro broker JMS client applications to operate regardless of whether or not they are

currently connected to a micro broker.

Windows Server 2003 Support

The Louts Expeditor Client for Desktop is now supported on the Windows Server 2003.

J2SE 5.0 SR6

Louts Expeditor now supports applications built against J2SE 5.0 SR6.

Rich Text Editor Proxy Servers

The Rich Text Editor now supports access through a proxy server.

Embedded Browser Proxy Servers

The Embedded Browser now supports access through a proxy server.

JSF Widget Library (JWL)

Lotus Expeditor Client now provides JSF Widget Library (JWL) version 3.0.7.

Web Services Resource Framework (WSRF)

Lotus Expeditor Client for Desktop now ships Web Services Resource Framework (WSRF) 1.2.1

Java Access Bridge

Lotus Expeditor Client for Desktop now provides the Java Access Bridge, a technology targeted at

developers of assistive technologies. It provides the tools that enable products to work with

Windows and Java applications.

Eclipse standaloneUpdate Command

The Eclipse standaloneUpdate command is disabled in Lotus Expeditor 6.1.2. It is recommended

that you use provisioning interfaces to manage the platform.

Whitelist Security

Lotus Expeditor Client for Desktop 6.1.2 defines a multipurpose list of URLs, called a ″whitelist″,

that point to Eclipse update sites that the Lotus Expeditor provisioning subsystem uses to

determine from which sites users are allowed to install applications. If a user is allowed to go to

any arbitrary update site to download new or updated features, there is a security risk – the

integrity of the Lotus Expeditor platform could be compromised by malicious plug-ins. To reduce

the security risk, the administrator can use this list to limit the user to approved, safe update

sites.

Embedded Browser Connections

The embedded browser can now navigate to sites protected by Basic authentication through

HTTP or HTTPS connections on Windows.

Product overview 7

[[[

[[

[[[[[[[[[[

[[[

[[

[[

[[

[[

[[

[[

[[[[

[[[

[[[[[[[[

[[[

Page 20: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Sametime

Expeditor Client for Desktop 6.1.2 now embeds Sametime 8.0.

Lotus Expeditor Client for Devices 6.1.2

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

release, Lotus Expeditor Client for Devices 6.1.1. Here are the highlights of these new application

features:

New Device Platforms

v WM v6 Professional and Classic

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.

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 (for example, jclDesktop does

8 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[

[[[

[

[

[

Page 21: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java ME 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.

Access services

Access Services provide a familiar programming model for Java EE 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 Java EE 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 only Servlet 2.3/2.4 and JSP 1.2/2.0 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.

For 6.1.1, note that SSL support is not provided when running the Web container on jclDesktop and

jclDevice profiles.

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

Beans (EJBs) 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.

Product overview 9

Page 22: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The following key services support local and offline operations:

v You can use the JDBC API with DB2 Everyplace or Apache Derby 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.

Apache Derby 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 Apache Derby contains a larger number of features, it is approximately 2

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

v You can also use the Java Message Service (JMS) API with WebSphere MQ Everyplace (MQe) to send

and receive messages, called point-to-point messaging. 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.

v 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 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. In addition, you can now use the JMS API with the Micro Broker to support

point-to-point messaging for both online and offline operations.

v 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 and device clients, security services support: a key store, which provides an encrypted

local repository for user security information; accounts, which allows access to user account information

(for example, user ID and password). The desktop client supports single sign-on, which minimizes logon

prompts. Additional services include: database lifecycle management, which provides uniform

10 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 23: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

In addition, the desktop client supports portlet technology so users can interact with local portlets that

conform to the JSR 168 specification.

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:

Product overview 11

Page 24: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

defined for the application in which it displays

v Manages drag and drop of items within the toolbar

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 Standard Widget Toolkit (eSWT) and 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.

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.

Using the 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

12 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 25: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 the desktop client. However, custom

platforms require an OEM license from IBM®.

The toolkit is built on Eclipse 3.2.2 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.2, which is

built on top of the OSGi framework. For this release, Eclipse 3.2.2 plug-ins run as OSGi plug-ins. The

Plug-in Developer Environment (PDE) provided with Eclipse 3.2.2 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.

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 provides information to the 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 455.

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:

For 6.1.1:

v Microsoft Windows XP Service Pack 2

v Microsoft Windows Vista

v RedHat Enterprise Linux 4.0 WS with GTK support – Update 3 and 4

v SLED 10

v RedHat Enterprise Linux 5.0 WS with GTK Support – Eclipse 3.2.2 + Web Tools Project (WTP 1.5.3

only)

For 6.1.2:

v Microsoft Windows XP Service Pack 2

v Microsoft Windows Vista

v Redhat Enterprise Linux 4.0 WS with GTK support – Update 4 and 5

Product overview 13

Page 26: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Redhat Enterprise Linux 5.1 WS with GTK Support – Eclipse 3.2.2 + Web Tools Project (WTP 1.5.4)

v SLED 10 SP1

The toolkit also supports application development for the Lotus Expeditor runtime on the following

device platforms:

v Windows Mobile 2003 SE and Windows Mobile 5 (PPC and Phone Editions)

v Microsoft Windows CE 5 Professional and Microsoft Windows CE 4.2 (Micro Broker only)

v Nokia E90

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

For 6.1.1:

v Rational Application Developer (RAD) 7.0.0.2

v Rational Software Architect (RSA) 7.0.0.2

v Eclipse 3.2.2 + Web Tools Project (WTP) 1.5.3

v WebSphere Application Server Toolkit (AST) 6.1.1.2

For 6.1.2:

v Rational Application Developer (RAD) 7.0.0.4

v Rational Software Architect (RSA) 7.0.0.4

v Eclipse 3.2.2 + Web Tools Project (WTP) 1.5.4

v WebSphere Application Server Toolkit (AST) 6.1.1.4

Limitations when using Lotus Expeditor Toolkit on Eclipse + WTP: The following list describes

functionality of Lotus Expeditor Toolkit that are supported when Lotus Expeditor Toolkit is installed into

RAD, AST, and RSA, but are not supported when Lotus Expeditor Toolkit is installed into Eclipse + WTP:

v Embedded Transaction Projects - Eclipse + WTP does not allow for usage of the Embedded

Transaction Container Tools. If you plan to use these tools, you must install Lotus Expeditor Toolkit

into RAD, AST, or RSA.

v Samples gallery - The samples gallery is not part of Eclipse or WTP. Therefore, the provided samples

are not accessible from a samples gallery.

v Portlet tools - The portlet tools extend the portlet tooling that is part of AST and RAD. Therefore, to

use the portlet tooling you must install Lotus Expeditor Toolkit into RAD, AST, or RSA.

v WS-Security editors - The WS-Security editors extend the RAD security editors. You can build security

enabled web services for JSR-172 by hand, without the aid of the editors. To use the editors, you must

install Lotus Expeditor Toolkit into RAD, AST, or RSA. .

v Full JSF - RAD and AST do not include the WTP implementation of the JSF tooling. RAD will continue

to provided a more advanced level of JSF support. Therefore, the usage of JSF with Lotus Expeditor

will differ based on the level of base ware.

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” on

page 13.

14 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[

[

[

Page 27: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Setting up the Lotus Expeditor Toolkit

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

Setup for Desktop development: You must configure the toolkit before you can begin using it. A

configuration dialog is provided for this purpose, and is presented automatically after the toolkit is

installed and the IDE restarted.

To develop applications for the Lotus Expeditor Client for Desktop offering, configure the toolkit using

the following steps:

1. Select Lotus Expeditor for Desktop in the Test Environment field of the configuration dialog.

2. Validate that the contents of the Target Location field is correct. The initial contents of this field

contain the location where the Lotus Expeditor Development Runtimes feature was installed. If this

feature was not installed, Browse to the runtimes install location, such as the location of the native

Lotus Expeditor Client for Desktop offering.

3. Validate that the contents of the VM name field is correct. The default VM name is jclDesktop. If you

separately installed the Lotus Expeditor Runtimes DRE feature, you will also be able to select J2SE 5.0

in the dialog.

4. Validate that the Compiler compliance level is correct. This is set to the appropriate value for the VM

name selected and should not need to be changed.

5. Change the preference option that controls when the dialog is displayed if desired.

6. Select OK.

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.

For additional information on Toolkit configuration, see “Selecting and configuring test environments” on

page 28.

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

and device features. Upon the first startup of a workspace, a Toolkit Configuration dialog prompts you to

set the Test Environment for the Lotus Expeditor Toolkit. Choose Lotus Expeditor for Device and click

OK.

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 that appears when the

sample is imported.

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...

Product overview 15

Page 28: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

b. In the Launch Configuration Dialog that appears, right click Client Services. Click New.

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

d. Click Run.

Notice that 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 Client Services Launch Configuration.

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:

1. Select Run > Run...

2. Double-click Client Services.

3. Change the new configuration’s name.

4. Switch to the Target 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 in one

of two places.

The current configuration settings for the Lotus Expeditor Toolkit are displayed in the Test Environment

section of the preferences. These values were selected using the configuration dialog for the toolkit, and

can be accessed by selecting Window > Preferences > Client Services. Selecting Configure on this

preference page allows you to change your Lotus Expeditor Toolkit configuration. The dialog initially

populates with the current settings, and the Restore Defaults button can be used to reset the contents of

the dialog to the default values shipped with Lotus Expeditor Toolkit.

The Auto-Configuration Preference option can also be selected on this page. This preference option

controls when the configuration dialog for the toolkit is displayed. It can be displayed each time a

workspace opens, the first time a workspace opens, or not at all.

Additionally, the following Client Services preferences can be modified by selecting Window >

Preferences > Client Services > Development:

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

16 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 29: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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.

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.

The configuration process for the Lotus Expeditor Toolkit sets this to the default Target Definition that is

appropriate for your test environment. When developing applications for the Lotus Expeditor Client for

Desktop offering, the Target Definition will be set to Default Target.

Select the Targets to be available for development Selection

If the Targets are selected, they will be available in the development environment during a new Client

Services project creation or a new Client Services launch configuration. The unselected targets will not be

shown in the development environment. The default is all Targets selected.

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.

User-Defined Features

v Enable

This selection enables or disables this function. If it is enabled, the toolkit tries to find any user-defined

or third party features and plug-ins in the location specified. If it is disabled the toolkit will bypass the

function.

v Use Configured Location

If this function is enabled, the user may specify the location, other than default, where these

user-defined features and plug-ins are located.

This location is where the Lotus Expeditor Toolkit looks for user-defined or third party features and

plug-ins. The default location is <platform location>\com.ibm.pvc.tools.bde\xpdt. Under this path,

an eclipse folder with two children (features and plugins) should have been created. The features

and plugins folders should contain these user-defined features and plug-ins respectively.

v Browse

The Browse button will enabled if the “Use Configured Location” selection is unchecked/unselected.

The browse button will open the system folder dialog so the user can locate the installed location of

these user-defined features.

Product overview 17

Page 30: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 Definitions” and “Target features” on page 22

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-Package and Require-Bundle to reflect the packages imported by the project’s

classes. Refer to “Automatic management of manifest package dependencies” on page 22 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 Definitions: 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

18 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 31: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

For 6.1.1, the Lotus Expeditor Toolkit provides Target Definitions that represent the bundles available in

Lotus Expeditor, Notes® 8 and Sametime 7.5.1 runtimes.

For 6.1.2, the Lotus Expeditor Toolkit provides Target Definitions that represent the bundles available in

Lotus Expeditor and in the Notes 8.0 and 8.0.1 runtimes. Other Lotus Expeditor-based products, such as

Lotus Sametime, also provide Lotus Expeditor Toolkit Target Definitions in their product SDKs. Details

on installing these other Target Definitions into the Lotus Expeditor Toolkit can be found in the

Expeditor-based product SDK documentation. Please note that while the standalone Lotus Sametime

Target Definition is provided separately in the Lotus Sametime SDK, Lotus Expeditor 6.1.2 includes an

embedded version of Lotus Sametime that can be used to develop Lotus Expeditor-based applications

integrated with Lotus Sametime capabilities. For more information, refer to “Using the Lotus Expeditor

Toolkit with Lotus Sametime” on page 24.

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 Target 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"/>

Product overview 19

[[[[[[[[[

Page 32: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<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.personalitydefault.branding.feature) with your own feature. 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 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 Target 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.

Using Target Definitions to set the default status of optional plug-ins or features:

Lotus Expeditor allows you - with the use of the attribute default - to specify which optional features or

plug-ins are available for selection in the UI by default.

Unlike the “required” features or plug-ins that are not selectable from the UI, features or plug-ins using

the default attribute may be modified (checked or unchecked) from the UI. During an initial Client

Services launch configuration creation, the wizard displays all of the required features and plug-ins

(checked or grayed out) and the default features and plug-ins (checked). Using the default attribute, you

may modify this latter selection and save it, as well as restore the initial default selection by selecting

Restore Defaults from the UI Target page.

20 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[[

[[[[[[

Page 33: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The Target page has the following behavior:

Table 1. Target page ″default″ settings

Feature Toolkit

optional = true default = true checked / not grayed-out

optional = true default = false not checked / not grayed-out

optional = false default = true checked and grayed-out

optional = false default = false checked and grayed-out

no optional attribute specified optional = false

no default attribute specified default = true

Setting optional features and plug-ins to be selected by default:

Lotus Expeditor allows you to easily configure the UI default selection settings of optional features and

plug-ins.

To set an optional feature or plug-in to be selected by default, perform the following procedure:

1. Open an existing target definition file in a text editor or create a new one. The target definition file

must contain one or more feature or plug-in elements.

2. Select a feature or plug-in element that contains the optional attribute set to true. For example,

<feature id="com.ibm.abc.feature" optional="true">.

3. Preceded by a comma, add the default attribute and set it to true. Such as, <feature

id="com.ibm.abc.feature" optional="true", default="true"/>, or <plugin id="com.ibm.abc.plugin"

optional="true">. Note that not specifying the attribute default in these elements is exactly the same

as setting default="true". Therefore, it is necessary to specify the default attribute (as false) on those

features and plug-ins that you want unchecked by default or initially.

4. Save the file.

This feature will now show in the UI as checked (not greyed-out) by default.

Setting optional features and plug-ins to not be selected by default:

Lotus Expeditor allows you to easily configure an optional feature or plug-in so that it does not display

within the UI by default.

To set an optional feature or plug-in to not be selected by default, perform the following procedure:

1. Open an existing target definition file in a text editor or create a new one. The target definition file

must contain one or more feature or plug-in elements.

2. Select a feature element that contains the optional attribute set to true. For example, <feature

id="com.ibm.abc.feature" optional="true"/>.

3. Preceded by a comma, add the default attribute and set it to false. Such as, <feature

id="com.ibm.abc.feature" optional="true","default=false"/> or <plugin id="com.ibm.abc.plugin"

optional="true">. Note that not specifying the attribute default in these elements is exactly the same

as setting default="true". Therefore, it is necessary to specify the default attribute (as false) on those

features and plug-ins that you want unchecked by default or initially.

4. Save the file.

This feature now show in the UI as not checked (not grayed-out) by default.

Product overview 21

[

[[

[[

[[

[[

[[

[[

[[

[[[

[

[[

[

[[

[[

[[[[[

[

[

[

[[

[

[[

[[

[[[[[

[

[

Page 34: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Non-profiled Features: The Target Definitions used to configure the Lotus Expeditor Toolkit project

settings and launch configurations are a static snapshot of a runtime. Since runtimes can be dynamically

modified, Lotus Expeditor Toolkit can dynamically add new features. It treats these features as if they

were in the original Target Definition. Therefore, you can select new features in the project wizard, launch

configuration page, and so forth. These features display and group in the Target Definition wizard page

or on the Target tab of the launch configuration. At the top of the list of features, an element labeled User

Defined Features only displays if the Lotus Expeditor Toolkit finds these features in the location

configured in the Client Services preference page.

The configuration for enabling these user-defined features can be found in the Client Services Preference

page (Windows > Preferences... > Client Services > Development, under the User-Defined section of

the page). If the Enable checkbox is not selected, the additions of these features, if any, are also ignored

or not displayed. The user must copy these ″third-party″ or user defined features to the location

specified. The default location is <platform location>\com.ibm.pvc.tools.bde\xpdt. Under this path, the

user should ensure that an eclipse folder is added with two children - features and plugins. Under the

features folder, the list of user defined features should be added or copied. In the plugins folder, the list

of plug-ins referenced by these features should be added or copied.

Automatic management of manifest package dependencies: Dependency Management allows users to

include plug-ins in the build path without adding references to the Manifest. By using this mechanism to

include plug-ins in the build path, users can compile and develop their code with the convenient features

of Eclipse JDT. You can configure Dependency Management to help identify and add new package

dependencies from your project’s Java code.

It is important to note that this mechanism requires the developer to use the project’s Target Definition or

the table in the Automated Management of Dependencies section of the Manifest Editor 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.

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 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.

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.

22 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 35: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Configuring the Client Services launcher

To configure the Client Services launcher, perform the following procedure:

1. From the Java perspective, select Run > Run... to invoke the Launch Configuration Dialog wizard

2. Create a new Client Services launch configuration. Right click Client Services. From the pop-up

menu, select New.

At this point, you can run this configuration with default values or proceed to configure it further.

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 contains default values for the Program and VM argument data of this Target

Definition.

5. From the Target 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

Target 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.

Installing the IBM Desktop Runtime Environment for the Lotus Expeditor Toolkit

The IBM Desktop Runtime Environment is a separately ordered product that provides complementary

function for the Lotus Expeditor and Lotus Expeditor Toolkit.

For the Lotus Expeditor Toolkit, the IBM Desktop Runtime Environment contains an additional feature

that is separately installable into the active IDE. The Lotus Expeditor Toolkit must be installed prior to

installing these features

The Lotus Expeditor Developer Runtimes DRE is a packaging of the Java2 SE 5.0 J9 VM that is installable

into the toolkit. If you need capabilities of the J2SE 5.0 VM that are not available in the default jclDesktop

runtime environment, such as Swing or AWT, then you must install a new J9 VM definition. If you intend

to deploy your application on Lotus Expeditor using a J2SE 5.0 J9 VM, then use this J9 VM packaging so

that you deploy on the same J9 VM. By installing this feature, a new JRE definition will be defined in the

Java > Installed JREs preferences, and can be selected as one of the target platform JREs.

To install this additional feature, perform the following procedure:

1. Launch the IDE.

2. Select Help > Software Updates... > Find and Install...

3. From the Install/Update (Feature Updates) dialog, select Search for new features to install.

4. From the Install (Update Sites to Visit) dialog, create a New Update site definition.

5. If the DRE is available through a web site, select a New Remote Site. Otherwise, select a New Local

Site.

6. Browse to the location of the DRE (CD-ROM drive letter, or location where it may have been

unzipped on a mapped drive letter or mount). Then further navigate to [DRE location]/updates/tooling.

7. Select Finish.

8. When the Install (Search Results) dialog appears, select the Lotus Expeditor Developer Runtimes

DRE feature, then Next.

Product overview 23

Page 36: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

9. If the license terms are agreeable, select I accept the terms in the license agreement, then Next.

10. Select Finish to complete the installation.

Note: A dialog informing you that the feature is not signed may appear. Select Install to continue.

Once you have installed this feature, you can now select J2SE 5.0 as a VM in the Lotus Expeditor Toolkit

Configuration dialog that is displayed at IDE startup, or from the Client Services preferences page

available through Window > Preferences. By selecting this VM, you can now use all the capabilities

provided by the J2SE 5.0 VM.

Using the Lotus Expeditor Toolkit with Lotus Sametime

The Lotus Expeditor Toolkit can be used to develop Lotus Expeditor applications that include Lotus

Sametime 8.0 functionality or to develop applications that target a Lotus Sametime Connect client

installation.

To develop Lotus Expeditor applications that include Lotus Sametime 8.0 functionality, use Lotus

Expeditor Toolkit 6.1.2 and select Lotus Expeditor for Desktop Test Environment when opening a new

workspace. Then, specifically select the Default with Embedded Sametime Target for your projects and

Run configurations.

To develop applications that target a Lotus Sametime Connect client installation, use Lotus Expeditor

Toolkit 6.1.1 and refer to the Lotus Sametime SDK for instructions on installing and configuring the

toolkit for use with Lotus Sametime Connect 8.0.

You should also remove the section on Configuring for Lotus Sametime, and the Launching page should

only reference Embedded Sametime. For example, after developing your applications, you can launch

Lotus Expeditor with Embedded Sametime to test them from within the IDE.

Perform the following procedure to create a launch configuration and launch the Lotus Expeditor with

Embedded Sametime platform from within the IDE:

1. Select Run > Run...

2. Select Client Services.

3. Click New.

4. Enter a name.

5. Select Clear workspace data before launching.

6. Click Run.

The Default with Embedded Sametime target sets the VM arguments for the launch configuration. 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

Target tab and select the features to add or remove.

Configuring for Lotus Sametime

After installing the Lotus Expeditor Toolkit and restarting the IDE, you are presented with a dialog box

for toolkit configuration. From the Test Environment drop down box, select Lotus Sametime. The rest of

the fields are updated based on the default information for Lotus Sametime. If you have not installed

Lotus Sametime into the default location, you can browse to the appropriate Target Location for your

system before pressing OK. Note that in addition to setting the target platform, JRE and compiler

compliance level, the toolkit’s configuration process also sets the default target to Lotus Sametime. This

causes the target field to be set to Lotus Sametime in all dialogs where the target name must be given.

In version 6.1.1, the recommended setting for the auto-configuration preference is Attempt to configure

the toolkit the first time a workspace opens.

24 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 37: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In version 6.1.2, the recommended setting for the auto-configuration preference is Display the first time a

workspace opens.

If you select this radio button, you will only be prompted to configure the toolkit the first time you use a

workspace with the toolkit.

When the toolkit is configured, the target platform, JRE, compiler compliance level and default target

definition are selected.

If at any time you want to reconfigure the IDE environment, follow these steps:

1. From within the Eclipse IDE, select Window > Preferences.

2. Expand Client Services.

3. Select Configure.

4. From the Test Environment control, select the desired test environment.

5. Change the Target Location, Compiler compliance level or VM name (optional).

6. Click OK.

These instructions assume Lotus Sametime Connect was installed into the default location and that the

Lotus Expeditor Development Runtimes J9 VM (jclDesktop) has also been installed.

Configuring for Lotus Expeditor with Embedded Sametime

After installing the Lotus Expeditor Toolkit and restarting the IDE, you are presented with a dialog box

for toolkit configuration. From the Test Environment drop down box, select Lotus Expeditor for Desktop.

The rest of the fields are updated based on the default information for Lotus Expeditor. Select OK to

close the dialog window and complete the toolkit configuration.

In version 6.1.1, the recommended setting for the auto-configuration preference is Attempt to configure

the toolkit the first time a workspace opens.

In version 6.1.2, the recommended setting for the auto-configuration preference is Display the first time a

workspace opens.

If you select this radio button, you will only be prompted to configure the toolkit the first time you use a

workspace with the toolkit.

When the toolkit is configured, the target platform, JRE, compiler compliance level and default target

definition are selected.

If at any time you want to reconfigure the IDE environment, follow these steps:

1. From within the Eclipse IDE, select Window > Preferences.

2. Select Client Services.

3. Select Configure.

4. From the Test Environment control, select the desired test environment.

5. Change the Target Location, Compiler compliance level or VM name (optional).

6. Click OK.

After selecting the Lotus Expeditor for Desktop Test Environment, you must also change the Default

Target Selection for your workspace to Default with Embedded Sametime Target:

1. From within the Eclipse IDE, select Window > Preferences.

2. Expand Client Services.

3. Select Development.

4. From the Default Target Selection control, select the Default with Embedded Sametime Target.

Product overview 25

[[

[[

Page 38: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

5. Click OK.

These instructions assume that the Lotus Expeditor Development Runtimes and the Lotus Expeditor

Development Runtimes J9 VM (jclDesktop) have been installed.

Launching

After developing your applications, you can launch Lotus Sametime or Lotus Expeditor with Embedded

Sametime to test them from within the IDE.

Perform the following procedure to create a launch configuration and launch Lotus Sametime or the

Lotus Expeditor with Embedded Sametime platform from within the IDE:

1. Select Run > Run...

2. Select Client Services.

3. Click New.

4. Enter a Name.

5. Select Clear workspace data before launching.

6. Click Run.

The Lotus Sametime and Lotus Expeditor for Desktop target set the VM arguments for the launch

configuration. 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 target tab and select the features to add or remove.

Using the Lotus Expeditor Toolkit with Lotus Notes 8.0 or 8.0.1

These instructions assume Lotus Notes 8.0 or 8.0.1 was installed into the default location, and the Java 5

VM has been installed from the Lotus Expeditor DRE CD.

Note: Lotus Notes 8.0.1 development is supported in Lotus Expeditor 6.1.2 only.

Configuring for Lotus Notes 8.0

After installing the Lotus Expeditor Toolkit and restarting the IDE, you will be presented with a dialog

box for toolkit configuration. From the Test Environment drop down box, select Lotus Notes 8. The rest

of the fields will be updated based on the default information for Lotus Notes 8. If you have not installed

Lotus Notes 8 into the default location, you can browse to the appropriate Target Location for your

system before pressing OK. Note that in addition to setting the target platform, JRE and compiler

compliance level, the toolkit’s configuration process also sets the default target to Notes 8 Target. This

causes the target field to be set to Notes 8 Target in all dialogs where the target name must be given.

The recommended setting for the auto-configuration preference is Attempt to configure the toolkit the

first time a workspace opens. If you select this radio button, you will only be prompted to configure the

toolkit the first time you use a workspace with the toolkit.

When the toolkit is configured, the target platform, JRE, compiler compliance level and default target

definition will all be selected.

If at any time you want to reconfigure the IDE environment, follow these steps:

1. From within the Eclipse IDE, select Window > Preferences.

2. Expand Client Services.

3. Select Configure.

4. From the Test Environment control, select the desired test environment.

5. Change the Target Location, Compiler compliance level or VM name (optional).

6. Click OK.

26 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

Page 39: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In version 6.1.1, the recommended setting for the auto-configuration preference is Attempt to configure

the toolkit the first time a workspace opens.

In version 6.1.2, the recommended setting for the auto-configuration preference is Display the first time a

workspace opens.

If you select this radio button, you will only be prompted to configure the toolkit the first time you use a

workspace with the toolkit.

When the toolkit is configured, the target platform, JRE, compiler compliance level and default target

definition will all be selected.

Configuring for Lotus Notes 8.0 or 8.0.1

After installing the Lotus Expeditor Toolkit and restarting the IDE, you will be presented with a dialog

box for toolkit configuration. To develop applications for Lotus Notes 8.0 or 8.0.1, select Lotus Notes 8

from the Test Environment drop down box. The rest of the fields will be updated to match the default

information for the version of Lotus Notes that you have installed. If you have not installed Lotus Notes

8 or 8.0.1 into the default location, you can browse to the appropriate Target Location for your system

before pressing OK. Note that in addition to setting the target platform, JRE and compiler compliance

level, the toolkit’s configuration process also sets the default target to the target for Lotus Notes 8.0.1

development. Setting the default target causes the target field to be set to the Notes 8.0.1 Target in all

dialogs where the target name must be given.

To develop applications for Lotus Notes 8.0, follow these steps:

1. From within the Eclipse IDE, select Window > Preferences.

2. Expand Client Services.

3. Select Development.

4. Select Notes 8 Target as the default target selection.

5. Click OK.

The recommended setting for the auto-configuration preference is Display the first time a workspace

opens. If you select this radio button, you will only be prompted to configure the toolkit the first time

you use a workspace with the toolkit.

When the toolkit is configured, the target platform, JRE, compiler compliance level and default target

definition will all be selected.

Launching

After developing your applications, you can launch Lotus Notes 8.0 or 8.0.1 to test them from within the

IDE.

To create a launch configuration and launch Lotus Notes 8.0 or 8.0.1 from within the IDE, perform the

following procedure:

1. Select Run > Run...

2. Select Client Services.

3. Click New.

4. Enter a Name.

5. Select Clear workspace data before launching.

6. Click Run.

The Notes 8 Target and the Notes 8.0.1 Target both set the VM arguments for the launch

configuration. The tabs on the client services launcher function similar to the Eclipse PDE launcher, with

Product overview 27

[[

[[[[[[[[[[

[

[

[

[

[

[

[[[

[[

Page 40: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 or remove.

Selecting and configuring test environments

This section provides information on selecting and configuring test environments, using a Lotus

Expeditor extension point, and the Lotus Expeditor configuration wizard.

Enabling a test environment to display in the configuration wizard using a Lotus

Expeditor extension point

The current Lotus Expeditor Toolkit startup code automatically configures the test environment, by

configuring settings such as the JRE, compiler compliance level, and so on, through the Lotus Expeditor

Toolkit configuration wizard.

Using the extension point mechanism, the Lotus Expeditor Toolkit can provide the test environment data

in such a way, so that the startup code displays the test environment as a selectable option in the Lotus

Expeditor Toolkit configuration wizard. This allows you to select and configure test environments using

the configuration wizard’s graphical user interface.

The Lotus Expeditor Toolkit, through its extension point, already provides a list of test environments

(with their required parameters and values) including the Lotus Expeditor test environment that display

through the configuration wizard for selection. Additional test environments can be added to this list

using the extension point mechanism.

This section illustrates how to register test environment information through an extension point so the

Lotus Expeditor Toolkit configuration wizard can display it for selection and configuration.

Setting up a test environment for configuration using the extension point mechanism: Before you can

select and configure a test environment using the configuration wizard, you must first provide the test

environment (and its required parameters) though a Lotus Expeditor extension point, so that it can be

displayed in the configuration wizard. To do so, add the test environment (using the extension point

com.ibm.rcp.tools.environment.configuration) to the Lotus Expeditor Toolkit’s plugin.xml file. The

example below shows the Sametime 7.5 test environment being added using the extension point:

<extension name="Sametime 7.5" point="com.ibm.rcp.tools.environment.configuration.configurationEntries">

<vmInfoList defaultVMID="com.ibm.pvc.wct.runtimes.wct.runtimes.jcl.desktop.sdk.win32.x86">

<vmInfo id="com.ibm.pvc.wct.runtimes.wct.runtimes.jcl.desktop.sdk.win32.x86">

<compilerInfoList defaultCompilerInfo="1.4">

<compilerInfo complianceLevel="5.0" sourceLevel="5.0" trgtCodeGenLevel="5.0"/>

<compilerInfo complianceLevel="1.4" sourceLevel="1.3" trgtCodeGenLevel="1.2"/>

</compilerInfoList>

</vmInfo>

<vmInfo id="com.ibm.pvc.wct.runtimes.j2se.win32.x86">

<compilerInfoList defaultCompilerInfo="5.0">

<compilerInfo complianceLevel="5.0" sourceLevel="5.0" trgtCodeGenLevel="5.0"/>

</compilerInfoList>

</vmInfo>

</vmInfoList>

<platformInfo>

<platformBase path="C:\Sametimet7.5"/>

<platformExt pluginID="com.ibm.pvc.wct.runtimes.jcl.desktop.sdk.win32.x86" path="rcp"/>

</platformInfo>

<supportedOS os="win32"/>

<targetDefinitionList defaultTarget="com.ibm.rcp.tools.bde.target.sametime">

<targetDefinition id="com.ibm.rcp.tools.bde.target.sametime"/>

</targetDefinitionList>

</extension>

28 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 41: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Note: The extension point implementation above assumes that Sametime is implemented in

C:\Sametime7.5. If you have installed Sametime in a different directory, change the path attribute

in <platformBase> accordingly). The example also assumes that the host system uses the Windows

operating system.

Selecting and configuring test environments using the Lotus Expeditor

Configuration Wizard

This section explains how to select and configure a test environment using the Lotus Expeditor

Configuration Wizard.

If you are adding a new test environment, you must first create and name a test environment (with any

required parameters) using the extension point implementation, described in “Enabling a test

environment to display in the configuration wizard using a Lotus Expeditor extension point” on page 28.

The configuration wizard will list this test environment, along with the other test environments that are

provided as part of the Lotus Expeditor toolkit during startup of a workspace, or it can be accessed

through an Eclipse preference page. From the wizard, you may select the desired test environment for

your IDE.

The configuration wizard provides an easy method for you to configure a test environment.

Using the configuration wizard on startup to select and configure a test environment: When you

launch the IDE, the Lotus Expeditor startup displays the Lotus Expeditor configuration wizard. The

configuration wizard displays the list of test environments that were registered through the extension

point as well as the auto-configuration preference options. From this wizard, perform the following

procedure:

1. Select the test environment you wish to configure.

2. Choose one of the auto-configuration preference options to configure the environment, if desired.

Or...

Choose one of the Test Environment configuration preference options to configure the environment, if

desired.

3. Select OK.

The system configures the IDE to use the selected test environment. The configured values should match

the values provided through the extension point or the alternate values selected by you in the wizard.

The system saves the auto-configuration preference option you selected.

Launching the configuration wizard from the IDE to select and configure a test environment: To

launch the configuration wizard from the IDE, perform the following procedure:

1. Select Window > Preferences > Client Services.

2. Select the Configure button.

3. Select the test environment from the list to configure it.

4. Select OK to finalize the configuration.

The system configures the IDE to use the selected test environment. The configured values should match

the values provided through the extension point or the alternate values selected by you in the wizard.

Setting the configuration wizard to not run automatically: Perform the following procedure to

configure Lotus Expeditor to not run the configuration wizard automatically upon startup:

1. Select Window > Preferences > Client Services.

2. For 6.1.1, select the Do not attempt to auto-configure the toolkit radio button.

Or...

3. For 6.1.2, select the Never display radio button.

4. Click OK.

Product overview 29

[[

Page 42: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The configuration wizard will no longer display on startup.

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 Definition page displays. The selected Target Definition is the target specified in the

Preference page. You may select another Target via the Combo list.

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 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.

The 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. Expnad Client Services and select Client Services Fragment Project.

3. Click Next.

The Client Services Fragment Project page displays.

30 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 43: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Definition page displays. The selected Target Definition is the target specified in the

Preferences 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.

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 Definition 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.

Importing a Client Services project

To import a Client Services project, perform the following steps.

1. Select File > Import... > General > Existing Projects into Workspace.

2. Click Next.

Product overview 31

[[

[

[

Page 44: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

3. Browse to the directory where you want the project to be located.

4. If appropriate, select the Copy project into workspace checkbox.

Selecting this checkbox ensures that a copy of the project is created for the workspace. If you do not

select the checkbox, then the imported project’s path will be that of its original location.

Note that if you delete a project from the workspace, and in the Confirm project delete dialog select

Also delete contents under <project path>, the project will be deleted from its original location.

5. Select Finish.

Exporting a Client Services project

To export a Client Services project, perform the following steps.

1. Right click the project.

2. Select Export > General > File System and then Next.

3. Ensure that the project and all of its artifacts are selected. From the Options group, ensure that the

Create directory structure for files is also selected.

4. Select a target directory.

5. Click Finish.

Updating an imported Client Services project’s JRE System Library

A Client Services project may be created and then imported into many different platforms and

environments. To update its JRE in its classpath, perform the following procedure.

1. Expand the Client Services project.

2. Right-click its JRE System Library entry and select Configure...

3. In the Edit Library dialog that comes up, select the Workspace default JRE () radio button under the

System library group.

4. Click Finish.

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. Open the MANIFEST.MF file with the Manifest Editor.

3. Click on the Runtime tab, and add the external jar file to the Classpath section.

4. 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.

5. 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 Definition tab allows you to modify the previously selected Target Definition, Target

features, plug-ins and Feature plug-ins. You may also select any User-Defined Features that you

specified earlier.

The Options tab allows you to modify the Auto-Management preferences - Require-Bundle or

Import-package.

See “New Client Services Project Wizard” on page 510 for additional information.

32 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[[

[[

[

[[

[

[

[[

[

[

[[[

[

[

[[

[

Page 45: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Note: When a Client Services launch configuration runs, four applications are included in the default

configuration:

v Web Browser

v Order Entry Rich Client Sample

v Enterprise Management Agent Servlet

v Order Entry Web Sample

These features can be unchecked on the Target page of the launch, so that these four applications

are not included. As such, they will not appear on the Open buton of the Lotus Expeditor client.

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

(RSDP)

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.

Product overview 33

Page 46: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 Lotus Expeditor Toolkit provides archive files, which contain pre-built sample projects.

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 in an Eclipse with Web Tools Platform

(WTP) environment, but full function, including Eclipse ″Run on Server″ launch capabilities,

are not available.

To import one or more samples, follow these basic steps.

1. Select File > Import....

2. From the Import Wizard, select General > Existing Projects into Workspace and then click Next.

3. Select the Select archive file radio button and type the name of the specified jar file (as shown in

Table 2). Alternately, click Browse to select a jar from the archive directory in one of the following

directories:

com.ibm.rcp.tools.samplesgallery and com.ibm.rcp.tools.samplesgallery2

Contain version 6.1.x samples.

com.ibm.rcp.tools.device.samplesgallery

Contains samples that you can run on a device.4. Follow setup instructions provided in this section. Setup instructions are available as links in Table 2.

Table 2. Samples

File name Sample

accounts.jar “Accounts sample” on page 35

branding.jar “Branding sample” on page 37

composite.jar “Composite Application sample” on page 39

db2e.jar “DB2 Everyplace sample” on page 42

derby.jar “Derby sample” on page 44

echo.jar “Echo sample” on page 45

echosecure.jar “Echo Secure sample” on page 48

eclipseprefs.jar “Eclipse Preferences sample” on page 50

browser.jar “Embedded Browser sample” on page 51

ejbtestdriver.jar “Embedded Transaction Container sample” on page 52

ercpapp.jar.jar “eRCP E-mail sample” on page 54 (Device sample)

eswtdemo.jar “eSWT Demo sample” on page 55 (Device and Desktop

sample)

isync.jar “ISync sample” on page 56

jms.jar “JMS with MQe Provider sample” on page 64

34 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 47: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 2. Samples (continued)

File name Sample

jndi.jar “JNDI sample” on page 67

log.jar “Log and Log Reader sample” on page 69

mobadj.jar “Mobile Adjuster sample” on page 70 (Device sample)

mqe.jar “MQ Everyplace sample” on page 71

netstatus.jar “Network Status sample” on page 74

orderentry.jar “Order Entry sample” on page 75

osgiprefs.jar “OSGi Preferences Service sample” on page 78

pizzajsp.jar “Pizza JSP sample” on page 80

portletcomm.jar “Portlet Communication sample” on page 81

propertybroker.jar “Property Broker sample” on page 90

richapp.jar “Rich Application sample” on page 82

rte.jar “Rich Text Editor sample” on page 83

secwebapp.jar “Secured Web Application sample” on page 84

servicetracker.jar “Service Tracker sample” on page 86

calcportlet.jar “Simple Portlet sample” on page 88

portletviewer.jar “Simple Portlet Viewer sample” on page 89

webapplication.jar “Web Application sample” on page 91

weblog.jar “Web Application Log sample” on page 92

simpleaggr.jar “Portlet Aggregation Web Page sample” on page 93

xmlparser.jar “XML Parser sample” on page 95

5. The dialog shows the projects present in the archive jar. Select Finish to install the projects into your

workspace.

Specific instructions for each sample is provided in the following sections.

Accounts sample

This sample creates a Client Services project to illustrate the basic elements of a rich client application

that uses the Accounts API on Lotus Expeditor.

You can use this sample only on the desktop runtime.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of the Accounts API to create, delete, and list accounts

v Use of the Accounts API to read the contents of an account

v Use of the Accounts API to log in to a remote resource defined in an account

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.

Product overview 35

Page 48: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, accounts.jar, or browse to the

com.ibm.rcp.tools.samplegallery2 plug-in directory and select the jar file from the archive

directory.

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 Accounts Applications.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.accounts.browse 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.

Running the sample:

This sample contributes a new perspective and view to the Lotus Expeditor workbench: Accounts

Perspective and Accounts View.

You can perform the following tasks from the Accounts View:

v View a list of defined accounts, displayed by account name.

v Add an account: Select Add and complete the information in the dialog box shown. Select Refresh to

display the name of the added account in the list of accounts.

v Delete an account: Select the name of an account in the list and click Delete. The deleted account is

removed from the list.

v Display the contents of an account: Select an account in the list.

v Refresh the list of accounts. Click Refresh.

v Log in to an account: Select Login. A message is displayed in the lower left corner of the view,

indicating if the login was successful.

v Launch a browser to access a remote service defined in an account: Select an account and click

Launch.

Note: You must first select Login and successfully log in to an account before selecting Launch for that

account.

Troubleshooting:

Problem:

The sample application is not available in the launch list.

Cause:

The com.ibm.rcp.samples.accounts.browse plug-in is not present or does not resolve in the client

platform.

Action:

Verify that the com.ibm.rcp.samples.accounts.browse 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 use the b

com.ibm.rcp.samples.accounts.browse command. The second line of output indicates the plug-in

status. If the status is not RESOLVED or ACTIVE, there is a problem with the plug-in and its

36 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 49: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

dependencies. Use the diag com.ibm.rcp.samples.accounts.browse command to identify any

unsatisfied dependencies. Resolve any missing dependencies and restart the platform.

Problem:

There is an error message displayed in the lower left of the screen when you select an account and

click Login.

Cause:

The account information is invalid, or there is not a network connection to the resource defined in the

account.

Action:

Verify that the user ID, password, and server information is correctly defined in the account. Verify

that there is an active network connection from your client to the resource defined in the account. Related sample:

See the ISync Sample for additional examples using the Accounts APIsThis sample demonstrates how to use the ISync APIs to synchronize relational data from a DB2

Everyplace Sync Server to a local DB2 Everyplace or Derby database.

Branding sample

This sample creates a Client Services project to illustrate how to brand elements of the Lotus Expeditor

user interface.

You can use this sample only on the desktop runtime.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Branding the following elements of the user interface:

– Splash screen

– Title bar (icon and text)

– Banner bar (icon and text)

– About menu (icon and text)v Adding a View action to the menu bar to display or not display the banner bar

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, branding.jar, or browse to the

com.ibm.rcp.tools.samplegallery2 plug-in directory and select the jar file from the archive

directory.

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 Branding.

Product overview 37

[

[[[

Page 50: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.personality.branding plug-in is

selected.

e. Select the Main tab and select com.ibm.rcp.samples.personality.branding.SopwithLlamaProduct.

f. Select the Arguments tab and verify that –console is in the Program Arguments field.

g. Click Apply and then Run.3. To export the branding sample and use the new branding in a separately-installed runtime, you must

be familiar with the following tasks:

v Creating a feature

v Creating an update site

v (optional) Using the Global Install Handler

For details, see Help > Help Contents > Assembling and Deploying Lotus Expeditor Applications >

Assembling and deploying > Packaging applications for deployment.

To run the sample without creating a persistent setting for the new product:

a. Create a feature to contain the com.ibm.rcp.samples.personality.branding plug-in.

b. Create an update site to contain the feature.

c. Install the feature into a separately-installed runtime.

d. To activate the new branding, start the separately-installed runtime. To do so, use the rcplauncher

-product com.ibm.rcp.samples.personality.branding.SopwithLlamaProduct command.

To run the sample and configure the new product as a persistent setting:

a. Create a feature to contain the com.ibm.rcp.samples.personality.branding plug-in.

b. On the Installation tab of the Feature Manifest Editor, specify

com.ibm.rcp.installhandler.RCPInstallHandler as the Handler property of the Install Handler.

c. Create a file in the feature project named handler.properties and add the line

product=com.ibm.rcp.samples.personality.branding.SopwithLlamaProduct. Be sure to include this

file in the exported feature.

d. Create an update site to contain the feature.

e. Install the feature into a separately-installed runtime. The new product identity is used on

subsequent launches of the platform.

Running the sample:

This sample defines a personality that brands the workbench.

Actions include the following:

v Displays Llamas on the splash screen.

v Displays a Llama icon and the text Sopwith Llama Smorgashboard in the title bar.

v Displays a Llama icon and the title of the running application in the banner bar.

v Displays the text About Sopwith Llama Smorgashboard as the About selection in the Help menu.

v Displays a Llama icon and the text About Sopwith Llama Smorgashboard in the title of the About

dialog.

v Displays a Llama picture and the text Sopwith Llama Customer Smorgashboard in the About dialog.

v Adds View > Show > Banner to the menu bar so that you can toggle the display of the banner bar.

Troubleshooting:

Problem:

The sample application is not available in the launch list.

Cause:

The com.ibm.rcp.samples.personality.branding plug-in is not present or does not resolve in the client

platform.

38 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 51: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Action:

Verify that the com.ibm.rcp.samples.personality.branding 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 use the b

com.ibm.rcp.samples.personality.branding command. The second line of output indicates the plug-in

status. If the status is not RESOLVED or ACTIVE, there is a problem with the plug-in and its

dependencies. Use the diag com.ibm.rcp.samples.personality.branding command to identify any

unsatisfied dependencies. Resolve any missing dependencies and restart the platform.

Composite Application sample

This sample creates Client Services projects to illustrate the basic elements of developing composite

applications on Lotus Expeditor.

You can use this sample only on the desktop runtime.

Time required: 2 minutes

You can use this sample only on the desktop runtime. You must import the Portlet Communications

sample before running these samples. Key concepts demonstrated by the collection of projects in this

sample include the following:

v Declarative wiring through Property Broker for the following:

– SWT to SWT communication

– Portlet to Portlet communication

– Portlet to SWT communication

– SWT to Portlet communicationv Use of Click to Action menus to show compatible actions for a selected Property

v Dragging and dropping Property Broker property values between SWT views

v Reading portlet preferences set by the portal administrator

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, composite.jar, or browse to the

com.ibm.rcp.tools.samplegallery2 plug-in directory and select the jar file from the archive

directory.

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 Composite Application.

d. Select the Plug-ins tab and verify that the following plug-ins are selected:

com.ibm.rcp.samples.portletcommunication.portlets

com.ibm.rcp.samples.portletcommunication.views

com.ibm.rcp.samples.propertybroker.app

Product overview 39

Page 52: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

com.ibm.rcp.samples.propertybroker.browser

com.ibm.rcp.samples.propertybroker.managedbrowserc

com.ibm.rcp.samples.propertybroker.selector

com.ibm.rcp.samples.propertybroker.dynamicaction

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

f. Click Apply and then Run.3. Run one or more of the samples listed:

v “Running the sample – Portlet to Portlet Communication”

v “Running the sample – Portlet to SWT Communication”

v “Running the sample – SWT to Portlet Communication”

v “Running the sample – Browser” on page 41

v “Running the sample – Double Browser” on page 41

v “Running the sample – Cross Page Wire” on page 41

Running the sample – Portlet to Portlet Communication:

This sample contributes a perspective, named P2P Search. To run this sample, select Open > Composite

application Sample > Portlet Wiring samples > Portlet to Portlet Communication sample.

There are two views in this perspective:

v P2P quick search is a portal view that enables you to enter a text string. Click Submit to display this

string in the P2P search result view. This portal view also provides a Search resources for Lotus

Expeditor link. Click this link to display Lotus Expeditor text in the P2P search result view.

v P2P search result is a portal view that displays the text that you submit from the P2P quick search

view.

Note: The P2P quick search view is “wired” to the P2P search result view through the Property Broker to

demonstrate portlet-to-portlet communications.

Running the sample – Portlet to SWT Communication:

This sample contributes a perspective, named Portlet to SWT Communication. To run this sample, select

Open > Composite application Sample > Portlet Wiring samples > Portlet to SWT Communication

sample.

There are two views in this perspective:

v UrlSelector portlet is a portal view that enables you to type a Web address. Click Submit to display

the Web site for the Web address in the Controlled Browser view.

Important: You must specify a fully-qualified Web address. For example, http://www.google.com will

work. However, www.google.com will not work.

v Controlled Browser is a SWT view that displays the Web site that you enter in an embedded browser.

Note: The UrlSelector portlet view is “wired” to the Controlled Browser view through the Property

Broker to demonstrate portlet-to-SWT communications.

Running the sample – SWT to Portlet Communication:

To run this sample, select Open > Composite application Sample > Portlet Wiring samples > SWT to

Portlet Communication sample.

There are two views on this page:

v The SWT selector view contains a list of Web addresses set by the portal administrator.

v A portlet viewer displays the P2P Search Result portlet.

40 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 53: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Double-click to select one of the addresses in the SWT selector. The URL shows as the search text in the

P2P Search Result portlet.

Note: The SWT Selector view is “wired” to the P2P Search Result portlet through the Property Broker to

demonstrate SWT-to-portlet communications.

Running the sample – Browser:

This sample contributes a perspective, named Browser. Select Open > Composite application Sample >

Browser sample.

There are two views in this perspective:

v The SWT selector view displays a list of Web addresses set by the portal administrator.

v The SWT embedded browser view allows you to view selected Web sites.

Note: The SWT selector view is “wired” to the SWT embedded browser view through the Property

Broker to demonstrate SWT to SWT communications.

To open a Web site in the embedded browser view, double-click a URL in the SWT selector view. This

action sends an event with the Web address to the embedded browser view, which then displays the Web

site.

Running the sample – Double Browser:

This sample contributes a perspective, named Double Browser. Select Open > Composite application

Sample > Double Browser sample.

There are four views in this perspective:

v Two SWT selector views, on the left side of the perspective, display a list of Web sites set by the portal

administrator.

v Two embedded browser views, on the right side of the perspective, allow you to view selected Web

sites.

Note: Each SWT selector view is “wired” to a corresponding SWT embedded browser view through the

Property Broker to demonstrate SWT to SWT communications.

To open a Web site in the top embedded browser view, double-click a Web site in the top SWT selector

view. This action sends an event with the Web site to the top embedded Browser view, which then

displays the Web site.

To open a Web site in the bottom embedded browser view, double-click a Web address in the bottom

SWT selector view. This action sends an event with the URL to the bottom embedded Browser view,

which then displays the Web site.

To demonstrate drag and drop between the two SWT selector views, drag a Web address from the top

SWT selector view to the bottom SWT selector view, or vice versa. Release the mouse button, and select

the following action:

v Load a URL from the selector action

As a result, the embedded Browser view, associated with the target SWT selector view, displays the Web

site that was dragged and dropped from the originating SWT selector view.

Running the sample – Cross Page Wire:

Product overview 41

Page 54: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

This sample opens a page containing a URL selector. Double-clicking on a URL results in a new page

containing new views populated with the URL. Select Open > Composite application Sample > Cross

Page Wire Sample > URL Selector to Launch Dynamic Action Page.

Troubleshooting:

Problem:

The sample application is not available in the launch list.

Cause:

One or more of the plug-ins is not present or does not resolve in the client platform.

Action:

Verify that the plug-ins are contained in the runtime. If the plug-in is present, check the status of the

plug-in. Go to the Console view and use the b plug_in_name command. The second line of output

indicates the plug-in status. If the status is not RESOLVED or ACTIVE, there is a problem with the

plug-in and its dependencies. Use the diag plug_in_name command to identify any unsatisfied

dependencies. Resolve any missing dependencies and restart the platform.

Problem:

The P2P search application displays two views that show “The page cannot be found”.

Cause:

The Portlet Communication sample was not imported into the workspace or the associated plug-ins

were not specified in the runtime launch.

Action:

Verify that the Portlet Communication sample was imported into the workspace and verify the

associated plug-ins are selected in the launch configuration. Related sample:

See the Portlet Communication sample to wire two portlets together for action processingThis sample demonstrates two Java Specification Request (JSR) 168 portlets exchanging data.

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

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 or browse to the

com.ibm.rcp.tools.samplegallery plug-in directory and select the jar file from the archive directory.

42 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 55: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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

Product overview 43

Page 56: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Derby sample for an alternative database included with the platformThis sample illustrates the use of the local Derby database.

See ISync sample to synchronize content from a relational database on the server to a local Derby 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 Derby database.

See the JNDI sample to declaratively define (bind) a DataSource objectThis sample demonstrates the use of JNDI APIs and declarative JNDI.

Derby sample

This sample illustrates the use of the local Derby 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.derby. Key concepts

demonstrated in this sample are as follows:

v Creation of a Derby 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 Java class in the com.ibm.rcp.samples.derby

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, derby.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory and select the jar file from the archive directory.

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 Derby.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.derby plug-in is selected.

e. Select the Arguments tab and verify that –console is in the Program Arguments field.

44 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 57: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

f. Click Apply and then Run.3. To start the sample, enter start com.ibm.rcp.samples.derby in the Console view.

osgi> start com.ibm.rcp.samples.derby

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.derby command in the console, the following

message is displayed:

Cannot find bundle com.ibm.rcp.samples.derby

Cause:

The com.ibm.rcp.tools.samples.derby bundle is not available in your runtime.

Action:

Edit your launch configuration and verify that the com.ibm.rcp.samples.derby bundle is selected.

Problem:

When attempting to run the start com.ibm.rcp.samples.derby 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 Derby 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 Derby database.

See 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

Product overview 45

Page 58: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Throw and catch service specific exceptions

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, echo.jar, or browse to the com.ibm.rcp.tools.samplegallery

plug-in directory and select the jar file from the archive directory.

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:

v Version 6.1.1 output

v Version 6.1.2 outputosgi> 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,

46 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

Page 59: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

cago,offset=-21600000,dstSavings=3600000,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]],first

DayOfWeek=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_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=21,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-21

600000,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...

------------

osgi> stop com.ibm.rcp.samples.ws.echo.client

osgi> stop com.ibm.rcp.samples.ws.echo.server

osgi> stop com.ibm.rcp.samples.ws.echo.marshal

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> Iteration 1

Calling echo(Counter = 1)...

Product overview 47

Page 60: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

echo(Counter = 1) returned [{req1=Counter = 1}]

Calling getTime()...

getTime() returned java.util.GregorianCalendar[time=1189737420000,areFieldsSet=true,lenient=true,zone=java.util.TimeZoneTable[java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=01167631200000 : java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,

Calling echoWithException(Counter = 1)...

echoWithException() resulted in an exception with message: echoWithException called with parameter value Counter = 1

------------

Iteration 2

Calling echo(Counter = 2)...

echo(Counter = 2) returned [{req2=Counter = 2, req1=Counter = 1}]

Calling getTime()...

getTime() returned java.util.GregorianCalendar[time=1189737420000,areFieldsSet=true,lenient=true,zone=java.util.TimeZoneTable[java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=01167631200000 : java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,

Calling echoWithException(Counter = 2)...

echoWithException() resulted in an exception with message: echoWithException called with parameter value Counter = 2

------------

Iteration 3

Calling echo(Counter = 3)...

echo(Counter = 3) returned [{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1}]

Calling getTime()...

getTime() returned java.util.GregorianCalendar[time=1189737420000,areFieldsSet=true,lenient=true,zone=java.util.TimeZoneTable[java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=01167631200000 : java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,

Calling echoWithException(Counter = 3)...

echoWithException() resulted in an exception with message: echoWithException called with parameter value Counter = 3

------------

Iteration 4

Calling echo(Counter = 4)...

echo(Counter = 4) returned [{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1, req4=Counter = 4}]

Calling getTime()...

getTime() returned java.util.GregorianCalendar[time=1189737420000,areFieldsSet=true,lenient=true,zone=java.util.TimeZoneTable[java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=01167631200000 : java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,

Calling echoWithException(Counter = 4)...

echoWithException() resulted in an exception with message: echoWithException called with parameter value Counter = 4

------------

Iteration 5

Calling echo(Counter = 5)...

echo(Counter = 5) returned [{req3=Counter = 3, req2=Counter = 2, req1=Counter = 1, req5=Counter = 5, req4=Counter = 4}]

Calling getTime()...

getTime() returned java.util.GregorianCalendar[time=1189737420000,areFieldsSet=true,lenient=true,zone=java.util.TimeZoneTable[java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=01167631200000 : java.util.SimpleTimeZone[id=America/Chicago,offset=-21600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,

Calling echoWithException(Counter = 5)...

echoWithException() resulted in an exception with message: echoWithException called with parameter value Counter = 5

------------

osgi> stop com.ibm.rcp.samples.ws.echo.client

osgi> stop com.ibm.rcp.samples.ws.echo.server

osgi> stop com.ibm.rcp.samples.ws.echo.marshal

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

48 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 61: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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:

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.

Product overview 49

Page 62: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Eclipse Preferences sample

This 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 and select the jar file from the archive directory.

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.

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:

50 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 63: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Browser sample

This sample creates a Client Services project to illustrate the basic elements of launching an embedded

browser with Embedded Browser API’s in the Lotus Expeditor workbench.

You can use this sample only on the desktop runtime.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of the Embedded Browser API to launch a browser in the workbench for a particular URL

v Use of the Embedded Browser API to control the behavior of the embedded browser view

v Use of the Embedded Browser API to listen for events, such as changes to a new location (URL) in the

embedded browser

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, browser.jar, or browse to the

com.ibm.rcp.tools.samplegallery2 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.

Product overview 51

Page 64: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

c. Type a unique name for your configuration, such as Embedded Browser Application.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.ui.browser.launch 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.

Running the sample:

This sample contributes a new perspective and view to the Lotus Expeditor workbench: Browser

Perspective and Web Browser View.

The Web Browser View contains a browser window with a tab named the title of the active Web page.

The initial view is for http://www.ibm.com with a tab named IBM United States. To add another

browser view to the perspective, select Embedded Browser from the menu bar and select Add Browser.

A new embedded browser view is launched for http://www.lotus.com with a tab named IBM Lotus

Software.

Troubleshooting:

Problem:

The sample application is not available in the launch list.

Cause:

The com.ibm.rcp.samples.ui.browser.launch plug-in is not present or does not resolve in the client

platform.

Action:

Verify that the com.ibm.rcp.samples.ui.browser.launch 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 use the b

com.ibm.rcp.samples.ui.browser.launch command. The second line of output indicates the plug-in

status. If the status is not RESOLVED or ACTIVE, there is a problem with the plug-in and its

dependencies. Use the diag com.ibm.rcp.samples.ui.browser.launch command to identify any

unsatisfied dependencies. Resolve any missing dependencies and restart the platform.

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.

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

52 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 65: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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

* ********************************* *

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:

Product overview 53

Page 66: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

eRCP E-mail sample

This sample shows you how to construct an embedded Rich Client Platform (eRCP) application.

Time required: 2 minutes

A Client Services Rich Graphical User Interface (GUI) application uses the embedded Standard Widget

Toolkit (eSWT) and eJFace to draw its user interface. 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; on a device, views are

displayed as individual windows. No matter how they are displayed, embedded Rich GUI applications

are referred to as workbench applications because they never create their own top-level window.

Creation of a Rich GUI application includes three basic parts:

v UIPlugin class

v View classes

v Extensions

For more information on creating eRCP workbench applications, see http://www.eclipse.org/ercp.

Setup instructions:

Before you can run the sample, you must first change your target platform and import the sample into

your workspace.

1. To change your target platform:

a. Select File > Switch Workspace.

b. Enter a folder name and click OK.

c. A Lotus Expeditor Toolkit Configuration dialog appears. For Test Environment, choose Lotus

Expeditor for Device, then click OK.

54 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 67: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

d. Select Go to the workbench.

2. 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, ercpapp.jar, or browse to the

com.ibm.rcp.tools.device.samplegallery plug-in directory and select the jar file from the archive

directory.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.3. 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 eMailSample.

d. For the runtime JRE, select jclDevice Win32 x86.

e. Select the Target tab and set the target as Default Device Target.

f. Select the Plug-ins tab and verify that the org.eclipse.ercp.app plug-in is selected.

g. Click Apply and then Run. The eWorkbench is displayed.4. To start the sample, click eRCP eMail sample in the list of applications shown in the eWorkbench.

eSWT Demo sample

This sample contains a number of showcase applications that show embedded Standard Widget

Technology (eSWT) widgets, both alone, and combined to form some simple application functionality.

Time required: 2 minutes

Showcases demonstrated in this sample are as follows:

v Browser

v Calendar

v CaptionedControl

v Command

v Composite

v Low level graphics

v Label

v ListBox

v Menu

v MessageBox

v MobileShell

v MultiPageDialog

v Phonebook

v Table

v Tree

The sample will run on both device and desktop clients. For additional information about eSWT and

Mobile Extensions, see http://www.eclipse.org/ercp.

Setup instructions:

Product overview 55

Page 68: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Before you can run the sample, you must first change your target platform and import the sample into

your workspace.

1. To change your target platform:

a. Select File > Switch Workspace.

b. Enter a folder name and click OK.

c. A Lotus Expeditor Toolkit Configuration dialog appears. For Test Environment, choose Lotus

Expeditor for Device, then click OK.

d. Select Go to the workbench.

2. 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, eswtdemo.jar, or browse to the

com.ibm.rcp.tools.device.samplegallery plug-in directory and select the jar file from the archive

directory.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.3. 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 eSWTDemo.

d. For the runtime JRE, select jclDevice Win32 x86.

e. Select the Target tab and set the target as Default Device Target.

f. Select the Plug-ins tab and verify that the org.eclipse.ercp.swt.demo plug-in is selected.

g. Click Apply and then Run. The eWorkbench is displayed.4. To start the sample, click eSWT Demo in the list of applications shown in the eWorkbench.

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 Derby database.

Time required: 2 minutes

You can use this sample on both desktop and device runtimes.

On the desktop runtime, both Derby and DB2 Everyplace may be used as the client database. Accounts

may optionally be used to provide credential information to access the server.

On the device runtime, only DB2 Everyplace can be used as a client. Accounts cannot be used on the

device runtime.

To run this sample, you must have access to an IBM DB2 Everyplace Sync Server installation.

Key concepts demonstrated in this sample:

v Use of the ISync APIs

v Optional use of the Account APIs

Setup instructions:

56 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[[

[

[

[

[

Page 69: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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 and select the jar file from the archive directory.

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:yyyy, where xxxx is the IP address

of the DB2 Everyplace Sync Server, and yyyy is the port number being used by the application

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 Derby 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″

v The sample code is delivered to run on both desktop and device runtimes with the minimal

changes described above. To enable use of the accounts interfaces, additional steps are required.

Refer to “Accounts enablement” on page 60 for more details.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

Product overview 57

[[[[[

[[[

Page 70: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

**********************

58 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 71: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

*********************

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

**********************

*********************

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

Product overview 59

Page 72: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

Event Type: 1

Event Code: 1012

Progress: 100

**********************

Synchronization succeeded

Subscription Set: SUBSCRIPTION_SET1 Status: COMPLETED

osgi> stop com.ibm.rcp.samples.isync

Accounts enablement:

To enable the use of the accounts interfaces, follow these steps:

1. Create an account:

a. To use the Accounts interface, select File > Preferences > Accounts.

b. Select New Account.

c. Type a name for the account. For example, type ISYNC_SAMPLE.

d. Type the server for the account in the format http://server:port where server and port specify the

locations for your DB2e Sync Server instance.

e. Type the name and password. The properties files define nurse1/nurse1 for DB2e local target and

nurse2/nurse2 for Derby local target, but you can use any ID/password configured on the server.

f. Select OK to save the account definition.2. Specify the account name in the sample. In the file ISyncBundle.java, change the line from

sample.setAccountName( null ); to sample.setAccountName( "account_name" ); where account_name

specifies the account name specified in step 1c.

3. Enable the code specific to Accounts:

a. Edit the ISyncSample.java in this same package.

b. Un-comment the code marked with ACCOUNTS ENABLEMENT.

c. Add com.ibm.rcp.accounts to the Import-Package property:

1) Select the project, then right-click and select Client Services.

2) Select the Accounts feature in the target profile.

3) Select OK to save the changes.4. Run the sample as usual.

Troubleshooting:

60 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[

[

[

[

[[

[[

[

[[[

[

[

[

[

[

[

[

[

Page 73: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Product overview 61

Page 74: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Derby sample for an alternative database included with the platformThis sample illustrates the use of the local Derby database.

See the Accounts sample for use of the Accounts APIsThis sample creates a Client Services project to illustrate the basic elements of a rich client application

that uses the Accounts API on Lotus Expeditor.

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 63

v “Option B: Using the file-persistence-based micro broker instance” on page 63

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

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.

62 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[

Page 75: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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:

Product overview 63

Page 76: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

64 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 77: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Product overview 65

Page 78: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

66 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 79: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

Product overview 67

Page 80: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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.

68 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 81: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.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.

Product overview 69

Page 82: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Mobile Adjuster sample

This sample demonstrates how an enterprise can extend their Web applications to mobile employees by

implementing a services-oriented architecture using IBM Lotus Expeditor.

Time required: 2 minutes

Mobile Adjuster is an end-to-end solution demonstrating Lotus Expeditor technology in the enterprise

segment. The sample is designed for a mobile environment and operates in a totally disconnected state. It

70 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 83: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

uses DB2 Everyplace for data synchronization, and WebSphere MQ Everyplace for secure transactional

messaging when a connection is available. The MobileAdjuster application runs entirely on the device

and enables you to act as an insurance adjuster. In this role, you can view claim and customer

information, create and process claims, and synchronize data with the backend servers.

Setup instructions:

Before you can run the sample, you must first change your target platform and import the sample into

your workspace.

1. To change your target platform:

a. Select File > Switch Workspace.

b. Enter a folder name and click OK.

c. A Lotus Expeditor Toolkit Configuration dialog appears. For Test Environment, choose Lotus

Expeditor for Device, then click OK.

d. Select Go to the workbench.

2. 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, mobadj.jar, or browse to the

com.ibm.rcp.tools.device.samplegallery plug-in directory and select the jar file from the archive

directory.

e. The dialog shows the projects present in the archive jar file. Select Finish to install the projects

into your workspace.3. 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 MobileAdjuster.

d. For the runtime JRE, select jclDevice Win32 x86.

e. Select the Target tab and set the target as Default Device Target.

f. Select the Plug-ins tab and verify that the com.ibm.pvc.samples.mobileadjuster and

com.ibm.pvc.samples.mobileadjuster.logic plug-ins are selected.

g. Click Apply and then Run. The eWorkbench is displayed.4. To start the sample, click Mobile Adjuster in the list of applications shown in the eWorkbench.

Attention: The Mobile Adjuster sample also includes a server-side component with which the device

sample communicates. This is not required to run the Mobile Adjuster in stand-alone mode. See the

Mobile Adjuster readme file for information on how to install and run the server-side component.

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:

Product overview 71

Page 84: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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.

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

72 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 85: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

Product overview 73

Page 86: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Network Status sample

This sample creates a Client Services project to illustrate the basic elements of a rich client application

that uses the Network Layer API on Lotus Expeditor.

You can use this sample only on the desktop runtime.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of the Network Layer API to monitor network availability of a remote resource

v Use of the Network Layer API to detect status of a network connection and run application logic based

on this status

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, netstatus.jar, or browse to the

com.ibm.rcp.tools.samplegallery2 plug-in directory and select the jar file from the archive

directory.

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 Network Status Application.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.netstat.time 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.

Running the sample:

This sample contributes a new perspective, named Net Status Sample Perspective, to the Lotus

Expeditor workbench.

This perspective contains the Net Status view:

v In response to selecting the Check button, the Time field displays the network time determined based

on a connection to http://www.ibm.com or the local system time (if there is no active connection to

the remote resource). If the connection is online, the field shows the following message:

<time> network

If the connection is offline, the field shows the following message:

<time> system

74 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 87: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In both cases, <time> is displayed in a format appropriate to the current locale.

v The Network Status field provides the status of the network connection http://www.ibm.com. To

generate a network fault, disconnect the client from http://www.ibm.com (for example, remove your

network cable). Next, select Check to generate a network fault that results in the following messages:

<date and time> disconnected

<date and time> offlineStateChanged

When you reconnect to http://www.ibm.com (for example, reinsert your network cable), the field

shows the following messages:

<date and time> reconnected

<date and time> offlineStateChanged

where <date and time> is displayed in a format appropriate to the current locale.

Select Clear to clear the messages in the Network Status field.

Troubleshooting:

Problem:

The sample application is not available in the launch list.

Cause:

The com.ibm.rcp.samples.netstat.time plug-in is not present or does not resolve in the client

platform.

Action:

Verify that the com.ibm.rcp.samples.netstat.time 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 use the b

com.ibm.rcp.samples.netstat.time command. The second line of output indicates the plug-in status. If

the status is not RESOLVED or ACTIVE, there is a problem with the plug-in and its dependencies.

Use the diag com.ibm.rcp.samples.netstat.time command to identify any unsatisfied dependencies.

Resolve any missing dependencies and restart the platform.

Problem:

The network fault is not generated for disconnection or reconnection.

Cause:

The computer does not immediately detect that there is a disconnection or re-connection to

http://www.ibm.com.

Action:

Wait for several seconds after you disconnect your computer from the network and then select Check

to generate a network fault for disconnection. Wait for several seconds after you reconnect your

computer to the network and then look for the reconnected message in the Net Status field.

Order Entry sample

Order Entry is a three-tier, sample application that demonstrates the following components and

capabilities: Web container, Java Servlet 2.3, Eclipse Preferences, MQ Everyplace, JDBC, local database,

RCP views, and preference pages. On desktop platforms, Managed Datasources (Database Lifecycle) with

Apache Derby is used as the local database. On device platforms, DB2 Everyplace is used as the local

database.

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:

Product overview 75

Page 88: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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 local 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.

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 and select the jar file from the archive directory.

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 77

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.

76 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[

[[[[[

[[

[

Page 89: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

INFO: BaseMQeTransport: Transport thread started.

If you have already created orders, the following message is displayed in the Server application

console:

INFO: 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:

2007/09/27 15:01:28.328 INFO 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:

Product overview 77

[[

[

[[

[

[[

[

Page 90: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

INFO: BaseMQeTransport: Transport thread started.

If you have already created orders, the following message is displayed in the Server application

console:

INFO: 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:

2007/09/27 15:01:28.328 INFO RESPONSE RECEIVED

OSGi Preferences Service sample

This sample demonstrates the use of the OSGi Preferences Service to save and retrieve preference

information.

Time required: 2 minutes

78 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[

[[

[

[[

[

Page 91: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 and select the jar file from the archive directory.

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.

Product overview 79

Page 92: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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

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 and select the jar file from the archive directory.

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:

80 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 93: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 and select the jar file from the archive directory.

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.

Product overview 81

Page 94: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 Use of the com.ibm.rcp.ui.launcherSet extension point

v Assembly of an application with one perspective, two views/three views, and three actions

v Contributing a view to the sidebar

v Use of view options to prevent closing or moving of the views

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.

82 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[

[

Page 95: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

a. 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.

b. Choose one of the following:

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.

v Select Open > Samples > 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 com.ibm.rcp.ui.launcherSet extension

point.

The sidebar opens when an application is selected. The Sample Rich Application contributes the

Shelf View to the sidebar. Select View > Sidebar to open, close, or shrink the sidebar. Select

View > Sidebar Panels to hide or show the Shelf View on the sidebar.c. 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).

d. 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

Product overview 83

[[[[[

[[[

Page 96: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.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.

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.

84 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 97: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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.

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.

Product overview 85

Page 98: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 and select the jar file from the archive directory.

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.

86 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 99: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

Product overview 87

Page 100: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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:

88 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 101: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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:

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 88.

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.

Product overview 89

Page 102: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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:

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.

Property Broker sample

This sample creates a Client Services project to illustrate the basic elements of a rich client application

that uses the Property Broker API on Lotus Expeditor.

You can use this sample only on the desktop runtime.

Time required: 2 minutes

Key concepts demonstrated in this sample are as follows:

v Use of the Property Broker API so a view can send events to another view

v Use of the Property Broker API so a view can receive events from another view

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, propertybroker.jar, or browse to the

com.ibm.rcp.tools.samplegallery2 plug-in directory and select the jar file from the archive

directory.

90 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 103: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Property Broker Application.

d. Select the Plug-ins tab and verify that the com.ibm.rcp.samples.propertybroker.color 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.

Running the sample:

This sample contributes a perspective, named the Property Broker Demo Perspective, to the Lotus

Expeditor workbench. To start the sample in the Lotus Expeditor workbench, click Open and then click

Property Broker Color Sample.

This perspective contains the following three views:

v The Color List View in the left side of the perspective displays a list of colors. Right-click on a color

and either select Foreground or Background. The color is displayed in the appropriate Color Swatch

View.

v The Color Swatch View at the top right-side of the perspective is for the Foreground.

v The Color Swatch View at the bottom right-side of the perspective is for the Background.

Troubleshooting:

Problem:

The sample application is not available in the launch list.

Cause:

The com.ibm.rcp.samples.propertybroker.color plug-in is not present or does not resolve in the client

platform.

Action:

Verify that the com.ibm.rcp.samples.propertybroker.color 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 use the b

com.ibm.rcp.samples.propertybroker.color command. The second line of output indicates the plug-in

status. If the status is not RESOLVED or ACTIVE, there is a problem with the plug-in and its

dependencies. Use the diag com.ibm.rcp.samples.propertybroker.color command to identify any

unsatisfied dependencies. Resolve any missing dependencies and restart the platform.

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:

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.

Product overview 91

Page 104: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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:

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.

92 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 105: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Portlet Aggregation Web Page 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 88.

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:

Product overview 93

Page 106: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and select the jar file from the archive directory.

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.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.

94 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 107: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

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 and select the jar file from the archive directory.

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.

Product overview 95

Page 108: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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***

96 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 109: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 for portlets and

composite applications.

The portlet pattern is supported by the Portlet Application Model. This pattern is based on JSR 168.

The Composite Application pattern is supported by the Composite Application Model. Composite

applications draw upon functionality from multiple sources within and beyond the enterprise to support

horizontal business processes. In this model, multiple applications and components 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, 2008 97

Page 110: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

WebUI

RichUI

Local BusinessLogic Services

Web Services

Micro Broker

MQe

DB2e orDerby

EnterpriseManagement

Agent

Update Manager

WebServices

Micro BrokerBridge

MQGateway

DB2eSync Server

DeviceManagement

Server

Update sites

Portal Server

Consume and publishWeb Services

Publish and subscribeSend and receive

Send and receivesecure transactions

Synchronizerelational data

Server-managed SWinstall & maintenance

User-initiated SWinstall & Maintenance

Synchronize objects

ESB

ESB

Replicate

MessagingApplications

Lotus Expeditor "Connectors"

Lotus Expeditor - Client

Lotus Expeditor - Server

Portal Services(Desktop only)

SyncMLLibraries

Aggregation, role-basedaccess control

{SyncMLLibraries}

MessagingApplications

DATASync

RDB's

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 Java EE 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 Derby 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

98 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 111: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

data on the following Enterprise databases: DB2 Universal Database Informix Dynamic Server, Lotus

Domino Server, Oracle, Microsoft SQL Server, and Sybase Adaptive Server Enterprise.

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 Derby are both

embedded databases. However, DB2e is much smaller than Derby, so you might choose DB2e for

handheld devices such as PDAs and choose Derby, 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 application, or local Web Service.

Developing applications 99

Page 112: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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. MQe supports point-to-point messaging.

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 and point-to-point messaging, with

support for online and offline operations, and synchronous and asynchronous messaging.

100 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 113: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 PDAs 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 101

Page 114: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

API Lotus Expeditor Client for Desktop Lotus Expeditor Client for Devices

Java jclDesktop (default) jclDevice (supports Java ME

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.2 eRCP 1.0.2

Data Sync SyncML4J 2.6 SyncML4J 2.6

Database Access JDBC 3.0 or 4.0 with DB2e or Derby JDBC JSR 169 with DB2e

Database Sync ISync with DB2e or Derby ISync with DB2e

Messaging – Point-to-Point JMS 1.1 with MQe

JMS 1.1 with Micro Broker

JMS 1.1 with MQe

JMS 1.1 with Micro Broker

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

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 Java EE 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

102 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 115: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

its own threads, and so on. When the bundle shuts down, the framework calls the activator’s stop()

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

Developing applications 103

Page 116: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

automatically as required. A product’s components are grouped together into features. A feature is the

smallest unit of separately downloadable and installable functionality

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.

104 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 117: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 manifest specifies a bundle’s prerequisite and local classpath which are used for Java class

loading. The bundle manifest also may specify a bundle activator which is loaded and used for bundle

life cycle operations.

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.

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

Developing applications 105

Page 118: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

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.

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

106 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 119: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 with the jclDesktop JRE

This section provides detailed information on developing applications with the jclDesktop JRE.

Understanding the jclDesktop JRE

The default Java Runtime Environment (JRE) of Lotus Expeditor is IBM’s J9 VM with the jclDesktop class

libraries, an IBM-optimized subset of Java 5 that offers a smaller footprint and faster class loading than

standard Java Runtime Environments.

The jclDesktop runtime environment also leverages IBM’s JXE technology for improved class loading

performance which typically results in 20-30% faster startup than standard jar files. In addition, JXEs also

provide a reduction in overall memory consumption. More information can be found on IBM’s JXE

technology below.

The reduction in disk footprint that the jclDesktop class libraries and the J9 VM provide is quite

substantial. A standard Java 5 JRE takes approximately 65MB of space on disk, while the jclDesktop

runtime environment requires only approximately 17MB of space for installation. When creating

lightweight Lotus Expeditor-based client applications, a difference of over 45MB can make quite a

difference in client download/deployment time. In order to achieve this reduction in footprint, several

components of the Java 5 class libraries are not included in jclDesktop. Most specifically, AWT and

SWING. The preferred windowing API for Lotus Expeditor is SWT. SWT is provided as part of the core

Lotus Expeditor platform. The list of classes that have been removed from jclDesktop is not limited to

AWT and SWING.

The J9 VM is built using the ″embedded″ J9 version. Major differences to the ″full″ desktop VM include:

v A small JIT (Cinquecento) instead of the Large JIT (Testarossa)

v Embedded GC (Scavenger, Global GC with compaction) instead of Desktop GC

v No shared classes support

v A smaller footprint

More on JXE’s

A Java program is compiled into a set of .class files, typically collected into a set of jar files. Classloaders

use a classpath, containing one or more jars, to load classes. To obtain a class from a jar, the jar needs to

be opened and categorized. This involves I/O on the Java-level, using java.io.InputStream. After the

classloader finds the bytes representing the class file, it presents the bytes to the VM to be turned into an

internal representation. Classes are then verified and dependent classes are automatically loaded as a

result. All this makes class loading an expensive process.

Developing applications 107

[

[[[

[[[[

[[[[[[[[[

[

[

[

[

[

[

[[[[[[

Page 120: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The J9 VM automatically converts plug-in jars into a J9 Executable (JXE), which is an optimized,

pre-linked class loading format for faster class loading initialization. For efficiency, the J9 memory-maps

the JXE utilizing OS resource management. Because JXEs are created from a set of already resolved and

verified classes, there is much less verification needed on classes loaded from a JXE. This also improves

the cost of class-loading. IBM performance testing benchmarks indicate significant reduction in the cost

for class loading. IBM JXE technology is complementary to IBM’s JIT compiler strategy and is a critical

part of the client-side Java platform.

Developing with jclDesktop Unique Components

While the majority of the code written for a Java 5 runtime environment will run unchanged on the

jclDesktop platform there are a few cases where some modifications may be required. The areas detailed

in this section may require some code modifications for existing code to successfully execute on the

jclDesktop runtime.

Use of classes outside of the jclDesktop Java 5 Subset

To confirm that the set of Java 5 classes your code leverages is available when developing with

jclDesktop, simply target your Eclipse project at the jclDesktop JRE and confirm that no errors appear. If

you are still in the investigation stage of your development work with Lotus Expeditor and jclDesktop,

you can refer to the Javadoc section in Developing Applications for Lotus Expeditor to review the complete

list of Java APIs available with jclDesktop.

Below, are the new Java 5 enhancements not supported in jclDesktop (which do not manifest themselves

with new API):

v jclDesktop is on Unicode 3.0.1 level (not on Unicode 4.0) and thus does not support the new code point

API (in Character and String)

v Access to generic signature information through reflection is not supported

v Parsing of doubles and floats in Hex format is not supported

v java.text.DecimalFormat limits the maximum number of integer and fraction digits to 340

v jclDesktop does not support alternate providers for NIO character sets, sound, JCE and JSSE

Use of some of the standard Java system properties

While in general it is not good practice to leverage specific values of the standard Java system properties,

in some cases it may be required. If the existing code leverages any of the standard Java system

properties, modifications may need to be made in order to make VM specific decisions that are

appropriate based on J9 jclDesktop specific values. The following list provides the J9 jclDesktop specific

values for these standard Java system properties:

java.compiler

j9jit24

java.fullversion

see java.vm.info

java.runtime.name

J9 - VM for the Java platform

java.runtime.version

2.4

java.vendor

IBM Corporation

java.vendor.url

http://www.ibm.com/

108 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[

[

[[[[

[

[[[[[

[[

[[

[

[

[

[

[

[[[[[

[[

[[

[[

[[

[[

[[

Page 121: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

java.version

1.5.0 subset

java.vm.info

IBM J9 2.4 Windows XP x86-32 (JIT enabled)

J9VM - 20070929_014158_lHdFGQ

GC - 20070927_AB

JCL - 20070831_1218,dee

java.vm.name

J9

java.vm.vendor

IBM Corporation

Use of Sun’s JNDI LDAP Provider

If the existing code is using the default Sun JNDI LDAP provider, simply re-targeting the project to the

jclDesktop JRE may not surface the issue directly since most interaction with the JNDI provider is

through string literals. Although jclDesktop does not provide the default Sun JNDI LDAP provider, it

does provide an IBM implementation of a JNDI LDAP Provider to support this functionality. For details

on the IBM JNDI LDAP provider please refer to “Using the IBM JNDI LDAP Provider” on page 111.

Use of the Java Cryptography Architecture APIs

JSR-219 (Foundation 1.1) defines the optional Java Cryptography Extension (JCE) package that provides

an open interface to cryptographic algorithms.

The Java Cryptography Architecture separates the interface to cryptographic functionality from its

implementation. The JCE defines the cryptographic interface and the framework to be implemented by

configurable providers.

The jclDesktop JRE provides an implementation of the optional JCE package and a cryptographic

provider for it. At this time, only the J9 JCE Provider can be used with the J9 JCE implementation. For

details on the J9 JCR Provider please see “J9 JCE Provider Details.”

Use of the Java Secure Socket Extension and Provider

JSR-219 (Foundation 1.1) defines the optional Java Secure Socket Extension package that provides an

interface for Secure Sockets Layer (SSL) and Transport Layer Security (TLS) sockets.

Available with the J9 JRE is an implementation of the optional JSSE package. While the JSSE does allow

for configurable SSL socket providers, at this time the implementation is restricted to using the J9 JSSE

SSL socket implementation. For details on the J9 JCR Provider please see “J9 JSSE and Provider Details”

on page 110.

J9 JCE Provider Details

The J9 JCE Provider implements the following cryptography algorithm(s) and the associated support

classes (such as SecretKeyFactory and KeyGenerator).

v Symmetric cryptography algorithms:

– AES

– Blowfish

– DES

– DESede

– PBEWithMD5andDES

Developing applications 109

[[

[[

[

[

[

[[

[[

[

[[[[[

[

[[

[[[

[[[

[

[[

[[[[

[[[

[

[

[

[

[

[

Page 122: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

– PBEWithMD5andTripleDESv Asymmetric cryptography algorithms:

– RSA

The following cipher modes are supported for the above algorithms:

v CBC (Cipher Block Chaining)

v ECB (Electronic Codebook)

The following padding modes are supported for the above algorithms:

v PKCS5Padding

v SSL3Padding

v NoPadding

The J9 JCE Provider implements the following Message Authentication algorithm(s):

v HmacMD5

v HmacSHA1

The J9 JCE Provider implements the following Key Exchange algorithm(s) and the associated support

classes (such as AlgorithmParameterGenerator):

v DH (Diffie-Hellman)

The J9 JCE Provider supports the following Keystore types:

v JCEKS

J9 JSSE and Provider Details

The J9 JSSE implementation currently supports the SSL v3.0 and TLS v1.0 protocols . This support allows

it to establish secure connections with virtually all commercial web sites and SSL server implementations.

The following Cipher Suites are supported by the J9 JSSE implementation:

v SSL_RSA_WITH_3DES_EDE_CBC_SHA

v SSL_RSA_WITH_DES_CBC_SHA

v SSL_RSA_EXPORT_WITH_DES40_CBC_SHA

v SSL_RSA_WITH_NULL_SHA

v SSL_RSA_WITH_NULL_MD5

v SSL_RSA_WITH_RC4_128_SHA

v SSL_RSA_WITH_RC4_128_MD5

v TLS_RSA_WITH_AES_128_CBC_SHA

System properties

javax.net.ssl.SSLSessionContext.timeout

Sets the time in seconds that a session will be cached in the table before it is removed. The time

is measured from the sessions creation time. The default is 86400 (24 hours). This value comes

from JDK 1.5.0 and a recommendation in the book ″SSL and TLS: Designing and Building Secure

Systems″ by Eric Rescorla. A value of 0 means that sessions will never time out. For a value of <

0 the default value is applied.

javax.net.ssl.SSLSessionContext.cachesize

Sets the number of sessions that can be stored in the session table before it becomes full. A value

of 0 (or < 0) means there is no maximum table size. The default is 0. A full table would mean

110 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[

[

[

[

[

[

[

[

[

[

[

[[

[

[

[

[[[

[

[

[

[

[

[

[

[

[

[

[[[[[[

[[[

Page 123: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

only that new SSL sessions would not be resumable. This only means that each new connection

would do the full (slow) SSL handshake instead of the faster resume SSL handshake. SSL

connections could still be made.

Using the IBM JNDI LDAP Provider

Lotus Expeditor, with its jclDesktop JRE, provides an IBM implementation of a JNDI LDAP provider that

supports both V2 and V3 LDAP server interaction.

This collection of topics is not intended to be an introduction to JNDI or LDAP. It assumes you are

familiar with JNDI and how LDAP operates. For more introductory JNDI documentation please see Sun’s

Java website. The IBM JNDI LDAP provider fully supports the LDAP URL format defined in RFC 2255.

The common collection of tasks that differ from standard Sun JNDI LDAP are documented here.

Creating an Initial Context:

JNDI supports two different methods for a client to interact with an LDAP server. The first and most

common way is for the client to identify the server at context creation. Operations are then performed on

this open connection by passing DN based names to the context’s methods.

The following two properties support this type of operation:

v java.naming.factory.initial (Context.INITIAL_CONTEXT_FACTORY) - this property must be set to

com.ibm.jndi.LDAPCtxFactory.

v java.naming.provider.url (Context.PROVIDER_URL) - identifies the name and port of the LDAP server in

the form of a URL string. If this is not set then the IBM JNDI LDAP Provider defaults to

ldap://localhost:389.

The following code creates a connection to host ″ldapserver″ and retrieves an entry:

Properties env = new Properties();

env.put("java.naming.factory.initial", "com.ibm.jndi.LDAPCtxFactory");

env.put("java.naming.provider.url", "ldap://ldapserver");

DirContext ctx = new InitialDirContext(env);

Attributes entry = ctx.getAttributes("cn=example,o=IBM,c=US");

The second method to interact with an LDAP server using JNDI is to pass a URL string directly to the

context’s methods. This process, however, has the overhead of creating a new connection for each

operation, something which should be avoided if all operations are bound for a single server. The

following property supports this type of operation:

v java.naming.factory.url.pkgs (Context.URL_PKG_PREFIXES) - This property must be set to com.ibm.jndi

if passing URL strings as name inputs to a context’s method and connection to an LDAP server isn’t

required at context creation time.

The following code duplicates the previous example, with the exception of delaying connection to the

server until getAttributes is called:

Properties env = new Properties();

env.put("java.naming.factory.url.pkgs", "com.ibm.jndi");

DirContext ctx = new InitialDirContext(env);

Attributes entry = ctx.getAttributes("ldap://ldapserver/cn=example,o=IBM,c=US");

The IBM JNDI LDAP provider also supports mixing the two previous methods, that is, it is possible to

establish a connection to an LDAP server using java.naming.factory.initial and then later pass a URL

string as a name input to a method. This works whether java.naming.factory.url.pkgs is defined or not.

Note: Any connection to the LDAP server opened by InitialDirContext needs to be closed by calling

the close() method.

Binding to a Server / SASL Support:

Developing applications 111

[[[

[[[

[[[[

[

[[[

[

[[

[[[

[

[[[[[

[[[[

[[[

[[

[[[[

[[[

[[

[

Page 124: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In many cases a server must authenticate a client before certain operations are allowed. The LDAP

protocol refers to this as binding to the server.

When binding to the server the client specifies which LDAP protocol it wishes to ″speak″. There are two

versions of the LDAP protocol defined, V2 and V3. If the server only supports V2 then a protocol error is

returned when a client attempts to bind as a V3 client. The IBM JNDI LDAP provider supports binding

as either a V2 or V3 client.

v java.naming.ldap.version: Specifies the LDAP protocol version. Legal values are ″2″ or ″3″. If this

property is not set then this toolkit attempts to bind as a V3 client, then automatically steps down to

V2 if a protocol error is returned. The toolkit will not attempt to step down if this property is set.

Besides setting a protocol version, a bind also identifies a user to the server for authentication.

v java.naming.security.principal (Context.SECURITY_PRINCIPAL): The client’s ID. In almost all cases it is

in the form of a distinguished name.

v java.naming.security.credentials (Context.SECURITY_CREDENTIALS): The client’s credentials, that is, their

password.

The values which are sent to the server as part of a bind are identified above. However, LDAP also

supports different types of authentication mechanisms. The V2 LDAP protocol only supports one type of

bind, referred to as a ″simple″ bind. With this mechanism the clear text ID and credentials are sent to the

server. The V3 protocol extended authentication to also support Simple Authentication and Security Layer

(SASL) mechanisms. These allow more sophisticated ways of identifying a client to the server without

unnecessarily compromising the security of the user by sending their ID and password in clear text.

The IBM JNDI LDAP provider supports two different ways of specifying the authentication mechanism.

One way is unique to the IBM JNDI LDAP Provider and requires the name of the authentication class.

This allows the toolkit to be extended by specifying authentication classes outside the toolkit. Thus, the

application programmer is free to write their own SASL plug-ins. The following properties support this

way of specifying the authentication mechanism.

v java.naming.security.sasl: The name of the authentication class to use. The following classes are

shipped as part of the toolkit.

– com.ibm.ldap.LDAPSimpleBind: The clear text ID and credentials are sent to the server for

authentication. This mechanism is supported by both V2 and V3 servers. Note that the use of clear

text passwords is not recommended over open networks when there is no authentication or

encryption being performed by a lower layer.

– com.ibm.ldap.LDAPSaslExternal: The external SASL method attempts to bind using the underlying

security protocol already negotiated (such as SSL). In most cases the security principal and

credentials should be left uninitialized.

– com.ibm.ldap.LDAPSaslCRAM_MD5: The CRAM-MD5 SASL sends the security principal and

credentials (shared secret) to the server for authentication using a challenge-response protocol.

– com.ibm.ldap.LDAPSaslGSSAPI: The GSSAPI SASL method attempts to bind using Kerberos

authentication after obtaining credentials through a separate means, such as a kinit or integrated

login. In most cases the security principal and credentials bind arguments should be left

uninitialized.v java.naming.sasl.mode: A mode setting passed to the loaded SASL plug-in. This setting is ignored by

all pre-defined SASL plug-ins in the toolkit.

The second supported method to specify the authentication mechanism is compatible with Sun’s LDAP

toolkit. Instead of indicating the authentication class to load, the name of the authentication mechanism is

specified instead. The toolkit uses this method for specifying the authentication mechanism if the

java.naming.security.sasl property is not set.

v java.naming.security.authentication (Context.SECURITY_AUTHENTICATION): Specifies the name of the

authentication mechanism to use. The following values are supported by this property.

112 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[[[[

[[[

[

[[

[[

[[[[[[

[[[[[

[[

[[[[

[[[

[[

[[[[

[[

[[[[

[[

Page 125: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

– ″none″ - Do not authentication (anonymous bind).

– ″simple″ - Use simple authentication.

– ″EXTERNAL″ - Use external SASL mechanism.

– ″CRAM-MD5″ - Use CRAM-MD5 SASL mechanism.

– ″GSSAPI″ - Use GSS / Kerberos SASL mechanism.

The following property is set by this IBM JNDI LDAP Provider after the client has been successfully

authenticated:

v java.naming.authorization.identity: Set to the authorization identify of the client. Normally this is the

same as the specified client ID, however, the SASL mechanism may map the initial bind DN to another

value. An example of this is the external SASL, where the authorization identify is stored in the client’s

certificate.

The following example demonstrates setting properties to hard code the version protocol to ″3″ and

authenticating as ″Larry Meade″ using the CRAM-MD5 mechanism:

Properties env = new Properties();

env.put("java.naming.factory.initial", "com.ibm.jndi.LDAPCtxFactory");

env.put("java.naming.ldap.version", "3");

env.put("java.naming.provider.url", "ldap://ldapserver");

env.put(Context.SECURITY_PRINCIPAL, "cn=Larry Meade, o=IBM, c=US");

env.put(Context.SECURITY_CREDENTIALS, "secret");

env.put(Context.SECURITY_AUTHENTICATION, "CRAM-MD5");

DirContext ctx = new InitialDirContext(env);

The previous example can be modified to explicitly indicate the SASL class name. The

SECURITY_AUTHENTICATION line in the above example would need to be replaced with the following line:

nv.put("java.naming.security.sasl", "com.ibm.ldap.LDAPSaslCRAM_MD5");

Securing LDAP Credentials

The Lotus Expeditor Accounts framework can be used to secure client credentials for use with LDAP

servers. For details on using the Accounts framework please “Accounts framework” on page 465.

Advanced Topics:

The following information comprises jclDesktop JRE advanced topics.

LDAP Controls

The LDAP v3 specification adds controls as a way to send and receive extension information. Controls

sent to a server are referred as request controls. An example of which is one which tells the server to sort

the results of a search by a specified attribute. What request controls are supported is completely

dependent on the server. That is, a control may work on one type of server but fail on another. Controls

received from a server are referred to as response controls.

The JNDI 1.2 specification separates request controls into two distinct categories, those used when

connecting to a server and those used on any other operation. For a detailed discussion of request

controls please refer to LdapContext in Sun’s JNDI documentation.

This toolkit ships with one predefined control, ManageDsaIT. This control forces the server to treat search

references as normal LDAP entries, thus allowing them to be viewed and modified, instead of the data

they refer to. The following example demonstrates how to enable this control:

import com.ibm.jndi.ldap.control.ManageDsaIT;

Control[] cntl = new Control[1];

cntl[0] = new ManageDsaIT();

ctx.setRequestControls(cntl);

Developing applications 113

[

[

[

[

[

[[

[[[[

[[

[[[[[[[[

[[

[

[

[[

[

[

[

[[[[[

[[[

[[[

[[[[

Page 126: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Connect controls are only active when the client is binding to a server. Below is an example of how to

enable connect controls:

LdapContext ctx = new InitialLdapContext(env, cntl);

The following API is used to retrieve the last received response controls. Please refer to Sun’s

documentation for details on enabling control factories capable of mapping raw control data to specific

control classes.

Control[] cntl = ctx.getResponseControls();

Binary Attributes

The LDAP protocol is deficient in that it provides no distinction between retrieved binary and textual

attributes. Instead, it expects the client application to know how to handle the data. The IBM JNDI LDAP

Provider is helpful in that it converts textual attributes and returns them as Java strings. However, the

toolkit needs to know which attributes are binary and which represent character data. This toolkit

provides three different methods for handling what happens to retrieved attributes and whether or not

they are converted to strings.

When an attribute is retrieved the toolkit checks a list of known binary attribute names. The toolkit is

programmed to recognize the following set of common LDAP binary attributes:

v userPassword

v userCertificate

v cACertificate

v authorityRevocationList

v certificateRevocationList

v deltaRevocationList

v crossCertificatePair

v x500UniqueIdentifier

v photo

v personalSignature

v audio

v jpegPhoto

v javaSerializedObject

v thumbnailPhoto

v thumbnailLogo

v supportedAlgorithms

v protocolInformation

The programmer may specify their own list of binary attribute names using the following property:

v java.naming.ldap.attributes.binary (LDAPCtx.ATTRIBUTES_BINARY): A space separated list of user defined

binary attribute names in addition to the default set defined by the toolkit.

The following example identifies two additional user defined binary attributes:

ctx.addToEnvironment(LDAPCtx.ATTRIBUTES_BINARY,"gifPhoto fingerPrint")

The second method for handling binary attributes is recognition of the binary description option

supported by some V3 servers. When a ;binary is appended to the attribute name (such as,

jpegPhoto;binary) it is designated a binary value. The toolkit recognizes a binary attribute description

option when bound as a V3 user.

114 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[

[[[

[

[

[[[[[[

[[

[

[

[

[

[

[

[

[

[

[

[

[

[

[

[

[

[

[

[[

[

[

[[[[

Page 127: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Finally, the IBM JNDI LDAP Provide attempts to convert any attribute which is not defined as binary and

does not contain the binary attribute description option. If the conversion fails, the data is instead

returned as binary. However, the programmer should not rely on this working (it is possible to have non

UTF-8 data incorrectly converted).

Schema

Using this class library it is possible to retrieve, view and update an LDAP server’s schema structure.

Only servers which provide schema information defined by the Lightweight Directory Access Protocol

(v3) document are supported.

To retrieve a server’s schema, use the method getSchema(). The returned schema is represented as a tree,

where each sub-tree is a different component of the schema. The IBM JNDI LDAP Provider can parse the

following schema components:

v AttributeTypes, stored under sub-tree AttributeDefinition

v Object Classes, stored under sub-tree ClassDefinition

v Syntax Descriptions, stored under sub-tree SyntaxDefinition

v Matching Rules, stored under sub-tree MatchingRule

v IBM Attribute Types, stored under sub-tree IBMAttributeDefinition

The content of the entries, excluding IBMAttributeDefinition, have a one to one correspondence with the

schema defined in the Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions document.

IBMAttributeDefinition extends an attribute schema to hold IBM specific information. It is defined with

the following BNF:

IBMAttributeTypesDescription = "(" whsp

numericoid whsp

[ "DBNAME" qdescrs ] ; at most 2 names (table, column)

[ "ACCESS-CLASS" whsp IBMAccessClass whsp ]

[ "LENGTH" wlen whsp ] ; maximum length of attribute

[ "EQUALITY" [ IBMwlen ] whsp ] ; create index for matching rule

[ "ORDERING" [ IBMwlen ] whsp ] ; create index for matching rule

[ "APPROX" [ IBMwlen ] whsp ] ; create index for matching rule

[ "SUBSTR" [ IBMwlen ] whsp ] ; create index for matching rule

[ "REVERSE" [ IBMwlen ] whsp ] ; reverse index for substring

whsp ")"

IBMAccessClass =

"NORMAL" / ; this is the default

"SENSITIVE" /

"CRITICAL" /

"RESTRICTED" /

"SYSTEM" /

"OBJECT"

IBMwlen = whsp len

Schema definitions returned by the server, but unsupported by this class library, are saved but not

parsed. These entries contain exactly two attributes, one with an objectclass equal to the schema type

name (for example, objectclass=adddef) and another with the list of values. Unsupported schema

definitions may be viewed but not updated.

The following example retrieves the entire schema tree:

DirContext schemaCtx = ctx.getSchema("");

SearchControls cons = new SearchControls();

cons.setSearchScope(SearchControls.SUBTREE_SCOPE);

NamingEnumeration ne = schemaCtx.search("",

"(|(NUMERICOID=*)(objectclass=*))", cons);

The following example retrieves the schema for attribute cn:

Developing applications 115

[[[[

[

[[[

[[[

[

[

[

[

[

[[

[[

[[[[[[[[[[[[[[[[[[[

[[[[

[

[[[[[

[

Page 128: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

DirContext schemaCtx = ctx.getSchema("");

Attributes attrs = schemaCtx.getAttributes("AttributeDefinition/cn");

The following example attempts to add a schema definition for a new object class:

DirContext schemaCtx = ctx.getSchema("");

BasicAttributes attrs = new BasicAttributes();

attrs.put("NAME", "javaObject");

attrs.put("NUMERICOID", "1.3.6.1.4.1.42.2.27.4.2.2");

Attribute may = new BasicAttribute("MAY");

may.add("javaClassName");

may.add("javaSerializedObject");

attrs.put(may);

attrs.put("DESC", "Serialized Java object");

attrs.put("AUXILIARY", "true");

attrs.put("SUP", "top");

schemaCtx.createSubcontext("ClassDefinition/javaObject", attrs);

The com.ibm.jndi.LDAPSchemaCtx class has been specially extended to work with schema definitions from

a file. Two public constructors support reading schema information from a disk, one takes as an

argument a single filename and the other an array of filenames. The method dumpSchema() saves the

schema definition to a file. The following demonstrates this support:

LDAPSchemaCtx ctx = new LDAPSchemaCtx("schema.file");

ctx.dumpSchema("schema.sav");

Conformance Issues / Additional Properties

The following known differences exist between the IBM JNDI LDAP Provider and Sun’s ″JNDI

Implementor Guidelines for LDAP Service Providers (Draft 0.2)″.

v Naming federation is not supported

v Passing URL components beyond what is needed does not result in either a ConfigurationException or

an InvalidNameException

v The toolkit only supports storage and retrieval of Serializable Java objects, it does not automatically

support objects of type Reference or Referenceable. Also, the toolkit does not use the methods

DirectoryManager.getStateToBind or DirectoryManager.getObjectInstance to convert objects

v The toolkit provides its own SASL plug-in support; it does not support the Java SASL API because the

API currently exists as a preview-only package

v The toolkit supports unsolicited notification events but not namespace or object change events

v The toolkit ships its own SSL support which does not conform to Sun’s SSL interface specification

v The default value for java.naming.referral is follow, not ignore. Also, when this property is set to

ignore the toolkit does not automatically add the ManageDSAIt control to requests nor does it throw a

PartialResultException when a referral is received.

In addition to the properties defined elsewhere in this document, the following property is also

supported:

v com.ibm.jndi.ldap.so_timeout: Defines the number of milliseconds a context will block waiting for

data from a server. The default timeout is 5 minutes. A timeout of zero is interpreted as an infinite

timeout.

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.

116 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[

[[[[[[[[[[[[

[[[[

[[

[

[[

[

[[

[[[

[[

[

[

[[[

[[

[[[

[

Page 129: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 325.

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 com.ibm.eswe.workbench.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.

Developing applications 117

Page 130: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Title Bar

Menu Bar

Main Data Area

Status Bar

Toolbar/Coolbar

Sidebar

Open View View View

Figure 3. User interface organization

118 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 131: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

Sidebar: A sidebar provides a means for end users to multi-task or work with other applications while

working in a single application. For example, users can chat with someone on their buddy list or check

their calendar while viewing mail in the main window. The shelf views may vary based on what the user

is doing such that relevant views are seen alongside the application in which the user is working. These

views are first generated when an application is open. As the user switches between applications, the

views are updated to ensure that the relevant panels are on display. When the user closes all applications,

the views are removed and the sidebar disappears. A sidebar is only shown when there is at least one

application open in the main area, and at least one visible shelf panel.

Each sidebar can be resized and put into different “modes.” There are three modes the sidebar can be in:

open/expanded, thin, and closed/collapsed. This allows users to benefit from the shelf views without

having the shelf views be obtrusive. Users can adjust the width of the sidebar by dragging the vertical

sash that separates the sidebar from the rest of the client. Users can also instantly collapse and expand

the sidebar by clicking on the collapse bar located in the middle of that sash, where an arrow is

Developing applications 119

Page 132: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

displayed that points in the direction in which the sidebar will collapse or expand. In addition, the View

menu at the top of the window has options to change the mode of the sidebar.

When in “open” mode, users can collapse and expand each individual shelf view, or resize the shelves.

Users can also rearrange the shelves by dragging and dropping, and add or remove the shelves by

selecting or deselecting the panels from the View > Sidebar Panels menu. If the sidebar sash is dragged

such that the width becomes small enough, the sidebar will go into “thin” mode. When in thin mode,

only the icons can be seen. A click on an icon of an application will expand the view both vertically (if

the shelf is collapsed) and horizontally. When the sidebar is in “collapsed” mode, none of the shelves can

be seen, and the only thing remaining is the sash and collapse bar facing the opposite direction to allow

the user to expand the sidebar again.

The following preference can be used by deployers in their plugin_customization.ini file to turn off

sidebar completely in their product.

com.ibm.rcp.ui/SHELF_VISIBLE=false

Application Launcher: The Launcher is represented in the user interface as a button labeled Open. It is

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.

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

120 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 133: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 such as 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.

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.

Developing applications 121

Page 134: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

122 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 135: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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

Developing applications 123

Page 136: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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:

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;

}

124 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 137: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 the services available, an event sequence, or the life cycle that

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:

rcplauncher -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. There are two ways to create a personality – you can either build one from scratch or

you can extend an existing personality.

Creating a personality from scratch: To create a personality from scratch, use the following procedure:

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);

}

public void createWindowContents(final Shell shell) {

Developing applications 125

Page 138: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

// Create your layout and menus here. See Eclipse documentation

// for details on WorkbenchWindowAdvisor.createWindowContents

}

public void postWindowOpen() {

super.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"

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.

Extending an existing personality: To create a personality based on an existing personality, do the

following:

1. Create a class that extends the personality you want to extend. For example, if you want to extend a

personality defined by ParentPersonalityWorkbenchWindowAdvisor and want to change it so that the

Menubar, Toolbar and Status line do not display, and you want to set its shell bounds, then you

would do the following:

126 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 139: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

public class ChildPersonalityWindowAdvisor extends ParentPersonalityWorkbenchWindowAdvisor {

private IWorkbenchWindow window;

public ChildPersonalityWindowAdvisor(IWorkbenchWindowConfigurer configurer) {

super(configurer);

setShowMenuBar(false);

setShowToolBar(false);

setShowStatusLine(false);

}

public void postWindowCreate() {

window = getWindowConfigurer().getWindow();

Shell shell = window.getShell();

Rectangle bounds = shell.getBounds();

shell.setBounds(bounds.x, bounds.y, 300, 700);

}

}

2. Create a factory class and define your extension as documented in “Creating a personality from

scratch” on page 125.

The extension point startBundles enables defining a set of bundles that should be associated with a

Personality.

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 503.

Lifecycle events

The events in the startup lifecycle in a personality are:

v fillActionBars

v createWindowContents

v postWindowCreate

v preWindowOpen

v postWindowOpen

Once postWindowOpen completes, the 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

Developing applications 127

Page 140: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

CreateActionBarAdvisor method, and instantiates DefaultActionBarAdvisor. DefaultActionBarAdvisor

overrides the fillActionBars method, and calls the actionBuilder.fillCoolBar and

ControlSetHelper.getInstance().fillCoolBar methods in it.

Contributing to the sidebar

This section discusses the “shelfViews” programming model, and explicitly explains how to contribute a

shelf view to the Lotus Expeditor sidebar. There are basically two steps:

1. Create a view and add a contribution to the org.eclipse.ui.views extension point.

2. Contribute the view to the com.ibm.rcp.ui.shelfViews extension point to have it appear in the

sidebar.

“shelfViews” Programming Model: Lotus Expeditor makes use of the eclipse IViewPart interface to be

able to tie each shelf view to the workbench. Each view part has a view site that connects it to the

workbench, allowing the view to register any global actions with the site’s action bars, including access to

its own panel menu, a local toolbar, and the status line. The view can also register any context menus

with the site, or register a selection provider to allow the workbench’s ISelectionService to include the

part in its tracking.

When creating a view to be shown in a Lotus Expeditor shelf view, the class should either implement the

interface, org.eclipse.ui.IViewPart, or subclass the abstract class, org.eclipse.ui.part.ViewPart.

Subclassing ViewPart is the suggested method, to save the developer from implementing the view from

scratch. Subclasses of ViewPart must implement the following methods:

v createPartControl(Composite parent) – to create the view’s controls

v setFocus() – to receive focus

After creating the class, a contribution to the org.eclipse.ui.views extension point must be added to the

plugin.xml file for the plug-in, as seen in the following example:

<extension point="org.eclipse.ui.views">

<view

name="Sample View"

icon="icons/sample.gif"

class="sample.views.SampleView"

id="sample.views.SampleView">

</view>

</extension>

Make sure the following attributes are specified:

v The name attribute describes the String to be displayed in the titlebar.

v The id attribute is the unique identifier of the view. This is also what is used to refer to the view when

contributing to the shelfViews extension point.

v The class attribute specifies what class is referenced in this extension.

v The icon attribute describes the icon to be displayed in the top left corner of the titlebar. The standard

size is 16x16 pixels.

The view should be optimally viewed in a frame approximately 186 pixels wide. The view is also

resizeable. Thus, make sure the content can be scrolled (if applicable), and any toolbars do not get cut off,

or have chevrons pointing to more actions.

Contributing to the shelfViews extension point: In the plugin where the view is defined, add an

extension to the com.ibm.rcp.ui.shelfViews extension point as demonstrated in the following example

taken from the shelfView.exsd schema file:

<pre>

<!-- first define view -->

<extension point="org.eclipse.ui.views">

<view

name="Sample View"

128 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 141: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

icon="icons/sample.gif"

class="sample.views.SampleView"

id="sample.views.SampleView">

</view>

</extension>

<!-- next, define shelf view -->

<extension point="com.ibm.rcp.ui.shelfViews">

<shelfView

id="SampleViewShelf"

view="sample.views.SampleView"

region="MIDDLE"

page="RIGHT"

showTitle="true"/>

</extension>

</pre>

<!-- notice that the com.ibm.rcp.ui.shelfViews "view" attribute corresponds

to an org.eclipse.ui.views "id" attribute -->

Note that the com.ibm.rcp.platform.shelfViews extension point has been deprecated.

The id attribute uniquely identifies the shelf view. Thus, if the same id is used more than once, only one

of those views will be registered.

The view attribute corresponds to the id specified in the view contribution.

The region attribute is an optional means of describing what area of the sidebar the view should belong

to. Possible values are “TOP,” “MIDDLE,” and “BOTTOM.” Items within the same placeholder region

will be ordered based on when the view gets loaded. Thus, the contributor of the view cannot control the

placing of views within the same placeholder region. If nothing is specified, the view will automatically

be placed on the bottom.

The page attribute describes which sidebar the view should belong. For Lotus Expeditor, the value

“RIGHT” should be specified such that the view appears in the sidebar on the right side of the client.

The showTitle attribute describes whether or not the titlebar should be shown. For Lotus Expeditor, a

value of “true” should be specified such that all views in the sidebar have a titlebar and look uniform.

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.

There are two methods to lay out components of a composite application. The first method is to use the

composite application composition user interface offered by WebSphere Portal Server. This document

refers to that type of composite application as ″Portal-hosted″. The second method to lay out components

of a composite application is used when WebSphere Portal is not available, and involves

programmatically laying out the components in an Eclipse perspective. More details for these two

methods are included in later sections.

Building composite applications using Portal UI

Portal-hosted composite applications are created from composite application templates which are either

blank (no components) or contain existing components. These templates are created using the WebSphere

Portal Templates feature.

Developing applications 129

Page 142: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Refer to the composite applications topic in the WebSphere Portal Express 6.0 Information Center.

Note: In WebSphere Portal, the visual components are referred to as “portlets”. Because Lotus Expeditor

makes composite applications of more components than just portlets, you must wrap all those

non-portlet components as proxy portlets. To perform this kind of functionality, you must install

Lotus Expeditor NCI to extend WebSphere Portal server capabilities to manage Lotus Expeditor

clients. For more information on Lotus Expeditor NCI, refer to Assembling and Deploying Lotus

Expeditor Applications For more information about installing the NCI component into Portal, refer

to Installing with the Network Client Installer. In the “Sample composite application project”

section below, the basic steps of wrapping non-portlet components as proxy portlets are described.

Additionally, you must have any portlets that you wish to project in the Expeditor runtime

wrapped in a Client Services plug-in – the Lotus Expeditor toolkit can convert existing portlet

projects and existing WAR filess to a Client Services plug-in.

When the portlets you want to include in the composite application are available on the portal, you can

begin creation of a Portal-hosted composite application in one of two ways, either by using the

WebSphere Portal user interface or the Lotus Expeditor user interface. To view a list of existing composite

applications hosted by a specific WebSphere Portal server and create new composite applications using

the Lotus Expeditor user interface, you must set the Home Portal Account preference in Lotus Expeditor.

Once you have set this preference, Lotus Expeditor associates with the WebSphere Portal server set in the

preference. You can find more detailed information in the section, Specifying a home portal page in the

Lotus Expeditor Information Center.

To create composite applications using the WebSphere Portal user interface:

1. Open a browser to the Portal and log in.

2. Click Templates from the main Launch menu of the Portal user interface.

3. Go to the Application Library tab and select the New button.

4. A list of composite application templates to displays. You will use these as a starting point.

For complete information about using the WebSphere Portal user interface to create composite

applications, refer to composite applications.

To create composite applications using the Lotus Expeditor user interface:

1. Launch and log into Lotus Expeditor.

2. Click Portal Applications from the main Launch menu.

Note: This link will only appear if the Home Portal Account preference has been set.

3. The Portal applications catalog opens. Click New to begin.

Note: When you create a composite application using Lotus Expeditor, it is also created on the remote

Portal.

There are two different types of components, which can be part of a composite application: a portlet

application which can only be rendered on the Portal but not in Lotus Expeditor (an error message is

shown in a placeholder view within the composite application) or a portlet application which can be

successfully rendered on both Portal and on Lotus Expeditor. For instructions on creating a component

that can be successfully rendered on both Portal and Lotus Expeditor, please refer to “Developing Portlet

applications” on page 228.

Building a composite application programmatically in Eclipse

You can lay out components of composite applications in an Eclipse perspective. Use this method when

WebSphere Portal is not available.

130 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 143: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Refer to the IBM Redpaper at the following URL for information on developing composite applications

using Eclipse: http://www.redbooks.ibm.com/abstracts/REDP4241.html?Open

Accessing topology meta data

Each component specified in the composite application topology layer can contain a number of

name/value pairs called preferences. These are not to be confused with user preferences or client

preferences.

To retrieve these values on the client you need to use the TopologyHandler service and the key for the

preference you want to retrieve. An alternate method for retrieving the topology meta data for a

component is through the Eclipse Extension Registry API. Each component meta data set is packaged as

an eclipse extension which extends the com.ibm.rcp.topologyhandler.components extension point. This

allows consumers to listen for registryChanged events and to respond to the data changes accordingly.

Components, views, and preferences

A component (in this context) refers to an entity that exists within a portal defined application page. On a

portal page a portlet is a component. In Eclipse, there are views that exist within a perspective, the

Eclipse equivalent to a portal page in a composite application. The preferences for components are the

underlying points of variability for a portlet. Serialized as XML these preferences look like the following:

<preference name="launcherPath">

<base:value value="/" readOnly="false" xsi:type="base:String" required="false" />

</preference>

<preference name="autoStart">

<base:value value="false" readOnly="false" xsi:type="base:String"

required="false" />

</preference>

An administrator, application assembler, or developer can set this data, which could be consumed by the

desktop client code and manipulated as desired. The following sections provide some sample client side

code illustrating how to retrieve the data and use it within your applications.

TopologyHandler service and the OSGi framework

The TopologyHandler is a registered OSGi service. To retrieve the service you should include code like the

following:

Activator.context = context;

Above is the BundleContext object from your bundle/plug-in activator.

ServiceTracker tracker =

new ServiceTracker(

context, TopologyHandler.class.getName( ), null);

tracker.open( );

TopologyHandler handler = (TopologyHandler )tracker.getService( );

Be sure to check for a null handler in dynamic environments where components are installed and

uninstalled on a frequent basis. You can get a list of application unique identifiers by calling the

following method on the TopologyHandlerService:

String[] guids = handler.getApplicationGUIDs();

You can use the findPage() API to find a specific page within the composite application. If you started

with a page alias (supplied by an action to your component, for example) you can create a page criteria

and invoke the findPage() method. The following code attempts to find the page in the specified

Composite Application of the preference com.ibm.rcp.alias = my.alias.name.

Developing applications 131

[[[[

Page 144: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Map criteria = new HashMap( ); criteria.put("com.ibm.rcp.alias" , "my.alias.name");

Page p = (Page )handler.findPage(appId, criteria);

This retrieves the first page within the given Composite Application that matches the criteria passed in

through the map. Once you obtain the Page object, you can then call Page.getPerspective(), which

provides the perspective ID for that page object and allows you to open it using the Eclipse workbench

API.

The TopologyHandler interface allows for gaining access to the ComponentData interface for component

meta data. To do this you would do the following:

ComponentData cd = handler.getComponentData(id);

String[] values = cd.getPreference("my.preference.key");

Each call to getPreference returns an array of String values because it is possible that a preference

contains multiple values. If your preference contains only a single value you need only be concerned with

the first element in the array. The ‘id’ parameter shown above is the object ID of the component that

defines the preference. If your implementation resides within an Eclipse view part, you can simply use

the secondaryID of the viewpart as the object ID. Otherwise, if you do not know the component ID you

must use the TopologyHandler APIs to traverse through the components for the page you desire. To

accomplish this you can use something similar to the following example:

Navigation tree = handler.getApplicationNavigationTree(appID);

The navigation tree returned from this method returns a composite element that contains all of the pages

and labels for the application. Only pages can contain components. When you have found the desired

navigation element, you must type cast it to a Page object. The Page interface allows for the retrieval of

all component IDs contained by the page.

String[] components = thePage.getComponents( );

For (int i = 0; i < components.length; i++) {

ComponentData cd = handler.getComponentData(components[i]);

// Process component data here

String[] values = cd.getPreference("my.preference.key");

// Manipulate data

}

If your implementation resides within an Eclipse view part, you can simply use the secondaryID of the

viewpart as the object id or you can pass in the full view instance ID of the format <view

id="">:<secondary view="">.

The following sample illustrates using the SWTHelper located in the property broker component:

/** Initial list of URL links. */

String[] baseURLs = new String[] {

"http://www.ibm.com"};

/*

* This code reads any additional URLs that are defined as portlet

* preferences. That is one mechanism for projecting data items

* to the client from the server.

*/

if (handler != null){

ComponentData data = handler.getComponentData(SWTHelper.getFullViewID(_this));

if (data != null) {

int index = 1;

while(true){

String[] urldata = data.getPreference("urls_" + index++);

if (urldata != null && urldata.length > 0){

132 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[[[[

Page 145: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

String[] newArray = new String[ urldata.length + baseURLs.length];

System.arraycopy(baseURLs, 0, newArray, 0, baseURLs.length);

System.arraycopy(urldata, 0, newArray, baseURLs.length, urldata.length);

baseURLs = newArray;

}

else

break;

}

}

}

return baseURLs;

The following sample illustrates using the secondary ID:

ComponentData viewData = handler.getComponentData(getViewSite( ).getSecondaryId( ));

if (viewData != null) {

String[] title = viewData.getPreference("com.ibm.rcp.title");

if (title.length != 0)

setPartName(title[0]);

else

setPartName(viewData.getId( ));

}

Using the Eclipse extension registry API

An alternate method to retrieve component level data is through the Eclipse Extension Registry. To do

this you can implement the code similar to the example shown below.

The following example demonstrates retrieving a title preference and a custom preference for a

component through the Eclipse Extension Registry API. It is setting the part name for the view to the title

and a text field to the custom preference my.preference.welcomeText. The extension ID is equal to the

objectID of the component that contains the preferences.

IExtensionRegistry reg = RegistryFactory.getRegistry( );

IExtensionPoint point =

reg.getExtensionPoint( "com.ibm.rcp.topologyhandler.components");

IConfigurationElement config = null;

IExtension[] extension = point.getExtensions( );

for (int i = 0; i < extension.length; i++) {

if (extension[i].getSimpleIdentifier().equals(id))

config = extension[i].getConfigurationElements()[0];

}

if (config != null) {

String title = config.getAttribute("com.ibm.rcp.title");

Text text = new Text( parent, SWT.BOLD);

String welcomeText =

config.getAttribute("my.preference.welcomeText");

if ( welcomeText != null) {

text.setText( welcomeText);

this.setPartName( title + " Portlet");

}

}

Sample composite application project

This topic provides a list of steps that you must complete to create a composite application project which

is made up of an SWT view component and a portlet component.

Developing applications 133

Page 146: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

We will also discuss how to define the rich client properties on the Portal UI as a step in assembling the

composite applications on WebSphere Portal and then provisioning the application on the Lotus

Expeditor client.

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 Lotus ComponentDesigner

v Eclipse

v Eclipse Web Tools Platform (WTP) project, which extends the Eclipse platform with tools for

developing Java EE Web applications.

Creating an SWT view component

The SWT component view consists of an Eclipse plug-in containing one or more views and, optionally, a

corresponding ’dummy’ portlet to represent each of the views on the server side. This example focuses

on creating just one view.

If you want to have portal management of your view, you must perform the procedure found in the

section “Creating a dummy portlet” on page 136.

To create an SWT component view, complete the following steps:

1. Create an Eclipse plug-in project to contain your view.

The view can be bundled into an existing plug-in. However, all views in a single plug-in share the

same definitions for properties and actions. In most circumstances it is best to have one view per

plug-in.

2. Using an Eclipse-based development tool, create a view in the new plug-in.

This involves creating a class that extends the ViewPart class, and adding in an org.eclipse.ui.views

extension point. In the class attribute, reference the Java class you created, give it a unique ID, and a

descriptive name. For components, the allowMultiple attribute must be set to true.

3. Some views will publish properties as their values change. Your Eclipse view can publish a property

by using the SWTHelper (com.ibm.rcp.propertybroker.swt.api.SWTHelper) class. This helper class

removes the complexity of identifying the View instance the property came from by having the caller

simply pass in a this pointer to the view:

PropertyValue value = PropertyFactory.createPropertyValue(prop, value); SWTHelper.changedProperties(new PropertyValue[]{value}, this);

4. Some views will consume actions:

v SWT based views should create a handler class that implements the IAction

(org.eclipse.jface.action.IAction) interface.

Implement the runWithEvent() method in your handler. The event passed into this method is of

type Event (org.eclipse.swt.widgets.Event) and implements the PropertyChangeEvent

134 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 147: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

(com.ibm.rcp.propertybroker.event.PropertyChangeEvent) interface. 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 PropertyChangeEvent finalEvent = (PropertyChangeEvent)event;

//get name and value of 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());

...

}

}

The SWT component should use the SWTHelper class to publish its properties as described above in

step 3.

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.

v Core Eclipse commands that are non-SWT based should implement the IHandler

(org.eclipse.core.commands.IHandler) interface.

Use this interface if your application cannot 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 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 PropertyChangeEvent pce = PropertyChangeEvent)event.getTrigger();

//get name and value of event

...

}

}

Note: Your component should implement either IAction or IHandler, but not both.5. To enable view-to-view communication, register your action with the broker by extending the

com.ibm.rcp.propertybroker.PropertyBrokerAction extension point.

6. 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.

Developing applications 135

Page 148: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

7. Create an Eclipse Update Site project and import your feature, 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.

Creating a dummy portlet:

To enable portal management of your view, you must first create a dummy portlet.

To do so, perform the following procedure:

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 you want to make available. For more information, see

“Defining actions and properties” on page 427. 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 Input parameters:

– 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>

</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"/>

136 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 149: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

</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>

The following are Lotus Expeditor specific steps, and may not be applicable depending on your

development platform.

3. Return to the SWT view portlet. 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 update.

4. Verify the portlet’s installation by searching for it from Portlet Management > Portlets.

5. Navigate to Templates > Application, create a new application, and make the following edits:

v From the Content tab, define the layout for the application and add the portlet to the page.

v From the Rich Client tab, select This portlet represents an SWT view on the rich client, then type

the ID of the SWT view plug-in into the Eclipse view id field.

v From 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 (wires that

open an event in a second page), you must designate them as global actions. To do so, select

Manage Actions and then click the Global check box.

Enhancing the sample by adding 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 an SWT view component” on page 134 before you can perform

the steps below.

To create a portlet component, complete the following steps:

1. Using an Eclipse-based development tool that supports portlet development, 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.

Developing applications 137

[[[

Page 150: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

3. Using Rational Application Developer or the Java EE 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.

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 action, 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.

Defining the Rich Client properties on the Portal UI

This section explains how to define the respective Rich Client properties for the composite application in

the Portal UI in order for the application to be accessed on the Lotus Expeditor client. Note that these

steps are important when your composite applications are being assembled on the Portal and then

accessed on the Lotus Expeditor client.

There are a few pre-requisite steps needed for this section:

1. Install the Network Client Installer component into your WebSphere Portal server platform. Refer to

Installing the Network Client Installer.

2. Create your SWT components and generate the deployable plug-in bundles in the form of an update

site. The SWT components should be represented in Portal in the form of dummy portlet (or proxy

portlet). The dummy portlet should be deployed and assembled in the Sample composite application

on Portal. Refer to “Creating an SWT view component” on page 134 for information on completing

these steps.

3. Create your portlet component(s) and generate the deployable plug-in bundles in the form of an

update site. The portlet component(s) should be deployed and assembled in the Sample composite

application on Portal. Refer to “Enhancing the sample by adding a portlet component” on page 137

for information on completing these steps.

Next, we’ll define the Rich Client properties on the Portal UI:

1. Login to the Home Portal page in your Portal Server. From the Templates > Application page, open

the Sample composite application.

2. Select the composite application page and open the page action list. Select Edit Page Layout.

138 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 151: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Note: At this point, it is assumed you have both assembled your component into a sample

composite application on the Portal Server and wired the components together.

3. Click on the Rich Client tab to open the Rich Client Administration page. Here, you will define the

Rich Client properties for your composite application to make it rich client friendly.

4. Under the Page Properties section, select the properties you wish to enable when your composite

application runs in the rich client Lotus Expeditor client. For example, selecting the Add to the

launcher option adds your application icon on the launch menu when you start the Lotus Expeditor

client. Click OK to save your settings.

5. The Portlets section contains a list of all the portlet components that are part of your composite

application. Edit the instance properties for the portlets by selecting the pencil icon.

6. Navigate to the Rich Client Properties section. Provide the Eclipse SWT view ID or the Portlet

context root value for the component that you have selected. If it is an Eclipse SWT component, then

provide the view ID for your SWT component (you can find the view ID for your SWT component

in the plugin.xml file). If it is a portlet component, then provide the context root value for your

portlet project (do not include the portlet name). Click OK to save your settings.

7. Navigate to the Feature requirements section and click Add to specify the feature and update site

information to show the component in the Lotus Expeditor client. Provide the feature ID, its version

and the matching rule needed. Then provide the Eclipse update site that provides the feature. Click

Done to save your settings.

8. Navigate to the Layout Properties page to provide the settings for the layout of the application on

the Lotus Expeditor client.

9. Repeat steps 6-8 for all portlet components that are part of the composite application.

10. Save all your changes in the sample composite application.

Using the steps above, you have now defined the rich client properties for all the components of your

composite application. These properties are needed to access and render your Sample composite

application components on the rich client friendly Lotus Expeditor client.

Finally, we’ll open the Lotus Expeditor client and provision and install our Sample composite application

from the Portal server:

1. Open the Lotus Expeditor client.

2. Select Open > Portal applications.

3. Select the Sample composite application from the application catalog and launch it. You can also

Synchronize your Lotus Expeditor client with the Portal server. Please remember that your Home

Portal account settings are specified in your Lotus Expeditor client.

Creating multiple SWT components in an Eclipse plugin

This section explains how you can create several Property Broker actions within a single Eclipse plug-in.

There are situations where you might want multiple composite application components in a single

Eclipse plug-in. The Lotus Expeditor extension point, PropertyBrokerDefinitions, can account for this.

The sample below illustrates how you can use the map element of the extension to provide a certain

number of actions within a single plug-in.

The sample has two components defined in a single extension and contained in the same WSDL

(wsdl/tester.wsdl). You can map a specific action name in the WSDL with a new name to be registered

in the broker. The sample uses the same name for both. The owner of the actions is assigned as the

respective View ID. This declares the View ID as the SWT_ACTION’s owner, and will be registered as such

when the extension is processed.

Sample View Extension

Developing applications 139

Page 152: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

One key point to recognize is for a composite application the views are added to the Eclipse perspective

in a generic manner. This means the view must be configured to allow for multiple instances of the view.

You can specify this in the view extension by assigning the allowMultiple attribute to true.

<extension

point="org.eclipse.ui.views">

<view

allowMultiple="true"

class="com.ibm.rcp.samples.propertybroker.selector.View"

id="com.ibm.rcp.samples.propertybroker.selector.view"

name="URL Selector View">

</view>

</extension>

Sample Property Broker Definitions Extension

<extension

id="PBTesterTargetID"

point="com.ibm.rcp.propertybroker.PropertyBrokerDefinitions">

<handler

file="wsdl/tester.wsdl"

type="SWT_ACTION">

<map

actionId="setText"

class="com.ibm.rcp.propertybroker.tester.actions.TargetAction"

owner="com.ibm.rcp.propertybroker.tester.views.TargetView"

wsdlActionName="setText"/>

<map

actionId="sendText"

class="com.ibm.rcp.propertybroker.tester.actions.SendTextAction"

owner="com.ibm.rcp.propertybroker.tester.views.TestView"

wsdlActionName="sendText"/>

</handler>

</extension>

Sample WSDL

<definitions name="TargetPBTestService"

targetNamespace="http://com.ibm.propertybroker.standardtypes"

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://com.ibm.propertybroker.standardtypes"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

<types></types>

<message name="InMessage">

<part name="textIn" type="xsd:string"/>

</message>

<message name="OutMessage">

<part name="textOut1" type="xsd:string"/>

<part name="textOut2" type="xsd:string"/>

<part name="textOut3" type="xsd:string"/>

<part name="textOut4" type="xsd:string"/>

</message>

<portType name="SetTextService">

<operation name="SetTargetTextOperation">

<input message="tns:InMessage"></input>

</operation>

<operation name="SendTextOperation">

<output message="tns:OutMessage"></output>

</operation>

</portType>

<binding name="PBTartgetBinding" type="tns:SetTextService">

140 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 153: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<portlet:binding/>

<operation name="SetTargetTextOperation">

<portlet:action name="setText"

type="standard"

caption="Sets text in a window"

description="This action sets text in a window"

actionNameParameter="ACTION_NAME"/>

<input>

<portlet:param/>

</input>

</operation>

<operation name="SendTextOperation">

<portlet:action name="sendText"

type="standard"

caption="Sends text out"

description="This action sends out text"

actionNameParameter="ACTION_NAME"/>

<output>

<portlet:param/>

<portlet:param/>

<portlet:param/>

<portlet:param/>

</output>

</operation>

</binding>

</definitions>

Displaying multiple pages in one tab

A composite application that has multiple pages can have the pages displayed in one tab. This is

achieved through the following attribute:

com.ibm.rcp.useNavigator = ’true’

Note: If this attribute is not present and the composite application has multiple pages, then the default

value is ’true’.

Setting this attribute shows the default navigator (which displays the pages in a tree style) on the left side

of the client.

Along with the com.ibm.rcp.useNavigator attribute, the following attribute can be used to specify

whether the application should have its own navigation model or use the default navigator:

com.ibm.rcp.navigationModel = ’custom’

If the above attribute is not present or the value is not set to ’custom’, then the default navigator displays

the pages. Otherwise, the application must provide a user interface for navigating through the pages in

the application.

Creating a custom navigator for composite applications, for 6.1.1

To obtain a custom look and feel, developers may desire to create a custom navigator to move between

the pages of their composite applications, instead of using the default navigator. Creating a custom

navigator gives you the following advantages:

v Options to change the look and feel of the navigator

v Options to change the screen location of the navigator

v Extended options to control visibility

v Can be arranged similarly to other components, to conserve and maximize work space

Developing applications 141

[

[[[

[

[

[

[

Page 154: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Can interact and communicate with other components

Composite Application Infrastructure, Topology, and Navigation page hierarchy

and preferences

In order to create a custom navigator for composite applications, you should have a high level

understanding of the underlying data structure for composite applications. Composite applications

consist of one or more application pages, grouped together in a hierarchy. At the top of the hierarchy is

the root page. The root page does not appear within the Composite Application Editor (CAE), and you

cannot switch to it or add components to it. However, it is provided through the Topology Handler as a

consistent starting point to group top level pages. These top level pages, in turn, can be containers for

other child pages, and so on for as many levels as required.

Clients can access the page hierarchy model through the TopologyHandler service. The TopologyHandler

provides an API to both the hierarchical page model and the components within each page. Each page

and component within an application can contain any number of name/value pairs representing

meta-data for the object. For more information on accessing the TopologyHandler service, refer to “Using

the TopologyHandler service” on page 143.

Lastly, when creating a custom navigator, you will need to configure some application and page

properties in order to emulate some of the original functionality of the default navigator. The properties

tell the underlying composite application infrastructure that you are overriding the default navigation

system. First, from the Advanced page properties settings window in the Composite Application Editor,

set com.ibm.rcp.navigationModel as ″custom″ and com.ibm.rcp.useNavigator as ″true″ . This makes each

perspective show in the same tab. By default, these application page settings display each page of your

composite application in the same tab. For any page you want displayed in a separate tab, set

com.ibm.rcp.useNavigator to ″false″ for that page’s properties.

Custom navigator layout and design

It is possible to create a custom navigator that has a look and feel that supports your workflow. This

allows you to programmatically discover the pages in an application, and to switch between those pages.

The options displayed are driven by properties set on the custom navigator component. However such a

component must be created or otherwise acquired.

You should consider what type of user interface best suits your application. Does it have its own look

and feel? Do you want to try to copy another application’s look and feel that works cooperatively with

your component? Or do you need to merge it seamlessly with your operating system? Some ″navigators″

might have no UI at all.

For example, the breadcrumb navigator outlined in a later section is more than just a JFace viewer that

shows the navigation hierarchy. It is actually a hybrid view with two components on it - a Home button,

and a Sibling Button Navigator. The component is created in two basic levels - a view and a widget. The

view contains the Home button and also contains the JFace viewer for the current pages’ siblings. As a

result, this is not simply a basic component that relates to the navigation, but rather a custom UI

component that can be define in a variety of ways. You can add other buttons and widgets to the view,

and from the views perspective the button navigator is just another widget in its space.

The code for the view aspect is straightforward. You create the button, create the viewer, and then simply

initialize the viewer with the Navigation element for the current perspective. “Sample one” on page 146

contains an example.

The topology handler service is used to set the JFace viewer with its input; in this case, a navigation

element of the current Eclipse perspective. The button viewer (inside setInput) uses the ContentProvider

to acquire its parent, then all of its parent’s children (including itself). Given that information, the viewer

simply creates a button for each of its siblings and itself.

142 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[[

[[[[[[[

[[[[[

[[[[[[[[

[

[[[[

[[[[

[[[[[[[

[[[

[[[[

Page 155: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The component model for Composite Applications is at the view layer. As a result, any properties you

want to pass on to widgets would be defined and handled at the view part layer. The view part would

then consume those properties (which would be filled in using the CAE) and set the different fields on

the underlying widgets it contains.

Using page alias names in a custom navigator

When using a custom navigator, you may want to designate a page alias for the pages within your

navigator model. This can be done both from portal and within the Composite Application Editor (CAE)

tool. From within the CAE, select a page in the page hierarchy, edit the page properties under the

Advanced section, and add the preference com.ibm.rcp.alias. You can then choose what you want the

page alias to be. For WebSphere Portal based composite applications, the NCI Rich Client Layout Admin

Portlet provides a field for you to enter the page alias name for the page. Once you set your alias name,

the TopologyHandler service can be used to find a page within a composite application based on certain

criteria. The API to accomplish this exists in the TopologyHandler service interface, as shown in “Sample

two” on page 146.

The criteria is a Map object containing name/value pairs used to locate a given page object. The map can

contain any number of name/value pairs you wish. If the criteria specified matches that of more than one

page, the first page found will be the object returned.

With Lotus Expeditor, pages are implemented as Eclipse perspectives. As a result, the task of navigating

between pages is accomplished by using the Eclipse platform routines to navigate to a perspective with

the right ID. The IDs for pages, however, are assigned by the platform and maintained by the Topology

Handler. They must be retrieved from the Topology Handler in order to use them. In turn, to retrieve the

pages in an application you must have the ID for that application, which can also be retrieved from the

Topology Handler.

Using the TopologyHandler service

The TopologyHandler is an OSGi service that is part of the Composite Application Infrastructure. It is

made up of two main pieces – a core component and a user-interface component built on top of the core.

The TopologyHandler core acts as the underlying data model for a composite application. The topology of

an application consists of the Page/Navigation hierarchy of the application, the components which are

contained in each page, and the meta data associated with each page and component. The

TopologyHandler provides an API for accessing the data for pages and components. For more information

on the TopologyHandler API, refer to the Javadoc section of Developing Applications for Lotus Expeditor.

Since the TopologyHandler is registered with the runtime as an OSGi service, it can be retrieved as shown

below (in step 1) by using a ServiceTracker object.

Page alias names and source code examples

The following steps provide instruction on creating source code that finds a given page within an

application that has a specific alias name:

Step 1 - Retrieve the TopologyHandler service:

// Retrieve the TopologyHandler OSGi service

TopologyHandler handler;

ServiceTracker tracker = new ServiceTracker(context, TopologyHandler.class.getName( ), null);

tracker.open( );

handler = (TopologyHandler )tracker.getService( );

tracker.close( );

Step 2 - Get the composite application ID:

Developing applications 143

[[[[

[

[[[[[[[[[

[[[

[[[[[[

[

[[[[[[[[[

[

[[

[

[[[[[[[

[

Page 156: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In this particular step, it is assumed that the current perspective is a composite application perspective.

Since the Object ID of a page maps to its perspective ID, you can get the perspective ID and use it as the

parameter for our call to the TopologyHandler service to retrieve the navigation element. You can then get

the page’s application GUID by calling the getApplication() method on the navigation object.

String currentPerspective = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getPerspective().getId());

Navigation n = handler.getNavigation(currentPerspective);

String appId = n.getApplication();

Step 3 - Find the desired page:

Once you have an application ID, there are a variety of ways you can find the page you want. For

example, you can transverse all the pages that belong to that application. Use the

getApplicationNavigationTree API to get the root page, and then getNavigation() recursively to tree the

values:

// Traverse all the pages of the given application

void traversePages(String appId)

{

// This gets the root page from the application

Navigation node = handler.getApplicationNavigationTree(appId);

// Now we recurse starting with the root page

traversePage(node);

}

// Operate on the page, and then recurse through all of the children

private void traversePage(Navigation node)

{

if (node instanceof Page)

{

... // perform the operation on the page

}

// recurse through each of the children

Navigation[] children = node.getNavigation();

for (int i = 0; i < children.length; i++)

traversePage(children[i]);

}

Alternatively, if you are starting with a page alias (supplied by an action to your component, for

example) you can create a page criteria. This allows you to search the pages in the application topology

in order to find the page which matches your criteria. Shown below is sample code for finding a page

that meets criteria specified in a HashMap. Since all pages have meta data associated with them in the

Topology model, you can search for the page or pages which contain the name/value pairs you are

searching for.

// Here we are specifying the application ID and the hash map of name/value pairs to search under

public Page findPage(String application, Map criteria) {

// First get the root node in the navigation tree for this composite application

// by passing in the application GUID.

// We invoke the getApplicationNavigationTree method on the TopologyHandler to return the root

// node which is a Navigation object

Navigation nav = handler.getApplicationNavigationTree(application);

List pages = new ArrayList( );

// Call our recursive method to traverse the tree and fill the list with the pages meeting

// the criteria

findPageRecursive(nav, criteria, pages);

if (pages.size( ) > 0) {

if (pages.get(0) instanceof Page)

return (Page )pages.get(0);

}

144 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[

[

[[[[

[[[[[[[[[[[[[[[[[[[[[

[[[[[[

[[[[[[[[[[[[[[[[[[[

Page 157: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

return null;

}

public void findPageRecursive(Navigation nav, Map criteria, List result) {

// Returns the child navigation elements for this Navigation object

Navigation[] children = nav.getNavigation( );

// Iterate through the children and attempt to find a page which meets the criteria passed

// in via the HashMap

for (int index = 0; index < children.length; index++) {

Iterator i = criteria.entrySet( ).iterator( );

while (i.hasNext( )) {

Entry entry = (Entry )i.next( );

String[] value = children[index].getPreference((String )entry.getKey( ));

if (value != null) {

for (int idx = 0; idx < value.length; idx++) {

if (value[idx].equals(criteria.get(entry.getKey( )))) {

result.add(children[index]);

}

}

}

}

findPageRecursive(children[index], criteria, result);

}

}

Step 4 - Make the page switch

The final step is to acquire the perspective ID from the page and use the Eclipse workbench APIs to make

the change:

void switchTo(Page newPage)

{

String newPerspecitveID = newPage.getPerspective();

IWorkbench workbench = PlatformUI.getWorkbench();

IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();

workbench.showPerspective(newPerspecitveID, window);

}

Custom navigator example

The below example details how to create a ″breadcrumb″ style custom navigator for composite

applications which explains the basics elements of the API’s and model used for the navigation system.

This style of navigator is useful in that it only requires one horizontal line of screen space. Breadcrumb

navigation provides a drop down list of the composite application pages. Clicking an entry in the list

gives you a menu of all the sub-pages for that entry. This allows you, by selecting the root page from the

navigator, to view the navigation for the entire application in a single menu.

This example navigator contains a Widget, a View, and content and label providers. The viewer extends

from org.eclipse.jface.viewers.ContentViewer and enforces a content provider derived from

ITreeContentProvider- which is the basic navigational model for all composite applications. You can,

however, limit your application to a single page level or multiple levels. The label provider is derived

from ILabelProvider.

Basic Labels are used for the UI code, however, the SWidgets are those that ship with Lotus Notes and

Lotus Expeditor. As a result, the navigator has the look and feel of the client. In addition, the Theme,

Color and Font registry are probed to determine which ones to use. The advantage of the

Model-View-Controller pattern is that the view component is not aware of the objects or of the model it

presents – it only knows that the model is a tree or could be a tree. You will notice the entire widget only

works with Objects, relying on the providers for the implementation specific calls.

Developing applications 145

[[[[[[[[[[[[[[[[[[[[[[[[[[

[

[[

[[[[[[[

[

[[[[[[

[[[[[

[[[[[[

Page 158: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The View for this example, in this case BreadCrumbNavigatorView, is very basic. It implements a

SelectionListener interface where it is called back with the original Object it passed in for the menus.

This makes the abstraction complete - while the widget provides the menu, the view acts on the selection.

The widget only works with objects, the providers supply the content (objects, labels and images), and

the view provides the action to take when a menu option is selected. “Sample three” contains an

example.

The content and label providers are where all of the implementation specific code resides for handling

the Topology Handler model. This means this breadcrumb widget can be used with any model, not just

Topology. In composite applications, the model is a hierarchy of pages and labels (a tree). You can,

however, provide a content provider that limits the scope of the pages based on other criteria (for

example, properties on the pages or components). The code you see in the providers is specific to it.

The content provider, TopologyNavContentProvider, is detailed in “Sample four” on page 147.

The label provider, TopologyNavLabelProvider, is shown in “Sample five” on page 148:

“Sample six” on page 149 contains the complete code of the breadcrumb navigator example.

Sample one

public void createPartControl(Composite arg0) {

getProperties();

Button home = createHomeButton(arg0);

nav = new ButtonNavViewer(arg0, SWT.NONE, this);

nav.setContentProvider(new TopologyNavContentProvider());

nav.setLabelProvider(new TopologyNavLabelProvider());

TopologyHandler handler = TopologyHandlerFactory.getHandler( );

Navigation n = handler.getNavigation(getSite().getWorkbenchWindow().getActivePage().getPerspective().getId());

nav.setInput(n);

}

Sample two

**

* Finds a page withing the specified application which contains the preferences

* specified by the <code>criteria<code> map. If no such page is found, then null

* is returned.

*

* @param application The GUID of the composite application

* @param criteria The HashMap of preferences to be matched with the page desired

* @return The page object meeting the criteria or null if none are found

*/

public Page findPage(String application, Map criteria);

Sample three

package com.foo.bc.ca.navigator;

import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.core.runtime.IStatus;

import org.eclipse.core.runtime.Status;

import org.eclipse.swt.SWT;

import org.eclipse.swt.widgets.Composite;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ui.WorkbenchException;

import org.eclipse.ui.part.ViewPart;

import org.eclipse.ui.progress.UIJob;

import com.foo.bc.ca.navigator.internal.TopologyNavContentProvider;

import com.foo.bc.ca.navigator.internal.TopologyNavLabelProvider;

import com.ibm.rcp.topology.Navigation;

146 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[

[[[[[

[

[

[

[[[[[[[[[[[[[[[[[[

[

[[[[[[[[[[

[[[[[[[[[[[[[[[[

Page 159: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

import com.ibm.rcp.topology.Page;

import com.ibm.rcp.topology.TopologyHandler;

import com.ibm.rcp.topologyhandler.TopologyHandlerFactory;

public class BreadCrumbNavigatorView extends ViewPart implements NavigationSelectionListener {

BreadCrumbNavViewer nav = null;

@Override

public void createPartControl(Composite arg0) {

nav = new BreadCrumbNavViewer(arg0, SWT.NONE, this);

// We set our content provider on our viewer - alternatively one can create their own content provider

// This particular one gets the model from the Topology model

// This uses the standard Eclipse Model-View-Controller design pattern for rendering domain objects

nav.setContentProvider(new TopologyNavContentProvider());

nav.setLabelProvider(new TopologyNavLabelProvider());

TopologyHandler handler = TopologyHandlerFactory.getHandler( );

Navigation n = handler.getNavigation(getSite().getWorkbenchWindow().getActivePage().getPerspective().getId());

nav.setInput(n);

}

@Override

public void setFocus() {

// TODO Auto-generated method stub

}

public void selectionChanged(Object obj) {

if (obj instanceof Page){

Page page = (Page )obj;

try {

// Call the regular Eclipse API for switching pages when an object in the viewer is selected

// In this case, Page objects are selected so we switch to that perspective by calling the

// Page.getPerspective()

// API on the page object which returns the perspective ID the object maps to

PlatformUI.getWorkbench().showPerspective(

page.getPerspective(),

PlatformUI.getWorkbench().getActiveWorkbenchWindow());

} catch (WorkbenchException e) {

e.printStackTrace();

}

}

}

}

Sample four

package com.ibm.rcp.ca.navigators.model.providers;

import java.util.ArrayList;

import java.util.List;

import org.eclipse.jface.viewers.ITreeContentProvider;

import org.eclipse.jface.viewers.Viewer;

import org.osgi.util.tracker.ServiceTracker;

import com.ibm.rcp.ca.navigators.Activator;

import com.ibm.rcp.topology.Label;

import com.ibm.rcp.topology.Navigation;

import com.ibm.rcp.topology.TopologyHandler;

import com.ibm.rcp.topologyhandler.TopologyHandlerFactory;

public class TopologyNavContentProvider implements ITreeContentProvider{

private TopologyHandler handler;

public TopologyNavContentProvider( ) {

// Use a service tracker to retrieve the TopologyHandler

ServiceTracker tracker =

new ServiceTracker(

Activator.getContext(), TopologyHandler.class.getName(), null);

tracker.open();

// Get the topology handler service

Developing applications 147

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 160: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

handler = (TopologyHandler )tracker.getService();

tracker.close();

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)

*/

public Object[] getChildren(Object parentElement) {

// Since this is an ITreeContentProvider we override the necessary methods

// Here we are retrieving the child nav elements for the Navigation object

// passed in.

List children = new ArrayList( );

if (parentElement instanceof Label) {

Label root = (Label )parentElement;

// Get the children for the label

Navigation[] nav = root.getNavigation( );

for (int index = 0; index < nav.length; index++) {

if (nav[index].isHidden( ))

continue;

children.add(nav[index]);

}

}

return children.toArray(new Navigation[0]);

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)

*/

public Object getParent(Object element) {

Navigation nav = (Navigation )element;

Navigation parent = handler.getNavigation(nav.getParent( ));

return parent;

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)

*/

public boolean hasChildren(Object element) {

Navigation nav = (Navigation )element;

return nav.getNavigation( ).length > 0;

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)

*/

public Object[] getElements(Object inputElement) {

return getChildren(inputElement);

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.IContentProvider#dispose()

*/

public void dispose( ) {

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)

*/

public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

}

}

Sample five

package com.foo.bc.ca.navigator.internal;

import java.io.File;

import java.net.MalformedURLException;

import java.net.URL;

import org.eclipse.jface.resource.ImageDescriptor;

import org.eclipse.jface.viewers.ILabelProvider;

import org.eclipse.jface.viewers.ILabelProviderListener;

import org.eclipse.swt.graphics.Image;

import com.ibm.rcp.topology.Navigation;

148 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[

[[[[[[[[[[[[

Page 161: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

import com.ibm.rcp.topology.Page;

public class TopologyNavLabelProvider implements ILabelProvider{

public Image getImage(Object element) {

if (element instanceof Page) {

Page page = (Page )element;

String imagePath = page.getImage( );

if (imagePath != null){

try {

URL url = new File(imagePath).toURL( );

ImageDescriptor desc = ImageDescriptor.createFromURL(url);

return desc.createImage( );

}

catch (MalformedURLException e) {

}

}

}

return null;

}

public String getText(Object element) {

Navigation nav = (Navigation )element;

return nav.getName( );

}

public void addListener(ILabelProviderListener listener) {

// TODO Auto-generated method stub

}

public void dispose() {

// TODO Auto-generated method stub

}

public boolean isLabelProperty(Object element, String property) {

// TODO Auto-generated method stub

return false;

}

public void removeListener(ILabelProviderListener listener) {

// TODO Auto-generated method stub

}

}

Sample six

Below is the complete code for the breadcrumb navigator.

Note that the InputJob class is a background job used to initially set the input for the navigator viewer.

In this sample, it is placed in the background to ensure that the TopologyHandler service has time to

initialize and load the application topologies for all installed composite applications. Once the navigation

(page) object has become available from the TopologyHandler service, the input for the Eclipse viewer is

set. which populates the navigator widget.

public class InputJob extends Job {

private ServiceTracker tracker;

private Object input;

private String id;

Developing applications 149

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[

[

[[[[[

[[[[[[

Page 162: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

/**

* @param arg0

*/

public InputJob(String id) {

super("INPUT_JOB");

setUser(false);

setSystem(true);

// Create the service tracker for the job

tracker = new ServiceTracker(Activator.getContext(), TopologyHandler.class.getName(), null);

tracker.open();

this.id = id;

}

public Object getInput() {

return input;

}

/* (non-Javadoc)

* @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)

*/

@Override

protected IStatus run(IProgressMonitor progress) {

try {

// Here we are starting a job to set the input for the content provider. Since the

// TopologyHandler is an OSGi service, we need to wait until the service is available

// before we attempt to get the root navigation and set the input.

progress.beginTask("Initializing Component", IProgressMonitor.UNKNOWN);

// Wait for the topologyhandler service to become available

TopologyHandler handler = (TopologyHandler )tracker.waitForService(0);

Navigation nav = handler.getNavigation(id);

while (nav == null) {

nav = handler.getNavigation(id);

Thread.sleep(250);

}

input = nav;

}

catch (InterruptedException e) {}

finally {

tracker.close();

}

return Status.OK_STATUS;

}

}

public class ButtonNavigatorView extends ViewPart implements NavigationSelectionListener, IPartListener2 {

ButtonNavViewer nav = null;

boolean showHomeBtn = true;

@Override

public void createPartControl(Composite arg0) {

getProperties();

nav = new ButtonNavViewer(arg0, SWT.NONE, this);

nav.setShowHome(showHomeBtn);

150 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 163: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

nav.setContentProvider(new TopologyNavContentProvider());

nav.setLabelProvider(new TopologyNavLabelProvider());

String id = getSite().getWorkbenchWindow().getActivePage().getPerspective().getId();

final Composite comp = arg0;

// We created a job listener here for the input job since we know when the job is complete,

// the TopologyHandler

// service is available and we can set the input to the viewer.

// We do this by hopping on the UI thread, setting the input to the viewer, then redrawing our

// control to show the updated contents

InputJob job = new InputJob(id);

job.addJobChangeListener(new JobChangeAdapter() {

@Override

public void done(IJobChangeEvent arg0) {

InputJob job = (InputJob )arg0.getJob();

final Object input = job.getInput();

Display disp = Display.getCurrent();

if (disp == null)

disp = Display.getDefault();

disp.asyncExec(new Runnable() {

public void run() {

if (input != null) {

nav.setInput(input);

// Update the composite

comp.layout();

comp.redraw();

comp.update();

}

}

});

}

});

job.schedule();

getSite().getWorkbenchWindow().getActivePage().addPartListener(this);

}

@Override

public void dispose() {

nav.dispose();

super.dispose();

}

@Override

public void setFocus() {

// TODO Auto-generated method stub

}

public void selectionChanged(Object obj) {

if (obj instanceof Page){

Page page = (Page )obj;

try {

PlatformUI.getWorkbench().showPerspective(

page.getPerspective(),

PlatformUI.getWorkbench().getActiveWorkbenchWindow());

} catch (WorkbenchException e) {

Developing applications 151

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 164: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

e.printStackTrace();

}

}

}

void getProperties() {

BundleContext bc = Activator.getContext();

ServiceReference serviceRef = bc

.getServiceReference(TopologyHandler.class.getName());

if (serviceRef != null) {

TopologyHandler topologyHandler = (TopologyHandler) bc

.getService(serviceRef);

// After we get the topology service - we call the getComponentData API in order to

// get the meta data associated with this component. In order to retrieve the data

// we pass in the secondary ID for the view which maps to a ComponentData object.

// In this case we are retrieving the preference "com.ibm.rcp.ca.navigator.showhome"

// which is used to determine if a button should be shown in the navigator. This data

// can be set in the Composite Application Editor or from Portal in the portlet preferences

if (topologyHandler != null) {

ComponentData data = topologyHandler.getComponentData(getViewSite().getSecondaryId());

if (data != null) {

String[] values = data.getPreference("com.ibm.rcp.ca.navigator.showhome"); //$NON-NLS-1$

if ((values != null) && (values.length > 0))

showHomeBtn = values[0].compareToIgnoreCase("true") == 0;

}

}

}

}

// PartListener callback used to ensure the Input is retrieved and the navigator view is updated with

// the proper data for the current composite application

public void partActivated(IWorkbenchPartReference arg0) {

IWorkbenchPart part = arg0.getPart(false);

if ( part == this){

String id = getSite().getWorkbenchWindow().getActivePage().getPerspective().getId();

InputJob job = new InputJob(id);

job.addJobChangeListener(new JobChangeAdapter() {

@Override

public void done(IJobChangeEvent arg0) {

InputJob job = (InputJob )arg0.getJob();

final Object input = job.getInput();

Display disp = Display.getCurrent();

if (disp == null)

disp = Display.getDefault();

disp.asyncExec(new Runnable() {

public void run() {

if (input != null) {

nav.setInput(input);

nav.composite.layout();

nav.composite.redraw();

nav.composite.update();

}

}

});

}

});

152 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 165: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

job.schedule();

}

}

public void partBroughtToTop(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partClosed(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partDeactivated(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partHidden(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partInputChanged(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partOpened(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partVisible(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

}

Creating a custom navigator for composite applications, for 6.1.2

To obtain a custom look and feel, developers may desire to create a custom navigator to move between

the pages of their composite applications, instead of using the default navigator. Creating a custom

navigator gives you the following advantages:

v Options to change the look and feel of the navigator

v Options to change the screen location of the navigator

v Extended options to control visibility

v Can be arranged similarly to other components, to conserve and maximize work space

v Can interact and communicate with other components

Composite Application Infrastructure, Topology, and Navigation page hierarchy

and preferences

In order to create a custom navigator for composite applications, you should have a high level

understanding of the underlying data structure for composite applications. Composite applications

consist of one or more application pages, grouped together in a hierarchy. At the top of the hierarchy is

the root page. The root page does not appear within the Composite Application Editor (CAE), and you

cannot switch to it or add components to it. However, it is provided through the Topology Handler as a

consistent starting point to group top level pages. These top level pages, in turn, can be containers for

other child pages, and so on for as many levels as required.

Developing applications 153

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[

[[[

[

[

[

[

[

[[

[[[[[[[

Page 166: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Clients can access the page hierarchy model through the TopologyHandler service. The TopologyHandler

provides an API to both the hierarchical page model and the components within each page. Each page

and component within an application can contain any number of name/value pairs representing

meta-data for the object. For more information on accessing the TopologyHandler service, refer to “Using

the TopologyHandler service” on page 155.

Lastly, when creating a custom navigator, you will need to configure some application and page

properties in order to emulate some of the original functionality of the default navigator. The properties

tell the underlying composite application infrastructure that you are overriding the default navigation

system. First, from the Advanced page properties settings window in the Composite Application Editor,

set com.ibm.rcp.navigationModel as ″custom″ and com.ibm.rcp.useNavigator as ″true″ . This makes each

perspective show in the same tab. By default, these application page settings display each page of your

composite application in the same tab. For any page you want displayed in a separate tab, set

com.ibm.rcp.useNavigator to ″false″ for that page’s properties.

Custom navigator layout and design

It is possible to create a custom navigator that has a look and feel that supports your workflow. This

allows you to programmatically discover the pages in an application, and to switch between those pages.

The options displayed are driven by properties set on the custom navigator component. However such a

component must be created or otherwise acquired.

You should consider what type of user interface best suits your application. Does it have its own look

and feel? Do you want to try to copy another application’s look and feel that works cooperatively with

your component? Or do you need to merge it seamlessly with your operating system? Some ″navigators″

might have no UI at all.

For example, the breadcrumb navigator outlined in a later section is more than just a JFace viewer that

shows the navigation hierarchy. It is actually a hybrid view with two components on it - a Home button,

and a Sibling Button Navigator. The component is created in two basic levels - a view and a widget. The

view contains the Home button and also contains the JFace viewer for the current pages’ siblings. As a

result, this is not simply a basic component that relates to the navigation, but rather a custom UI

component that can be define in a variety of ways. You can add other buttons and widgets to the view,

and from the views perspective the button navigator is just another widget in its space.

The code for the view aspect is straightforward. You create the button, create the viewer, and then simply

initialize the viewer with the Navigation element for the current perspective. “Sample one” on page 157

contains an example.

The topology handler service is used to set the JFace viewer with its input; in this case, a navigation

element of the current Eclipse perspective. The button viewer (inside setInput) uses the ContentProvider

to acquire its parent, then all of its parent’s children (including itself). Given that information, the viewer

simply creates a button for each of its siblings and itself.

The component model for Composite Applications is at the view layer. As a result, any properties you

want to pass on to widgets would be defined and handled at the view part layer. The view part would

then consume those properties (which would be filled in using the CAE) and set the different fields on

the underlying widgets it contains.

Using page alias names in a custom navigator

When using a custom navigator, you may want to designate a page alias for the pages within your

navigator model. This can be done both from portal and within the Composite Application Editor (CAE)

tool. From within the CAE, select a page in the page hierarchy, edit the page properties under the

Advanced section, and add the preference com.ibm.rcp.alias. You can then choose what you want the

page alias to be. For WebSphere Portal based composite applications, the NCI Rich Client Layout Admin

154 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[

[[[[[[[[

[

[[[[

[[[[

[[[[[[[

[[[

[[[[

[[[[

[

[[[[[

Page 167: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Portlet provides a field for you to enter the page alias name for the page. Once you set your alias name,

the TopologyHandler service can be used to find a page within a composite application based on certain

criteria. The API to accomplish this exists in the TopologyHandler service interface, as shown in “Sample

two” on page 157.

The criteria is a Map object containing name/value pairs used to locate a given page object. The map can

contain any number of name/value pairs you wish. If the criteria specified matches that of more than one

page, the first page found will be the object returned.

With Lotus Expeditor, pages are implemented as Eclipse perspectives. As a result, the task of navigating

between pages is accomplished by using the Eclipse platform routines to navigate to a perspective with

the right ID. The IDs for pages, however, are assigned by the platform and maintained by the Topology

Handler. They must be retrieved from the Topology Handler in order to use them. In turn, to retrieve the

pages in an application you must have the ID for that application, which can also be retrieved from the

Topology Handler.

Using the TopologyHandler service

The TopologyHandler is an OSGi service that is part of the Composite Application Infrastructure. It is

made up of two main pieces – a core component and a user-interface component built on top of the core.

The TopologyHandler core acts as the underlying data model for a composite application. The topology of

an application consists of the Page/Navigation hierarchy of the application, the components which are

contained in each page, and the meta data associated with each page and component. The

TopologyHandler provides an API for accessing the data for pages and components. For more information

on the TopologyHandler API, refer to the Javadoc section of Developing Applications for Lotus Expeditor.

Since the TopologyHandler is registered with the runtime as an OSGi service, it can be retrieved as shown

below (in step 1) by using a ServiceTracker object.

Page alias names and source code examples

The following steps provide instruction on creating source code that finds a given page within an

application that has a specific alias name:

Step 1 - Retrieve the TopologyHandler service:

// Retrieve the TopologyHandler OSGi service

TopologyHandler handler;

ServiceTracker tracker = new ServiceTracker(context, TopologyHandler.class.getName( ), null);

tracker.open( );

handler = (TopologyHandler )tracker.getService( );

tracker.close( );

Step 2 - Get the composite application ID:

In this particular step, it is assumed that the current perspective is a composite application perspective.

Since the Object ID of a page maps to its perspective ID, you can get the perspective ID and use it as the

parameter for our call to the TopologyHandler service to retrieve the navigation element. You can then get

the page’s application GUID by calling the getApplication() method on the navigation object.

String currentPerspective = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getPerspective().getId();

Navigation n = handler.getNavigation(currentPerspective);

String appId = n.getApplication();

Step 3 - Find the desired page:

Developing applications 155

[[[[

[[[

[[[[[[

[

[[[[[[[[[

[

[[

[

[[[[[[[

[

[[[[[[[[[

[

Page 168: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Once you have an application ID, there are a variety of ways you can find the page you want. For

example, you can transverse all the pages that belong to that application. Use the

getApplicationNavigationTree API to get the root page, and then getNavigation() recursively to tree the

values:

// Traverse all the pages of the given application

void traversePages(String appId)

{

// This gets the root page from the application

Navigation node = handler.getApplicationNavigationTree(appId);

// Now we recurse starting with the root page

traversePage(node);

}

// Operate on the page, and then recurse through all of the children

private void traversePage(Navigation node)

{

if (node instanceof Page)

{

... // perform the operation on the page

}

// recurse through each of the children

Navigation[] children = node.getNavigation();

for (int i = 0; i < children.length; i++)

traversePage(children[i]);

}

Alternatively, if you are starting with a page alias (supplied by an action to your component, for

example) you can create a page criteria and invoke the findPage() method.

The following code attempts to find the page in the specified Composite Application of the preference

com.ibm.rcp.alias = my.alias.name.

Map criteria = new HashMap( );

criteria.put("com.ibm.rcp.alias" , "my.alias.name");

Page p = (Page )handler.findPage(appId, criteria);

This retrieves the first page within the given Composite Application that matches the criteria passed in

through the map. Once you obtain the Page object, you can then call Page.getPerspective(), which

provides the perspective ID for that page object and allows you to open it using the Eclipse workbench

API.

Step 4 - Make the page switch:

The final step is to acquire the perspective ID from the page and use the Eclipse workbench APIs to make

the change:

void switchTo(Page newPage)

{

String newPerspecitveID = newPage.getPerspective();

IWorkbench workbench = PlatformUI.getWorkbench();

IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();

workbench.showPerspective(newPerspecitveID, window);

}

Custom navigator example

The below example details how to create a ″breadcrumb″ style custom navigator for composite

applications which explains the basics elements of the API’s and model used for the navigation system.

This style of navigator is useful in that it only requires one horizontal line of screen space. Breadcrumb

navigation provides a drop down list of the composite application pages. Clicking an entry in the list

156 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[

[[[[[[[[[[[[[[[[[[[[[

[[

[[

[[[[

[[[[

[

[[

[[[[[[[

[

[[[[

Page 169: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

gives you a menu of all the sub-pages for that entry. This allows you, by selecting the root page from the

navigator, to view the navigation for the entire application in a single menu.

This example navigator contains a Widget, a View, and content and label providers. The viewer extends

from org.eclipse.jface.viewers.ContentViewer and enforces a content provider derived from

ITreeContentProvider- which is the basic navigational model for all composite applications. You can,

however, limit your application to a single page level or multiple levels. The label provider is derived

from ILabelProvider.

Basic Labels are used for the UI code, however, the SWidgets are those that ship with Lotus Notes and

Lotus Expeditor. As a result, the navigator has the look and feel of the client. In addition, the Theme,

Color and Font registry are probed to determine which ones to use. The advantage of the

Model-View-Controller pattern is that the view component is not aware of the objects or of the model it

presents – it only knows that the model is a tree or could be a tree. You will notice the entire widget only

works with Objects, relying on the providers for the implementation specific calls.

The View for this example, in this case BreadCrumbNavigatorView, is very basic. It implements a

SelectionListener interface where it is called back with the original Object it passed in for the menus.

This makes the abstraction complete - while the widget provides the menu, the view acts on the selection.

The widget only works with objects, the providers supply the content (objects, labels and images), and

the view provides the action to take when a menu option is selected. “Sample three” on page 158

contains an example.

The content and label providers are where all of the implementation specific code resides for handling

the Topology Handler model. This means this breadcrumb widget can be used with any model, not just

Topology. In composite applications, the model is a hierarchy of pages and labels (a tree). You can,

however, provide a content provider that limits the scope of the pages based on other criteria (for

example, properties on the pages or components). The code you see in the providers is specific to it.

The content provider, TopologyNavContentProvider, is detailed in “Sample four” on page 158.

The label provider, TopologyNavLabelProvider, is shown in “Sample five” on page 160.

“Sample six” on page 161 contains the complete code of the breadcrumb navigator example.

Sample one

public void createPartControl(Composite arg0) {

getProperties();

Button home = createHomeButton(arg0);

nav = new ButtonNavViewer(arg0, SWT.NONE, this);

nav.setContentProvider(new TopologyNavContentProvider());

nav.setLabelProvider(new TopologyNavLabelProvider());

TopologyHandler handler = TopologyHandlerFactory.getHandler( );

Navigation n = handler.getNavigation(getSite().getWorkbenchWindow().getActivePage().getPerspective().getId());

nav.setInput(n);

}

Sample two

**

* Finds a page withing the specified application which contains the preferences

* specified by the <code>criteria<code> map. If no such page is found, then null

* is returned.

*

* @param application The GUID of the composite application

Developing applications 157

[[

[[[[[

[[[[[[

[[[[[[

[[[[[

[

[

[

[[[[[[[[[[[[[[[[[[

[

[[[[[[

Page 170: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

* @param criteria The HashMap of preferences to be matched with the page desired

* @return The page object meeting the criteria or null if none are found

*/

public Page findPage(String application, Map criteria);

Sample three

package com.foo.bc.ca.navigator;

import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.core.runtime.IStatus;

import org.eclipse.core.runtime.Status;

import org.eclipse.swt.SWT;

import org.eclipse.swt.widgets.Composite;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ui.WorkbenchException;

import org.eclipse.ui.part.ViewPart;

import org.eclipse.ui.progress.UIJob;

import com.foo.bc.ca.navigator.internal.TopologyNavContentProvider;

import com.foo.bc.ca.navigator.internal.TopologyNavLabelProvider;

import com.ibm.rcp.topology.Navigation;

import com.ibm.rcp.topology.Page;

import com.ibm.rcp.topology.TopologyHandler;

import com.ibm.rcp.topologyhandler.TopologyHandlerFactory;

public class BreadCrumbNavigatorView extends ViewPart implements NavigationSelectionListener {

BreadCrumbNavViewer nav = null;

@Override

public void createPartControl(Composite arg0) {

nav = new BreadCrumbNavViewer(arg0, SWT.NONE, this);

// We set our content provider on our viewer - alternatively one can create their own content provider

// This particular one gets the model from the Topology model

// This uses the standard Eclipse Model-View-Controller design pattern for rendering domain objects

nav.setContentProvider(new TopologyNavContentProvider());

nav.setLabelProvider(new TopologyNavLabelProvider());

TopologyHandler handler = TopologyHandlerFactory.getHandler( );

Navigation n = handler.getNavigation(getSite().getWorkbenchWindow().getActivePage().getPerspective().getId());

nav.setInput(n);

}

@Override

public void setFocus() {

// TODO Auto-generated method stub

}

public void selectionChanged(Object obj) {

if (obj instanceof Page){

Page page = (Page )obj;

try {

// Call the regular Eclipse API for switching pages when an object in the viewer is selected

// In this case, Page objects are selected so we switch to that perspective by calling the

// Page.getPerspective()

// API on the page object which returns the perspective ID the object maps to

PlatformUI.getWorkbench().showPerspective(

page.getPerspective(),

PlatformUI.getWorkbench().getActiveWorkbenchWindow());

} catch (WorkbenchException e) {

e.printStackTrace();

}

}

}

}

Sample four

package com.ibm.rcp.ca.navigators.model.providers;

import java.util.ArrayList;

158 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[[[[

Page 171: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

import java.util.List;

import org.eclipse.jface.viewers.ITreeContentProvider;

import org.eclipse.jface.viewers.Viewer;

import org.osgi.util.tracker.ServiceTracker;

import com.ibm.rcp.ca.navigators.Activator;

import com.ibm.rcp.topology.Label;

import com.ibm.rcp.topology.Navigation;

import com.ibm.rcp.topology.TopologyHandler;

import com.ibm.rcp.topologyhandler.TopologyHandlerFactory;

public class TopologyNavContentProvider implements ITreeContentProvider{

private TopologyHandler handler;

public TopologyNavContentProvider( ) {

// Use a service tracker to retrieve the TopologyHandler

ServiceTracker tracker =

new ServiceTracker(

Activator.getContext(), TopologyHandler.class.getName(), null);

tracker.open();

// Get the topology handler service

handler = (TopologyHandler )tracker.getService();

tracker.close();

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)

*/

public Object[] getChildren(Object parentElement) {

// Since this is an ITreeContentProvider we override the necessary methods

// Here we are retrieving the child nav elements for the Navigation object

// passed in.

List children = new ArrayList( );

if (parentElement instanceof Label) {

Label root = (Label )parentElement;

// Get the children for the label

Navigation[] nav = root.getNavigation( );

for (int index = 0; index < nav.length; index++) {

if (nav[index].isHidden( ))

continue;

children.add(nav[index]);

}

}

return children.toArray(new Navigation[0]);

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)

*/

public Object getParent(Object element) {

Navigation nav = (Navigation )element;

Navigation parent = handler.getNavigation(nav.getParent( ));

return parent;

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)

*/

public boolean hasChildren(Object element) {

Navigation nav = (Navigation )element;

return nav.getNavigation( ).length > 0;

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)

*/

public Object[] getElements(Object inputElement) {

return getChildren(inputElement);

}

/* (non-Javadoc)

* @see org.eclipse.jface.viewers.IContentProvider#dispose()

*/

public void dispose( ) {

}

/* (non-Javadoc)

Developing applications 159

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 172: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)

*/

public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

}

}

Sample five

package com.foo.bc.ca.navigator.internal;

import java.io.File;

import java.net.MalformedURLException;

import java.net.URL;

import org.eclipse.jface.resource.ImageDescriptor;

import org.eclipse.jface.viewers.ILabelProvider;

import org.eclipse.jface.viewers.ILabelProviderListener;

import org.eclipse.swt.graphics.Image;

import com.ibm.rcp.topology.Navigation;

import com.ibm.rcp.topology.Page;

public class TopologyNavLabelProvider implements ILabelProvider{

public Image getImage(Object element) {

if (element instanceof Page) {

Page page = (Page )element;

String imagePath = page.getImage( );

if (imagePath != null){

try {

URL url = new File(imagePath).toURL( );

ImageDescriptor desc = ImageDescriptor.createFromURL(url);

return desc.createImage( );

}

catch (MalformedURLException e) {

}

}

}

return null;

}

public String getText(Object element) {

Navigation nav = (Navigation )element;

return nav.getName( );

}

public void addListener(ILabelProviderListener listener) {

// TODO Auto-generated method stub

}

public void dispose() {

// TODO Auto-generated method stub

}

public boolean isLabelProperty(Object element, String property) {

// TODO Auto-generated method stub

return false;

}

public void removeListener(ILabelProviderListener listener) {

160 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[

[

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 173: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

// TODO Auto-generated method stub

}

}

Sample six

Below is the complete code for the breadcrumb navigator.

Note that the InputJob class is a background job used to initially set the input for the navigator viewer.

In this sample, it is placed in the background to ensure that the TopologyHandler service has time to

initialize and load the application topologies for all installed composite applications. Once the navigation

(page) object has become available from the TopologyHandler service, the input for the Eclipse viewer is

set. which populates the navigator widget.

public class InputJob extends Job {

private ServiceTracker tracker;

private Object input;

private String id;

/**

* @param arg0

*/

public InputJob(String id) {

super("INPUT_JOB");

setUser(false);

setSystem(true);

// Create the service tracker for the job

tracker = new ServiceTracker(Activator.getContext(), TopologyHandler.class.getName(), null);

tracker.open();

this.id = id;

}

public Object getInput() {

return input;

}

/* (non-Javadoc)

* @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)

*/

@Override

protected IStatus run(IProgressMonitor progress) {

try {

// Here we are starting a job to set the input for the content provider. Since the

// TopologyHandler is an OSGi service, we need to wait until the service is available

// before we attempt to get the root navigation and set the input.

progress.beginTask("Initializing Component", IProgressMonitor.UNKNOWN);

// Wait for the topologyhandler service to become available

TopologyHandler handler = (TopologyHandler )tracker.waitForService(0);

Navigation nav = handler.getNavigation(id);

while (nav == null) {

nav = handler.getNavigation(id);

Thread.sleep(250);

}

input = nav;

Developing applications 161

[[[[

[

[

[[[[[

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 174: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

catch (InterruptedException e) {}

finally {

tracker.close();

}

return Status.OK_STATUS;

}

}

public class ButtonNavigatorView extends ViewPart implements NavigationSelectionListener, IPartListener2 {

ButtonNavViewer nav = null;

boolean showHomeBtn = true;

@Override

public void createPartControl(Composite arg0) {

getProperties();

nav = new ButtonNavViewer(arg0, SWT.NONE, this);

nav.setShowHome(showHomeBtn);

nav.setContentProvider(new TopologyNavContentProvider());

nav.setLabelProvider(new TopologyNavLabelProvider());

String id = getSite().getWorkbenchWindow().getActivePage().getPerspective().getId();

final Composite comp = arg0;

// We created a job listener here for the input job since we know when the job is complete,

// the TopologyHandler

// service is available and we can set the input to the viewer.

// We do this by hopping on the UI thread, setting the input to the viewer, then redrawing our

// control to show the updated contents

InputJob job = new InputJob(id);

job.addJobChangeListener(new JobChangeAdapter() {

@Override

public void done(IJobChangeEvent arg0) {

InputJob job = (InputJob )arg0.getJob();

final Object input = job.getInput();

Display disp = Display.getCurrent();

if (disp == null)

disp = Display.getDefault();

disp.asyncExec(new Runnable() {

public void run() {

if (input != null) {

nav.setInput(input);

// Update the composite

comp.layout();

comp.redraw();

comp.update();

}

}

});

}

});

job.schedule();

getSite().getWorkbenchWindow().getActivePage().addPartListener(this);

162 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 175: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

@Override

public void dispose() {

nav.dispose();

super.dispose();

}

@Override

public void setFocus() {

// TODO Auto-generated method stub

}

public void selectionChanged(Object obj) {

if (obj instanceof Page){

Page page = (Page )obj;

try {

PlatformUI.getWorkbench().showPerspective(

page.getPerspective(),

PlatformUI.getWorkbench().getActiveWorkbenchWindow());

} catch (WorkbenchException e) {

e.printStackTrace();

}

}

}

void getProperties() {

BundleContext bc = Activator.getContext();

ServiceReference serviceRef = bc

.getServiceReference(TopologyHandler.class.getName());

if (serviceRef != null) {

TopologyHandler topologyHandler = (TopologyHandler) bc

.getService(serviceRef);

// After we get the topology service - we call the getComponentData API in order to

// get the meta data associated with this component. In order to retrieve the data

// we pass in the secondary ID for the view which maps to a ComponentData object.

// In this case we are retrieving the preference "com.ibm.rcp.ca.navigator.showhome"

// which is used to determine if a button should be shown in the navigator. This data

// can be set in the Composite Application Editor or from Portal in the portlet preferences

if (topologyHandler != null) {

ComponentData data = topologyHandler.getComponentData(getViewSite().getSecondaryId());

if (data != null) {

String[] values = data.getPreference("com.ibm.rcp.ca.navigator.showhome"); //$NON-NLS-1$

if ((values != null) && (values.length > 0))

showHomeBtn = values[0].compareToIgnoreCase("true") == 0;

}

}

}

}

// PartListener callback used to ensure the Input is retrieved and the navigator view is updated with

// the proper data for the current composite application

public void partActivated(IWorkbenchPartReference arg0) {

IWorkbenchPart part = arg0.getPart(false);

if ( part == this){

String id = getSite().getWorkbenchWindow().getActivePage().getPerspective().getId();

InputJob job = new InputJob(id);

job.addJobChangeListener(new JobChangeAdapter() {

@Override

public void done(IJobChangeEvent arg0) {

Developing applications 163

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 176: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

InputJob job = (InputJob )arg0.getJob();

final Object input = job.getInput();

Display disp = Display.getCurrent();

if (disp == null)

disp = Display.getDefault();

disp.asyncExec(new Runnable() {

public void run() {

if (input != null) {

nav.setInput(input);

nav.composite.layout();

nav.composite.redraw();

nav.composite.update();

}

}

});

}

});

job.schedule();

}

}

public void partBroughtToTop(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partClosed(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partDeactivated(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partHidden(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partInputChanged(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partOpened(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

public void partVisible(IWorkbenchPartReference arg0) {

// TODO Auto-generated method stub

}

}

Built-in properties for Eclipse Components

The composite application component level resides at the workbench part layer - the Editor and View

parts. These parts can expose a SelectionProvider, so that the workbench is aware this particular part

164 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[

[[

Page 177: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

exposes a selection object for other parts to act on. The Composite Application Infrastructure (CAI)

provides a default output property for components that register a selection provider with the workbench.

This selection is then intercepted by CAI and exposed as a Property Broker property named ″Selection

Changed″. This selection is currently exposed as an xsd:string type and can only be wired to compatible

types. The output property then appears in the Composite Application Editor as an output property that

can be wired to receiving actions.

Exploring more advanced functionality of composite applications

After you have gained a basic understanding of composite applications, you can explore more advanced

functionality of the composite application infrastructure.

Composite applications 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

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

com.ibm.portal.app.component.Serializable 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

Developing applications 165

[[[[[[

Page 178: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

com.ibm.portal.app.component.Serializable interface.

v CAI URL format – Each composite application hosted on the Portal and opened on the client is

defined by a CAI URL with the following format (square brackets [ ] denote optional parts)

cai:///appInstanceID[/pageID]?[hint][&clnk=t]

where:

– cai:// is the start of the CAI URL format

– appInstanceID is the unique identifier for the application

– [/pageID] is an optional unique identifier for a page in the application

– [hint] is the URL for retrieving the application if it is not already available in the client. Although

this piece is options, if it is not used and the applications is not already installed in the client, then

the application will fail to open.

– [&clnk=t] is an option that indicates that the application was not opened from a bookmark.

Currently this option is only used by Lotus Notes 8.

Opening a connection to a CAI URL will cause the corresponding application to be projected to the

client or updated if already on the client, and then opened in the user interface to the specified page. If

no page is specified, the first page in the application is opened.

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

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.

166 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 179: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Apache Derby 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.

Developing applications 167

Page 180: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Apache Derby.

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 Apache Derby 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 Apache Derby comparison: DB2 Everyplace and Apache Derby are similar, but

have features that might make one a better choice for client needs.

Table 3. DB2 Everyplace and Apache Derby comparison

DB2 Everyplace Apache Derby

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

168 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 181: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 3. DB2 Everyplace and Apache Derby comparison (continued)

DB2 Everyplace Apache Derby

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

Apache Derby 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.

Developing applications 169

Page 182: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Apache Derby) 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 Apache Derby 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

170 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 183: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

(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 definition 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 Apache Derby target feature for project access to

Developing applications 171

Page 184: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

the Apache Derby 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 Apache Derby 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 “Using the Lotus Expeditor Toolkit” on page 12.

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.

172 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 185: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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. 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 Apache Derby 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 Apache Derby 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: Prior to accessing a managed datasource, the datasource

definition and any associated schema definitions must be defined. Refer to Defining managed data

sources for more information on setting up managed datasource definitions.

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:

The processing of schema operations for a managed datasource may take some time to complete,

depending upon the number of steps that need to be performed. While performing these actions, the

application may need to wait for the actions to complete. An application may receive progress updates

during the schema processing by defining a listener.

To define a listener, first create a class that implements org.eclipse.core.runtime:

public class TestProgressMonitor implements IProgressMonitor {

...

public void done() {

System.out.println("Processing is done!");

}

...

}

Developing applications 173

Page 186: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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):

InitialContext context = new InitialContext();

DataSource source = (DataSource) context.lookup("jdbc/DerbyDS");

Connection connection = source.getConnection();

Note: By definition, the default managed datasource has no schema definitions associated with it, so no

scripts or tasks are performed on the first access of the database. Therefore, you cannot count on

tables having been created or data being populated into those tables. You may use the default

managed datasource and write JDBC code to perform your own database updates. You can also

define a virtual datasource with schemaReferences to perform the database updates on first

database access, and then lookup the virtual datasource name, rather than the default datasource

name. Refer to Defining managed data sources for more information on setting up managed

datasource definitions.

Apache Derby

Derby is a full-featured, open source relational database engine that is written and implemented

completely in the Java programming language. It provides users with a small-footprint standards-based

database engine that can be tightly embedded into any Java based solution. Derby ensures data integrity

and provides sophisticated transaction support. In its default configuration there is no separate database

server to be installed or maintained by the end user. For more information on Derby, visit the Derby Web

site at http://db.apache.org/derby/manuals/index.html.

The Derby Web site contains the following useful documentation, as well as others:

v Getting Started with Derby: Includes a self-study tutorial for users new to Derby and a quick-start guide

for experienced JDBC users. Introduces the sysinfo and ij tools that come with Derby. Describes the

libraries and scripts that are included with Derby.

v Derby Developer’s Guide: Describes how to use JDBC to access Derby databases. It is intended for

developers building Derby applications.

v Derby Tools and Utilities Guide: Explains the ins and outs of ij, dblook and sysinfo, and describes bulk

export and import.

v Derby Reference Manual: Provides reference information, including SQL syntax and descriptions of the

system catalogs.

Developing Embedded Transaction applications

Note: Embedded Transaction applications have been deprecated from this release and will be removed in

a future release. Please contact IBM support for additional information.

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.

174 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 187: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 4. 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 178

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 180

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 190

Debugging and testing the Embedded Transaction

application.

“Debugging and testing applications” on page 449

Deploying the Embedded Transaction application to a

runtime.

“Deploying projects for local testing” on page 459

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

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 and Derby

v JDBC DataSource support

v JNDI support

v Container-managed Relationships

The following features are not supported:

v Stateful Session Beans

Developing applications 175

Page 188: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

Note: Since BigDecimal support is not included in the JSR169 driver used with J2ME databases, CMP

beans can not have BigDecimal fields when JSR169/J2ME drivers are used for persistence.

The programming models for the Embedded Transaction container and WebSphere’s Java EE 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 180.

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 Java EE 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 local data. This provides more affinity with

the Java EE EJB 2.1 programming model. While Java EE 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 Java EE EJB’s

implementations.

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.

176 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 189: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Transaction management: The Java EE 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 transactions.

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 Java EE 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

Java EE-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 an instance of the

TxnDataSource class, a subclass of the JDBC Data Source. This class is defined in an internal package.

While this TxnDataSource instance is accessible by all via JNDI, it should only be used for CMP beans.

Using a TxnDataSource in the 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.

Container managed relationships: Entity beans can be related to each other. For example, a Book bean

can be related to an Author bean.

The relationships between beans can be one-to-one, one-to-many, or many-to-many.

Developing applications 177

Page 190: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

As the name implies, when using container managed relationships, the container is responsible for the

maintaining the relationships between the beans.

Creating Embedded Transaction projects

This section provides details on 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 449 for further general information. Refer to “Debugging

and testing Embedded Transaction applications” on page 194 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 Eclipse Core Components, and Embedded Transaction Container

service selected.

178 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 191: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Note: When developing ETC applications for devices on Lotus Expeditor, you must manually import the

javax.naming package, as it is no longer included in the jclDevice boot classpath. Ensure the

following packages are imported into your MANIFEST: Import-Package:

v javax.naming

v javax.naming.spi

v javax.naming.directory

v javax.naming.event

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 Eclipse Core Components and

Embedded Transaction Container features.

5. If you select Next, the Target Platform page displays. Eclipse Core Components 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 > Development >

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:

Developing applications 179

Page 192: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Target database type

You can select either DB2e or Derby. Derby refers to Derby v10 and higher.

ETC logging level

You can select the level of trace information logged to the console during deployment and to the

OSGi LogService during 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 ETC logging level can be set at the workspace level.

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 Java EE 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 190.

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. This class must extend the BaseJDBCFinder class.

Typically the business logic of a finder method 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:

180 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 193: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

}

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(arg0, arg1)

v Collections must be used as the return type for multi-result finders. An Enumeration return type is not

supported.

Developing applications 181

Page 194: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 is the actual implementation, and CustomerHome is

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 ).

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 that is to be used for CMP persistence must be done

before JNDI binding.

Note: For information on using JDBC DataSource to access JDBC data bases, refer to “Data access

application development best practices” on page 172.

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);

}

182 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 195: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.” 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 {

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 Java EE 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 per connection; this limit was increased to 256 in DB2e v9.1. 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

Developing applications 183

Page 196: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java EE TranactionManager, the embedded transaction container’s transaction manager

does not provide an implementation of javax.transaction.TransactionManager, nor does it

support two phase commit.

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

Note: When using programmatic transaction management, embedded transaction application developers

must commit or rollback any transactions they have opened. Failure to properly close the

transaction will prevent any other transactions from being opened on that thread, independent of

what bundle is doing the opening.

Note: By default, programmatically opened transactions will remain open until an explicit commit or

rollback is called. Any attempt to open another transaction on the same thread as the open

transaction will result in an “CWPEC5804E: Thread associated with another transaction” error.

Note: The txn.duration.begin.threshold parameter is introduced to help when an erroneous

application, that does not perform the proper commit/rollback, has been installed. This parameter

sets a time limit, in seconds, after which any attempt to open a new transaction on a thread that

has an open transaction will cause the open transaction to be rolled back and the newly request

transaction to be opened. To set this parameter, add the following options to the VM arguments in

the rcpinstall.properties file: -Dtxn.duration.begin.threshold=x, where x is the integer value of

the number of seconds

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.

184 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 197: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

The following code details a custom bundle activator:

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, session beans are used to model business services. 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, 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 persistence 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.

Developing applications 185

Page 198: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

186 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 199: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

18. Use the Embedded Transaction Deployment Descriptor to fill in the ETC specific fields. Errors are

reported for any missing fields.

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.

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.

Developing applications 187

Page 200: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

17. Use the Embedded Transaction Deployment Descriptor to fill in the ETC specific fields. Errors are

reported for any missing fields.

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.

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.

188 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 201: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

16. Use the Embedded Transaction Deployment Descriptor to fill in the ETC specific fields. Errors are

reported for any missing fields.

Implementing container-managed relationships

To create a relationship between existing beans, perform the following procedures:

1. Open the EJB Deployment Description. This opens the EJB Deployment Descriptor in the editor.

2. From the overview tab, look for the section labeled Relationships 2.0, and select Add...

3. In the Add Relationship dialog, select a source bean from the left and a source bean from the right.

4. In the Relationship Name field, enter a meaningful name for this relationship.

5. In Description field, add a description for this relationship.

6. Select Next.

7. Select a multiplicity for both parts of this relationship.

If either many-to-one or many-to-many is chosen, then a return type will need to be specified under

Role Name. This must be either a Java Collection or a Java Set.

8. Name the relationship.

9. Select Finish. The new relationship is added to the specified EJB Project.

10. Use the Embedded Transaction Deployment Descriptor to fill in the ETC specific fields. Errors are

reported for any missing fields.

Developing applications 189

Page 202: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 191 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 automatically runs whenever an Embedded Transaction project is, one, selected to be run on

a Lotus Expeditor runtime that is launched through the tools, or, two, selected to be exported as a

Deployable plug-in and fragments. Refer to “Debugging and testing applications” on page 449 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.

Note: This file should not be edited directly; the Embedded Transaction Deployment Descriptor Editor

should be used to edit this file.

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.

190 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 203: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

abstract-finder-helper class that the user has supplied for the EJB, and also optionally 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 CMP 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.

ejbivar

Specifies the name of the table column that provides persistence for the CMP entity beans fields.

cmp-field

The name of the CMP entity bean field to be persisted. The value of this field should match the

value specified in the EJB deployment descriptor, ejb-jar.xml.

Embedded Transaction Deployment Editor

Information in the “Embedded Transaction Deployment Descriptor” on page 190 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. Stateless Session Beans, BMP Beans and CMP Beans will all display fields for the

Jndi-Name and the Local-Jndi-Name. CMP Beans will also have additional fields.

Table 5. Embedded Transaction Deployment Editor Bean Fields (common to Stateless Session Beans, BMP Beans

and CMP Beans)

Editor Field Description/Comments

Jndi-Name The name through which the deployed Home is accessed

via the naming service. This is a mandatory field when

EJB has a remote component interface. The tooling will

generate a default value, which is beanName (for example,

Bean1).

It is not assumed that the Home will be bound to a

java:/comp/env Context, so the name supplied in the

deployment information is used exactly “as is”.

Developing applications 191

Page 204: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 5. Embedded Transaction Deployment Editor Bean Fields (common to Stateless Session Beans, BMP Beans

and CMP Beans) (continued)

Editor Field Description/Comments

Jndi-Local-Name The name through which the deployed Local Home is

accessed via the naming service. This is a mandatory

field when EJB has a local component interface. The

tooling will generate a default value, which is

Local_beanName (for example, Local_Bean1).

It is not assumed that the Home will be bound to a

java:/comp/env Context, so the name supplied in the

deployment information is used exactly “as is”.

Table 6. Embedded Transaction Deployment Editor Bean Fields (for CMP Beans only)

Editor Field Description/Comments

Jndi-Name The name through which the deployed Home is accessed

via the naming service. This is a mandatory field when

EJB has a remote component interface. The tooling will

generate a default value, which is beanName (for example,

Bean1).

It is not assumed that the Home will be bound to a

java:/comp/env Context, so the name supplied in the

deployment information is used exactly ″as is″.

Jndi-Local-Name The name through which the deployed Local Home is

accessed via the naming service. This is a mandatory

field when EJB has a local component interface. The

tooling will generate a default value, which is

Local_beanName (for example, Local_ Bean1).

It is not assumed that the Home will be bound to a

java:/comp/env Context, so the name supplied in the

deployment information is used exactly ″as is″.

TxnDataSource This field specifies the name through which the

TxnDataSource that provides connections to the datastore

can be accessed from the naming service. This is a

mandatory field.

Table Name This field specifies the name of the relational database

table that provides persistence for this EJB. This field is

taken from the ejb-jar.xml file. It can not be modified in

this editor.

Edit ejb-jar.xml using the Deployment Descriptor

(ejb-jar.xml) editor, changes will be reflected in

embedded transaction editor.

CMP Fields This is a table that maps fields in the bean to the column

in the table that is used to persist that field’s value.

DB Column Name For each field in the CMP bean, there is a row in the

CMP Fields table. The second column in this table must

be populated with the name of the column in the table

that will be used to persist the corresponding field’s

value.

192 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 205: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 6. Embedded Transaction Deployment Editor Bean Fields (for CMP Beans only) (continued)

Editor Field Description/Comments

Finder Helper This field must be populated if there are non-primary

finders defined in this bean’s Local and/or Remote

Home interfaces.

If there are no such methods defined in these interfaces,

this field should be blank. The value of the field must be

a fully qualified class name of the class which

implements BaseJDBCFinder that contains the

implementation of the non-primary finder method(s). For

example, if your class is in the com.ibm.sample package,

and the class name is MyFinderImplementer, then enter

the following into the text field -

com.ibm.sample.MyFinderImplementer.

Note: This class must be created in same source folder as

the ejb-deploy.xml. For example, if the eejb-deploy.xml

file is under the source folder ejbModule , then this class

must also be under that source folder. Refer to

“Implementing finder methods” on page 180 for more

information on non-primary finders and their

implementation.

Deployed Class This field specifies the name of the deployed bean

implementation class. This is a required field.

Deployed-Class name must be a valid non-NULL Java

identifier.

Note: The database table used to persist instances of a CMP bean can be a pre-existing table or a table

created purely for the persistence of these instances.

Table 7. Embedded Transaction Deployment Editor Bean Fields (for beans with container managed relationships)

Editor Field Description/Comments

Package Name During deployment, code will be generated for persisting

these relationships. This is the name of the package that

will contain the generated code.

Relationship The name of the relationship. This field is taken from the

ejb-jar.xml file. It can not be modified in this editor.

TxnDataSource This field specifies the JNDI name used to access the

TxnDataSource that provides connections to the datastore

used to store the relationship.

Table Name This field specifies the name of the relational database

table that provides persistence for this relationship.

Note:

v Relationship data is stored in a separate database table (the “link table”). Each row of the link

table represents a relationship between two Entities (for example, A and B). The link table

contains a set of columns for the primary key of the first Entity, a set of columns for the primary

key of the second Entity, and an optional “discriminator” column. A link table’s column names

must follow the naming schema specified by the custom deployment information for the

corresponding CMP primary key columns, except that every column is prefixed by either r1_ or

r2_, depending on whether the column is associated with the “role 1” or “role 2” EJB.

v The link table must contain a column for every primary-key column used by A and B. Whether

R is uni-directional or bi-directional, the embedded transaction container will maintain a row in

the link-table for every relationship instance that exists between an instance of A and an instance

Developing applications 193

Page 206: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

of B. Each row in the link-table therefore uniquely identifies, and maintains sufficient persistent

state for, a relationship instance. This is straight-forward for one-to-one relationships, because

they may contain only a single row for a given pair of A and B instances. Since a CMR field

may be typed as java.util.Collection, the corresponding link table that backs a many-to-many

relationship must allow multiple rows to exist for a given instance of A or B. The discriminator

column is required when it is possible to have multiple relationships between the same two

Entities, in order to avoid duplicate primary keys in the link table. The embedded transaction

therefore requires that such link-tables contain an additional discriminator column that can store

Strings that are exactly forty characters long. This column must be named discriminator.

v When creating the tables used to persist the relationships, the above naming rules must be

strictly adhered to.

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 449.

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

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 in the documentation Assembling and Deploying Lotus Expeditor Applications.

For information on setting VM arguments when launching the runtime, refer to Configuring platform

logging and tracing in the documentation Assembling and Deploying Lotus Expeditor Applications.

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...)

194 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 207: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java EE 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

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 Java EE 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.

Developing applications 195

Page 208: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java EE 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 should not be set on the Java files in the generated-source folder.

Developing Lotus Sametime applications

This section provides information on Lotus Sametime application development.

Understanding Lotus Sametime application development

IBM Lotus Sametime Connect is a market-leading product and platform for real-time collaboration. Lotus

Sametime provides instant messaging and presence and Web conferencing features that enable people to

collaborate in real time, regardless of their physical location.

Why extend IBM Lotus Sametime Connect?

Lotus Sametime Connect 7.5.1 offers more than simple instant messaging and presence features. Because

it is built on Eclipse, a variety of plug-ins that expand the functionality of Lotus Sametime Connect are

shipped with the product, and third parties can build additional plug-ins. Some examples of plug-in

capabilities that could be added by third parties are enhanced audiovisual conferencing; instant polls of a

user community; or the ability to capture, store, and search instant message conversations or meetings.

The ability to create plug-ins to meet the growing needs of the instant messaging community, combined

with its already proven security model and numerous user interface enhancements, makes Lotus

Sametime Connect a powerful tool to help companies harness the potential of their employees.

In addition, and perhaps most important, the instant messaging and presence features in Lotus Sametime

Connect 7.5.1 are used by IBM managed client products, including future releases of IBM Lotus Notes 8.

This means that the plug-ins you build for Lotus Sametime Connect 7.5.1 will work with the managed

client products, as long as you adhere to the public interfaces documented in this guide. Your investment

in developing plug-ins for Lotus Sametime Connect 7.5.1 gives you access to a market that goes beyond

Lotus Sametime Connect users.

For more help understanding Lotus Sametime application development, please refer to the Lotus

Sametime Software Developer’s Kit, 7.5.1 Integration Guide which is available as part of the Lotus

Sametime Software Development Kit. This can be found at the IBM developerWorks website.

196 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 209: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Enabling projects for Lotus Sametime application development

This section discusses enabling projects for Lotus Sametime application development.

Client Services target profile features

The Lotus Expeditor Toolkit provides Client Services target profile support. These target profiles simplify

the creation and configuration of Lotus Sametime application projects, enabling you to select the Lotus

Sametime APIs, and provide automatic management of the requisite Lotus Sametime libraries. When

developing a Lotus Sametime application, you must select either the Client Services Sametime Target or

the Default with Embedded Sametime Target target profiles for your Client Services project. For more

information configuring your Test Environment for Lotus Sametime application development, please refer

to “Using the Lotus Expeditor Toolkit with Lotus Sametime” on page 24.

The following table provides a list of the target features and the capabilities that each provides in a Client

Services project.

Table 8. Client Services project target features and capabilities

Feature Name Provided Capability

Sametime Chat Feature Contains APIs that allow control over chat window

behavior. Also contains the ChatAction class and the chat

action extension point for chat window toolbar

contributions.

Sametime Contact List Feature Contains APIs for buddylist events and manipulation as

well as an extension point for contributing to the contact

list action bar.

Sametime Core Service Feature Contains the ServiceHub API required to retrieve

Sametime public APIs.

Sametime IM Community Feature Contains APIs for working with Sametime IM

communities as well as the Directory Service API for

looking up users and user information.

Sametime Livenames API Feature Contains APIs that allow callers to resolve names into

live objects with presence information. Also contains the

LiveNameSelection interface for popupMenu contributions

and an API to display business cards.

Sametime Message Event Feature Contains a general purpose local message event bus and

a multitude of message event types which callers can tap

into and generate.

Sametime People Feature Contains APIs for working with people and groups.

Provides a richer set of people APIs than the Livenames

API.

Sametime RTC Core Feature Contains the RTC APIs required to allow developers to

get a handle to the Sametime Java Toolkit. It contains

many rich public APIs for manipulating the Sametime

IM session.

Sametime UI Feature Contains the branding API and extension point required

to customize the look and feel of the client.

Sametime Java Toolkit Feature Contains the lower level protocol based toolkit APIs that

allow developers to leverage the functionality and

services provided by Sametime.

For more information on Client Services projects, refer to “Using the Lotus Expeditor Toolkit” on page 12.

Developing applications 197

Page 210: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Developing Lotus Sametime logic

The Lotus Sametime Developer’s Kit Version 7.5.1 provides all of the detailed information needed for

Lotus Sametime application development. The Lotus Sametime Software Development Kit can be found

at the IBM developerWorks website.

The Lotus Sametime Developer’s Kit contains a collection of information targeted at a wide range of

application developers. The subset of information that is targeted at Lotus Expeditor Toolkit development

with Lotus Sametime is contained in the Sametime Connect Toolkit. This toolkit contains samples that can

be imported into your Lotus Expeditor Toolkit. It also provides Javadoc and PDF versions of several

developers guides that provide detailed information on the Sametime APIs and detailed explanations of

the samples provided.

Since the Sametime Connect Toolkit does not require the Lotus Expeditor Toolkit, it provides instructions

on downloading and configuring a separate Eclipse SDK in sections 4.1.2 through 4.1.5 in the Lotus

Sametime Software Developer’s Kit, 7.5.1 Integration Guide, these sections can be ignored. The Lotus

Expeditor Toolkit already provides the base Eclipse SDK and configuration needed for Lotus Expeditor

and Sametime development. In addition, the section discussing creating a launch configuration (section

4.1.7) can also be ignored, as the Lotus Expeditor Toolkit test environments and Client Services Run

Configurations handle all the details of launching Lotus Sametime Client applications.

For more information on using the Lotus Expeditor Toolkit with Sametime, please refer to “Using the

Lotus Expeditor Toolkit with Lotus Sametime” on page 24.

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.

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”);

198 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 211: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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"

/>

</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);

}

}

Developing applications 199

Page 212: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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();

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 317.

Developing update manager applications

Lotus Expeditor for Devices provides the same application management API as Lotus Expeditor for

Desktop.

200 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 213: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 and micro broker provide a point-to-point JMS provider, while

the micro broker also 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

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 (known as a topic) with an intermediary (a broker). The broker then compares those

subscription topics to the topics of messages sent by other applications (publishers) and forwards

messages to those subscribers where a match is made.

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, and includes the message

topic.

A single message sent by a publisher may be matched and sent to many subscribers. 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.

A typical situation would be as follows:

Developing applications 201

Page 214: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Each subscriber individually subscribes with the broker to receive messages published to the

“Temperature” topic.

v A publication is sent from the publisher to the broker with “Temperature” as its topic.

v The broker checks its internal record of subscriptions and sends the message to each subscriber that

has registered to receive messages with the topic “Temperature”.

The following figure shows a simple publish and subscribe application that includes one publisher, one

broker, and three subscribers.

A publish and subscribe application may have more than one publisher, more than one subscriber, and

even more than one broker. If necessary, an application can be both a publisher and a subscriber to one or

more brokers.

Topics and hierarchical topic names: A topic is a character string that describes the data that is

published in a publish and subscribe system.

Figure 4. A simple publish and subscribe application

202 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 215: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Topics are created in the broker when a client sends a request to subscribe to or publish a message to a

given topic. For example, when a client subscribes to a topic, that topic is registered within the broker

simply because a client is subscribed to it and will thus receive any future matching publications. It is not

necessary for a client to create topics as a specific step independent of a subscription request.

Topics are key to the successful delivery of messages in a publish and subscribe system. Rather than

specifying destination addresses for each message, a publisher assigns a topic to the message. The

message broker then matches the topic against a list of clients (subscribers) who have subscribed to that

topic, and delivers the message to each of those clients where a successful match is made.

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

204.

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 namespace as a flat, linear structure, it is better to build a topic tree

as 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:

finance

finance/stock

finance/stock/ibm

finance/stock/xyz

Figure 5. Hierarchical topic tree

Developing applications 203

Page 216: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, but three specific characters have

special meanings. These characters (″/″, ’#″, and ″+″) allow solution designers flexibility in controlling

message flow by choosing carefully the topics that are specified for each message.

The topic level separator (″/″) introduces hierarchical structure into the overall topic namespace, while

the the multi-level wildcard and single-level wildcard can be used for subscriptions. Note, however, that

the wildcards 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, a subscription to finance/stock/ibm/# receives messages published to all of 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/# matches the

singular finance, where # represents zero levels, as well as all topics further down the hierarchy.

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 immediately following the topic

level separator character. Therefore, # and finance/# are both valid, but finance# is not valid. The

multi-level wildcard must also 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 a single 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.

The single-level wildcard can be used at any level in the topic tree, and in conjunction with the

multilevel wildcard. The single-level wildcard must follow 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 may be used anywhere within the topic tree. For example, finance/+ and

finance/+/ibm are both valid. It cannot be used as part of a name. As a result,

finance/stock/ibm/+price is not 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:

204 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 217: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v A topic must be at least one character long.

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

both ″+/+″ 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 64 KB 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 213.

What is a publisher?

A publisher is a client application that creates a publication message, associates it with a topic, and sends

the message to the broker. The broker is responsible for distributing the message to all applications

subscribed to that 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 to all applications that have subscribed

to the publication’s topic and distributes it to those applications.

If configured to do so, 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 all of a topic’s subscribers, the broker deletes it. However, the

topic publisher can request that the broker keep a copy of the publication, which is then called a retained

publication. The broker saves a retained publication and any new subscriber to its topic receives a copy of

the publication. Note that only a single retained publication is saved per topic.

The advantage of retained publications is that applications making new subscriptions to the topic will

immediately receive the retained publication and will not have to wait until the next message on the

topic is published. This allows the application to initialize itself immediately, rather than having to wait

an indeterminate amount of time until it first receives a message.

Note: Only MQTT messages may be published as retained messages (see ADD LINK HERE Messaging

Protocols for more information). JMS messages do not support this function. Both MQTT and JMS

clients support receiving retained publications, but JMS clients can see no difference between

normal and retained publications, whereas MQTT clients can detect the difference.

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 one or more subscription messages to the broker. These messages define the topics

in which the application is interested. The broker then sends publication messages to the subscribing

Developing applications 205

Page 218: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

application whenever a publication matching one of the set of client topics is processed. When the

application no longer wants to receive publications, it can unsubscribe from topics to which it has

previously subscribed.

A publish and subscribe messaging topology is a flexible arrangement that allows applications to be

added and removed without impacting other applications. 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.

Of course, the topic name and the format of the data in the message have to be well defined, as these are

the common pieces of information shared between a publishing and subscribing application. Once these

are established, you can add or remove applications to publish or subscribe as required.

Table 9. 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 that needs

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 202 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 a 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.

206 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 219: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

There aretwo 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

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, at which

time they are forwarded to the subscriber.

Publish/Subscribe messaging is supported in the micro broker using both the MQTT protocol and the

JMS API; these are discussed further in ADD LINK HERE Messaging “Protocols”.

Point-to-point messaging

In contrast with publish/subscribe messaging, which allows a publisher to send a message to multiple

subscribers, point-to-point messaging is designed to allow communication from one message producer to

one message consumer.

Note that this is at the individual message level. A single producer can send messages to multiple

consumers and a consumer can receive messages from many producers. However, a particular message

will be sent from one producer to just one consumer.

Queues provide the underlying mechanism by which messages sent by producers are held by the micro

broker until a consuming application is ready to receive and process them. Queuing allows you to:

v Communicate between programs (which might each be running in different environments) without

having to write the communication code.

v Select the order in which a program processes messages.

v Balance loads on a system by arranging for more than one program to service a queue when the

number of messages exceeds a threshold.

v Increase the availability of your applications by arranging for an alternative system to service the

queues if your primary system is unavailable.

In message queuing terminology, a message is a collection of data sent by one program and intended for

another program. A queue manager is a system program that provides queuing services to applications. It

provides an application programming interface so that programs can put messages onto, and get

messages from, the queues it manages. A queue manager also provides additional functions so that

administrators can create new queues, alter the properties of existing queues, and control the operation of

the queue manager.

Message queuing is a technique for indirect program-to-program communication. It can be used within

any application where programs communicate with each other. Communication occurs by one program

putting messages onto a queue (owned by a queue manager – the micro broker in this case) and another

program getting the messages from the queue. There are no physical connections between programs that

communicate using message queues. This process is illustrated in the figure below.

Developing applications 207

Page 220: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

As already mentioned, the point-to-point messaging paradigm provides one-to-one messaging. Programs

requesting others to do work do not have to wait for the reply to a request. They can do other work, and

process the reply either when it arrives or at a later time. When writing a messaging application, you

need not know (or be concerned about) when a program sends a message, or when the target is able to

receive the message. The message is not lost; it is retained by the queue manager until the target is ready

to process it. The message stays on the queue until it is removed by a program.

A program can assign a priority to a message when it puts the message onto a queue. This determines

the position in the queue at which the new message is added. Programs can get messages from a queue

either in the order in which the messages appear in the queue, or by getting a specific message. (A

program might want to get a specific message if it is looking for the reply to a request that it sent earlier.)

The physical nature of a queue depends on the operating system on which the queue manager is

running. A queue can either be a volatile buffer area in the memory of a computer, or a data set on a

permanent storage device, such as a disk. The physical management of queues is the responsibility of the

queue manager and is not made apparent to the participating application programs. Programs access

queues only through the external services of the queue manager. Typical operations include opening a

queue, putting messages on it, getting messages from it, and closing the queue. An administrative

interface provides the ability to set and inquire about the attributes of queues.

The micro broker incorporates a queue manager that supports point-to-point messaging and queues as

described above.

When you enable the option to create queues dynamically (the default setting), the micro broker creates a

queue automatically if a message consumer or producer is created for a previously unknown queue.

Dynamic queues have the benefit that administration is unnecessary unless you want to change the

default values for settings, such as maximum queue depth. A dynamic queue will automatically expire

and be deleted if it sits empty and is not used for a defined amount of time. See Configuring the broker

for more information.

Messaging protocols

The micro broker supports two types of messaging for communicating with its clients and with other

brokers. The first uses messages built according to the MQTT V3 protocol (details of which are publicly

available, see below), while the second uses the Java Messaging Service (JMS) API specification.

Each of these methods has its own strengths and weaknesses. The following is a brief summary their

features:

JMS

The micro broker JMS client provides a rich messaging interface for business applications, and contains

the following functionality:

v Implements the J2EE JMS 1.1 standard interfaces

MessageMessage Sender Receiver

Message Server

MessageQueue

Figure 6. Point-to-point messaging

208 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 221: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Supports all of the JMS message payload types (Text, Bytes, Object, Map, Stream)

v Supports both persistent and non-persistent delivery modes (equivalent to QoS2 and QoS0 for MQTT –

see below)

v Provides JMS constructs and transactional models

v Supports synchronous and asynchronous consumers

v Supports durable subscriptions

v Supports JMS selectors

v Supports the “No local” property

v Supports the JNDI administration model

v Does not support XA transactions

MQTT

The micro broker MQTT client is designed for applications that need a lightweight but functional

protocol. It includes the following functionality:

v Designed to support specialized embedded applications, particularly in constrained environments

v Uses the MQTT pervasive messaging protocol

v Supports only the publish/subscribe messaging paradigm

v Supports asynchronous message delivery only

v Supports retained publications

v Provides a raw byte message format with no user defined header properties

v Offers no support for application control of transactions, “no local” or message selectors

v Provides three qualities of service (QoS) for message delivery as per the MQTT specification (see

below)

v Provides an optimized proprietary programming model

v Implements a listener callback pattern for delivery of messages, loss of network connectivity, and so on

The JMS interface is well documented in the Sun specification. The next section provides some further

information about the ADD LINK HERE MQTT protocol.

MQTT

The MQTT protocol is a messaging protocol designed to enable messaging to and from tiny devices such

as sensors and actuators. A typical sensor might be a thermocouple, measuring the temperature of a

component within an overall process. An example of an actuator could be a valve that controls the flow

of coolant to the component.

Refer to WebSphere MQ Telemetry Transport and http://www.mqtt.org for more detailed information

about the MQTT protocol specification.

The micro broker implements the server half of the MQTT protocol. This allows MQTT clients to connect

as publishers and subscribers. Note that MQTT does not support point-to-point messaging.

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.

Developing applications 209

Page 222: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 be selected on a message-by-message basis, allowing less important messages to be

published using QoS 0 and the most important messages to be delivered using QoS 2.

Publishing and subscribing clients both specify a QoS to use. When they differ, the micro broker sets the

QoS or a message being sent to a client to 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 for some time. This is known as an in doubt

window. In this situation, 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 previous state information held in relation to the client on connection and discard any client

state information after the client disconnects. State for a client can be maintained by the broker by setting

the clean session property to false. Then, if the client is disconnected, it can resume its work with the

server from the point of disconnection.

Client state information held in the broker includes subscriptions registered by the client and any

publications destined for the client. This state data also includes information about any in-flight message

delivery at the point of disconnection. Thus, if a disconnection occurs while a QoS 1 or QoS 2 message

flow is in progress and a clean session is set to false, the client and broker will attempt to complete the

flow when reconnected. Note that this does not mean that the MQTT client can continue to send

messages while disconnected from a broker, only that any in-flight message flows at disconnect time may

be resumed.

Note: The JMS client provides a buffered mode, should support for messaging while the client is

disconnected be needed.

210 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 223: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, should the client disconnect 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

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

The Lotus Expeditor micro broker component is a small message broker that provides a messaging fabric

for integrating various parts of a solution. It is particularly aimed at resource limited environments such

as those that may be found in “edge of network” devices running applications that measure and control

physical properties (temperature and fluid flow, for example) using 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. It allows use of both publish and subscribe and point-to-point messaging

models. The messaging infrastructure it provides allows lightweight messaging clients to communicate

with each other, within a single device, across a network, and to integrate 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.

Developing applications 211

Page 224: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 methods to monitor flood levels through the use of pervasive computing technologies. These 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

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

These are found at the edge of the network, and include components such as RFID readers,

motion sensors, and light stacks.

Edge server

This is 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

This system manages a retail location, warehouse, or distribution center. Multiple edge servers

may be connected to a premises server.

Enterprise server

This is the “back-office” system that manages global information from all premises servers.

A basic use case validates that a pallet 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 tag data, performing

tasks such as removing duplicate tag readings. The filtered tag data is 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. This process may require an exchange with message the enterprise server to perform the

212 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 225: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

At 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 on the edge server, and

accepts command and control messages that are mapped to the device sensors and actuators.

Certain messages are routed to the premises server for processing. In this example, a tag is sent to the

premises server to validate that it is expected at this retail location. The micro broker accepts messages

destined for the premise servers and ensures the message is delivered to another micro broker on the

premises server. Typically, a bridging component in the premises server micro broker is then used to

route messages, destined for the back-office enterprise level servers to be processed.

Understanding the micro broker components: The micro broker logically consists of three major

components: the broker, the bridge, and the clients. In addition, an administration interface provides a

method of controlling the behavior of the micro broker.

Broker

The broker is the component to which client applications connect to perform both point-to-point and

publish and subscribe messaging. It handles putting and getting messages from queues, and the matching

of publications to subscriptions and the subsequent distribution of publications to subscribing

applications. The broker also manages the persistence of messages to ensure message delivery at the

required quality of service.

It acts as a hub for routing messages between clients and with the aid of the bridge, other messaging

servers. The broker can store messages destined for a client that is not connected and make them

available to the client when it reconnects. In addition, it stores messages on behalf of the bridge and

makes them available when the messaging servers that the bridge connects to are on line.

The broker supports three different types of persistence for storing messages and subscriptions. The type

of persistence is selected when a broker is created and is based on how the broker is to be used in a

particular situation. The types of persistence supported are:

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. The persistent store is a purpose-designed high-performance message store that

resides in flash memory, on disk, or where appropriate for the particular device running the

micro broker.

Bridge

The bridge is the component of the micro broker that connects and routes messages to and from 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

Developing applications 213

Page 226: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v WebSphere Application Server

v Any JMS provider

The bridge can route messages between the micro broker and one or more other messaging servers. If the

bridge cannot connect to a specific messaging server, messages destined for that 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.

The bridge is a key component in the micro broker, as it is the link back into the enterprise. It performs

the following functions:

v Allows administrators to define transformation logic to modify or discard messages as they flow to

and from the micro broker

v Maps message flows from destinations within the micro broker to those of a remote messaging server

and vice versa

v Allows local queues and topics to be routed to and from remote queues and topics - If desired, queues

may be routed to topics and vice versa, as well as queues to queues and topics to topics

Three connectors are supplied to connect the bridge to remote endpoints. They consist of two types of

JMS connector and an MQTT connector:

v WebSphere MQ JMS to connect to a remote WebSphere MQ queue manager

v JNDI JMS to bridge to a third-party JMS provider that supports JNDI administered objects

v Connects the micro broker to another messaging server that supports the MQTT protocol such as

WebSphere Message Broker or another micro broker

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.

In general, clients do not persist messages; they simply provide a means for an application to interact

with other clients (applications and services) using a broker (note that the JMS client, however, provides a

buffered mode, discussed below). Before a client can interact with a broker, the client 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 to which it has subscribed. The broker can store

messages on behalf of a client, allowing the client to receive stored messages when it next connects. 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 JMS API specification. It also provides a buffered mode in which an

application is able to send messages regardless of the true state of the connection with the micro

broker. This allows the client to operate in environments where the connection to the micro broker may

214 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 227: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

not always be available. The client stores the messages, forwarding them to the broker when the

connection is reestablished. 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 in devices with

constrained environments or where there is a specific requirement to use the MQTT protocol. As IBM

WebSphere Message Broker 6 supports the MQTT v3 protocol, this client may also be used to directly

connect to it.

Prerequisites: There are no additional prerequisites for the micro broker itself, the micro broker bridge

core and MQTT bridge connection other than the supplied OSGi bundles. If the micro broker bridge is to

be used with the MQ JMS or a JNDI JMS provider, the minimum level of Java required is J2SE 1.4.2 or

the version specified by your JMS provider, if this is greater. Note that in order for the micro broker

bridge to successfully reference your JNDI JMS provider through the OSGi runtime, your JMS provider

classes and JAR files need to be made available using an OSGi bundle.

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.

The micro broker acts as a message hub for the clients connected to it, allowing them to send messages to

each other. Clients can run in the same process (Virtual Machine (VM) that implements the Java

specifications) as the micro broker, in a different process on the same computer, or even on a different

computer, thus providing a powerful messaging infrastructure.

MicroBroker

Client

Client

Client

Client

Client

Client

Developing applications 215

Page 228: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

A broker 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 adapters. 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 connected 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 can store messages and deliver

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 may be on-board with the micro broker.

Three tier: The micro broker 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 and point-to-point queue spaces to

the WebSphere MQ queue space or publish and subscribe topic space.

JNDI-enabled JMS providers

The bridge maps the micro broker publish and subscribe topic and point-to-point queue spaces to

the JMS provider’s queue space or publish and subscribe topic space.

These systems can then route messages on to yet 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 on page 217 shows a set of micro broker

components that are linked together as peers, some of which are linked to the enterprise.

216 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 229: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Environments: micro broker can be run within and without OSGi in the following environments. There

are different instructions for using the micro broker depending on where it is being run. Please follow the

correct documentation for your desired environment.

OSGi: The OSGi Alliance defines a platform for the packaging and dynamic delivery of Java software

services to networked devices. This is achieved using a consistent component-based architecture for the

development and delivery of Java software components known as bundles and services. micro broker is

provided as a number of OSGi bundles and services for use in an OSGi environment. See

http://www.osgi.org for more information about OSGi.

Non-OSGi: The OSGi bundles are simply jar files with specific information included in their manifest

files. These jar files can be used in a non-OSGi environment and are made available by including the

relevant jars on the class path.

OSGi:

The OSGi Alliance defines a platform for the packaging and dynamic delivery of Java software services to

networked devices.

This is achieved using a consistent component-based architecture for the development and delivery of

Java software components known as bundles and services. micro broker is provided as a number of OSGi

bundles and services for use in an OSGi environment. See http://www.osgi.org for more information

about OSGi.

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 217

Page 230: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Non-OSGi: The OSGi bundles are simply jar files with specific information included in their manifest

files. These jar files can be used in a non-OSGi environment and are made available by including the

relevant jars on the class path.

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 10. MQ Everyplace and micro broker comparison

WebSphere MQ Everyplace Micro broker and MQTT

JMS provider included Yes; Point-to-Point provider Yes; Point-to-Point and Publish and

Subscribe

Messaging paradigm Point-to-Point (queue-based) Point-to-Point and Publish and

Subscribe

Implementation type Java-based (platform-independent)

implementation

Java-based (platform-independent)

implementation

Bridging Supports bridge to WebSphere MQ

and WebSphere Message and Event

Brokers

Supports bridge to any generic JMS

provider, or specifically WebSphere

MQ and WebSphere 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 Yes

Built-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 definition features

The Lotus Expeditor Toolkit provides Client Services target definition support. These target definitions

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

definitions 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 11. 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 or MQ Telemetry Transport Client JMS

Support and Java Message Service (JMS) APIs

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

218 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 231: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

For more information on Client Services projects, refer to “Using the Lotus Expeditor Toolkit” on page 12.

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 12. 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.

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

Developing applications 219

Page 232: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 12. Network Layer Plug-ins (continued)

Plug-in Contribution

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 Layer 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

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;

220 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 233: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

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

com.ibm.rcp.locationmanager.LocationManager.setPreferOffline), there is no need to implement the

callback methods goOnline() or goOffline().

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

Developing applications 221

Page 234: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

//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:

<?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

222 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 235: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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 ConnectFault) {

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>

Developing applications 223

[[[[[[[[[[[[[[[[[[[

Page 236: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

224 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 237: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

} 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;

}

};

Developing applications 225

Page 238: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

//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.

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.

Configuring the proxy settings for Lotus Expeditor

The proxy setting is global, that is, the whole runtime share the same proxy settings. The HTTP/HTTPS

connection is stateless and picks up whatever proxy settings at the time the application opens the

connect.

Both basic and NTLM proxy servers are supported. If connecting thru an NTLM proxy, the proxy server

must support NTLM v1.

226 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

Page 239: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The following Eclipse preference information should be added to the com.ibm.rcp.net.http node:

v http.ProxyHost - indicates the proxy server host (String default null)

v http.ProxyPort - indicates the proxy server port (int default 80)

v http.nonProxyHosts - indicates the hosts which should be connected to directly and not through the

proxy server; the value can be a list of hosts, each separated by a ″|″, for example:

http.nonProxyHosts=“www.foo.com|localhost"

v http.IsSecureProxy - indicates whether the proxy needs a user ID and password (boolean default

false)

The following example code details the configuration of proxy settings for Eclipse preferences:

IScopeContext context = null;

IEclipsePreferences prefNode = null;

try {

if(prefNode == null) {

context = new InstanceScope();

prefNode = context.getNode("com.ibm.rcp.net.http");

}

} catch (Exception ex) {

ex.printStackTrace();

}

prefs2.putInt("http.ProxyPort", 80);

prefs2.put("http.ProxyHost", x.xx.xx.xx");

prefs2.putBoolean("http.IsSecureProxy", true);

prefs2.put("http.nonProxyHosts", "127.0.0.1|ww.oreilly.com |localhost");

If the proxy server requires a user ID and password, the following information is required in the

Account:

v Account name - use PROXY.ACCOUNT

v Authentication type - use PROXY.BASIC or PROXY.NTLM (reserved for future use)

v Account user name - use Account.USER_NAME

v Account password

The following code details the placement of the proxy user ID, password and authentication type into the

Account:

AccountsManager accountManager = AccountsManagerFactory.getAccountsManager();

Account account = accountManager.getAccountByName("PROXY.ACCOUNT");

try {

if(account==null){

account = new Account();

account.setProperty(Account.USER_NAME, user); //$NON-NLS-1$

account.getLoginContext().setPassword(passwd); //save the password

account.setName("PROXY.ACCOUNT");

account.setType("PROXY.BASIC");

accountManager.addAccount(account);

}else{

account.setProperty(Account.USER_NAME, user); //$NON-NLS-1$

account.getLoginContext().setPassword(passwd); //save the password

account.setName("PROXY.ACCOUNT");

account.setType("PROXY.BASIC");

accountManager.updateAccount(account);

}

}catch (AccountsException e) {

e.printStackTrace();

}

Developing applications 227

Page 240: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java

EE 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 13. Portlet development activities

Task Reference

Understanding Client Services Portlet development. “Understanding Portlet applications”

Working with Client Services Portlet projects. “Creating Portlet projects” on page 231

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 233

Importing Portlet application projects. “Importing Client Services Portlet projects” on page 233

Debugging and testing Portlet applications. “Debugging and testing Client Services Portlet

applications” on page 236

“Client Services Server” on page 450

Deploying Client Services Portlet applications. “Deploying projects for local testing” on page 459

Using the command line WAB tool to convert a WAR to

a WAB.

“WAB Utility” on page 336

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

Client Services Portlet application must also be a valid OSGi bundle. Refer to “Working with OSGi

bundles” on page 505 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 Java EE 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 336.

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.

228 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 241: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

/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.

Developing applications 229

Page 242: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

/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.

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 14. 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.

Basic Portlet A Portlet application that extends the GenericPortlet

class defined in the Java Portlet Specification 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:

230 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 243: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.x 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 518):

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.

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 233 describes how to use the Lotus Expeditor 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 233.

Creating Portlet projects

This section provides information on creating Portlet projects.

Developing applications 231

Page 244: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.1. Refer to

“Portlet API and Type support” on page 230 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 Definition page to make target definition and target features and

plug-ins selections. The Target Definition page displays the current default Target Definition which is

set on the Client Services Preference page. The Eclipse Core Component, 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 Java EE Portlet project to a Client Services Portlet project

To convert an existing Java EE 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 (RSDP) or WebSphere Application Server Toolkit

(AST) with the Lotus Expeditor Toolkit installed.

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 Definition selection page. Eclipse Core Components, 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 514 for information on how to use

this wizard.

232 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 245: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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:

Developing applications 233

Page 246: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 15. 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.

The Portlet aggregation function is not available for all types of projects and on all platforms. For

example, the Portlet aggregation functionality provided by the Lotus Expeditor Portlet Tooling is not

supported on the WebSphere Application Server Toolkit platform. To use this function and aggregate

Portlets, you must install the Lotus Expeditor Toolkit into the Rational Software Development Platform.

In addition, you can only use the Portlet aggregation function with the following types of projects:

v Client Services Portlet projects

v Client Services Web projects

v JSR168 Portlet projects targeting

v WebSphere Application Server 6.1

v Dynamic Web projects

The Add to Portlet JSP function is only available when aggregating JSPs that are part of the above types

of projects.

Securing Portlet application resources

Though the Java EE 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 Java EE 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>

<portlet-name>TestPortlet</portlet-name>

</portlet-collection>

<user-data-constraint>

<transport-guarantee>CONFIDENTIAL</transport-guarantee>

</user-data-constraint>

</security-constraint>

234 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 247: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Customized Portlet Modes Support

Portal vendors may define custom Portlet modes for vendor specific functionality (for example, the

″config″ mode in IBM WebSphere Portal). JSR-168 also allows a Portlet to support these vendor specific

modes. JSR-168, Appendix A, defines a list of Portlet mode names, including ″about″, ″config″,

″edit_defaults″, ″preview″, and ″print″, as well as their suggested utilization.

In Lotus Expeditor, these five custom modes are supported by the Portlet container. As a result, if your

JSR-168 Portlet contains any of the above five modes, or a sub-set of them, the modes will work on Lotus

Expeditor, and you can access them through both Portlet viewer and the Portlet aggregation pages.

If your Portlet contains custom modes other than the above five, they will not be supported by Lotus

Expeditor’s Portlet container. You will not be able to access the modes through the either the Portlet

viewer or Portlet aggregation page, and you will receive a WARNING in the Lotus Expeditor system log.

″Config″ mode support in JSR-168 Portlets

The following examples provides details on supporting ″config″ mode in a JSR-168 Portlet.

1. Define the ″config″ mode in the Portlet descriptor (portlet.xml):

<portlet-app>

...

<portlet>

...

<supports>

...

<portlet-mode>config</portlet-mode>

...

</supports>

...

</portlet>

<custom-portlet-mode>

<name>config</name>

<description>...</description>

</custom-portlet-mode>

...

</portlet-app>

2. Support the ″config″ mode in the plugin.xml:

<extension point="com.ibm.pvc.webcontainer.application">

...

<portletOptions>

Developing applications 235

[[[[[

[[[

[[[

[

[

[

[[[[[[[[[[[[[[[[[

[

[[[

Page 248: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<portlet>

<portlet-name>DatePortlet</portlet-name>

<supports>

...

<portlet-mode>config</portlet-mode>

</supports>

...

</portlet>

</portletOptions>

</extension>

3. Override the GenericPortlet.doDispatch() method to add your application logic for ″config″ mode:

protected void doDispatch(RenderRequest request, RenderResponse response) throws

PortletException, IOException {

if("config".equals(request.getPortletMode().toString())){

...

return;

}

super.doDispatch(request, response);

}

The JSR-168 Portlet now supports the ″config″ mode.

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.

236 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[[[[[

[

[[[[[[[[[[

[

Page 249: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Developing applications 237

Page 250: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Open

will display MyApplication as one of the selectable applications. Refer to “Debugging and testing

applications” on page 449 for more information on how to launch the client platform.

238 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 251: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 117 and

“Using widgets on devices” on page 120.

Creating a simple Rich Client Application for devices

This section provides device specific information for creating Rich Client Applications.

Note: Manufacturers of WinCE devices may customize the WinCE build provided on their devices and

may remove function they deem unnecessary on the device. For instance, on the Symbol MC9090,

full image and sound support is not provided. The Internet Explorer and browser widgets cannot

display PNG images. The javax.sound API does not function. When developing applications for

WinCE devices, you should check that all the devices you intend to support include the

capabilities you need.

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. A Lotus Expeditor Toolkit Configuration dialog appears. For Test Environment, choose Lotus

Expeditor for Device, then click OK.

4. Select Go to the workbench.

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 Client Services 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.

Developing applications 239

Page 252: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

3. Select org.eclipse.ui.part, org.eclipse.ui.plugin, then click OK.

4. Click Save.

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.

7. Change the application name to something user friendly.

Next, add a view for your application:

1. On the Extensions tab click Add.

240 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 253: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 to one of the following based on intended use of the view:

v org.eclipse.ercp.category.normal

v org.eclipse.ercp.category.large

v org.eclipse.ercp.category.status

Connect your view to your application:

1. Right click the application element under org.eclipse.ercp.eworkbench.application in the All

Extensions list.

2. Click New > views.

3. Copy the view ID specified in the section above to the Normal field.

4. Click Save.

Using the eRCP templates to create a Rich GUI application:

Lotus Expeditor allows you to create a template for an eRCP Rich GUI application by invoking the Client

Services Project creation wizard.

There are two templates for eRCP Rich GUI applications:

v eRCP Basic Application Template - A wizard template that creates a minimal Basic embedded Rich

Client Application containing a text field, two check boxes, and two radio buttons.

v eRCP e-Mail Application Template - A sample class that demonstrates how to plug-in a new

workbench view. The view shows data obtained from the model. The sample creates a dummy model

on the fly, however, a real implementation would connect to the model available in this or another

plug-in (for example, the workspace). The view is connected to the model using a content provider.

To invoke the templates, perform the following procedure:

1. Select File > New > Project...

2. Expand the Client Services folder.

3. Select Client Services > Next.

4. Enter a project name.

5. Click Next and then Next again.

6. Select one of the eRCP templates.

7. Click Next and then Finish.

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. Press Apply and then Run.

Developing applications 241

[

[[

[

[[

[[[[

[

[

[

[

[

[

[

[

Page 254: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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. Expand 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.

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.

g. Repeat this process to rename org.eclipse.ercp.app.preferences to my.app.preferences.

h. Repeat this process to rename org.eclipse.ercp.app.views to my.app.views.9. Modify the sample code:

a. Modify the manifest to uniquely identify the plug-in:

1) Expand META-INF.

2) Open MANIFEST.MF.

3) Change org.eclipse.ercp.app reference in Bundle-SymbolicName to my.app.b. Modify the extension IDs:

1) Select the Extensions tab.

2) Expand everything under org.eclipse.ercp.eWorkbench.applications.

3) Select eRCP eMail Sample (application) and change the ID to my.app.

242 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 255: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

4) Change normal to my.app.views.normal.

5) Change 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.

7) Save and close the manifest.

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.c. Modify the resource file to uniquely identify the plug-in in the user interface:

1) Open plugin.properties. Modify the appname value to: My App.

2) Save and 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.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 restrict this site to devices (optional):

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:

Developing applications 243

Page 256: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 on a Windows Mobile or WinCE device, 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.

To install an eRCP workbench application on a Nokie E90 device see the Nokia eRCP User’s Guide.

Running an eRCP eWorkbench application

To run an eRCP eWorkbench application on a Windows Mobile or WinCE device, perform the following

procedure:

1. Select Start > Programs > Lotus Expeditor.

2. Select My App.

To run an eRCP eWorkbench application on a Nokia E90 device, perform the following procedure:

1. Select Applications.

2. Select Installations.

3. 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. Another 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 is greater than 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.

244 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 257: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 StyleService 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 service is initialized with CSS content and

any widgets that have registered themselves with the style service are updated with style properties that

reflect the new CSS content.

Using themes in 6.1.1

After constructing a widget, you can call the StyleManager to apply the proper styling. 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 SAC: Simple API for CSS 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 style 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.

Developing applications 245

Page 258: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

SButton myButton = new SButton(parent, SWT.PUSH);

myButton.setData(StyleManager.CSS_CLASS, “LaunchButton”);

StyleManager.getInstance().style(myButton, false, false);

Using themes in 6.1.2

The personality framework class provided by the com.ibm.rcp.personality.framework plug-in manages

the initialization of the StyleService and retrieves the appropriate CSS content. Currently, there is no

support for programmatically contributing CSS content to the style service.

SWTEx widgets are registered with the StyleService by default.

To register a standard SWT widget with the style service:

1. Obtain a reference to the StyleService using the OSGi service locator or the SWT Display.

For example:

StyleService styleService = Display.getCurrent().getData(StyleService.class.getName());

Another example:

ServiceTracker themeServiceTracker = new ServiceTracker(context, IThemeService.class.getName(), null);

themeServiceTracker.open();

IThemeService themeService = (IThemeService)themeServiceTracker.getService();

StyleService styleService = themeService.getStyleService();

URL cssURL = new URL(cssLocation);

styleService.parse(cssURL);

2. Make a single call to the style() method for the widget.

For example, the following code registers an instance of Button with the style service:

Button myButton = new Button(parent, SWT.PUSH);

styleService.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.

246 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[[[

[

[

[

[

[

[

[[[[[[

[

[

[[

[

[

Page 259: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

Button myButton = new Button(parent, SWT.PUSH);

styleService.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);

Button myButton = new Button(myComposite, SWT.PUSH);

myComposite.setData(StyleService.CSS_CLASS, “MainWindowâ€);

styleService.style(myButton, false);

...

// Create a button widget of class LaunchButton and style it

// but do not update the button if the styles change

Button myButton = new Button(parent, SWT.PUSH);

myButton.setData(StyleService.CSS_CLASS, “LaunchButtonâ€);

styleService.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

CSS content: The CSS content that makes up a theme is comprised of elements, classes and pseudo

classes that are specific to the Lotus Expeditor platform. The properties and value formats, with the

exception of a few CSS extensions, are standard CSS. The StyleService does not support the entire CSS

specification as defined by WC3. Lotus Expeditor currently onlt support what is needed to theme and

Developing applications 247

[

[[[

[

[[[[[[[[[[[[[[[[

[

Page 260: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

brand the client. The following list details the elements and classes that are supported, and how they

map to elements and classes of the Lotus Expeditor platform. The term ″classes″ refer to CSS classes and

not Java classes. Elements map directly to the corresponding standard and custom widgets of the same

name (minus the ‘S’ for SWidgets). Thus, a shell class maps to the Shell widget and the button class

maps to the Button and SButton widgets. There is one exception to this convention: the sideshelf

element. The sideshelf element maps to the SViewStack widget.

The following is a list of properties that are currently supported by each widget:

Note:

v These are the properties that have been tested thus far and are required to implement the visual

design for Lotus Expeditor, Lotus Notes 8 and Lotus Sametime Connect 7.5.1. There are some

cases where support for properties - such as border-radius - are inconsistent. For example, the

viewform widget only supports specifying border radius for the top left and top right corners.

Padding and margin property support may also be inconsistent. There is also a limitation when

specifying border radius with values greater than zero: only a single border color and width

may be specified.

v The preference value com.ibm.rcp.ui/UI_FONT_FACE allows you to override the CSS font property

font-family below. For example, if you want to use the Japanese font ″MS PGothic″, add the

following line in the plugin_customization.ini file in the branding plug-in:

com.ibm.rcp.ui/UI_FONT_FACE=MS PGothic

The ″MS PGothic″ font displays as the UI font. This also works for Chinese GB18030 support.

Specifically, to use the GB18030 font, add the following line in the plugin_customization.ini

file:

com.ibm.rcp.ui/UI_FONT_FACE=SimSun-18030

Be aware that using the UI_FONT_FACE value replaces all font-family CSS values.v button (classes: LaunchButton, CloseButton, TabCloseButton, LaunchChevron, CollapseButton)

– border-top-width

– border-left-width

– border-bottom-width

– border-right-width

– border-radius color

– border-color

– font-family

– font-size

– font-weight

– background-color

– list-style-image

v tabfolder

– color

– background-color

v tabfolder > tabitem

– color

– border-radius

– border-color

– border-width

– background-color

– font-family

– font-size

248 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 261: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

– font-weight

v tabfolder > tabitemMenu

– border-top-width

– border-left-width

– border-bottom-width

– border-right-width

– border-radius

– color

– border-color

– font-family

– font-size

– font-weight

– background-color

v composite (classes: LaunchArea, TabFolderList, CommonNavigatorView, CommonViewWithPreview )

– color

– font-family

– font-size

– font-weight

– border-radius

– border-width

– background-color

v coolbar

– background-color

– border-radius

v toolbar (classes: chevron, statusline, view, DockedLauncher)

– border-width

– border-radius

– border-color

– background-color

v toolbar > toolitem

– color

– font-family

– font-size

– background-color

– margin-top

– margin-right

– margin-bottom

– margin-left

– padding-left

– padding-top

– padding-right

– padding-bottom

– border-color

– border-width

– border-radius

Developing applications 249

Page 262: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v coolbar > gripper

– list-style-image

v sash, sideshelf > sash (class: Preview)

– color

– border-color

– background-color

v sideshelf

– color

– border-top-width

– border-right-width

– border-bottom-width

– border-left-width

– border-color

– background-color

v statusline

– font-family

– font-size

– font-weight

– color

– background-color

v viewform

– color

– font-family

– font-size

– font-weight

– background-color

– border-top-left-radius

– border-top-right-radius

– border-top-bottom-radius

– border-top-bottom-radius

– border-width

– border-color

v viewform > title

– color

– font-family

– font-size

– font-weight

– border-top-left-radius

– border-top-right-radius

– background-color

v viewform > title > menuButton

v viewform > title > minimizeButton

v viewform > title > restoreButton

v viewform > title > maximizeButton

– list-style-image

250 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 263: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v menu

– color

– border-color

– background-color

– border-radius

– border-left-color

– border-right-color

– border-bottom-color

v menu > menuitem

– color

– background-color

– font-family

– font-size

– font-weight

v shell (class: MainWindow)

– background-color

v separator (classes: TabPageSeparator, ToolbarPageSeparator, StatusLineSeparator)

– background-color

v table > row

– color

– background-color

v table > row > narrowview

– border-bottom-color

– border-bottom-width

v table > columnheader

– border-style

– border-width

– border-top-color

– border-left-color

– border-right-color

– border-bottom-color

v table > columnheader > column, table > columnheader > column > sorted

– color

– border-style

– border-width

– background-color

– font-family

– font-size

– font-weight

– border-top-color

– border-left-color

– border-right-color

– border-bottom-color

Custom widgets: The SWidgets are a collection of custom SWT widgets that are designed for use in

Lotus Expeditor applications.

Developing applications 251

Page 264: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 action bar. 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

252 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 265: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.SCoolBar

v com.ibm.rcp.swt.widgets.SCoolItem

v com.ibm.rcp.swt.widgets.SToolBar

v com.ibm.rcp.swt.widgets.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 pull-down 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:

Developing applications 253

Page 266: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<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.

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:

Before completing the steps below, you must complete the steps defined in “Contributing custom controls

to the main toolbar statically.”

254 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 267: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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\"");

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);

}

Developing applications 255

Page 268: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

<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);

256 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 269: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

return new Status(IStatus.OK,

Activator.PLUGIN_ID,

IStatus.OK,

"Setting up controlSet Activities complete",

null);

}

};

job.schedule();

}

Custom table control: 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 com.ibm.rcp.jface.viewers.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.

Developing applications 257

Page 270: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v com.ibm.rcp.jface.viewers.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:

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 com.ibm.rcp.jface.viewers.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 com.ibm.rcp.jface.viewers.IExtendTableLabelProvider.

For example:

public int columnSpan(Object element, int columnIndex) {

if (arg0 instanceof GroupedMetadata){

if (element instanceof Categories){

switch(columnIndex){

case 0:

return _viewer.getTable().getColumnCount();

}

}

return 0;

}

public boolean isExpandable(Object element, int columnIndex) {

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) {

System.out.println("treeCollapsed(TreeEvent e) : " + e.toString());

258 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 271: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

STableItem item = (STableItem)e.item;

_viewer.refresh(item.getData(), true);

}

public void treeExpanded(TreeEvent e) {

System.out.println("treeExpanded(TreeEvent e) : " + e.toString());

STableItem item = (STableItem)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 com.ibm.rcp.jface.viewers.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. The

com.ibm.rcp.jface.viewers.TableViewer class provides an equivalent capability to the

org.eclipse.jface.viewers.TableViewer, but uses the com.ibm.rcp.swt.swidgets.table.STable as the

underlying display widget. This enables the TableViewer to take on the visual characteristics defined by

the default theme.

the TableViewer 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 TableViewer 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");

Developing applications 259

Page 272: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

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);

260 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 273: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Table 16. 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 TableViewer _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 TableViewer _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 261

Page 274: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

});

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

262 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 275: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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();

STableColumn[] 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 263

Page 276: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

layoutdata.add(cols[2], 1); //date

cols[2].setAlignment(STableColumn.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();

STableColumn[] 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(STableColumn.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.

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.

264 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 277: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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.

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();

Developing applications 265

Page 278: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

_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);

}

}

}

};

6. Call the FindStartsWithDialog() method to display the results. For example:

new FindStartsWithDialog(getSite().getShell(), findString, listener);

}

});

For example:

266 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 279: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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

LauncherManager.getInstance() 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.

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:

Developing applications 267

Page 280: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

– 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.

268 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 281: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

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);

}

Developing applications 269

Page 282: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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;

270 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 283: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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");

}

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. */

Developing applications 271

Page 284: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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$

}

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);

272 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 285: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

}

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)");

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

}

Developing applications 273

Page 286: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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;

}

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);

}

}

}

}

274 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 287: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

Developing applications 275

Page 288: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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);

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);

276 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 289: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 com.ibm.rcp.swt.swidgets.table.STableCell -- 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 com.ibm.rcp.swt.swidgets.table.STableItem -- The base class of all components of a table.

v com.ibm.rcp.swt.swidgets.table.STableColumn -- Represents a vertical column in the table. The

column width, alignment, header attributes, and so on are customizable through the STableColumn class

methods.

v com.ibm.rcp.swt.swidgets.table.STableRow -- Represents a row of data in the table. The STableRow

provides access to the individual STableCell objects in the row.

v com.ibm.rcp.swt.swidgets.table.STable -- 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:

Developing applications 277

Page 290: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

}

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” on page 245 for more information.

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.

278 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 291: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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. 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;

} });

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

Developing applications 279

Page 292: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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

280 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 293: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

Developing applications 281

Page 294: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 503.

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.

282 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 295: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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, 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 449). 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 237.

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 237).

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.

Developing applications 283

Page 296: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

If your view is to be used in Composite Applications or has multiple instances on a single perspective,

then you must specify the attribute allowMulitple=true in your view extension declaration.

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:

284 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 297: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 17. 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");

Understanding threading

When developing application components that interact with the user interface, it is important to

understand the threading model that is in use.

Developing applications 285

[[[

Page 298: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

A single UI thread is responsible for processing user interface events, such as lower level mouse clicks

and movement, keystrokes, and painting, as well as the control event handling such item selection. It is

important that event handlers return as quickly as possible, otherwise, the ability of the user interface

thread to handle events is severely affected, resulting in the appearance of a hung user interface.

Long running or blocking operations should not be run on the UI Thread. Examples of long running

operations include database operations, web services calls, or extensive computational logic. If operations

such as these must be run in response to events - for example, OK or Submit buttons within the UI - or

even when creating the view, then the view should initiate a separate thread or job to perform the

activity.

This results in a more complicated view, but if not done, the UI is not responsive to user requests. Since

controls must typically be updated only on the UI Thread, it requires that the Thread or Job work with

the view to display the updates once obtained. Starting work to run on the UI thread requires the use of

the syncExec or asyncExec methods of the Display object. The org.eclipse.ui.progress.UIJob or

org.eclipse.ui.progress.WorkbenchJob can also be used for work that needs to run on the UI thread.

public class MyViewPart extends ViewPart {

private Display display = null;

public void createPartControl(Composite arg0) {

new Thread( new Runnable() {

public void run() {

// do some work

List customers = new ArrayList();

// fill in the customers list

setCustomers( customers );

}

}).start();

}

public void setCustomers( List customers )

{

display.asyncExec( new Runnable() {

public void run() {

// update the view with customers

}

} );

}

public void setFocus()

{

}

}

The choice of using a Thread or a Job to perform the long running operations depends on the user

interface requirements. Both allow deferring the long running operations from the UI Thread. If user

notification or interaction is desired during the activity, then a Job should be used, as it provides for user

interaction through the progress monitor and progress view.

Additional information regarding threading can be found in the Eclipse Platform Plug-in Developers

Guide.

See also “Accessing SWidgets and JFaceEX objects” on page 281.

Customizing existing applications

This section provides information on customizing existing applications.

286 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[

[[[[[

[[[[[

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

[[[[

[[

[

Page 299: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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>

</extension>

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>

Developing applications 287

Page 300: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

<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

503 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 503. 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

288 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 301: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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.

Developing applications 289

Page 302: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Using the getSuggestions string:

SpellChecker isc = TextAnalyzerFactory.getSpellCheckerInstance();

isc.setLocale(TextAnalyzerConstant.LANGUAGE_ID_EN_US);

MisspelledWord[] misWords = isc.checkSpelling(txtToCheck,5,true);

// ......

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

290 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 303: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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();

Developing applications 291

Page 304: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

292 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 305: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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;

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)

Developing applications 293

Page 306: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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)

{

// 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) {

294 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 307: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

// 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;

}

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()

Developing applications 295

Page 308: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

{

SimpleUtils.openDictionaries(this.masters);

}

private void closeAllDictionaries()

{

SimpleUtils.closeDictionaries(this.masters);

}

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

}

296 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 309: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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)

{

//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

Developing applications 297

Page 310: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

ignorePrefs &= ~prefID;

}

return true;

}

private static boolean canIgnore(String word, int ignorePrefs) {

if ((ignorePrefs & SpellCheckerPreference.PREF_IGNORE_WORD_FILE) ==

SpellCheckerPreference.PREF_IGNORE_WORD_FILE) {

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:

298 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 311: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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/

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;

Developing applications 299

Page 312: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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"

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.

300 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 313: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

v Utilizes the proxy preference setting within the Lotus Expeditor client. For more information about

proxy settings, please refer to “Configuring the proxy settings for Lotus Expeditor” on page 226. If

both Browser and Lotus Expeditor preferences contain proxy information, the Lotus Expeditor proxy

preference setting is used.

To implement an embedded browser, perform the following steps:

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:

Developing applications 301

Page 314: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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

}

});

v Status change event:

myEmbeddedBrowser.addStatusTextListener (new EmbeddedBrowserStatusTextListener (){

Public void changed(EmbeddedBrowserStatusTextEvent event){

//get the changed status text and set it as the new status text

302 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[[[

Page 315: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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”);

4. You can implement basic HTTP authentication to a Web address.

Note: This is only supported on Windows systems.String url="http://www.ibm.com"; //Some Web address protected by Basic Authentication

try {

boolean isSecure=false;

URL jurl = new URL(url);

String host = jurl.getHost(); //get Host

String path = jurl.getPath(); //get Path

String protocol=jurl.getProtocol();

if(protocol!=null && protocol.equalsIgnoreCase("http")){

//get Secure

isSecure=false;

}else if(protocol!=null && protocol.equalsIgnoreCase("https")){

isSecure=true;

}else{

//not supported protocol

}

int port = (jurl.getPort() == -1 ? jurl.getDefaultPort() : jurl.getPort()); //get Port

boolean retValue= myEmbeddedBrowser.setBasicAuth(host,port,path,isSecure,userName,password);

catch (MalformedURLException e) {

//Error reports

} catch (Exception ee){

//error reports

}

myEmbeddedBrowser.setUrl(url); //load the Web address

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.

In addition, you can define values for the following embedded browser preferences:

Field name Acceptable values Description

static java.lang.String

ALLOW_DOWNLOAD_OVERWRITE

"true"(default) or "false" Determines whether to overwrite

the local file

static java.lang.String ALLOW_SCRIPTS "true"(default) or "false" Determines whether Javascript

and ActiveX are enabled.

Developing applications 303

[

[

[[[[[[[[[[[[[[[[[[[[[[[

Page 316: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Field name Acceptable values Description

static java.lang.String

BROWSER_EDITOR_ID

Non empty String Defines the embedded browser

editor id.

static java.lang.String

BROWSER_VIEW_ID

Non empty String Defines the embedded browser

view id.

static java.lang.String CONFIG_ID Non empty String

Default value is: an increased number

string: “1”, “2”, “3”......

Specifies the configuration id of

the embedded browser

configuration.

static java.lang.String CONFIG_TITLE String

Default value is: “”

Specifies the title of the

embedded browser

configuration.

static java.lang.String

CONTROLLED_DOWNLOAD_

DOMAIN_LIST

String list, the list separator is ″,″, each

host name should not contain a

protocol string. For example:

www.abc.com, abc.company.com

Default value is: null

List of domains from which a

user cannot download

unsolicited files.

static java.lang.String

CONTROLLED_DOWNLOAD_PATH

A valid path string.

Default value is: null

Local path to which to save a

downloaded file.

static java.lang.String

DOMAINS_DENY

"true"(default) or "false" 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 String list, the list separator is ″,″, each

host name should not contain a

protocol string. For example:

www.abc.com, abc.company.com

Default value is: null

List of domains for restricting

navigation.

static java.lang.String

DOWNLOAD_DOMAINS_DENY

"true"(default) or "false" 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

String list, the list separator is ″,″, each

host name should not contain a

protocol string. For example:

www.abc.com, abc.company.com

Default value is: null

List of domains for restricting

unsolicited file download.

304 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 317: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Field name Acceptable values Description

static java.lang.String

ENABLE_APPLET

"true"(default) or "false" Determines whether to support

Java2 Applets. Applies to

Internet Explorer browsers only.

static java.lang.String

ENABLE_BOOKMARKS

"true"(default) or "false" Determines whether Bookmark

functions are enabled.

static java.lang.String

ENABLE_CONTEXT_MENU

"true"(default) or "false" Determines whether a right click

displays a context menu. Applies

only to Internet Explorer.

static java.lang.String ENABLE_HELP "true"(default) or "false" Determines whether the F1 key

displays an associated Help

topic.

static java.lang.String FILE_PERMIT "true"(default) or "false" Determines whether a browser

can access local files and certain

Mozilla ″about:″ pages.

static java.lang.String HOME_URL A location string. Default value is: 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.

static java.lang.String ID Non empty String Default value is: an

increased number string: “1”, “2”,

“3”......

Specifies the ID of the embedded

browser configuration.

static java.lang.String INITIAL_URL A location string. Default value is: null Default Web address for the

browser. This is the address that

displays when the browser first

opens.

static java.lang.String LAUNCH_TYPE "editor" or "view" or “”(default) Specifies the launch type for the

browser instance. Options are

″editor″ or ″view.″

static java.lang.String

LOCK_TOOL_BAR

"true"(default) or "false" 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

ILTPATokenManager object

Default value is: null

Provided by the launcher, this

object implements the

ILTPATokenManager interface.

static java.lang.String

POPUP_DOMAINS_DENY

"true"(default) or "false" 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.″

Developing applications 305

Page 318: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Field name Acceptable values Description

static java.lang.String

POPUP_DOMAINS_LIST

String list, the list separator is ″,″, each

host name should not contain a

protocol string. For example:

www.abc.com, abc.company.com

Default value is: null

List of domains for restricting

unsolicited popups.

static java.lang.String POPUP_STYLE “default”(default) or “popup” or

“embedded”

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

A URL string. Default value is: null Specifies the automatic proxy

configuration URL. If this field is

set, other proxy setting fields are

ignored.

static java.lang.String PROXY_BY_PASS String list of host names, the list

separator is ″|″. For example:

“www.abc.com | abc.company.com”

Default value is: 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.

static java.lang.String

PROXY_FTP_PORT

A positive int value. Default value is: 0 Defines the proxy port for the

FTP protocol.

static java.lang.String

PROXY_FTP_SERVER

A string of server location or IP

address. Default value is: null

Proxy server for the FTP

protocol.

static java.lang.String

PROXY_GOPHER_PORT

A positive int value. Default value is: 0 Defines the proxy port for the

Gopher protocol.

static java.lang.String

PROXY_GOPHER_SERVER

A string of server location or IP

address. Default value is: null

Proxy server for the Gopher

protocol.

static java.lang.String

PROXY_HTTP_PORT

A positive int value. Default value is: 0 Defines the proxy port for the

HTTP protocol.

static java.lang.String

PROXY_HTTP_SERVER

A string of server location or IP

address. Default value is: null

Proxy server for the HTTP

protocol.

static java.lang.String PROXY_PORT A positive int value. Default value is: 0 Unified proxy port. Defines the

port number for the proxy

server. If set, this setting is used

for all network protocols.

static java.lang.String PROXY_SERVER A string of server location or IP

address. Default value is: null

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

A positive int value. Default value is: 0 Defines the proxy port for

SOCKS.

306 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 319: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Field name Acceptable values Description

static java.lang.String

PROXY_SOCKS_SERVER

A string of server location or IP

address. Default value is: null

Proxy server that supports

SOCKS packages.

static java.lang.String

PROXY_SSL_PORT

A positive int value. Default value is: 0 Defines the proxy port for the

SSL protocol.

static java.lang.String

PROXY_SSL_SERVER

A string of server location or IP

address. Default value is: null

Proxy server for the SSL

protocol.

static java.lang.String

SHOW_BOOKMARK

"true"(default) or "false" Determines whether the

Bookmark button is enabled.

static java.lang.String SHOW_HISTORY "true"(default) or "false" Determines whether the Back

and Forward buttons are

enabled.

static java.lang.String SHOW_HOME "true"(default) or "false" Determines whether the Home

button is enabled.

static java.lang.String

SHOW_PAGE_CONTROL

"true"(default) or "false" Determines whether the Stop

and Refresh buttons are enabled.

static java.lang.String SHOW_PRINT "true"(default) or "false" Determines whether the Print

button is enabled.

static java.lang.String

SHOW_TOOL_BAR

"true"(default) or "false" 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

"true"(default) or "false" Determines whether the URL

entry field is displayed. If false,

the user cannot type in URLs.

static java.lang.String TITLE String Default value is: “” Embedded Browser preference

name: title String specifying the

browser title

static java.lang.String

USE_BROWSER_HOME

"true"(default) or "false" 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

"true" or "false"(default) Determines which view icon to

display based on the embedded

browser type, Internet Explorer

or Mozilla.

Developing applications 307

Page 320: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Field name Acceptable values Description

static java.lang.String

USE_BROWSER_STATUS

"true"(default) or "false" Determines whether status text

is obtained from Browser

StatusText events or from DOM

mouseover events.

static java.lang.String

USE_BROWSER_TITLE

"true"(default) or "false" 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

An array of the preference value. Array of embedded browser

preferences for an end user.

static java.lang.String WEB_BROWSER A WebBrowser object

Default value is: null

Internal field.

For more information about the preferences, please refer to the Javadoc section of Developing Applications

for Lotus Expeditor for com.ibm.rcp.ui.browser.BrowserPreference in the Embedded Browser component.

To set embedded browser preferences programmatically, perform the following steps:

1. Define the embedded browser configuration ID.

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.

308 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 321: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Key Value options Default value Description

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.

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.

Developing applications 309

Page 322: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Key Value options Default value Description

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.

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.

310 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 323: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Key Value options Default value Description

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:

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.

Developing applications 311

Page 324: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The Rich Text Editor utilizes proxy preference settings within the Lotus Expeditor client. For more

information about proxy settings, please refer to “Configuring the proxy settings for Lotus Expeditor” on

page 226

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;

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.lockToolbar(false); This line can unlock the toolbar.

// 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>" +

312 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[

Page 325: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

"<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

}

}

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);

Developing applications 313

Page 326: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 303.

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();

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 18. 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.

314 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 327: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 18. Configurable items (continued)

Preferences Values Default Descriptions

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.

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

Developing applications 315

Page 328: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

In addition, Nokia eRCP’s implementation of eSWT is not entirely complete. Some widgets may be

constructed but may not show up on the display. See Nokia eRCP’s Release Notes for more information.

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.

316 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 329: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Developing applications 317

Page 330: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

318 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 331: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Definition page. For more information on Client Services projects please refer

to “Using the Lotus Expeditor Toolkit” on page 12.

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.

The Synchronization schedules page is part of the Lotus Expeditor preferences dialog. It provides users

the ability to specify 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 (for example, 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 synchronization 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.

Developing applications 319

Page 332: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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).

Note: The sync service must send the following events for each sync unit being synchronized:

1. SYNC_STARTED.

2. SYNC_COMPLETED or SYNC_ABORTED.

3. SYNC_PROGRESS.

The first two are required for scheduling purposes, the last is required for Sync UI purposes.

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:

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:

<?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>

320 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 333: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<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.

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.

Developing applications 321

Page 334: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 {

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(Context.getCompletedWorkUnits());

sb.append("/");

sb.append(pContext.getTotalWorkUnits());

}

322 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 335: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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);

}

Developing applications 323

Page 336: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

324 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 337: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Rational

Application Developer documentation Developing Web sites and applications 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 19. Web development activities

Task Reference

Understanding Client Services web application concepts. “Understanding Web Applications”

Working with Client Services Web projects versus

Dynamic Web projects, and when to use one versus the

other.

“Creating Web Application projects” on page 326

Developing Client Services web application logic. This

encompasses any special development considerations

when coding and constructing the web application logic.

“Accessing resources packaged in JAR bundles” on page

329

“Using JSP Standard Tag Libraries” on page 330

“Java Server Faces (JSF) development” on page 331

“Struts development” on page 332

Exporting web application bundles. “Exporting Web Application bundles” on page 336

Securing the web application through user authentication

and authorization.

“Securing Web Application resources” on page 333

Debugging and testing the web application. “Debugging and testing applications” on page 449

Deploying the web application to a runtime. “Deploying projects for local testing” on page 459

Using the command line WAB tool to convert a WAR to

a WAB.

“WAB Utility” on page 336

Configuring the web container. Refer to the Web Container configuration information in

the documentation Assembling and Deploying Lotus

Expeditor Applications

Web container logging. “Web Container Logging” on page 340

Configuring web projects for incremental JSP translation “Configuring web projects for incremental JSP

translation” on page 339

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 505 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

Developing applications 325

[[[

Page 338: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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” 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 329.

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 327.

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 336.

Creating Web Application projects

This section provides information on Web Application project creation.

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.

326 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 339: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 449 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 20. 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

Allows you to set and configure the facets that should be enabled for the project.

Table 21. 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 6.1

Dynamic Web Module 2.4

Java 5.0

The above facets are pre-selected, and

cannot be de-selected. You can

modify the versions.

Developing applications 327

Page 340: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Web Module panel

Allows you to configure the web module settings.

Table 22. 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 23. 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

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 ″Eclipse Core Components″

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

v JavaServer Faces Widget Library

(JWL)

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 514 for information on how to use this wizard.

328 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 341: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Web application resources

This section provides information on how to access Web Application resources.

Accessing resources packaged in JAR bundles:

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().

Registering and accessing static Web application resources in Lotus Expeditor:

The basic Web Server in Lotus Expeditor, the HttpService, allows users to dynamically register, unregister

and access (using a URL) static resources such as GIFs, PDFs, HTML files and any other resources that

may be packaged in a Web application archive.

Since the HttpService plugs into the advanced Web Server in Lotus Expeditor, the Web Container, these

static resources can be accessed from the ports the Web Container is configured to listen on. One

important thing to note is that although the resource serving capability is similar to that of traditional

httpservers (such as the IBM HTTP Server (IHS)), from a development/deployment standpoint code must

still be written in order for this capability to work. In addition, the static resources must be packaged as

part of an Eclipse plug-in. You cannot simply drop them in a familiar directory as you would with IHS.

The following example illustrates how to:

v Use a OSGi ServiceTracker to track the HttpService

v Use the HttpService to register the static resources in your Web application.import org.osgi.framework.BundleActivator;

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceReference;

import org.osgi.service.http.HttpService;

import org.osgi.service.http.NamespaceException;

import org.osgi.util.tracker.ServiceTracker;

import org.osgi.util.tracker.ServiceTrackerCustomizer;

public class Activator implements BundleActivator, ServiceTrackerCustomizer {

private ServiceTracker httpServiceTracker;

private BundleContext context;

Developing applications 329

Page 342: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

/* (non-Javadoc)

* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)

*/

public void start(BundleContext context) throws Exception {

this.context = context;

httpServiceTracker = new ServiceTracker(context, HttpService.class.getName(), this);

httpServiceTracker.open();

}

/* (non-Javadoc)

* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)

*/

public void stop(BundleContext context) throws Exception {

httpServiceTracker.close();

}

/* (non-Javadoc)

* @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)

*/

public Object addingService(ServiceReference reference) {

HttpService service = (HttpService) context.getService(reference);

try {

if (service != null) {

service.registerResources("/files", "/tmp", null);

}

} catch (NamespaceException e) {

e.printStackTrace();

}

return service;

}

/* (non-Javadoc)

* @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)

*/

public void modifiedService(ServiceReference reference, Object obj) {

}

/* (non-Javadoc)

* @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)

*/

public void removedService(ServiceReference reference, Object obj) {

HttpService service = (HttpService) context.getService(reference);

if (service != null) {

service.unregister("/files");

}

}

}

In the above application code, the resources located in the /tmp folder of the Web application are

registered with the HttpService under the /files alias. To access these resources, use the following URL:

http://<server_address>:<server_port>/files/<resource_name>

For example, if a resource XYZ.gif was packaged in the /tmp folder and the Web Container is listening on

a local port 80, then the URL to access the resource would be: http://localhost:80/files/XYZ.gif.

Using JSP Standard Tag Libraries

The Lotus Expeditor platform includes the JSP Standard Tag Libraries (JSTL) 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.

330 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 343: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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” on page 332 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.

Note: The Enhanced Faces component facet cannot be uninstalled once it is selected. You should only

include the Enhanced Faces component if you intend to develop JSF applications using IBM JSF

support.

Using the IBM JavaServer Faces (JSF) Extension or the JavaServer Faces Widget Library (JWL): To

configure the project to use the IBM JSF extension and JWL, add the Enhanced Faces component facet (in

addition to the JSTL and Base Faces facets) to the project. This facet can be selected on the Project Facets

page during the Client Services web project creation, or added from the project’s Properties > Project

Facets page, for the existing Client Services web project.

Note: The createEditor tag is a custom tag used for the document editor JSPs. It is included in the

DocEditor.jar. The J2SE JRE is required to work with this tag. It does not work with the jclDesktop

JRE. J2SE is part of the Device Runtime Environment (DRE). You can get J2SE by installing the

DRE into the toolkit using the installation instructions for the DRE.

Using the JavaServer Faces Widget Library (JWL) without the default faces configuration: The Lotus

Expeditor runtime provides two flavors of JWL support. The plug-in com.ibm.rcp.jsf.ext provides JWL

support along with the default faces configuration for JWL. The plug-in com.ibm.rcp.jsf.ext.impl

provides JWL support, but does not include the faces configuration. By default, the tooling sets the Client

Services web project development environment to use com.ibm.rcp.jsf.ext, which provides the faces

configuration. Certain application environments have a conflict with the default JWL faces configuration.

If you are developing for such an environment, you can switch to JWL without the configuration as

follows:

1. Right click on the project and select Properties.

2. Select the Client Services properties page.

3. On the Target Definition tab, find the feature IBM JavaServer Faces (JSF) Extensions.

4. Expand this feature using the +.

5. De-select com.ibm.rcp.servlet.jsf.ext.

Developing applications 331

[[[

Page 344: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

6. Click OK to save this change.

If you are using the WAB Utility to translate an existing WAR file, you can specify that the application

requires JWL without the default configuration by adding the following option: -configlessJWL.

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” on page 331. 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.

Note: The Enhanced Faces component facet cannot be uninstalled from the target project once it is

selected. You should only include the Enhanced Faces component if you intent to develop JSF

applications using IBM JSF support.

WAB Tool: Add the following options when invoking the WAB tool in order to translate the WAR file

using the Sun JSF Reference Implementation:

v Use the –jsf option with the Sun qualifier as follows: -jsf=sun

v Use the –classpath option to specify the location of the Sun JSF libraries. You need to specify the full

path to the two JSF libraries jsf-api.jar and ws-jsf.jar, as well as the directory that contains them.

Separate these paths with the proper delimiter (‘;’ for Windows and ‘:’ for Linux). These libraries can

be found in the following location under the toolkit installation directory:

/eclipse/plugins/com.ibm.pvc.wct.runtimes_6.1.0.0/rcp/eclipse/plugins

/com.ibm.pvc.servlet.jsf_1.1.0.0

The following example assumes the libraries are in the c:/jsf directory:

wab myApp.war –jsf=sun –classpath c:/jsf/jsf-api.jar;c:/jsf/ws-jsf.jar;c:/jsf

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

XML. Struts encourages application architectures based on the Model 2 approach, which is essentially 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.

332 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[

Page 345: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

4. Upon creation of the Client Services web project, the following jars are added to your Client Services

web project:

v commons-beanutils.jar

v commons-collections.jar

v commons-digester.jar

v commons-fileupload.jar

v commons-lang.jar

v commons-logging.jar

v commons-validator.jar

v jakarto-oro.jar

v struts.jar

These jars include the necessary functionality required for web application developers to develop

struts application that utilize the struts tiles component of the struts framework as well as others.

For further information on how to develop struts applications using the struts tile tag library,

including configuration of struts deployment files, please refer to the struts documentation available

in the Rational Software Development Platform.

Securing Web Application resources

This section provides information on securing Web Application resources.

Configuring a Web Application: The Web Container supports the declarative Java EE 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>

Developing applications 333

Page 346: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<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

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);

334 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 347: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

useradmin.createRole(username, Role.User);

}

/**

* Plug-in stop method

*/

public void stop(BundleContext bc) throws Exception {

}

}

Delete 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.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 Internet Explorer 7 to access a secured Web application: When using Internet Explorer 6, the

user was informed the program has encountered a problem with a HTTPS delivered webpage via a

modal dialog box. The user was then asked to make a security decision. Internet Explorer 7 follows the

“secure by default” paradigm, whose behavior is slightly different - no modal dialog box is presented to

the user. Instead, upon encountering a certificate problem, Internet Explorer 7 presents an error page

explaining the problem with the certificate. The error page conveys to the user there is a problem with

the website’s security certificate. The user may choose to ignore the warning and proceed in spite of the

certificate error (unless the certificate was revoked). If the user clicks through a certificate error page, the

address bar fills with red to serve as a persistent notification of the problem.

Internet Explorer 7 blocks navigation to HTTPS sites that present a digital certificate that has any of the

following problems:

v Certificate was issued to a hostname other than the current URL’s hostname

Developing applications 335

Page 348: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Certificate was issued by an untrusted root

v Certificate is expired

v Certificate is revoked

Note: If you receive an error message stating that ’Internet Explorer was unable to display the webpage’ when

using Internet Explorer 7, you may need to update the browser security settings. Navigate to Tools

> Internet Options > Advanced > Security, and update the settings accordingly.

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.

Note: If you export a Client Services Web Project or Client Services Portal Project as a plug-in with

source, it is recommended you use the directory structure format. This is due to a limitation in

Eclipse that prevents the plug-in from importing correctly if it is imported into an Eclipse

workspace.

To export a plug-in in a directory structure format, clear the Package plug-ins as individual JAR

archives checkbox on the Options tab of the first page of the Export Deployable plug-ins and

fragments wizard.

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 459. 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 Rational environment, it is located in the following directory (where RAD_HOME is the directory

that your Rational Software Development platform has been installed to):

RAD_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” on page 337 for details on how to use the WAB utility.

336 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 349: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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 24. 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>.

Developing applications 337

Page 350: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 24. WAB Utility options parameters (continued)

Option Description

-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.

-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.

-importpackage A comma separated list of package names to be added to

the Import-Package header of the manifest file.

-exportpackage A comma separated list of package names to be added to

the Export-Package header of the manifest file.

-bundleversion Specifies the value of Bundle-Version in the manifest file.

Default is 1.0.0.

-bundleactivator Specifies the bundle activator class to be used as the

value of Bundle-Activator in the manifest file. Default

will use the standard web bundle activator class.

-targetruntime The version of the runtime which this application is

targeting. Valid values are ″6.0″, ″6.1″, and ″6.1.1″.

Default is ″6.1.1″.

-configlessJWL This application requires the JWL implementation bundle

that does not include a faces configuration. Default is to

use JWL with the configuration.

-ignoreerrors Allows the WAB file to be created even if JSP translation

errors are encountered. Useful in situations where it is

known that certain JSP errors will not affect the intended

use of the web application.

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 Java EE level 1.3 and 1.4 and EJB modules for Java EE level 1.2 and 1.3. A Client

338 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 351: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Dynamic JSP support

The Lotus Expeditor platform includes support for running web applications that dynamically generate

JSPs or modify the content of existing JSP’s at runtime. Web or Portlet applications developed using the

WebSphere Portlet Factory toolkit are examples of applications that require dynamic JSP support.

In order to take advantage of dynamic JSP support, developers and users must perform the following

procedure:

1. Install the Lotus Expeditor 6.1.x client from the Lotus Expeditor product CD. Choose the default

settings during installation.

2. Launch the Lotus Expeditor 6.1.x client

3. Select File > Application > Install.

4. Select Search for new features to install.

5. Select Next.

6. Select the Add Folder Location button to create a new Local update site and point to the

\desktop\updates\platform directory of the Lotus Expeditor product CD.

7. Select Finish.

8. Select the Web Container - JSP Compiler Bridge and the Eclipse Java Development Tools features

from the runtimes category of the update site.

Upon installation of the these features, the Lotus Expeditor 6.1.x platform supports dynamic JSP’s.

Note: When using the dynamic JSP support for the Lotus Expeditor Toolkit, ensure the Web Container -

JSP Compiler Bridge and Eclipse Java Development Tools features are selected in the Client

Services target profile. Target profiles provide a convenient method for you to specify the set of

components included in your debug and test platform. For more information on Client Services

projects and target profiles, refer to “Using the Lotus Expeditor Toolkit” on page 12.

Configuring web projects for incremental JSP translation

The Lotus Expeditor Toolkit can be configured for incremental JSP translation so that only JSP files whose

prior translations are out of date due to project changes will be translated.

A client services web project by default translates all JSP files each time a project is run or exported from

the tools. This JSP translation occurs even on files that were not modified since the last translation. The

incremental JSP translation can be enabled or disabled at the workspace preferences level and also on a

per project basis. When incremental JSP translation is disabled, all JSPs are translated whenever the web

project is run or exported.

To enable or disable the incremental JSP translation at the workspace preferences level:

1. Select Window > Preferences > Client Services > Web.

2. Select or de-select the Enable incremental JSP translation checkbox.

To enable or disable the incremental JSP translation feature on a per project basis:

1. Right click the project in the IDE. From the context menu, select Properties.

2. In the Properties dialog, select Client Services > Web.

Developing applications 339

[[[

[[[[[

[

[

[

[

[

[

Page 352: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

3. Select the Enable project specific settings checkbox and select or de-select the Enable incremental

JSP translation checkbox.

Note: The incremental JSP translation does not detect and retranslate a JSP that uses the include directive

to statically include another JSP which has changed. When statically-included JSPs are being

updated, the translation can be forced by either disabling the incremental JSP translation or by

using Project > Clean.

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 following table shows the mapping between the Web Container log levels and the levels used by

JDK:

Table 25. 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

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 Java EE Perspective.

2. From the project Explorer view, select the Client Services web project to be tested.

340 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[[[[

Page 353: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java EE 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...)

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.

Developing applications 341

Page 354: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.4 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 static Web services clients that are

similar to JSR-172 clients.

An application that consumes 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

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.x 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.4 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 generation of JAX-RPC based clients that are

compliant with the Lotus Expeditor Runtime.

For more information about JAX-RPC, please visit JAX-RPC Project.

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.

342 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 355: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Web Services clients that are similar to a JSR-172

specification 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.

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.

Developing applications 343

Page 356: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

344 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 357: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

Table 26. 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

Developing applications 345

Page 358: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

346 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 359: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 for 6.1.1: 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 resource bundle for 6.1.2:

This step details the development of an OSGi service that exposes a physical resource such as a database,

Java bean, or a file system. For a resource, you must define a Java interface (or a Java class) and, if

necessary, provide for its implementation. For simplicity, it is assumed that the developer provides an

implementation to the Java interface.

To use the standard plug-in development wizard to create an OSGi plug-in to expose this interface as

OSGi service, perform the following procedure:

1. Select File > New > Project > Plug-in Project.

2. Provide the Project Name.

3. Choose Target Platform as an OSGi Framework: standard.

Developing applications 347

Page 360: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

4. Select Finish to create the Resource Bundle Project in the workspace.

In the newly created Resource Bundle Project, you must define a Java Interface that describes the physical

resource, as well as provide its implementation. While describing a WS-Resource using a Java Interface,

keep in mind the following:

v Use the getXxx() or isXxx(), and the setXxx() methods to define the Resource Properties of the

WS-Resource.

– Use getXxx() with the non-boolean return type and the defined respective setXxx() method.

– Use isXxx() with the boolean return type and the defined respective setXxx() method.

Note: In the above case, the WS-Resource Provider Wizard will interpret the value xxx as the

resource property.v All other methods in the Java Interface are interpreted as Service Methods of the WS-Resource.

The Java Interface that describes the WS-Resource...

v Should not include methods with more than one parameter.

v Should not include overloaded methods.

v Should use data-types (as method return types, and method parameters) listed in the section

“Supported data types” on page 354. Use of any data-types other than the supported data-types may

lead to unexpected behavior, though no warning or error messages will display.

Note: To resolve the resource bundle’s dependencies among other WS-Resource bundles, the resource

bundle should include the package information of the Java Interface or Java Class (referred to

above) as an Export-Package: entry in its Manifest file. In absence of this information, other

dependent bundles will show compilation errors.

Developing the Web Services bundle and adapter bundle for 6.1.1: Lotus Expeditor Toolkit provides wizards to

generate the WS-Resource Adapter and Web service components. The WS-Resource Web service

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 for

6.1.1” on page 373 for detailed steps.

v Click Next.

348 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 361: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 27.

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’.

Developing applications 349

Page 362: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 27. (continued)

Data Types minOccurs maxOccurs nillable Description

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.

Developing the Web Services bundle and adapter bundle for 6.1.2:

The WSRF Toolkit provides a wizard to generate the WS-Resource Adapter and Web service plug-in

projects. The WS-Resource Web service component is completely generated by the tool and ready for

deployment. The WS-Resource Adapter component generated by tool can be deployed only after making

suitable modifications as explained in this section. The wizard uses this Java Interface as a starting point,

and allows you to further augment and customize the WS-Resource description.

Perform the following steps to create the WS-Resource Web service component and the related

WS-Resource Adapter component for the given Resource bundle:

1. Select File > New > Other.

2. Select Client Services > Mobile Web Services > WS-Resource Provider.

3. In the WS-Resource details page:

a. Provide the WS-Resource Name (for example, PrinterResource)

b. Provide the Java Interface (or class) of the Resource from the Resource Bundle project for the

WS-Resource class.

c. Add the Resource bundle project and the dependant Jars to the Resource Classpath list.

d. Select the appropriate WS-Resource interfaces that should be implemented:

Note: WS-Resource property specification is mandatory for all WS-Resources.

e. Select Expose service methods to expose the other methods of the Resource interface as a custom

port-type of the WS-Resource, in addition to the standard WSRF port-types

f. To secure the WS-Resource:

350 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 363: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

1) Select Enable Web services security. This generates the required templates and files to support

the SOAP message level security.

Refer to “Securing a WS-Resource for 6.1.1” on page 373 for detailed steps.

Or...

Refer to “Securing a WS-Resource for 6.1.2” on page 375 for detailed steps.

2) Select Enable Web container security to secure transport layer authentication and

authorization.

Refer to “Securing a WS-Resource for 6.1.1” on page 373 for detailed steps.

Or...

Refer to “Securing a WS-Resource for 6.1.2” on page 375 for detailed steps.g. Click Next.

If the error message ″Error while loading class...″ appears, first revisit the list of JARs provided in

the Classpath list, and then review the input Java Interface or class for the constraints listed later

in this section.4. In the WS-Resource properties selection page:

a. Select the properties of the WS-Resource that should be exposed.

b. You can also define additional properties to the WS-Resource, by selecting the Add property

button.

1) Specify the name of the property.

2) Select the property type.

You should only use data-types listed in “Supported data types” on page 354 as property

types.

3) If the property is an array, select the Array type check box.

4) Click OK.c. Click Next.

5. The Web service methods selection page displays if you chose to expose Web service methods. From

this page, select the methods that should be exposed as Web service methods, and click Next.

6. In the Project details page, provide the name and location for the creation of new projects for the

WS-Resource Web Service and WS-Resource Adapter. Then click Next.

7. In the Plug-in details page provide the following information:

v Plug-in name

v Plug-in ID

v Plug-in Version8. Click Finish.

The WSRF Toolkit creates two projects in the workspace, one each for the WS-Resource adapter and the

WS-Resource web service.

Note: The WS-Resource Provider wizard works on a bottom-up approach for generating a WSDL

description (for example, given the Java Interface, a WSDL description is generated). The generated

WSDL description follows non-wrapped style. Thus, 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:

Developing applications 351

[

[

Page 364: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 28. Default multiplicity and nillable attributes table

Data Types minOccurs maxOccurs nillable Description

Primitive types (int) 1 1 false The property can not

be ’null’.

Wrapper types

(Integer)

1 1 true The property can be

’null’.

Primitive array types

(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

(Integer[])

0 unbounded true The property can be

’null’. If the property

is not ’null’, the

individual array

elements can be

’null’.

Complex types (URI) 1 1 true The property can be

’null’.

Complex array types

(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: Currently, the generated WS-Resource Provider exposes all the operations of the

WS-ResourceProperties specification. The wizard does not provide a facility to deselect operations

designated as ″optional″ by the WSRF specification. Similarly, when you choose to implement the

WS-ResourceLifeTime interface, all operations of the WS-ResourceLifeTime specification will be

exposed.

Note: Currently, 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, or plug-in provider

name. Entering non-English text in the wizard fields may result in undesirable behavior.

Creating a WS-Resource client for 6.1.1: To generate the client stub, the WS-Resource should have been

deployed and started on the Lotus Expeditor runtime.

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 for 6.1.1” on page 373 for detailed steps.

352 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 365: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Creating a WS-Resource client for 6.1.2:

This section discusses how to create a WS-Resource client using the WS-Resource Client Wizard. The

wizard generates the WS-Resource Client project for a WS-Resource using the WS-Resource description

available either in the WSDL (published by the WSRF Runtime) or in the WS-Resource Web Service

Interface (generated by the WS-Resource Provider Wizard, in the Web Service Project).

Perform the following steps to create the WS-Resource Client component:

1. Select File > New > Other.

2. Select Client Services > Mobile Web Services > Create WS-Resource Client.

3. In the WS-Resource details page:

a. Select the Input Source and specify the source-parameters.

1) If the source is WSDL, then specify the HTTP URL of the WSDL of the WS-Resource,

published by the WSRF Runtime.

2) If the source is a Web service interface, then specify the Web service interface’s name. Include

all the dependent JARs in the classpath.b. Select Enable Web services security to securely access the WS-Resource.

Note: You may need to update the generated Java classes and configuration files.

Developing applications 353

Page 366: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Refer to “Securing a WS-Resource for 6.1.1” on page 373 for detailed steps.

Or...

Refer to “Securing a WS-Resource for 6.1.2” on page 375 for detailed steps.

c. Click Next.4. In the Project details page, provide the Name and Location of the WS-Resource client project. Then

click Next.

5. In the Plug-in details page, provide the following information:

v Plug-in name

v Plug-in ID

v Plug-in Version6. Click Finish.

After clicking Finish, the Lotus Expeditor Toolkit creates the project in the workspace, for the

WS-Resource client.

Note the following:

v The WS-Resource Client wizard has been verified to work with the WSDL generated by the WSRF

Runtime. Similarly, the WS-Resource Client wizard has been verified to work with the Web Service

Interface generated by the WS-Resource Provider wizard.

v Client-stub generated using other client generation tools may produce undesirable results.

v Currently, the wizard does not support non-English text for project name, package prefix, plug-in

name, plug-in ID, or plug-in provider name. Entering non-English text in the wizard fields may result

in undesirable behavior.

v Modifying the generated package name or class names of the WS-Resource Client projects may result

in undesirable behavior.

v The SOAP messages exchanged between the WS-Resource provider and WS-Resource client follow

non-wrapped style. Currently, the WS-Addressing implementation is customized to handle

non-wrapped style SOAP messages.

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

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

354 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

Page 367: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 for 6.1.1: WS-Resource Web services generated by the toolkit do not

require any changes. Alternatively, WS-Resource Adapters generated by Lotus Expeditor Toolkit require

you to provide an implementation of the business logic in the generated classes.

The tool generates the following sub-components in the adapter plug-in:

Table 29. Adapter plug-in sub-components

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.

<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.

Developing applications 355

Page 368: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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;

356 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 369: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

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)

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 {

Developing applications 357

Page 370: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

}

}

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++) {

358 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 371: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 provider application for 6.1.2:

This section provides detailed information for modifying the WS-Resource Web service and WS-Resource

Adapter.

Modifying the WS-Resource Web service

The WS-Resource Web service component generated by the WS-Resource Provider Wizard is ready for

packaging and deployment. However, it may require some changes for the following reasons:

v To enforce “SOAP over HTTP” binding

v By default, SOAP over ‘OSGi Service Invocation mechanism’ will be used if the WS-Resource and its

consumer are residing on the same OSGi Runtime environment.

v While service invocation happens through OSGi mechanism, the HTTP web container provided

authorization will be bypassed.

v The Activator class of the Web service bundle generated by the WS-Resource Provider Wizard will

contain the following code snippet.

props.put(BindingConstants.SUPPORTED_BINDINGS, BindingConstants.OSGI_BINDING);

v In order to enforce SOAP over HTTP, remove this line of code, from the Activator.

v To provide Security Authenticator / Authorization logic

Refer to “Securing a WS-Resource for 6.1.1” on page 373 for detailed steps.

Or...

Refer to “Securing a WS-Resource for 6.1.2” on page 375 for detailed steps.

Modifying the WS-Resource Adapter

The WS-Resource Adapter component generated by the WS-Resource Provider Wizard requires you to

provide additional implementation in the generated classes. The tool generates the following

sub-components in the adapter plug-in:

Developing applications 359

[

Page 372: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 30. Adapter plug-in sub-components

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.

<ResourceName>LifeTimeManager 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 The base class for <ResourceName>PropertyManager,

bridging the WSRF implementation and WS-Resource

Adapter.

<ResourceName>PropertyManager Contains empty implementations for managing the

WS-Resource properties. Developers should provide

implementation to the methods based on the scenario.

<ResourceName>ServiceManager Contains default implementation for the Service

methods.

<ResourceName>AdapterIfc 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

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:

360 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 373: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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)

Developing applications 361

Page 374: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

}

}

362 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 375: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

Developing applications 363

Page 376: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

}

364 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 377: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

//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

Developing applications 365

Page 378: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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{

operationContext.getCurrentThreadsContext();

366 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 379: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

Developing applications 367

Page 380: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

}

368 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 381: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

..................

}

Developing applications 369

Page 382: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Understanding interactions among WS-Resources:

Interactions among multiple WS-Resources can be achieved through invoking an operation of one

WS-Resource from another WS-Resource’s client or provider component.

In either case, each WS-Resource application should be individually developed by following the steps

mentioned for “Developing WS-Resource providers” on page 347 and “Creating a WS-Resource client for

6.1.1” on page 352 or “Creating a WS-Resource client for 6.1.2” on page 353. In addition, while invoking

an operation of one WS-Resource (WS-Resource B) from another WS-Resource’s (WS-Resource A) client or

provider, you must include the following code in the implementation of WS-Resouce B’s client or

provider:

// Before invoking the operation get the current message context and reference it to a

// new message context variable

MessageContext msgContext = MessageContext.getCurrentThreadsContext();

// Set the current message context to a value "null" so that next operation invocation

// (of WS-Resource B) is done with a fresh message context.

MessageContext.setCurrentThreadsContext(null);

//invoke the operation of another WS-Resource (WS-Resource B) from its client instance

SecureAddressTestClient secureAddressClient = new SecureAddressTestClient();

EndpointReference addressEPR = secureAddressClient.createResource();

// Once the WS-Resource operation invocation is successful, re-set the current message

// context to previous message context value, referenced to the message context

// variable.

MessageContext.setCurrentThreadsContext(msgContext);

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.

370 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[[

[[[[[[

[[[[[[[[[[[[[[[[[[[[[

[

Page 383: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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: For 6.1.1, 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).

Developing applications 371

Page 384: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Note: It is not recommended to deploy a WS-Resource provider and its corresponding WS-Resource

client in the same instance of an OSGi environment.

Note: If the WS-Resource client is security enabled, edit the bundle Manifest to include security file

package in the “Export-Package” list. You can refer to “Creating a secure WS-Resource Client” on

page 378 for details on the security file package.

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.

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.

Deploying a WS-Resource Client with an application bundle:

With Lotus Expeditor, you can use a WS-Resource client within an application bundle to access a

WS-Resource, export a WS-Resource client as a Java library (JAR), and package it along with the bundle.

To package a WS-Resource client with a bundle, perform the following steps:

1. Export the WS-Resource Client Stub as a JAR file.

2. Copy the JAR file into the project folder of the bundle (the bundle with which the WS-Resource client

should be packaged).

3. Edit the bundle Manifest to include the WS-Resource client’s required bundles (the Required-Bundle

in the WS-Resource Client Bundle Manifest file) in the “Required-Bundle” list.

4. If the WS-Resource client is security enabled, edit the bundle Manifest to include the security file

package in the “Export-Package” list. You can refer to “Creating a secure WS-Resource Client” on

page 378 for more information on the security file package.

5. Edit the bundle Manifest to include the WS-Resource client JAR in the Bundle-ClassPath.

372 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[[[

[

[[

[

[

[[

[[

[[[

[

Page 385: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

6. Edit the build configuration of the bundle to include the WS-Resource client JAR while building the

bundle.

7. Export the bundle and deploy it in the OSGi environment.

Note: The application bundle’s classes should not include any that have the same fully-qualified Java

class name, as it exists for any of the classes within the JAR.

Securing a WS-Resource for 6.1.1

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.

Note: For Secured resources, the WSRF tool generates KeyStore files (.jks files) that are compatible with

the J2SE environment. If the WSRF applications are deployed in a jclDesktop environment,

application developers should replace the default generated KeyStore files with ones created using

the JCL API.

Note: The jclDesktop profile cannot read the file serverSample.jks created using other profiles such as

J2SE due to the limitation of the jclDesktop profile’s ability to read a J2SE keystore and vice versa.

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 375 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’

Developing applications 373

[[

[

[[

[

Page 386: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Value Description

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:

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.

374 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 387: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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″.

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.

Securing a WS-Resource for 6.1.2

The WSRF Runtime provides two modes of security enablement for WS-Resources, Web services security

and Web container security.

Web services security

In this mode, the WSRF Runtime leverage the multiple security configurations offered by Mobile

Web services. You may enable this level of security while generating providers or clients. The

generated code contains the additional security templates and authenticator classes that can be

configured to enable SOAP message level security. Depending on the configurations you select,

the services can be secured by signing or encrypting the messages or by authenticating and

authorizing the message based on the user credentials in the message header.

The supported security configurations are listed below:

v sign only

v encrypt only

v sign and encrypt

v authentication only

v sign and authentication

v encryption and authentication

v sign, encryption and authentication

Web container security

In this mode, the Web service leverages the Basic Authentication mechanisms provided by the

Developing applications 375

[[[

[[[[[[[

[

[

[

[

[

[

[

[

[[

Page 388: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Web container. Since the Web Container supports the declarative J2EE security model, the Web

descriptor of the Web Service specifies the security policy (roles, access control, and so on)

declaratively in a web.xml file.

To enable security with either method, it is necessary that both provider (sever-side) and client

(client-side) be enabled with the same Web services security configuration.

Note: The jclDesktop profile cannot read the file serverSample.jks created using other profiles such as

J2SE due to the limitation of the jclDesktop profile’s ability to read a J2SE keystore and vice versa.

Securing a WS-Resource with Web service security:

In this mode, the WSRF Runtime leverage the multiple security configurations offered by Mobile Web

services. You may enable this level of security while generating providers or clients. The generated code

contains additional security templates and authenticator classes that can be configured to enable SOAP

message level security. Depending on the configurations you select, the services can be secured by

signing or encrypting the messages or by authenticating and authorizing the message based on the user

credentials in the message header.

Creating a secure WS-Resource provider: In order to create a WS-Resource with Web services security

enabled, you must use the WS-Resource Provider Wizard of the WSRF Toolkit and follow the steps

described in “Developing the Web Services bundle and adapter bundle for 6.1.1” on page 348 or

“Developing the Web Services bundle and adapter bundle for 6.1.2” on page 350. In addition, in the

WS-Resource details page of the wizard, select the Enable Web services security option.

The following files will be generated in the export directory of the package containing the file

BundleActivator.java:

v ibm-webservices-ext.xmi,

v ibm-webservices-bnd.xmi

v serverSample.jks

v wssecurity.xml

Note: The serverSample.jks is for testing purposes 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.

The supported keystore type is JKS. To use a different key store, modify the ibm-webservices-bnd.xmi

file. The keystore element’s storepass and path attribute should be modified to have new values. Refer to

“Editing the Mobile Web Services security configuration” on page 410 for details on required

modifications in the ibm-webservicesclient-bnd.xmi file.

If you want to enable the security configurations that involve ‘authentication’, you must write the

Custom Authenticator and Custom Authorizer classes.

Developing custom authenticators and custom authorizers:

The WS-Resource Web service component generated by the WS-Resource Provider Wizard for a secure

WS-Resource includes a skeletal custom authenticator and authorizer Java class in the WS-Resource Web

service bundle. The skeletal custom authenticator Java class can be identified by the name

Authenticator.java and the skeletal custom authorizer Java class can be identified by the name

Authorizer.java.

You must provide implementation for the following methods of these classes:

v doAuthenticate() method of Authenticator.java - Authenticates users to access the WS-Resource.

376 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[

[[

[[

[

[[[[[[

[[[[[

[[

[

[

[

[

[[[

[[[[

[[

[

[[[[[

[

[

Page 389: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Your authentication logic involves obtaining the user information, username and password from the

WSRFAutheticatorContext parameter and authenticate the user against a user-repository (file, database,

LDAP). If the authentication fails, you must throw WSSException.

The tool generated code in the class <ResourceName>Authenticator.java also includes the following

helper methods. You can use these helper methods to obtain contextual information such as UserName

and Password while implementing the Authorization logic.

public void doAuthenticate(WSRFAutheticatorContext authMessageContext)

throws WSSException {

String username = authMessageContext.getUsername();

String password = authMessageContext.getPassword();

// Authenticates a client based on username and password

boolean authResult = ...;

if (!authResult) {

throw new WSSException(

"Failed authentication for the user: " + username

);

}

}

v doAuthorize() method of <ResourceName>Authorizer.java - Authorizes users to access the

WS-Resource, Resource properties and service methods.

Similar to authentication logic, authorization logic also involves extracting the client’s username and

user role information from the WSRFAuthorizerContext parameter and authorizing a client request as

per the authorization policy (whether or not the user has permission to perform the task on the target).

If the authorization fails, you must throw the WSSException.

The tool generated code in the class <ResourceName>Authorizer.java also includes helper methods. You

can use these methods to obtain contextual information, such as the Resource Id, SOAP Header,

Operation name, Resource Properties being accessed, and so on. This can be obtained while

implementing the Authorization logic.

public void doAuthorize(WSRFAuthorizerContext authMessageContext)

throws WSSException {

String username = authMessageContext.getUsername();

List roles = authMessageContext.getRole();

// Authorizes a client based on username and role information

boolean authResult = ...;

if (!authResult) {

throw new WSSException(

"Failed authorization for the user: " + username

);

}

}

}

In addition, you must perform the following steps to get any user role information:

1. Register the Web Services provider as a web application to the Web Container.

If the provider is created with the option Enable Web container security selected, you need not do

this step. Otherwise, refer to “Registering a Mobile Web Services provider as a web application with

the Web Container” on page 403 for more information.

2. Define the security roles and constraints in the web.xml file.

Refer to “Defining security roles and constraints in the web.xml file” on page 404 for more

information.

Deploying a secure WS-Resource:

You are required to update the Platform Configuration File with the security configuration as a System

Property for each secure WS-Resource deployed on the OSGi Environment.

Developing applications 377

[[[

[[[

[[[[[[[[[[[[[[

[[

[[[[

[[[[

[[[[[[[[[[[[[[

[

[

[[[

[

[[

[

[[

Page 390: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The property-name and value must subscribe to the following format:

<Web services Plug-in ID>.wsrf.security.type = <Security Configuration>

Above, <Web services Plug-in ID> represents the plug-in ID of the Web services plug-in generated by

the WS-Resource Provider Wizard. <Security Configuration> represents one of the following values

illustrated in the table below.

Table 31.

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’

sign_encrypt_authenticator For security as ‘sign, encrypt and authenticate’

sign_authenticator For security as ‘sign and authenticate’

encrypt_authenticator For security as ‘encrypt and authenticate’

For example, to enable security as ‘authentication only’ in the PrinterResource, and the Web service

component’s bundle symbolic name is printerresourceWebservice, then you would set the Configuration

Property as:

printerresourceWebservice.wsrf.security.type=authenticator

You can delete the Security Configuration entry from the Platform Configuration File to turn off security

for the WS-Resource.

Creating a secure WS-Resource Client: In order to create a client for a secure WS-Resource (with Web

services security), you must use the WS-Resource Client wizard and follow the steps described in

“Creating a WS-Resource client for 6.1.1” on page 352 or “Creating a WS-Resource client for 6.1.2” on

page 353. In the WS-Resource details page of the wizard, select Enable Web services security option.

The WS-Resource Client Wizard generates the following additional security file packages:

v [package-prefix].client.security.authenticator

v [package-prefix].client.security.encrypt

v [package-prefix].client.security.encrypt_authenticator

v [package-prefix].client.security.sign

v [package-prefix].client.security.sign_authenticator

v [package-prefix].client.security.sign_encrypt

v [package-prefix].client.security.sign_encrypt_authenticator,

The above security file packages contain the following files:

v clientSample.jks

v ibm-webservicesclient-bnd.xmi

v ibm-webservicesclient-ext.xmi

v wssecurityclient.xml

Note: 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 clientSample.jks.

Developing client applications to access a secure WS-Resource for Web services security:

378 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[[[

[[

[[

[[

[[

[[

[[

[[

[[

[[[

[[[

[

[[

[[[[

[

[

[

[

[

[

[

[

[

[

[

[

[

[[[

[

Page 391: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

This section provides information on setting client-side security configurations user credentials.

Setting client-side security configurations

Your client application must use the same Security Configuration setting as that of the WS-Resource

provider. The Security Configuration is set as the JVM’s System Property . The property-name and value

must subscribe to the following format:

<WS-Resource Name="">.wsrf.security.type = <Security Configuration="">

Where, [WS-Resource Name] is the value you provided while creating the WS-Resource using

WS-Resource Provider Wizard. [Security Configuration] is one of the following illustrated in the table

below. The property value must be the same as that of the WS-Resource provider’s security configuration,

detailed below:

Table 32.

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’

sign_encrypt_authenticator For security as ‘sign, encrypt and authenticate’

sign_authenticator For security as ‘sign and authenticate’

encrypt_authenticator For security as ‘encrypt and authenticate’

For example, for a WS-Resource configured with security as ‘authentication only’ and WS-Resource

Name: ‘PrinterResource’, the client application must use the same security configuration by setting the

System property variable as:

printerResource.wsrf.security.type=authenticator

Setting client-side user credentials

For security configurations involving Authentication, you must provide a list of User IDs and passwords.

To do so:

v Locate the ibm-webservicesclient-bnd.xmi file in the respective package generated by the

WS-Resource client wizard tool – which could be one or more of:

– [package-prefix].client.security.authenticator

– [package-prefix].client.security.encrypt_authenticator

– [package-prefix].client.security.sign_authenticator

– [package-prefix].client.security.sign_encrypt_authenticator.v Edit the file to provide the user ID and password, as below:

<basicAuth userid="Joe" password="Joe123"/>

You can delete the security configuration to turn off security while accessing the WS-Resource.

Creating WS-Resources with Web container security:

In this mode, the Web service leverages the Basic Authentication mechanisms provided by the Web

container. Since the Web Container supports the declarative J2EE security model, web descriptor of the

Web Services specifies the security policy (roles, access control, and so on) declaratively in a web.xml file.

Developing applications 379

[

[

[[[

[

[[[[

[[

[[

[[

[[

[[

[[

[[

[[

[[[

[[[

[

[

[[

[[

[

[

[

[

[

[

[

[

[[[

Page 392: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Creating secure WS-Resource providers: In order to create a WS-Resource with Web Container

authentication enabled, you must use the WS-Resource Provider wizard and follow the steps described in

“Developing the Web Services bundle and adapter bundle for 6.1.1” on page 348 or “Developing the Web

Services bundle and adapter bundle for 6.1.2” on page 350. In the WS-Resource details page of the

wizard, select enable Web Container Authentication option.

The WS-Resource Web service component generated by the wizard includes a template web.xml file. You

must modify the security-constraint related information in the generated web.xml file.

Configuring Web container security:

The WS-Resource Web service component generated by the WS-Resource Provider wizard for a

WS-Resource with Web Container authentication support includes the template web.xml file detailed in

this section.

Refer to “Securing Web Application resources” on page 333 for information on configuring Web

Applications, using the User Admin Service to create users and roles, and using the Admin Utility for

OSGi to create users and roles.

The <security-constraint>, <login-config>, <security-role> sections of the XML document must be

updated as shown below:

Note: The code below in italics must be filled in by the developer. The tool generates the remainder of

the content.<web-app id="WebApp">

<display-name>BasicStore123</display-name>

<context-param>

<param-name>transportSecurityEnabled</param-name>

<param-value>false</param-value>

</context-param>

<servlet>

<servlet-name>WebSvcHttpServlet</servlet-name>

<display-name>WebSvcHttpServlet</display-name>

<servlet-class>com.ibm.pvcws.internal.service.WebSvcHttpServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>WebSvcHttpServlet</servlet-name>

<url-pattern>/</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.htm</welcome-file>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<security-constraint>

<web-resource-collection>

<web-resource-name>Manager</web-resource-name>

<url-pattern>/ws/pid/ManagerService</url-pattern>

<http-method>GET</http-method>

<http-method>POST</http-method>

</web-resource-collection>

<auth-constraint>

<role-name>role1</role-name>

</auth-constraint>

</security-constraint>

<login-config>

<auth-method>BASIC</auth-method>

</login-config>

<security-role>

<role-name>role1</role-name>

</security-role>

380 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[

[[

[

[[[

[[[

[[

[[

[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[

Page 393: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<security-role>

<role-name>role2</role-name>

</security-role>

<security-role>

<role-name>role3</role-name>

</security-role>

</web-app>

Developing client applications to access a secure WS-Resource for Web application security:

Your client application must provide proper user credentials while accessing the secure WS-Resource. In

order to set the user credentials in the request message, the OperationContext must be updated with the

username and password.

The following code snippet illustrates the steps involved to send a createWSResource request with the

username ”Joe” and password “Joe123”.

WSAddressingService wsaService = new WSAddressingServiceImpl();

EndpointReference toEPR = wsaService

.createEndpointReference("http://localhost:80/ws/pid/b3");

OperationContext opContext = new OperationContext();

WSResourceSoap_Stub stub = new WSResourceSoap_Stub();

opContext.setToEPR(toEPR);

String username = "Joe";

String password = "Joe123";

opContext.setUserCredentials(username, password);

stub.setCurrentOperationContext(opContext);

Date date = new Date(System.currentTimeMillis() + 36000);

Calendar calendar = Calendar.getInstance();

calendar.setTime(date);

toEPR = stub.createWSResource(null, calendar);

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:

Developing applications 381

[[[[[[[

[

[[[

[[

[[[[[[[[[[[[[[[[[[[[

[

Page 394: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 399 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:

v Modifies BundleActivator to implement ServiceTrackerCustomizer methods -

addingService(),modifiedService() and removedService() to perform life cycle management in the

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

382 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 395: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 393 for more

information.

Lotus Expeditor for Devices does not support running Web Services providers.

Creating a Mobile Web Services provider with service-specific exceptions:

Lotus Expeditor allows you to expose any Client Services project that implements a valid JSR-172

interface throwing service-specific exceptions as a Web service provider.

To create a Lotus Expeditor Web services provider throwing service-specific exceptions, perform the

following procedure:

1. Create a Client Services Project.

2. Create a Java Interface and add the methods for throwing service-specific exceptions.

3. Create a Java Class that implements the interface.

4. Right-click the Java class and select Expose as Mobile Web Service Provider.

5. Select the Java interface.

6. Select the checkbox Generate WSDL Fault.

7. Select Next.

8. Select any classes requiring custom marshalling.

9. Select Finish.

10. Launch the Client Services project in a runtime workbench.

The client services project BundleActivator will now expose the Web service class as an OSGi-based Web

service provider. In addition, the WSDL that defines the Web service provider will be generated in the

workspace with WSDL:faults defining the service-specific exceptions.

Next, add the Web service methods to the Java interface that throws service-specific exceptions:

public int getID(String name) throws NameNotFoundException;

Implement the Java interface in the Java class:

public int getID(String name) throws NameNotFoundException;

{

if(name!=null)

return id;

else

throw new NameNotFoundException(“Name not foundâ€);

}

Web Service methods can also be designed to throw multiple service-specific exceptions:

public int getID(String name) throws NameNotFoundException,AccessException;

Developing applications 383

[

[

[[

[[

[

[

[

[

[

[

[

[

[

[

[[[

[

[

[

[[[[[[[

[

[

Page 396: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In addition, the exposeService() method in the Provider application must set the property

com.ibm.pvcws.wsdlfault to true in order to process service-specific exceptions. If this property is not set

(the default), then the runtime will not throw any service-specific exceptions.

private void exposeService(WebServiceProvider provider) {

Hashtable props = new Hashtable();

props.put(org.osgi.framework.Constants.SERVICE_PID, "FooImpl");

props.put("com.ibm.pvcws.wsdl", "");

props.put("com.ibm.pvcws.wsdlfault", "true");

context.registerService(test.fooservice.IFoo.class.getName(),

new test.fooservice.FooImpl(), props);

provider.exportPid("FooImpl");

}

Design considerations for writing service-specific exceptions:

When creating Mobile Web Services providers with service-specific exceptions, there are many important

considerations to keep in mind.

v There must be one constructor defined with parameter types matching the return types of all getter

methods.

v Exception classes should have defined at least one getter method (for example, the default

getMessage() ) and have its corresponding constructor.

v The number of constructor parameters should match the number of defined getters.

v The getters should be defined in the same order of the parameter types specified by the constructor.

v Exception classes can have multiple constructors (excluding default constructor) but should provide at

least one appropriate constructor, with the parameter types matching the getter return types in that

sequence.

v You may or may not define setters.

v You may or may not define public/private members.

A Service Provider Interface may define methods, which can throw service specific exceptions:

public interface FaultTestInterface {

// Defined MyException as a service-specific Exception

public void testFault() throws MyException ;

}

The definition for a service-specific exception can have a few variants, as shown in the following

examples:

Sample Exception Class I (complete Java Bean)

public class MyException extends java.lang.Exception {

public String errorMessage;

public QName faultCode;

public MyException(String errorMessage, QName faultCode) {

super();

this.errorMessage = errorMessage;

this.faultCode = faultCode;

}

public String getErrorMessage() {

return errorMessage;

}

public void setErrorMessage(String errorMessage) {

this.errorMessage = errorMessage;

}

384 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[

[[[[[[[[[[

[

[[

[[

[[

[

[

[[[

[

[

[

[[[[[[

[[

[

[[[[[[[[[[[[[[[[[

Page 397: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

public QName getFaultCode() {

return faultCode;

}

public void setFaultCode(QName faultCode) {

this.faultCode = faultCode;

}

}

Sample Exception Class II (Partial Java Bean)

public class MyException extends java.lang.Exception {

private String errorMessage;

private QName faultCode;

public MyException(String errorMessage, QName faultCode) {

super();

this.errorMessage = errorMessage;

this.faultCode = faultCode;

}

public String getErrorMessage() {

return errorMessage;

}

public QName getFaultCode() {

return faultCode;

}

//No Set Method is defined in the exception class

Sample Exception Class III (Partial Java Bean)

public class MyException extends java.lang.Exception {

private QName faultCode;

//No private/public variable for the errorMessage

public MyException(String errorMessage, QName faultCode) {

super(errorMessage);

this.faultCode = faultCode;

}

public String getErrorMessage() {

return super.getMessage();

}

public QName getFaultCode() {

return faultCode;

}

}

All of the above Listings for the exception classes are valid and result in the listed Schema.

In Addition to the above mentioned variants of service-specific exception classes, the exception class can

also be defined without any public/private members.

Sample Exception Class IV

public class MyException extends java.lang.Exception {

public MyException(String errorMessage, QName faultCode) {

super(errorMessage);

}

Developing applications 385

[[[[[[[[

[

[[[[[[[[[[[[[[[[[[[[

[

[[[[[[[[[[[[[[[[[[[

[

[[

[

[[[[[[

Page 398: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

public String getErrorMessage() {

return super.getMessage();

}

//No private/public variable defined

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.

386 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[[[

[

Page 399: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

f. Optionally, select the Configure Security check box to configure Web Services Security for the

client.

g. Select Next.

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 393 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 399 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;

Developing applications 387

Page 400: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

public class MyBundleActivator

extends implements BundleActivator, HttpSettingListener

{

String endpoint = null;

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";

388 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 401: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

private static Map settingsMap = new HashMap();

public void settingsAdded(String pid, Dictionary properties)

{

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;

}

Developing applications 389

Page 402: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Integer httpsPort_ = (Integer)settings.get(

PROPERTY_HTTPS_PORT );

if (httpsPort_ != null)

{

httpsPort = httpsPort_.intValue();

validSetting = true;

found = true;

}

}

if (!found)

{

validSetting = false;

httpPort = 0;

}

}

}

If the Web service throws service-specific exceptions, your client interface and stubs must be designed to

throw those exceptions back to the application. The stub code will be generated accordingly by the Lotus

Expeditor Toolkit to handle the faults. In addition, the service-specific exception classes will be modified

to provide marshalling and unmarshalling code.

The client application (bundle activator) must catch and handle the service-specific exceptions:

com.ibm.test.ServiceInterfaceSoap_Stub stub =

new com.ibm.test.ServiceInterfaceSoap_Stub();

try{

int ID = stub.getID(null);

}catch (NameNotFoundException nfe){

}

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. To solve this problem,

set a property on the Web services provider exposeService method in order to differentiate

between the two.

390 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[[[

[

[[[[[[[

Page 403: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 OSGi

life cycle management. Hence the methods addingService(),modifiedService() and removedService()

must be added to the Bundle Activator code.

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");

Developing applications 391

Page 404: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

*/

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)” on page 393 for more information.

Note: For J2SE 1.5 based environment - If the Web Services clients need to set a connection timeout on a

specific request, the property response_timeout can be set on the stub or can be passed to the

register() method. The example below pertains to dynamic clients, but you can also set the same

property in the Stub.

Hashtable props = new Hashtable();

props.put("response_timeout","3000"); // where 3000 is in milliseconds

//The service interface class is passed along with the wsdl URL and props.

if (!wsManImpl.register(wsproviderwithdate.BirthDay.class,wsdlURL, props)) {

....

}

392 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 405: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

If the Web service throws service-specific exceptions, your client interface must be designed to throw

those exceptions back to the application. The Web Services runtime will handle the marshalling and

unmarshalling of the service-specific exceptions. As a result, those classes do not need to be modified.

However, the client application (bundle activator) needs to catch and handle the service-specific

exceptions:

if (svcs != null) {

// if the web service throws service-specific exception catch and handle the exception

try{

com.ibm.echo.Service stub = (com.ibm.echo.Service)svcs[0];

// invoke the web service method using the stub

}catch(MyException me){

//handle exception

}

Running multiple dynamic clients: Retrieving a stub object using the OSGi service mechanism works well

when running a single Web service or consuming different Web Services that do not create any package

conflicts. However, when you are running multiple dynamic clients that export the same packages (for

example, Client A and Client B exporting the same package, com.ibm.test), consume services from the

same Web service, or set different configuration properties on the dynamic stub, unexpected behaviors

have been observed. In such cases, it is recommended that you use the following mechanism when

retrieving the stub object for a given WSDL.

The following is an example of how to invoke the runtime API to access the dynamic proxy. This

approach is less complex than the one described above. The consumeService method must be modified,

and no Service tracking logic is required.

// The service interface class is passed along with the wsdl URL and props.

if (!wsManImpl.register(MyWebService.class,wsdlURL, props)) {

throw new Exception("Unable to consume service " + wsdlURL);

}

MyWebService stub = (MyWebService)wsManImpl.getProxy();

Note:

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. Lotus Expeditor Toolkit 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 OSGi Web Services engine.

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.

Developing applications 393

[[[

Page 406: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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().

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

394 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 407: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

Developing applications 395

Page 408: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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:

396 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 409: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

{

PropertyEntry entries[] = (PropertyEntry[])value;

for(int i = 0; i < entries.length; i++) {

((Properties)handle).put(entries[i].key, entries[i].value);

}

}

Developing applications 397

Page 410: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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(

ClassDescriberMarshalFactory.class.getName(),

new CalendarMarshalFactory(),

null);

}

To register the serializers, construct the two factories and register them as ClassDescriberMarshalFactory

services.

398 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 411: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Securing Mobile Web Services

This section provides information on securing Mobile Web Services.

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

381. 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:

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.

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 and jclDevice profiles cannot read the file serverSample.jks that is created using

other profiles such as J2SE due to the limitation of the jclDesktop and jclDevice profiles’ ability to

read a keystore and vice versa. We are planning to remove this limitation in a future release.

Developing applications 399

Page 412: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 410.

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.

b. Select Client Services > Mobile Web Services > Mobile Web Services Provider Security

Configuration.

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 Server type and the Security template from

the drop down menus (refer to “Creating secure Mobile Web Services providers” on page 399 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 and jclDevice profiles cannot read a serverSample.jks file that has been created

using other profiles such as J2SE due to the limitation of the jclDesktop and jclDevice profiles’

ability to read a keystore and vice versa. This limitation will be removed in a future release.

Developing custom authenticators or custom authorizers for Web Services providers: The Mobile Web

Services Security runtime provides a default authenticator for client authentication:

com.ibm.pvcws.wss.internal.auth.module.BasicAuthenticator.

It accesses org.osgi.service.useradmin.UserAdmin service internally to authenticate clients. You can use

this authenticator when UserAdmin manages your clients. However, custom authenticator is required when

you want to use a different user registry.

The Mobile Web Services Security runtime does not provide a default authorizer for client authorization.

This means that a custom authorizer is required whenever you want to authorize clients.

Developing custom authenticators: When a custom authenticator is required, you must develop a class that

implements the com.ibm.pvcws.wss.auth.Authenticator interface. The Authenticator interface consists of

two methods:

public interface Authenticator {

public String getAlias();

public void authenticate(AuthenticationContext context) throws WSSException;

}

400 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 413: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The Authenticator.getAlias() method should return a unique identifier. The Web Services Security

runtime invokes the Authenticator.authenticate() method to authenticate the clients. In the process,

com.ibm.pvcws.wss.auth.AuthenticationContext passes the username and user password used for client

authentication. The AuthenticationContext class has two methods:

public class AuthenticationContext extends Context {

public String getUsername();

public String getPassword();

}

The AuthenticationContext.getUsername() method returns the client’s username. You can acquire the

necessary username and password for clients uising these two methods only when there is a

UsernameToken in the request message.

The following is an example of the custom authenticator implementation:

import com.ibm.pvcws.wss.WSSException;

import com.ibm.pvcws.wss.auth.Authenticator;

import com.ibm.pvcws.wss.auth.AuthenticationContext;

public class SampleAuthenticator implements Authenticator {

public String getAlias() {

return this.getClass().getName();

}

public void authenticate(AuthenticationContext context) throws WSSException {

String username = context.getUsername();

String password = context.getPassword();

// Authenticates a client based on username and password

boolean authResult = ...;

if (!authResult) {

throw new WSSException(

"Failed authentication for the user: " + username

);

}

}

}

After you develop your custom authenticator, you need to update the Activator file in your Web Services

provider project to expose the authenticator as an OSGi service. Please add the following snippet in bold

into the Activator file. When you register your custom authenticator as a OSGi service in start() method,

you need to instantiate your custom authenticator:

private org.osgi.framework.ServiceRegistration authenticationService = null;

public void stop(BundleContext context) throws Exception {

plugin = null;

super.stop(context);

if (authenticationService != null) {

authenticationService.unregister();

}

if (tracker != null)

tracker.close();

}

public void start(BundleContext context) throws Exception {

super.start(context);

this.context = context;

authenticationService = context.registerService(

com.ibm.pvcws.wss.auth.Authenticator.class.getName(),

new SampleAuthenticator(),

Developing applications 401

Page 414: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

null

);

tracker = new ServiceTracker(context, serviceProvider, this);

tracker.open();

}

You must also update the Web Services Security configuration in your Web Services provider project.

Please refer to “Editing the Mobile Web Services security configuration for custom authenticators or

custom authorizers for Mobile Web Services providers (scenario #5)” on page 417.

Developing custom authorizers: When custom authorizer is required, you must develop the class that

implements the com.ibm.pvcws.wss.auth.Authorizer interface. The Authorizer interface consists of two

methods:

public interface Authorizer {

public String getAlias();

public void authorize(AuthorizationContext context) throws WSSException;

}

The Authorizer.getAlias() method should return a unique identifier. The Web Services Security runtime

invokes the Authorizer.authorize() method to authorize the clients. In the process,

com.ibm.pvcws.wss.auth.AuthorizationContext passes the username and user role information used for

client authentication. The AuthorizationContext class has two methods:

public class AuthorizationContext extends Context {

public String getUsername();

public java.util.List getRole();

}

The AuthorizationContext.getUsername() method returns the client’s username. The

AuthorizationContext.getRole() method returns the user role information. While you can authorize the

clients with just these two pieces of information, you need some additional steps described below in

order to get user role information.

The following is an example of the custom authorizer implementation:

import com.ibm.pvcws.wss.WSSException;

import com.ibm.pvcws.wss.auth.Authorizer;

import com.ibm.pvcws.wss.auth.AuthorizationContext;

import java.util.List;

public class SampleAuthorizer implements Authorizer {

public String getAlias() {

return this.getClass().getName();

}

public void authorize(AuthorizationContext context) throws WSSException {

String username = context.getUsername();

List roles = context.getRole();

// Authorizes a client based on username and role information

boolean authResult = ...;

if (!authResult) {

throw new WSSException(

"Failed authorization for the user: " + username

);

}

}

}

After you develop your custom authorizer, you must also update the Activator file in your Web Services

provider project to expose the authorizer as an OSGi service. Please add the following code (below, in

402 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 415: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

bold) into the Activator file. When you register your custom authorizer as an OSGi service in the start()

method, you must instantiate your custom authorizer.

private org.osgi.framework.ServiceRegistration authorizationService = null;

public void stop(BundleContext context) throws Exception {

plugin = null;

super.stop(context);

if (authorizationService != null) {

authorizationService.unregister();

}

if (tracker != null)

tracker.close();

}

public void start(BundleContext context) throws Exception {

super.start(context);

this.context = context;

authorizationService = context.registerService(

com.ibm.pvcws.wss.auth.Authorizer.class.getName(),

new SampleAuthorizer(),

null

);

tracker = new ServiceTracker(context, serviceProvider, this);

tracker.open();

}

You must also update the Web Services Security configuration in your Web Services provider project.

Please refer to “Editing the Mobile Web Services security configuration for custom authenticators or

custom authorizers for Mobile Web Services providers (scenario #5)” on page 417.

In order to acquire user role information, you must follow two additional steps:

v “Registering a Mobile Web Services provider as a web application with the Web Container”

v “Defining security roles and constraints in the web.xml file” on page 404

Registering a Mobile Web Services provider as a web application with the Web Container: All Mobile Web

Services projects are Client Services projects. In the Java EE world, the user roles and constraints are

provided using the web.xml file, which is generated as part of the Web project. Since Mobile Web Services

do not have the web.xml file, you must create it manually, and register it with the Web Container.

When user role information is required, you must register your Web Services provider as a web

application to the Web Container, as the Web Container loads necessary role information from the

WEB-INF/web.xml file in your Web Services provider project. It then passes the information through a

ThreadLocal variable. In order to register your Web Services provider as a web application, add the

following code (below, in bold) to the activator file in your Web Services provider project:

private void registerWebSvcWithWebcontainer() {

org.osgi.service.webapplication.WebApplication webApp =

new org.osgi.service.webapplication.WebApplication() {

public java.util.Dictionary getServletContextAttributes() {

return null;

}

public void deploymentException(Exception e) {}

};

java.util.Hashtable props = new java.util.Hashtable();

// YOUR-SERVICE-PID is set as a org.osgi.framework.Constants.SERVICE_PID below.

props.put(org.osgi.service.webapplication.WebApplication.WEBAPP_CONTEXT,

"/ws/pid/YOUR-SERVICE-PID");

context.registerService(org.osgi.service.webapplication.WebApplication.WEBAPP_SERVICE,

webApp, props);

Developing applications 403

Page 416: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

}

private void exposeService(WebServiceProvider provider) {

Hashtable props = new Hashtable();

props.put("com.ibm.pvcws.jaxrpc.soap.handler", "com.ibm.pvcws.wss.WSSHandler");

props.put("com.ibm.pvcws.wss.config.ext", "YOUR-EXPORT-FOLDER/ibm-webservices-ext.xmi");

props.put("com.ibm.pvcws.wss.config.bnd", "YOUR-EXPORT-FOLDER/ibm-webservices-bnd.xmi");

props.put("com.ibm.pvcws.wss.config.sdesc", "YOUR-SERVICE-DESC");

props.put("com.ibm.pvcws.wss.config.sport", "YOUR-SERVICE-PORT");

props.put(org.osgi.framework.Constants.SERVICE_PID, "YOUR-SERVICE-PID");

props.put("com.ibm.pvcws.wsdl", "");

context.registerService(YOUR-SERVICE-INTERFACE.class.getName(), new YOUR-SERVICE-CLASS(), props);

provider.exportPid("YOUR-SERVICE-EXPORT-PID");

registerWebSvcWithWebcontainer();

}

You must also import the org.osgi.service.webapplication plug-in in the META-INF/MANIFEST.MF file, as

the code above requires that bundle. In order to import the plug-in, select the META-INF/MANIFEST.MF file

and open it with the Plug-in Manifest Editor. Then, select the Dependencies tab, click Add for the

required plug-in, and select org.osgi.service.webapplication from the list of plug-ins.

Defining security roles and constraints in the web.xml file: When user role information is required, you must

also update the WEB-INF/web.xml file to include security roles and constraints. If the web.xml file does not

exist in your project, you must create it first. Then, modify the web.xml file as follows.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app id="WebApp_ID">

<display-name>YOUR-MANIFEST-SYMBOLNAME</display-name>

<context-param>

<param-name>transportSecurityEnabled</param-name>

<param-value>false</param-value>

<description>Used to turn off transport-level security. This setting will

override the security constraints specified in the web.xml descriptor</description>

</context-param>

<servlet>

<servlet-name>WebSvcHttpServlet</servlet-name>

<display-name>WebSvcHttpServlet</display-name>

<servlet-class>com.ibm.pvcws.internal.service.WebSvcHttpServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>WebSvcHttpServlet</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

<welcome-file-list>

<welcome-file>index.html</welcome-file>

<welcome-file>index.htm</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

<security-constraint>

<web-resource-collection>

<web-resource-name>YOUR-RESOURCE-NAME</web-resource-name>

<url-pattern>/*</url-pattern>

<http-method>POST</http-method>

</web-resource-collection>

<auth-constraint>

<role-name>YOUR-REQUIRED-ROLE-FOR-THIS-RESOURCE</role-name>

</auth-constraint>

</security-constraint> <login-config>

<auth-method>BASIC</auth-method>

404 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 417: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

</login-config>

<security-role>

<role-name>YOUR-ROLE</role-name>

</security-role></web-app>

When you modify the web.xml file, you must fill in the bold parts above according to your Web Services

provider project and your environment. Please refer to “Securing Web Application resources” on page 333

to understand how to update the web.xml file.

Retrieving authorized username and user role information inside the Mobile Web Services provider application:

When you use your custom authorizer in your Web Services provider, your provider application can

retrieve and use authorized username and user role information through a ThreadLocal variable.

com.ibm.pvcws.wss.auth.WSSUserAuthContext can access the ThreadLocal variable. The

WSSUserAuthContext class consists of two methods:

public class WSSUserAuthContext {

public String getUser();

public List getRoles();

}

The WSSUserAuthContext.getUser() method returns the authorized username. The

WSSUserAuthContext.getRoles() method returns user role information as a list of strings. When you want

to know the authorized username or user role information, please add the following code to your

provider application:

// Extracts the user context authorized in the Web Services Security runtime from a ThreadLocal variable

com.ibm.pvcws.wss.auth.WSSUserAuthContext context =

com.ibm.pvcws.wss.auth.WSSUserAuthContext.getCurrentContext();

// Gets the authorized username

String username = context.getUser();

// Gets the user role information as a list of Strings

List roles = context.getRoles();

Creating secure Mobile Web services clients: In order to secure Web services clients, refer to “Creating

Mobile Web Services clients” on page 386. 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.

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 Lotus Expeditor 6.x.

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

Developing applications 405

Page 418: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

– 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

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

Note: 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.

Note: The jclDesktop and jclDevice profiles cannot read the file clientSample.jks created using other

profiles such as J2SE due to the limitation of the jclDesktop and jclDevice profiles’ ability to read a

keystore and vice versa. This limitation will be removed in a future release.

Note: 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

410.

406 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 419: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Client Services > Mobile Web Services > Mobile Web Services Provider Security

Configuration.

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 405 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.

Note: 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.

Note: The jclDesktop and jclDevice profiles cannot read the file clientSample.jks created using other

profiles such as J2SE due to the limitation of the jclDesktop and jclDevice profiles’ ability to read a

keystore and vice versa. This limitation will be removed in a future release.

Note: When you select ‘Basic authentication’ as a template, the Mobile Web Services security

configuration declares username: @USERNAME@, password: @PASSWORD@ 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

410.

Developing custom callback handlers for Mobile Web Services clients: The Web Services Security

runtime provides the following three default callback handlers:

v com.ibm.pvcws.wss.internal.auth.callback.NonPromptCallbackHandler: extracts the client’s username

and password from the Web Services Security configuration in your Web Services client project. It is

used for the Username token.

v com.ibm.pvcws.wss.internal.auth.callback.X509CallbackHandler: extracts the client’s X.509 certificate

based on the Web Services Security configuration in your Web Services client project. It is used for the

X.509 binary security token.

v com.ibm.pvcws.wss.internal.auth.callback.LTPAInCookieCallbackHandler: accesses the authentication

server with the client’s username and password based on the Web Services Security configuration in

your Web Services client project. It then, acquires the contents of the LTPA token for the client. It is

used for the LTPA binary security token.

You can use these callback handlers for some typical scenarios. However, a custom authenticator is

required when you want to acquire information in ways other than the ones described above. For

example, if you want to extract a client’s username and password dynamically from your own user

Developing applications 407

Page 420: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

registry. When a custom callback handler is required, you are responsible for developing the class that

implements the javax.security.auth.callback.CallbackHandler interface. The CallbackHandler interface

consists of two methods:

public interface CallbackHandler {

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException;

}

The CallbackHandler.handle() method requires some Callbacks to pass necessary information, such as

the username and password. The following is a list of Callbacks that is used in the Web Services Security

runtime:

v javax.security.auth.callback.NameCallback: used to pass the client’s username to the

com.ibm.pvcws.wss.internal.token.UsernameTokenGenerator.

v javax.security.auth.callback.PasswordCallback: used to pass the client’s password to the

com.ibm.pvcws.wss.internal.token.UsernameTokenGenerator.

v com.ibm.pvcws.wss.auth.callback.ContextCallback: used to get the

com.ibm.pvcws.wss.auth.CallbackContext.

v com.ibm.pvcws.wss.auth.callback.X509BSCallback: used to pass the client’s X.509 certificate to the

com.ibm.pvcws.wss.internal.token.X509TokenGenrator.

v com.ibm.pvcws.wss.auth.callback.LTPABinaryCallback: used to pass the client’s LTPA token to the

com.ibm.pvcws.wss.internal.token.LTPATokenGenrator.

Here are the methods for these callbacks that you can use:

public interface NameCallback {

public void setName(String name);

}

public interface PasswordCallback {

public void setPassword(char[]);

}

public interface ContextCallback {

public void com.ibm.pvcws.wss.auth.CallbackContext getContext();

}

public interface X509BSCallback {

public void setCert(java.security.cert.X509Certificate);

public void setKeyStorePath(String kspath);

public void setAlias (String alias);

}

public interface LTPABinaryCallback {

public void setBinary(String binary);

}

The callback handler sets the necessary callback information and returns it to the token generator that

invokes the callback handler. As a result, the programming style depends on the token generator. By

using UsernameTokenGenerator, you can develop your custom callback handler as follows:

import com.ibm.pvcws.wss.auth.CallbackContext;

import com.ibm.pvcws.wss.auth.CallbackHandlerConfig;

import com.ibm.pvcws.wss.auth.callback.ContextCallback;

import java.io.IOException;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.NameCallback;

import javax.security.auth.callback.PasswordCallbackimport;

import javax.security.auth.callback.UnsupportedCallbackException;

public class UsernameTokenCustomCallbackHandler implements CallbackHandler {

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

408 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 421: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

if ((callbacks == null) || (callbacks.length == 0)) {

throw new UnsupportedCallbackException(null, "There is no callback.");

}

// Gets necessary information from callbacks.

NameCallback namec = null;

PasswordCallback pwdc = null;

CallbackContext ctx = null;

int lc = callbacks.length;

for (int i = 0; i < lc; i++) {

Callback c = callbacks[i];

if (c instanceof NameCallback) {

namec = (NameCallback)c;

} else if (c instanceof PasswordCallback) {

pwdc = (PasswordCallback)c;

} else if (c instanceof ContextCallback) {

ContextCallback cc = (ContextCallback)c;

ctx = cc.getContext();

} else {

throw new UnsupportedCallbackException(c, "Unknown callback: " + c.getClass().getName());

}

}

// Gets the configuration if necessary.

CallbackHandlerConfig c = (CallbackHandlerConfig)ctx.getConfiguration();

// Gets the username and password dynamically (based on the configuration if necessary).

String username = ...;

char[] password = ...;

// Sets the username and password to the callback.

namec.setName(username);

pwdc.setPassword(password);

}

}

By using LTPATokenGenrator, you can develop your custom callback handler as follows:

import com.ibm.pvcws.wss.auth.CallbackContext;

import com.ibm.pvcws.wss.auth.CallbackHandlerConfig

import com.ibm.pvcws.wss.auth.callback.ContextCallback;

import com.ibm.pvcws.wss.auth.callback.LTPABinaryCallback;

import java.io.IOException;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.NameCallback;

import javax.security.auth.callback.PasswordCallbackimport;

import javax.security.auth.callback.UnsupportedCallbackException;

public class LTPATokenCustomCallbackHandler implements CallbackHandler {

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

if ((callbacks == null) || (callbacks.length == 0)) {

throw new UnsupportedCallbackException(null, "There is no callback.");

}

// Gets necessary information from callbacks.

LTPABinaryCallback binaryc = null;

CallbackContext ctx = null;

int lc = callbacks.length;

for (int i = 0; i < lc; i++) {

Callback c = callbacks[i];

if (c instanceof LTPABinaryCallback) {

binaryc = (LTPABinaryCallback)c;

} else if (c instanceof ContextCallback) {

ContextCallback cc = (ContextCallback)c;

Developing applications 409

Page 422: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

ctx = cc.getContext();

} else {

throw new UnsupportedCallbackException(c, "Unknown callback: " + c.getClass().getName());

}

}

// Gets the configuration if necessary.

CallbackHandlerConfig c = (CallbackHandlerConfig)ctx.getConfiguration();

// Gets the username and password dynamically (based on the configuration if necessary).

String username = ...;

char[] password = ...;

// Gets the authentication server URI dynamically (based on the configuraiton if necessary).

String serverURI = ...;

/* Use the ServerURL to connect to the authentication server where you can POST the username

and password to retrieve the LTPA Token. e.g in the case of WebSphere Application Server, The

URL is http://<hostname>:<port>/j_security_check. You can do HTTP POST to retrieve the tokens.

The application server returns LTPA Tokens in the form of cookies. They are already Base64

encoded. You can extract the appropriate token and pass it the setBinary method below. */

// Gets the Base64 encoded content of the LTPA token using the information above.

String content = null;

// Sets the LTPA token to the callback.

binaryc.setBinary(content);

}

}

After you develop your custom callback handler, you must also update the Web Services Security

configuration in your Web Services client project.

Lotus Expeditor for Devices does not support LTPA based callback handlers.

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

RAD 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 Web Services provider 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 Web Services

provider 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 Web Services

provider 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

410 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 423: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

message. The Web Services provider 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.

This section also introduces some scenarios using the custom authenticator, custom authorizer, and

custom callback handler.

Editing the 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. Select the wssecurityclient.xml file and open it with 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 the 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

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. Select the wssecurityclient.xml file and open it with 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:

Developing applications 411

Page 424: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

1. Select the wssecurity.xml file and open it with 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 the 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. Select the wssecurityclient.xml file and open it with 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. 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.

412 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 425: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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. Select the wssecurity.xml file and open it with 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.

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 the 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. Select the wssecurityclient.xml file and open it with the WS-Security Client Editor.

Developing applications 413

Page 426: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

414 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 427: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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. Select the wssecurity.xml file and open it with the WS-Security Provider Editor.

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.

Developing applications 415

Page 428: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.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.

416 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 429: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Editing the Mobile Web Services security configuration for custom authenticators or custom authorizers for Mobile

Web Services providers (scenario #5): Before editing the Mobile Web Services security configuration, this

scenario assumes that you selected Use template configuration under from the How to create Web

Services Security configuration menu. It also assumes you selected a security template that includes

Basic authentication only. To edit a Mobile Web Services security configuration in this scenario for the

Web services provider, perform the following procedure:

1. Select the wssecurity.xml file and open it with the WS-Security Provider Editor.

2. Expand the Request Consumer Binding Configuration Details on the WS binding tab.

3. Expand the Token Consumer section, select the con_unt item from the list, and select Edit. From the

next menu:

a. Add a new property.

b. Input com.ibm.pvcws.wss.authenticator as a Property Name and the classpath of your custom

authenticator as a Property Value if you want to use your custom authenticator.

c. Input com.ibm.pvcws.wss.authorizer as a Property Name and the classpath of your custom

authorizer as a Property Value if you want to use your custom authorizer.

d. Select OK.4. Save your changes to the wssecurity.xml file.

Editing the Mobile Web Services security configuration for Username token custom callback handler for Mobile

Web Services clients (scenario #6): Before editing the Mobile Web Services security configuration, this

scenario assumes that you selected Use template configuration from the How to create Web Services

Security configuration menu, as well as a security template that includes Basic authentication only. To

edit a Mobile Web Services security configuration in this scenario for the Web services client, perform the

following procedure:

1. Select the wssecurityclient.xml file and open it with the WS-Security Client Editor.

2. Expand the Security Request Generator Binding Configuration section on the WS binding tab.

3. Expand the Token Generator section, select the gen_unt item from the list, and select Edit. From the

next menu:

a. Remove the existing Callback handler, and input the classpath of your custom callback handler as

the Callback handler.

b. Select OK.4. Save your changes to the wssecurityclient.xml file.

Editing the Mobile Web Services security configuration for LTPA token callback handler for Mobile Web Services

clients (scenario #7): Before editing the Mobile Web Services security configuration, this scenario assumes

that you selected Use template configuration from the How to create Web Services Security

configuration menu, as well as security template that includes Basic authentication only. To edit a

Mobile Web Services security configuration in this scenario for the Web services client, perform the

following procedure:

1. Select the wssecurityclient.xml file and open it with the WS-Security Client Editor.

2. Expand the Request Generator Configuration section on the WS extension tab.

3. Expand the Security Token section, select the sec_token_unt item from the list, and select Edit. From

the next menu:

a. Remove the existing Name and input sec_token_ltpa as the new Name.

b. Select Custom token as the Token type.

c. Input http://www.ibm.com/websphere/appserver/tokentype/5.0.2 as a URI.

d. Remove the existing Local name and input LTPA as the new Local name.

e. Select OK.4. Expand the Security Request Generator Binding Configuration section on the WS binding tab.

Developing applications 417

Page 430: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

5. Expand the Token Generator section, select the gen_unt item in from the list, and select Edit. From

the next menu:

a. Remove the existing Token generator name and input gen_ltpa as the Token generator name.

b. Remove the existing Token generator class and input

com.ibm.pvcws.wss.internal.token.LTPATokenGenerator as the new Token generator class

c. Select sec_token_ltpa as the Security token.

d. Select Custom token as the Value type.

e. Remove the existing Local name and input LTPA as the new Local name.

f. Input http://www.ibm.com/websphere/appserver/tokentype/5.0.2 as a URI.

g. Remove the existing Callback handler and input com.ibm.pvcws.wss.internal.auth.callback.

LTPAInCookieCallbackHandler as the new Callback handler.

h. Remove the existing User ID and input an appropriate User ID.

i. Remove the existing Password and input an appropriate Password.

j. Add a new Callback Handler Property.

k. Input com.ibm.pvcws.wss.ltpaserver as a Property Name and the authentication server URL, such

as http://com.ibm.com/authenticationServer, as a Property Value.

l. Input com.ibm.pvcws.wss.ltpa.tokentype as a Property Name, LtpaToken for releases prior to

WebSphere Application Server V5.1.1, or LtpaToken2 for WebSphere Application Server V5.1.1 or

later as a Property Value.

m. Select OK.6. Save your changes to the wssecurityclient.xml file.

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 the OSGi framework.

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 386 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.

418 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 431: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 387 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 390 and “Custom serialization (marshalling)” on page 393 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

Developing applications 419

Page 432: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 support is enabled using the Apache Axis

1.4.

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.4 runtime

bundled in Lotus Expeditor v6.1.1.

The role for using the Apache Axis runtime is strictly for Client-Side only. Currently, the Apache Axis

runtime does not allow the exposure of Web Services. In addition, only minimal security is supported. If

the security is needed, SSL & Basic Authentication should 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 Clients

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:

420 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 433: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

1. Create a Client Services project. Please refer to “Creating a Client Services project” on page 30. Or

convert the project to a Client Services Project using Lotus Expeditor Toolkit, if needed:

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");

This approach is recommended when full control of the configurations is required. This also removes the

dependency of the JNDI, Apache Axis Proxy and the accounts.

Developing applications 421

Page 434: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

Using the Accounts tool to create accounts for Apache Axis Web services clients: To create accounts

for Apache Axis based Web services clients that use the JNDI mechanism for stub instance look up,

perform the following procedure:

1. From the Lotus Expeditor Client, select File > Preferences...

2. Select Accounts from the left panel.

422 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 435: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

3. Click the New Account button to create a new account.

4. The New Account dialog opens. This dialog allows you to create many different types of accounts.

Depending on what type of authentication is required for the web services, you can set various

configuration options for that particular account. There are four possible types of accounts you can

create for Web services clients based on the supported authentication types in Lotus Expeditor:

No authentication: This account only has basic information that a Web services client needs to

communicate with a Web service. The only information you need to provide is the end point address for

the Web service. This does not require any authentication specific information.

Fill in the following information and then click OK:

Table 33. Simple account properties

Field Entry Comments

Account Name <account_name> A unique name. This name will be

used by the application to look up

the information.

Description Description for the account.

Type HTTP/HTTPS This indicates what type of protocol

to use, it must be set to

HTTP/HTTPS.

Server <complete_end_point_address> The end point address for the Web

Service your application will connect

to. For example, http://127.0.0.1/EchoService/services/EchoService

You may leave the default values for the other properties. These values are not used.

Basic authentication: This type of account has the basic information plus some additional information that

a Web services application would need to authenticate with the server. This authentication happens at the

transport level (that is, the userid/password is sent in the HTTP header as part of the request to the

server).

In addition to the basic information, fill in the following information and then click OK.

Table 34. Basic authentication properties

Field Entry Comments

Name <userid> User identification. This name will be

used by the application to look up

the information.

Password <password> Password.

Authentication type HTTP Basic Under Advanced properties, select

HTTP Basic as the Authentication

type.

You can leave the default values for the Home Portal URL and the Authentication URL field. These

values are not used for Basic authentication.

LTPA token based authentication: This type of account contains basic account information plus additional

information to authenticate with the server using the LTPA mechanism. When you use the lightweight

third party authentication (LTPA) method, the security token is generated as part of the SOAP message.

Do not configure the client application for LTPA token authentication unless the authentication

mechanism configured in WebSphere Application Server v6.x is LTPA.

Developing applications 423

Page 436: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In addition to the basic information, fill in the following information and then click OK.

Table 35. LTPA token properties

Field Entry Comments

Name <userid> User identification. This name will be

used by the application to look up

the information.

Password <password> Password.

Authentication URI /j security check This must be changed based on your

server’s configuration. For

WebSphere Application Server

/j_security_check is the default.

Authentication Type J2EE form Under Advanced properties, select

J2EE Form as the Authentication

type.

You can leave the default values for the Home Portal URL. This value is not used for LTPA token based

authentication.

Username token based authentication: This is a unique type of account for Web services in Lotus Expeditor.

This account must be created as a secondary account. That means when you define this account, it does

not have its own user ID and password, as there is no login module associated with the Username Token

authentication type. It relies on the HTTP Basic or Java EE Form login modules to validate the

credentials. The account shares the credentials defined in an associated primary account. The box Allow

other accounts to use this log in information must be checked in the primary account so that it can be

tied to this secondary account.

When you use the BasicAuth authentication method, the security token that is generated is a

<wsse:UsernameToken> element with <wsse:Username> and <wsse:Password> elements. Lotus Expeditor

Apache Axis runtime supports text passwords only. Because passwords cannot be retrieved from the

server (and because most servers do not support it), Lotus Expeditor Apache Axis runtime does not

support password digest.

In addition to the basic information, fill in the following information and click OK.

Table 36.

Field Entry Comments

Account <name of the primary account> Under the Login information, select

the User name and password of an

existing account. Note that this

existing account must have an

authentication type of HTTP or Java

EE.

Authentication type User Name Token Under Advanced properties, select

User Name Token as the

Authentication type.

You can leave the default values for the other properties. These values are not used.

Site Minder based authentication: This type of account contains basic account information to login the

SiteMinder Web Access Manager. When a service is protected by SiteMinder, the security cookie sent back

by server is inserted into the HTTP header as part of the HTTP request.

424 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 437: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In addition to the basic information, fill in the following information and then click OK.

Table 37. Site Minder Properties

Name Entry Comments

Name <userid> User identification. This name is used

by the application to look up the

information.

Password <password> Password.

Authentication Type Site Minder Form Under Advanced properties, select

Site Minder Form (advanced) as the

Authentication type.

TAM based authentication: This type of account contains basic account information to login the Tivoli

Access Manager. When a service is protected by TAM, the security cookie sent back by server is inserted

into the HTTP header as part of the HTTP request.

In addition to the basic information, fill in the following information and then click OK.

Table 38. TAM Properties

Name Entry Comments

Name <userid> User identification. This name will be

used by the application to look up

the information.

Password <password> Password.

Authentication Type TAM Form Under Advanced properties, select

TAM Form (advanced) as the

Authentication type.

TAM Single Sign On based authentication: This type of account is only supported on Windows, and uses

the credentials of the operating system. In addition to what is done for TAM, the security cookie sent

back by the server is also inserted into the HTTP header as part of the HTTP request.

Since the credentials of operating system is reused, the user name and password are not required for this

type of account.

Table 39. TAM Single Sign On Properties

Name Entry Comments

Authentication Type TAM SPNEGO Under Advanced properties, select

TAM SPNEGO (advanced) as the

Authentication type.

PORTAL based authentication: This type of account is the same as LTPA based authentication, except that

it contains a JSESSIONID cookie. The LTPA token is inserted into the SOAP message header and the

JSESSIONID is inserted into the HTTP header as part of the Web services request.

Table 40. PORTAL based authentication

Name Entry Comments

Name <userid> User identification. This name will be

used by the application to look up

the information.

Password <password> Password.

Developing applications 425

Page 438: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 40. PORTAL based authentication (continued)

Name Entry Comments

Authentication URL /j_security_check This must be changed based on your

server’s configuration. For

WebSphere Application Server,

/j_security_check is the default.

Authentication Type J2EE Form Under Advanced properties, select

J2EE Form (advanced) as the

Authentication type.

Programmatically creating accounts for Apache Axis Web Services clients: One can create an account

programmatically that will be used by Apache 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.

– SM-FORM – For forms based authentication to access a SiteMinder protected resource

– TAM-FORM – For forms based authentication to access a TAM protected resource

– TAM-SPNEGO – For SPNEGO (Kerberos based) authentication to access a TAM protected resource

(TAM server must be configured to work with Active Directory)

– PORTAL-FORM - This authentication type is similar to J2EE-FORM, except that a JSESSIONID

(cookie) is inserted into the HTTP header as part of the request.v AuthProperties.AUTH_SERVER allows you to set the authentication URI from where the LTPA token

or session cookie 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 authentication 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);

426 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 439: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Note: The Lotus Expeditor Apache Axis runtime does not support Nonce (randomly generated token)

with Username Token authentication. The <wsse:Nonce> and <wsu:Created> elements are not

generated within the <wsee:usernameToken=""> element.

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.

Developing applications 427

Page 440: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

2. Right click the Client Services portlet project and select New > Other > Client Services > Wiring

Properties 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 > Wiring Properties 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.

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.

428 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 441: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

<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.

Developing applications 429

Page 442: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 sourcename - 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.

Property Broker Editor

In composite applications, Web Services Description Language (WSDL) files (XML files) containing name

spaces, properties, actions, and types are used by components for component interaction in a composite

application.

Components within a composite application can be wired together so a user-initiated action in one

component can trigger a programmed action in another component. This functionality is supported by

the use of properties, actions, types, and the property broker. The composite application components use

a model for declaring, publishing, and sharing this information with each other via the WebSphere Portal

property broker.

Components subscribe to the broker by publishing typed data items - properties and actions - that they

can share. Components can act either as a provider or as a recipient of these properties and actions.

These components may be developed and deployed separately or together and can exchange information

and react in a coordinated manner, thus improving the end-user experience. Conversely, as components

are removed, the remaining components will still be able to function correctly and in a coordinated

manner. The property broker is used to facilitate development of components that may be dynamically

integrated, without requiring previous coordination at development time. Composite applications can

simply be an assembly of multiple components with on-the-glass aggregation that keep the application

user focused on the business process, eliminating the need for the application user to switch between

applications or switch between open windows.

To derive additional value and further increase organizational productivity, you can have components

form causal relationships with other components through properties and actions. A property broadcasts a

value and an action consumes a value. In order to make sure that both sides are communicating

consistently, both properties and actions need to describe the type of value they broadcast or consume.

This ensures that sensible connections are made when the components are wired together.

WSDL files that are used in composite applications are created and edited using the Property Broker

Editor. This feature provides an easy way for you to describe property broker properties, actions, and

types without having to understand the WSDL format. You define the properties, actions, and types

through a simple interface which then generates the WSDL file required by property broker

implementations when you save the editor settings. The editor can be launched using either of the

following methods:

v To create a new Property Broker WSDL file using the New File wizard, selecting File > New > Client

Services > Wiring Properties.

v To edit an existing file, select it in the Navigator and then launch the editor using Open With > Wiring

Properties.

Refer to the Property Broker Editor help menu for instructions on how to:

v Define wiring properties

v Define property data types

430 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 443: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v Define wiring actions and action parameters

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

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, such as 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, allowing 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);

Developing applications 431

Page 444: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

- resource-bundle - Optional Resource Bundle that Property Broker will use to resolve externalized

strings.

432 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

Page 445: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

<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>

Developing applications 433

Page 446: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

</operation>

</binding>

</definitions>

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, 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);

434 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 447: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 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.

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.

Developing applications 435

Page 448: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 41. 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.x 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.

436 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 449: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

All methods on Logger are multi-thread safe.

The Lotus Expeditor 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.

Note: Using NL characters with JSR 47 logging on devices may cause unexpected results. ISO-8859-1

characters are recommended.

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 504.

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.

Developing applications 437

Page 450: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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?

438 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 451: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The following pattern can be used in each class to obtain a JSR47 logger:

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

Developing applications 439

Page 452: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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.

440 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 453: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 {

Developing applications 441

Page 454: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

if (logger.isLoggable(Level.FINER)) {

logger.entering(CLASSNAME,

"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 Target Definition tab. For more information on this screen, refer

to “Setting Client Services project properties” on page 32.

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.

442 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 455: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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/

Developing applications 443

Page 456: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

– 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.

444 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 457: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

Derby (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 172.

Alterntiavely, you will need to use the lifecycle capabilities provided by the platform to start these

bundles.

Refer to Managing lifecycle in the documentation Assembling and Deploying Lotus Expeditor

Applications 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 in the documentation Assembling and Deploying Lotus Expeditor

Applications 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.

Developing applications 445

Page 458: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

The administrative API for the Lotus Expeditor micro broker has moved to a separate bundle:

com.ibm.micro.admin. This means that you must migrate any bundles which use the ″Require-Bundle″

manifest entry to create a dependency on the micro broker for admin. Instead, make sure that all bundles

use the ″Import-Package″ manifest entry. This is a good practice for OSGi, and means that application

bundles are more resilient to other bundles being renamed, or code being moved.

Migrating Portlet applications

When upgrading an existing Lotus Expeditor 6.1 or 6.1.1 installation to Lotus Expeditor 6.1.2, users must

first update the Lotus Expeditor 6.1.2 install manifest to include the following provisioning command.

<feature id="com.ibm.rcp.portletcontainer.collaborator.feature" version="<feature_version>" size="37"

download-size="36" match="greaterOrEqual" action="uninstall" shared="false"/>

This uninstall command ensures that the com.ibm.rcp.portletcontainer.collaborator.feature is

removed prior to the launch of the platform. Note that 6.1.1 Portlet applications will not work property if

this feature exists in your Lotus Expeditor 6.1.2 installation.

Migrating Device applications using the setup file

When upgrading an existing Lotus Expeditor 6.1 or 6.1.1 installation to Lotus Expeditor 6.1.2 using setup

file, you must first uninstall the previous version of Expeditor.

Table 42.

Setup File Device

XPD-wm-setup.exe For Windows Mobile devices

Expeditor-wince5-setup.exe For WinCE devices

To migrate existing applications using the setup file, perform the following procedure:

1. Run the 6.1.2 setup file and uninstall the currently installed Expeditor 6.1 or 6.1.1 software.

a. Select Expeditor 6.1 or 6.1.1 from the list that appears.

b. With the Expeditor software highlighted, select Remove.

During the uninstallation process, you may be asked if you want to remove the workspace. Do not

remove the workspace. Preserving the workspace allows applications to be migrated to Expeditor

6.1.2 in the following step.

2. Run the 6.1.2 setup file a second time to install Lotus Expeditor 6.1.2.

The installation installs, using the workspace preserved in the previous step.

Running WebSphere Everyplace Deployment 6.0 Web Services

applications on Lotus Expeditor

To run WebSphere Everyplace Deployment 6.0 Web Services applications, the following changes must be

made to the application’s MANIFEST.MF file in order for it to run successfully in Lotus Expeditor 6.1.1. You

must also update the Require-Bundle option to reflect the dependency on the com.ibm.pvcws and

com.ibm.pvcws.osgi bundles as shown below:

Require-Bundle: com.ibm.pvcws, com.ibm.pvcws.osgi

Also, remove the following packages from the Import-Package statement in the MANIFEST.MF file;

446 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[[

[[

[[[

Page 459: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v javax.xml.namespace

v javax.microedition.xml.rpc

v javax.xml.rpc

To run WebSphere Everyplace Deployment 6.0 or Lotus Expeditor 6.1 dynamic client applications in the

Lotus Expeditor 6.1.2 runtime, do the following:

1. Add Require-Bundle: com.ibm.pvcws, com.ibm.pvcws.osgi to the MANIFEST.MF file.

2. In your Activator code for dynamic clients, get the proxyservice using

com.ibm.pvcws.proxy.WSProxyService.class.getName(), not by initializing it as a String

com.ibm.pvcws.proxy.WSProxyService.

Developing applications 447

[[

[

[[[

Page 460: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

448 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 461: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Java EE 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 Java EE 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 Java EE tools, it may be more natural to use if you are primarily doing Java EE

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 461 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, 2008 449

Page 462: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 Plug-ins 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 Java EE 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 Java EE or Web perspective when using the server tools to run

Java EE 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 Plug-ins 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 Java EE 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 Java EE 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.

450 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 463: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In order to add a non-Java EE Client Services project to a server, you must go to the advanced editing

screen (refer to “Editing a server” on page 450). 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 449. Be sure to use the Debug

> Debug... option in step 1.

Using the Debug Launch Configuration is the easiest way to launch and debug a platform, and perform

debugging tasks. If you choose not to use a Debug Launch Configuration from the toolkit, you can also

launch the Lotus Expeditor platform for debugging using the command line.

The instance of the Lotus Expeditor platform that is installed separately uses a technology known as JXEs

to improve runtime performance and reduce memory footprint. JXEs are created dynamically during

platform operation. However, the default configuration creates JXE files without debug information. This

inhibits the ability to set breakpoints. There are two options to enable successful setting of breakpoints:

1. If you infrequently launch the platform for debugging purposes, you can use the parameter -clean

when launching the platform. This removes existing JXE files, and the code (including debug

information, if available) will be loaded from the plug-in JAR files. Each launch recreates the JXEs,

and you will see this activity in the debugger as short lived threads that are started to create JXE files

for future launches.

2. If you frequently launch the platform for debugging purposes, you can disable the JXE support. This

will no longer create JXE files. Once completed with the debugging activities, you should reenable the

JXE support to take advantage of the performance improvements.

To disable JXE support, edit the rcpinstall.properties used for your configuration. The

rcpinstall.properties file is located in the .config directory of the workspace used when launching

your platform.

For 6.1.1, add the following line:

-Dosgi.framework.extensions=com.ibm.rcp.core.logger.frameworkhook

For 6.1.2, add the following line:

-Dnojxe=true

Then save the file.

To enable JXE support, remove the line -Dnojxe=true above, or change it to -Dnojxe=false.

To launch the platform for debugging, add the following parameters to the Lotus Expeditor launch

command line, where zzzz is an available port on your system:

-vmargs -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=zzzz

The platform will start and wait for the debugger to connect before continuing with the launch. If the

port selected is unavailable, the platform continues to launch, and the debugger will be unable to

connect.

Debugging and testing applications 451

[

[

[

Page 464: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Warning dialogs in the debugger with messages stating ’Unable to install breakpoint in <classname> due to

missing line number attributes’ indicate that debugging attributes are not available in the classes you are

attempting to debug. There are two possibilities:

1. The class does not actually contain debug information. If you have just exported the plug-in

containing the class, check the Java compiler preferences (Window > Preferences > Java > Compiler)

and verify that variable, line number, and source file attributes used by the debugger are all selected.

2. JXEs are being used to load class files, and do not contain debug information. Refer to the steps above

to adjust your launch configuration.

Note: If you changed the rcpinstall.properties file by adding the line specified above, be sure to

remove this line once you have completed debugging to again take advantage of the JXE

performance improvements.

Remote debugging and testing on devices

Lotus Expeditor’s remote debugging function automatically builds, packages, deploys, and launches your

project on a target device. In order to debug a Lotus Expeditor application, you must launch it using

specific debug options. You can launch Web applications or Client Service applications using a Debug

Launch Configuration from the Expeditor on Device launcher in the toolkit. The current release only

supports deploying one OSGi bundle to the remote device.

In the Eclipse based IDE, select Debug..., then create a new Expeditor on Device launch configuration.

Select the name of project you want to debug, and select a Device of Pocket PC or Nokia. For Connection

Properties, supply the IP address or host name of the remote system if required, and leave the default

values for other settings.

Note: If a problem occurs while launching a bundle on a device, check the error description in the

console output view or from the log file. The problems may be caused by unexpected errors from

the bundle.

When debugging on a Nokia E90 device, there are two main differences:

1. Because of the Nokia eRCP architecture, if you modify the MANIFEST.MF or plugin.xml files, you must

manually update the bundle status using the framework update command.

2. To correctly remove an application UI after debugging, the Nokia eRCP runtime must be stopped

using IAgentConfig.

Note: The support for the Nokia E90 is provided as early release code for internal evaluation and

testing. The support for the Nokia E90 may not be used for productive purposes.

Preparing debugging connection

For Windows Mobile and WinCE devices, the debugging connection is made via Microsoft ActiveSync.

For Nokia E90 devices, wireless LAN or Bluetooth connections can be used.

Once the device is connected, perform the following procedure:

1. For 6.1.1, obtain the device IP using the ConnTest tool, and copy this value to the Connection

Properties > IP field.

2. For 6.1.2, obtain the device IP using the IAgent Config tool.

a. From the device, navigate to Installations > IAgent Config.

452 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

Page 465: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

b. Click Options and select Show IP.

c. Copy this value to the Connection Properties > IP field.3. For Nokia devices, increase the connection response time to avoid time-outs.

4. From the device, navigate to Tools > Settings > Connection > Wireless LAN and select Options.

5. Select Advanced Settings and change Automatic Configuration to Disabled.

6. Increase both the Long retry limit and Short retry limit.

7. Disable Power saving.

While it is not required to install Nokia PC Suite, it is an option that can be used to install the Nokia

Instrumention Agent.

Note: Nokia PC Suite can not be used for remote debugging.

Installing debugging tools

Before debugging on devices, you must first install debugging tools for both Windows Mobile and Nokia

devices.

Windows Mobile devices must use the debug version of J9. The debug version also has an OSGi console

to let users manually manage OSGi bundles.

To install the debugging tools, perform the following procedure:

1. From the Expeditor Client CD, unzip \utils\DebugPackage.zip to a temporary directory.

2. Re-name the file j9dbg_ce5.exe or j9dbg_wm.exe (depending on your target device) to j9.exe.

3. Copy j9.exe to the \eclipse\ plugins\com.ibm.pvc.wece.device.win32.arm_6.1.2.0-{date}\jre\bin

folder on the device.

If you are using a Nokia device, the Nokia Instrument Agent must also be installed:

1. Download the Instrumentation Agent from Nokia and place it on the device.

2. For 6.1.1, and using the device File Manager, select the Agent SISX file to install the agent.

3. For 6.1.2, use the Nokia PC Suite to install the Instrument Agent.

4. (Optional) To use the OSGi console, download the Remote Console from Nokia to a desktop system.

The Remote Console accepts connections from the device to show the device’s OSGi console on the

PC. For more information, refer to the Nokia documentation provided with the Remote Console.

5. Download the debug build of J9, as well as the runtimes from Nokia and install them. The file name

is likely to be OSGiJXEUdeb-0?w??.SISX, where ″?″ is a numerical digit.

Setting Up the Lotus Expeditor Configuration

To set up the Lotus Expeditor configuration, perform the following procedure:

1. Create a project for debugging. It can be either a Client Services, Web Application or generic plug-in

Application.

2. Select Run > Debug...

3. Double-click Expeditor on Device.

4. Change the new configuration’s name.

5. Switch to the Java Application tab, and select a proper Project from the worksapce.

6. Select the target device for debugging

7. No changes are required for Connection Properties, except the Device IP for Nokia.

8. Select Debug.

Debugging and testing applications 453

[

[

[

Page 466: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

The debugger launches and your project is ready to debug. You can use common debug artifacts such as

threads, stack frames, variables, and breakpoints; and some common actions like suspending, stepping,

resuming, and terminating your application.

Testing on devices

You may use the OSGi console to manage bundles, see exception information, or interact with the OSGi

framework. For more information, please refer to the OSGi Alliance and Nokia eRCP Framework

documentation.

454 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 467: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 459.

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 the 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

© Copyright IBM Corp. 2004, 2008 455

Page 468: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

name of the eRCP application in front of the application id. For example, the following extension

identifies a bundle as an eRCP workbench application:

<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.

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:

456 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 469: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 457

Page 470: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

458 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 471: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

following fragment directory has been added to the library.path.append property in the

rcpinstall.properties file:

C:/Program Files/IBM/Lotus/Expeditor/rcp/eclipse/plugins/com.ibm.db2e.win32.x86_8.2.1.20050620/os/win32/x86

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 459

Page 472: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 455).

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.

Deploying plug-ins to devices

You should note that when a new feature is installed to a device, the Lotus Expeditor environment is not

usually restarted. However, in some instances, restarting is necessary for a plug-in to be utilized by other

plug-ins. For instance, if a plug-in needs to be early started or configured, or if other plug-ins do not

listen for the availability of a service being installed. These are situations only the developer of the

plug-in can recognize. Therefore, if your plug-in requires a restart of the platform, you must notify the

feature installer by providing a feature Install Handler. This can be specified in your feature XML. Be

aware that the install handler does not necessarily need to do anything. The presence of the handler

alone indicates that the Lotus Expeditor environment should be restarted after the feature is installed.

For more information on installer handlers, refer to the Eclipse documentation: Platform Plug-in

Developer Guide > Reference > Other reference information > Feature manifest.

460 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 473: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 43. Group 1 languages

Locale code Language

de German

© Copyright IBM Corp. 2004, 2008 461

Page 474: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 43. Group 1 languages (continued)

Locale code Language

es Spanish

fr French

it Italian

ja Japanese

ko Korean

pt_BR Portuguese (Brazil)

zh_CN Chinese (Simplified)

zh_TW Chinese (Traditional)

Table 44. 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 45. 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

462 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 475: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 45. 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.properties 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 463

Page 476: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

464 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 477: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, J2EE-FORM, Siteminder and TAM 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, J2EE-FORM, TAM-FORM, SM-FORM, and

TAM-SPNEGO) for HTTP, J2EE-FORM, TAM-FORM, SM-FORM, and TAM-SPNEGO 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 that 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.

© Copyright IBM Corp. 2004, 2008 465

Page 478: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v An Instant Messaging account, 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.”

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.

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. The default account TYPE is HTTP.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):

466 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 479: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

v setName

v setType

v setDescription

v setAuthType

v setProperty

v setProperties

The UID, NAME, DESCRIPTION, and TYPE properties must have values, but other properties are optional.

The UID is assigned by the Accounts API and should never be modified by the user.

Accounts UI

Lotus Expeditor also gives you the option to create an account from the UI.

When creating an Account via the Accounts UI, under the advanced section of the Accounts UI

Preference Page, the auth type descriptions correspond to the following raw auth types:

v HTTP Basic - HTTP

v TAM SPNEGO (advanced) - TAM-SPNEGO

v TAM Form (advanced) - TAM-FORM

v J2EE Form (advanced) - J2EE-FORM

v Site Minder Form (advanced) - SM-FORM

v User Name Token (advanced) - USERNAME_TOKEN

v Portal Form (advanced) - PORTAL-FORM

For more information on the Accounts UI, refer to Working with accounts in the Using Lotus Expeditor

Client documentation.

Restricting the editing and visibility of an Account in the Accounts UI

The following properties can be set to restrict the editing and visibility of an Account in the Accounts UI.

Read Only:

Set the following property in the Account object to make the Account read only in the Accounts

UI:

Account.NAME_READ_ONLY ("namereadonly")

If set to true, the UI will not allow the Name field to be modified. In addition, users will not be

able to delete this account from the UI. This key can be used by applications that want to setup

an account and reference it through a statically defined name.

Hide an Account from being displayed in the UI:

Set the following property in the Account object to true to make the Account invisible to users of

the Accounts UI:

Account.HIDE_IN_UI ("hideinui")

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.

Securing applications and data 467

[

[

[[

[

[

[

[

[

[

[

[[

[[

[[[

[

[[[

[[[

[

[

[[

[[

[

[

[[

Page 480: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

468 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[

[[

[[[[[[

[[

[

[[[[

[

[[

[

[[

[

[[

[[

[

[[[[[[[

[

[

[[

[

[

[

[[

Page 481: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

4. When you no longer want to monitor an account, remove the listener.

removeAccountChangeListener(AccountChangeListener listener)

Note: The following Account changes can be monitored by the AccountChangeListener: Addition of

an Account to persistent store, Update of an Account in persistent store, or Removal of an

Account from persistent store.

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 that 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.

Note: To support a customized account type, the HTTP/HTTPS URL handler assumes the non-basic

authentication is cookie based, in regards to the server/URL which needs an account. Note that,

basic authentication is credential based.

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.

Refer to the following procedure for instructions on how to manipulate a password associated with an

Account:

1. Retrieve the Account with the password you want to manage.

2. Initialize the service. Get the Account’s Login Context Service:

account.getLoginContextService()

A call made on the AccountsLoginContextServicre 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.

Note: Avoid any long running calls from the main SWT UI thread. If a call from the main UI thread

is long, it will lock up the entire SWT. The AccountsLoginContextService.login() method is a

potentially long running call that performs many operations, including displaying UI dialogs

and network operations. Not only does calling login() on the main UI thread have the

potential to lock up the SWT for the duration of the call, but it will potentially deadlock the

SWT completely due to the UI operations of the login() method. For this reason, calling

Securing applications and data 469

[

[

[[[

[

[[[

[

[

[[

[[

[[[

[

[[[

[[[[[

[[

[

[

[

[[[[

[[[[[[

Page 482: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

AccountsLoginContextService.login() from the main SWT UI thread is not allowed and will

result is a thrown exception. The exception is thrown to safeguard against a deadlock.

Wrapping the main UI thread in a ModalContext prevents this deadlock. This is because a

ModalContext will not lock out other UI operations. However, it is still recommend that login()

be called from a background thread. For more information on ModalContext, see ModalContext

from the Eclipse Platform API Specification.

3. Manage the password using one of the following methods. These methods communicate directly with

the Keystore, 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.

Authentication and accounts

If the HTTPS (or HTTP) site needs to be authenticated, you create an account first, either

programmatically or by using the account tool. You may then open a connection to the site using

java.net.url classes. The Lotus Expeditor customized HTTP/HTTPS URL handler checks whether an

account mapping to the address you want to connect to exists. If an account has been created in advance,

the HTTP/HTTPS URL handler does a login first and then creates the connection for you.

Accounts and platform login

When using Accounts, care must be taken not to trigger Platform Login before the Lotus Expeditor

workbench is fully loaded. Any operations on the Accounts’ Login Context (such as getPassword or

login()) may trigger Platform Login if the Platform has not been logged into yet.

This can be prevented by waiting for a PlatformLogin event, such as implementing an

ILoginContextEventListener and registering it as a listener with

SecurePlatform.getLoginContext.addListener(ILoginContextEventListener listener). Another option

is to check SecurePlatform.isLoggedIn().

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.

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

470 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

[[[[

[[[

[

[

[

[[[[

[

[[[[[

[

[[[

[[[[

Page 483: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 occasionally 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

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

}

}

Securing applications and data 471

Page 484: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

After you log into the client, you can use the Accounts API. You can use the

AccountsLoginContextService provided by the Accounts API to edit Account passwords.

Care must be taken not to initiate Platform Login before the workbench is up. Initiating Platform Login

before the workbench has been started may result in an error.

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.

The following authentication login modules are provided by the client:

v HTTP basic authentication

v J2EE Form-based authentication

v TAM Form- based authentication

v SiteMinder Form – based authentication

v TAM SPNEGO – 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 keystore (if the password has not already been written to the keystore). If the password

is new or has changed, it will be written to the keystore only after the HTTPBasicLoginModule validates

the password with the server.

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 by calling account.getLoginContext().login().

account.getLoginContext().login();

472 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[[

Page 485: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

Note: For the HTTP basic login, the username and password are sent over the network (via the HTTP

Header) in plaintext unless HTTPS is used.

Using form-based authentication

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.

There are three forms based login modules that support the forms based authentication method:

v J2EE-FORM – used when connecting to a server enabled to support the J2EE-FORM login method

standard.

– The method can be used to connect to a WebSphere Portal Server, however, as session tokens are not

returned upon submission of the form, sessions may expire without notice. The recommended

authentication type for connecting to a WebSphere Portal Server is PORTAL-FORM.v TAM-FORM – used when connecting to a TAM protected resource such as a WebSphere Portal Server.

– The backend resource is assumed to be configured to accept a TAM session cookie as authorization.v SM-FORM – used when connecting to a SiteMinder protected resource such as a WebSphere Portal

Server.

– The backend resource is assumed to be configured to accept a SiteMinder session cookie as

authorization.v PORTAL-FORM - used when connecting directly to a WebSphere Portal Server.

– If Global security is enabled on the WebSphere Application Server, and Lightweight Third-Party

Authentication (LTPA) is specified as the authentication mechanism, then when user authentication

succeeds, the form based authentication login module returns an LTPA token and a JSESSION ID

token.

The form-based authentication login modules 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.

When you utilize 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 correct

forms based login module 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 utilize 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.

Securing applications and data 473

Page 486: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, TAM-FORM, SM-FORM, or PORTAL-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 session cookie, such as

an LTPA token or other session token.

Note: Using any of the forms based login modules causes the initial authentication request to contain

the username and password in plaintext unless HTTPS is used.

Using SPNEGO authentication with Tivoli Access Manager

SPNEGO is an authentication protocol for Windows desktop client single sign-on with Intranet services.

Initially, Microsoft provided this authentication solution to allow Windows clients to use Microsoft

Internet Explorer for accessing resources on Microsoft Information Servers (IIS) without having to

re-authenticate. This single sign-on solution relies on proprietary Microsoft HTTP authentication

mechanisms.

The TAM-SPNEGO authentication type provides SPNEGO support to Lotus Expeditor applications. As

such, applications that use accounts with the TAM-SPNEGO authentication type can access resources

protected by Tivoli Access Manager (TAM) without having to reenter username and password

information. The end-user need only login once to the Windows domain before starting Lotus Expeditor.

The Tivoli Access Manager WebSEAL server must be configured to enable SPNEGO. The Web SEAL

server must be configured according to the instructions found in the WebSEAL Administration Guide.

The following are the client requirements for using SPNEGO authentication with TAM:

v Make sure your desktop computer has been added to the valid Windows Active Directory domain.

v Login to the operating system using your domain account, then start the Lotus Expeditor.

If you want to use this authentication type for a Home Portal Account, you must select TAM-SPNEGO as

the authentication type in the Home Portal Account preference page. You can also use this authentication

type for the Account API. Refer to the following example:

Account acc = new Account();

Cookie cookie= null; //Credential cookie will be returned if login successful.

acc.setName(spnego.test);

474 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 487: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

acc.setAuthType(TAM-SPNEGO); //The login configure name for SPNEGO.

acc.setType(HTTP);

acc.setProperty(Account.server, server url);

try{

LoginContext lc = acc.getLoginContext();

lc.login();

SingleSignonToken ssot = null;

ssot = lc.getSubject().getPrivateCredentials(SingleSignonToken.class).toArray()[0];

if(ssot!=null){

cookie = ssot.getSsoTokens()[0];

}

} catch(LoginException e){

}

To create a TAM-SPNEGO account, you need to specify the following properties:

v Set AuthType to TAM-SPNEGO.

v Set Type to either HTTP or HTTPS.

v The TAM WebSeal server’s URL must contain the server’s host name and port, the junction name, and

the application’s directory context.

For example, if the Windows Active Directory domain is us.ibm.com, the TAM WebSeal server’s

hostname is tam001, the junction name is /portal, and the application’s directory is /wps, then the

server’s URL should be: http://tam001.us.ibm.com/portal/wps.

Note: The URL must contain the ″full-qualified″ domain name.

There are many factors that cause SPNEGO authentication to fail, the most common cases are time and

DNS configuration. As SPNEGO uses Kerberos as the real authentication protocol, the client’s time needs

to be synchronized with the server. Additionally, ensure that the client machine’s name can be found

witjin the DNS server.

Considerations for connecting to remote servers using Web Services

Lotus Expeditor supports the following authentication types for connecting to remote servers using Web

Services:

Table 46. Supported Authentication Types

Authentication Type Action

HTTP Inserts a username and password, which are retrieved

from the account API, into a HTTP header as part of the

request to the server.

USERNAME-TOKEN 1. Inserts security cookies that are returned by the

server into a HTTP header as part of the request to

the server.

2. Inserts the <wsse:UsernameToken> element with the

<wsse:Username> and <wsse:Password> elements into

the soap message.

Note: An account with a USERNAME-TOKEN authentication

type uses the username and password of its master

account. If the master account uses a SPNEGO

authentication type, the USERNAME-TOKEN will not support

web services. This is because the master account is not

required to set a username or password, which are both

required by the <wsse:UsernameToken> element, and it is

not possible to get the required username and password

from the operating system.

Securing applications and data 475

[

[

[

[[

[[[

[

[

Page 488: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 46. Supported Authentication Types (continued)

Authentication Type Action

J2EE-FORM (LTPA) The LTPA security token generated as part of the SOAP

message.

TAM, SM, SPNEGO Inserts security cookies that are returned by the server

into a HTTP header as part of the request to the server.

PORTAL-FORM 1. Inserts the LTPA token in the soap header.

2. Inserts a JSESSIONID (cookie) in the HTTP header as

part of the request.

Considerations for accessing TAM and Siteminder protected resources from an

application

By default, the Accounts framework supports TAM (form based and SPNEGO authentication) and

Siteminder (form based authentication only). The following methods will enable your application to

utilize TAM and Siteminder support:

1. Use the Lotus Expeditor custom URL handler (java.net.URL):

The custom URL handler uses the Accounts framework to authenticate with the TAM or Siteminder

server. The application will not be required to set the appropriate TAM or SiteMinder related HTTP

headers, as this is done by the custom URL handler.

2. Use Accounts directly:

If your application chooses to use Accounts directly, then it must programatically call login() on the

Account’s login context service. Once the login has succeeded, future requests to get a TAM or

Siteminder protected resource must include all cookies included in the JAAS subject’s private

credentials.

Using platform single sign-on

Platform single sign-on (SSO) authenticates users by generating a random password and storing it in an

operating specific store. Enabling platform single sign-on gives users secure access to the platform and

the keystore without ever prompting the user. To use platform single sign-on, navigate to to the Password

preferences page and uncheck Prompt me for a password. Then, restart the platform. Or, set up the

platform manually:

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/ssoEnabled – 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

Note: These are Eclipse preference values. If the UI or other entities are already set, then they can no

longer be set by plugin_customization.ini.

476 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 489: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Implementing single sign-on with remote servers

The form-based authentication login modules provided with the client perform a form-based login

against a remote TAM, SiteMinder or WebSphere Portal server, and retrieve a cookie (or LTPA token, in

the case of WPS). The cookie or 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 cookie or 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.

Single sign on with a remove server is also supported for the HTTP basic authentication method. In this

case, the HTTP basic login module does the authentication. Once authentication is successful, the

username and password are placed in the JAAS subject and can be used in future requests to the server.

Contributing a login configuration

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.

Provide values for the following attributes of the <extension> element:

Securing applications and data 477

Page 490: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

– point - A fully qualified identifier of the target extension point, which in this case is

com.ibm.rcp.security.auth.loginModule.

– 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.

478 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 491: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

In the <callbackHandler> element, provide a value for the following attribute:

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

Using TrustManager and KeyManager

The Java security system, at its core, is a fully pluggable system of interfaces and classes - allowing

security providers to plug-in concrete implementations of security algorithms for the systems use.

The providers register their implementation in two ways:

v By declaratively listing the java.security.Provider class implementations into the java.security file.

v By dynamically registering them into the java.security.Security class.

Each provider is essentially a java.util.Properties implementation, which specifies the particular

algorithms that it supports using a fixed semantic. For instance, adding a value of KeyStore.IBMCS with a

target of com.ibm.rcp.security.IBMCSKeyStore to a provider’s capability map means that an instance of

Securing applications and data 479

Page 492: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

that class will be created when KeyStore.getInstance("IBMCS") is called. This model is used for almost

all of the SPIs in the security infrastructure that Java provides.

The Java 1.4.2 and Java 1.5 java.security.Provider class allows you to specify algorithms in the format

described above, each linked to a single string that is the classname of an implementation of the

associated SPI.

The core Security classes query the capability Hashmap of each installed provider for the first one that

supports the algorithm that was requested, and instantiates an instance of the value of the specified key

using Class.forName(). This means Java expects those classes to be available in the lowest levels of the

classloader hierarchy, at a minimum in the %JRE_HOME%/lib/ext directory.

In order to install security algorithms, an extender of java.security.Provider must be installed on the

classpath which is responsible for enumerating the algorithms that are backed by implementations within

the plug-in. The provider implementation must then be added to the list of installed providers listed in

the java.security file. Lotus Expeditor provider implementation is

com.ibm.rcp.security.ServiceProvider, and returns a set of algorithms that are targeted to proxy

implementations of each required SPI. Lotus Expeditor 6.1.x supports the following Java SPI model

proxying implementations:

v java.security.KeyStoreSpi

v javax.net.ssl.TrustManagerFactorySpi

v javax.net.ssl.KeyManagerFactorySpi

Implementing TrustManager and KeyManager in Lotus Expeditor

Lotus Expeditor uses the mechanism introduced above to allow other security providers to plug-in their

own implementation of security services, such as the customized TrustManager and/or KeyManager, into

the Lotus Expeditor infrastructure.

Hooking in the customized TrustManager

In order to verify the trustworthiness of a server certificate chain during an SSL handshake, the Java

Secure Sockets Extension (JSSE) includes an SPI to supply a javax.net.ssl.TrustManagerFactory that

instantiates javax.net.ssl.TrustManager implementations to facilitate the decision.

Lotus Expeditor support of the customized TrustManager: This section describes the specifics of how

Lotus Expeditor supports the customized TrustManager.

1. Installs security algorithms by specifying the implementation in the java.security file. For Example,

the Lotus Expeditor java.security file looks like this:

security.provider.1=com.ibm.rcp.security.ServiceProvider.

In Lotus Expeditor, the core security classes (for example, com.ibm.rcp.security.ServiceProvider) are

inside the com.ibm.rcp.base plug-in which uses the OSGi bootclasspath service to make the jar

participate in standard plug-in update mechanisms. The launch process adds those jars in the

bootclasspath.

2. Then the com.ibm.rcp.security.ServiceProvider bootstrap support is installed for a plug-in-based

TrustManagerFactory by performing the following:

private static final String TRUSTMANAGER_KEY = "TrustManagerFactory." +

TrustManagerFactoryProxy.getAlgorithm( );

private static final String TRUSTMANAGER_VAL = TrustManagerFactoryProxy.class.getName( );

This adds the proxy trust manager to the provider’s capabilities, and an instance of

com.ibm.rcp.security.ssl.TrustManagerFactoryProxy is instantiated when

TrustManagerFactory.getInstance( "ServiceProxy") is called. The proxy class has a single internal

interface, ITrustManagerFactorySpiFactory, with a single method:

480 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 493: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

01: import javax.net.ssl.TrustManagerFactorySpi;

02: ...

03: TrustManagerFactorySpi newInstance( );

04: ...

3. A single static system wide implementation of the interface

com.ibm.rcp.security.internal.ssl.PlatformTrustManagerFactorySpiFactory is packaged in the

com.ibm.rcp.security.jceproxy plug-in, and attached to the proxy class in com.ibm.rcp.base when

the plug-in starts. This plug-in class registers a service listener to listen for OSGi services added that

implement the PUBLIC API( com.ibm.rcp.security.ssl.TrustManagerFactorySpiService) for

installing OSGi based TrustManagerFactory implementations into the system

This interface is similar to the internal factory between the proxy and the service registry controller,

and has one method:

01: package com.ibm.rcp.security.ssl;

02:

03: import javax.net.ssl.TrustManagerFactorySpi;

04:

05: /**

06: * A factory interface for instantiating implementations of the

07: * <code>javax.net.ssl.TrustManagerFactorySpi</code> JSEE SPI. Implementations

08: * of this interface should be registered with OSGI, and will be returned

09: * when the <code>com.ibm.rcp.security.ServiceProvider</code> security

10: * provider is installed and configured in java.security.

11: */

12: public interface TrustManagerFactorySpiService {

13:

14: /**

15: * Return a new instance of <code>TrustManagerFactorySpi</code>

16: *

17: * @param arg - the argument passed from the provider.

18: *

19: * @return TrustManagerFactorySpi

20: */

21: TrustManagerFactorySpi newInstance( Object arg);

22:

23: }

This factory has the responsibility to be a controller that returns an implementation of

java.security.ssl.TrustManagerFactorySpi from the available service implementations of

com.ibm.rcp.security.ssl.TrustManagerFactorySpiService installed in the system.

Note that if the customer does not provide a customized implementation of a TrustManager,

PlatformTrustManagerFactorySpiFactory will call the NullTrustManagerFactory inside Lotus

Expeditor, and eventually call the default implementation of a TrustManager inside Lotus Expeditor.

Developer responsibilities for using the customized TrustManager: The following are the developer

responsibilities for using the customized TrustManager:

1. Provide an implementation of a java.security.ssl.TrustManagerFactorySpi Java security provider.

Inside the code, you must instantiate the customized implementation of a TrustManager.

package com.ibm.rcp.internal.security.ssl;

import java.security.InvalidAlgorithmParameterException;

import java.security.KeyStore;

import java.security.KeyStoreException;

import javax.net.ssl.ManagerFactoryParameters;

import javax.net.ssl.TrustManager;

import javax.net.ssl.TrustManagerFactorySpi;

public class NullTrustManagerFactory extends TrustManagerFactorySpi {

protected void engineInit( KeyStore keyStore)

throws KeyStoreException {

Securing applications and data 481

Page 494: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

throw new KeyStoreException( );

}

protected void engineInit( ManagerFactoryParameters parameters)

throws InvalidAlgorithmParameterException {

throw new InvalidAlgorithmParameterException( );

}

protected TrustManager[] engineGetTrustManagers( ) {

return new TrustManager[] {new NullTrustManager( )};

}

}

2. Provide an implementation of the com.ibm.rcp.security.ssl.TrustManagerFactorySpiService OSGi

factory interface. Inside newInsance(), you must create an instance of NullTrustManagerFactory,

which will eventually call your customized implementation of a TrustManager.

import javax.net.ssl.TrustManagerFactorySpi;

import com.ibm.rcp.security.ssl.TrustManagerFactorySpiService;

public class NullTrustManagerFactoryService implements TrustManagerFactorySpiService {

private static TrustManagerFactorySpiService INSTANCE = new NullTrustManagerFactoryService ();

public static final TrustManagerFactorySpiService getInstance() {

return INSTANCE;

}

public TrustManagerFactorySpi newInstance(Object arg) {

return new NullTrustManagerFactory();

}

public String toString() {

return "NullTrustManagerFactoryService";

}

}

3. Package the two classes into a plug-in.

4. Register the implementation of the service with the OSGi framework, typically in the start() method

of the plug-in.

// Install the your TrustManager service

String tmpServiceName = TrustManagerFactorySpiService.class.getName();

TrustManagerFactorySpiService tmpService = NullTrustManagerFactoryService.getInstance();

context.registerService(tmpServiceName, tmpService, null);

5. Set the ID of the plug-in as the value of the ssl.TrustManagerFactory.ServiceProxyProvider key, as

well as in the start() method.

//set the default trust manager provider to the your trustmanager

//service

Security.setProperty(TrustManagerFactorySpiService.SECURITY_PROPERTY_PROVIDER,

getBundle( ).getSymbolicName());

6. If you choose to use your own JRE, you must edit the java.security file’s list of providers and their

preference orders. To do this, add the following line at the top of the list:

security.provider.1=com.ibm.rcp.security.ServiceProvider

Then increment the value for the rest of the lists. For example:

security.provider.1=com.ibm.jsse2.IBMJSSEProvider2

Becomes...

security.provider.2=com.ibm.jsse2.IBMJSSEProvider2

In addition, the following two lines must abe added to the java.security file. If they are not present,

modify or add them.

482 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 495: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

ssl.TrustManagerFactory.algorithm=ServiceProxy

SSLContext.Algorithm=SSL

Hooking in the customized KeyManager

In order to verify the trustwothiness of a client certificate chain during an SSL handshake, the Java Secure

Sockets Extension (JSSE) includes an SPI to supply a javax.net.ssl.KeyManagerFactory that instantiates

javax.net.ssl.KeyManager implementations to facilitate the decision.

The following sections illustrate the flow of how the customized KeyManager is hooked into the Lotus

Expeditor infrastructure and what developers need to do to provide the implementation of KeyManager.

Lotus Expeditor support of the customized KeyManager: This section explains the specific ways Lotus

Expeditor supports the customized KeyManager.

1. Installs security algorithms by specifying the implementation in the java.security file. For Example,

the Lotus Expeditor java.security file looks like this:

security.provider.1=com.ibm.rcp.security.ServiceProvider.

In Lotus Expeditor, the core security classes (for example, com.ibm.rcp.security.ServiceProvider) are

inside the com.ibm.rcp.base plug-in which uses the OSGi bootclasspath service to make the jar

participate in standard plug-in update mechanisms. The launch process adds those jars in the

bootclasspath.

2. Installs the com.ibm.rcp.security.ServiceProvider bootstrap support for a plug-in based

KeyManagerFactory by performing the following:

private static final String KEYMANAGER_KEY = "KeyManagerFactory." +

KeyManagerFactoryProxy.getAlgorithm( );

private static final String KEYMANAGER_VAL = KeyManagerFactoryProxy.class.getName( );

This adds the proxy key manager to the provider’s capabilities, and instantiates an instance of

com.ibm.rcp.security.ssl.KeyManagerFactoryProxy when KeyManagerFactory.getInstance(

"ServiceProxy") is called. The proxy class has a single internal interface,

IKeyManagerFactorySpiFactory, with a single method:

01: import javax.net.ssl.KeyManagerFactorySpi;

02: ...

03: KeyManagerFactorySpi newInstance( );

04: ...

3. There is a single, static, system-wide implementation of this interface,

com.ibm.rcp.security.internal.ssl.PlatformKeyManagerFactorySpiFactory. It is packaged in the

com.ibm.rcp.security.jceproxy plug-in, and attached to the proxy class in com.ibm.rcp.base when

the plug-in starts. This plug-in class registers a service listener to listen for added OSGi services that

implement the PUBLIC API( com.ibm.rcp.security.ssl.KeyManagerFactorySpiService) for installing

OSGi based KeyManagerFactory implementations into the system.

This interface is similar to the internal factory between the proxy and the service registry controller,

and has one method:

01: package com.ibm.rcp.security.ssl;

02:

03: import javax.net.ssl.KeyManagerFactorySpi;

04:

05: /**

06: * A factory interface for instantiating implementations of the

07: * <code>javax.net.ssl.KeyManagerFactorySpi</code> JSEE SPI. Implementations

08: * of this interface should be registered with OSGI, and will be returned

09: * when the <code>com.ibm.rcp.security.ServiceProvider</code> security

10: * provider is installed and configured in java.security.

11: */

12: public interface KeyManagerFactorySpiService {

13:

14: /**

15: * Return a new instance of <code>KeyManagerFactorySpi</code>

16: *

17: * @param arg - the argument passed from the provider.

Securing applications and data 483

Page 496: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

18: *

19: * @return KeyManagerFactorySpi

20: */

21: KeyManagerFactorySpi newInstance( Object arg);

22:

23: }

This factory now has the responsibility to be a controller that returns an implementation of

java.security.ssl.KeyManagerFactorySpi from the available service implementations of

com.ibm.rcp.security.ssl.KeyManagerFactorySpiService installed in the system.

Note that if the customer did not provide the customized implementation of a KeyManager,

PlatformKeyManagerFactorySpiFactory calls the NullKeyManagerFactory inside Lotus Expeditor, which

eventually calls the default implantation of a Nullkeymanager. The Nullkeymanager does not check the

client certificate. As a result, if you need to check the client certificate, it is important you provide a

KeyManager implementation.

Developer responsibilities for using the customized KeyManager: This section describes the

responsibilities for using the customized KeyManager:

1. Provides an implementation of a java.security.ssl.KeyManagerFactorySpi Java security provider.

Inside the code, you must instantiate the customized implementation of a KeyManager.

package com.ibm.rcp.internal.security.ssl;

import java.security.InvalidAlgorithmParameterException;

import java.security.KeyStore;

import java.security.KeyStoreException;

import javax.net.ssl.ManagerFactoryParameters;

import javax.net.ssl.KeyManager;

import javax.net.ssl.KeyManagerFactorySpi;

public class NullKeyManagerFactory extends KeyManagerFactorySpi {

protected void engineInit( KeyStore keyStore)

throws KeyStoreException {

throw new KeyStoreException( );

}

protected void engineInit( ManagerFactoryParameters parameters)

throws InvalidAlgorithmParameterException {

throw new InvalidAlgorithmParameterException( );

}

protected KeyManager[] engineGetKeyManagers( ) {

return new KeyManager[] {new NullKeyManager( )};

}

}

2. Provide an implementation of com.ibm.rcp.security.ssl.KeyManagerFactorySpiService OSGi factory

interface. Inside newInsance(), you must create an instance of NullKeyManagerFactory, which will

eventually call your customized implementation of a KeyManager.

3. Package the two classes into a plug-in.

4. Register the implementation of the service with the OSGi framework, typically in the start() method

of the plug-in.

// Install the your KeyManager service

String tmpServiceName =

KeyManagerFactorySpiService.class.getName();

KeyManagerFactorySpiService tmpService = NullKeyManagerFactoryService.getInstance();

context.registerService(tmpServiceName, tmpService, null);

484 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 497: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

5. Set the ID of the plug-in as the value of the ssl.KeyManagerFactory.ServiceProxyProvider key, as

well as in the start() method.

//set the default key manager provider to the your keymanager

//service

Security.setProperty(KeyManagerFactorySpiService.SECURITY_PROPERTY_PROVIDER,

getBundle( ).getSymbolicName());

6. If you choose to use your own JRE, you must edit the java.security file’s list of providers and their

preference orders. To do this, add the following line at the top of the list:

security.provider.1=com.ibm.rcp.security.ServiceProvider

Then increment the value for the rest of the lists. For example:

security.provider.1=com.ibm.jsse2.IBMJSSEProvider2

Becomes...

security.provider.2=com.ibm.jsse2.IBMJSSEProvider2

In addition, the following two lines must abe added to the java.security file. If they are not present,

modify or add them.

ssl.TrustManagerFactory.algorithm=ServiceProxy

SSLContext.Algorithm=SSL

Wiring the customized TrustManager/KeyManager with the HTTPS connection

(SSL) 2.1.1

The Lotus Expeditor provides a custom socket factory (PlatformSSLProtocolSocketFactory, inside

com.ibm.rcp.security.jceproxy) that implements

org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory interface.

Inside com.ibm.rcp.net.http register the custom protocol (PlatformSSLProtocolSocketFactory) as the

default handler for HTTPS protocol. The Lotus Expeditor HTTP and HTTPS URL handler will be

registered early in the runtime instead of the default J9 VM HTTP/HTTPS URL handler. The HTTP

plug-in then attaches itself to PlatformSSLProtocolSocketFactory instead of the DefaultSSL

ProtocolSocketFactory if using default J9 VM URL handler.

PlatformSSLProtocolSocketFactory gets an instance of TrustManager/KeyManager with a type of

ServiceProxy. In this way, you set up the core Java HttpsUrlConnection to use the ServiceProxy type of

JSSE TrustManager/KeyManager. Again, if there is no customized implementation of TrustManager or

KeyManager, the default implementation of Lotus Expeditor TrustManager/KeyManager is used.

Securing applications and data 485

Page 498: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

486 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 499: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, 2008 487

Page 500: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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. Start the Managed Settings plugin (com.ibm.rcp.managedsettings). The plugin 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.

There are three ways to start the plugin:

v Use one of the lifecycle extension points provided by Lotus Expeditor.

v Use standard OSGi and Eclipse methods for starting plug-ins.

v Call a method in the plugin. The method runUpdate(boolean force, boolean synchronous), which

is discussed in step 2, is a likely candidate for this purpose.2. The first managed settings update occurs asynchronously when the com.ibm.rcp.managedsettings

plug-in starts. After the update, the update job automatically re-schedules itself to rerun after the

update interval has expired. However, there are several reasons why you might wish to run an

update at another time.

v You want to make sure that all settings have been fully updated before the application needs them.

In this case, you may wish to call the runUpdate() method with the synchronous argument set to

true. This ensures that the method does not return until the update is complete. If an update has

already finished and the update interval has not expired, this method has no effect.

v You have reason to know that there is new settings data on the server and don’t want to wait until

the update interval expires to fetch them. In this case, you want to call the runUpdate(boolean

force, boolean synchronous) method with the force argument set to true. This forces an update to

run even if the update interval has not expired.

v You wish to make sure that the managed settings plugin has been started but don’t want to run an

update if one has already run recently. In this case, you want to call the runUpdate(boolean force,

boolean synchronous) method with the force argument set to false and the synchronous argument

set to false. If the update interval has not expired, this method will return without doing any

work. If the interval has expired, it will run the update asynchronously.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.

488 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 501: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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);

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

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 489

Page 502: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

490 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 503: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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 47. 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

Enabling applications for configuration 491

Page 504: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 47. Additional Element Descriptions (continued)

Element or Attribute Name Description

preference Root Element for each key/value pair definition

default-locale Defines which language to use when the requested

language has no values

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 “Working with Preference Sets” on

page 490

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 “Working with Preference Sets” on

page 490

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>

492 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 505: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<description>Frequency of automatic report updates.</description>

</language>

<language locale= "ja">

<display-name>JA-Update Interval</display-name>

<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>

Enabling applications for configuration 493

Page 506: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

<max>20</max>

</constraints>

<language locale= "en">

<display-name>Company Access Code</display-name>

<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>

494 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 507: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

</constraints>

<language locale= "en">

<display-name>Allow simultaneous logon</display-name>

<description>Allow account to be logged on in multiple

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 48. 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.

Enabling applications for configuration 495

Page 508: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 48. Additional Sample Information (continued)

Title of Preference Preference Qualifier/Key Rule Details

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.

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. Refer to the Platform Plug-in Developer’s Guide

in the Eclipse Help 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.

496 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 509: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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 500 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.

Enabling applications for configuration 497

Page 510: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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 );

498 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 511: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 );

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.x 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:

Enabling applications for configuration 499

Page 512: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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:

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

500 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 513: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

Best Practices for file storage with the Lotus Expeditor platform

This section provides some suggestions on where to store application related file data when using the

Lotus Expeditor platform.

The Lotus Expeditor platform uses two main storage areas on the file system. The first is in the

installation directory. Here the installer initially installs the platform, and additional applications may also

be installed (as features and plug-ins). Since the deployment patterns for platform consumers may vary,

applications should, in general, treat the install directories as read-only locations, and also avoid

modifying files contained in plug-ins, as well as writing files back to plug-in directories.

Where should applications write data?

The suggested and preferred location for writing files is the workspace.

The workspace contains the following directories after initial installation:

v applications - an eclipse install site where applications private to the user are stored.

v logs - the directory containing the platform logs.

v .config - The Eclipse configuration information for the Lotus Expeditor platform instance being run.

v .metadata - Contains individual plug-in related data.

For data that is specific to an individual plug-in, consider using the metadata area for the plug-in to store

data. For data shared among many plug-ins, consider creating a directory in the root of the workspace -

identified by application name or feature id - in which information specific to the application is stored.

How do I locate files?

To locate the workspace, use one of two methods:

1. The API org.eclipse.core.runtime.Platform.getInstanceLocation() returns the location of the

workspace.

import org.eclipse.core.runtime.Location;

import org.eclipse.core.runtime.Platform;

Location location = Platform.getInstanceLocation();

String instanceAreaPath = location.getURL().getPath();

File f = new File( instanceAreaPath );

2. Alternatively, the Lotus Expeditor platform uses the System property rcp.data to identify the location

of the workspace.

File f = new File( System.getProperty( "rcp.data" ) );

Once a file object is obtained, standard file operations to create files or directories can be performed.

Enabling applications for configuration 501

Page 514: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

To locate directories intended for plug-in specific usage, use the

org.eclipse.core.runtime.Platform.getStateLocation() API. The path will generally be something of

the form /.metadata/.plugins/:

import org.eclipse.core.runtime.Location;

import org.eclipse.core.runtime.IPath;

IPath state = Platform.getStateLocation( Platform.getBundle( "my_bundle") );

File f = new File( state.toFile(), "my_file" );

Plug-in data persists beyond removal of the plug-in from the platform.

What types of files can I store?

There are no restrictions on the types of files that can be stored. However, some deployment patterns

maintain the workspace directory on a network share, so storing extremely large files on a network share

might be detrimental to performance.

What can I store in files?

There are no restrictions on file content. Some deployment patterns maintain the workspace directory on

a network share, or perhaps even on removable drives. In these situations, the drive letter, and therefore

the path to the workspace can change from launch to launch. Files should refrain from storing absolute

paths, as it may result in inaccessible data on some deployment patterns. The Lotus Expeditor platform

uses ${rcp.data} and ${rcp.home} in its configuration file (rcpinstall.properties) as placeholders to

reference the workspace and installation dir respectively. These properties are then replaced prior to

launch.

502 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 515: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 49. 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 50. File menu

Menu Item Sub-menu Item Menu ID Activity Pattern

Close com.ibm.rcp.ui.filemenu.close com\.ibm\.rcp\.platform\.personality/com\.ibm\.rcp\.ui\.filemenu\.close

separator

Application > applications com\.ibm\.rcp\.platform\.personality/applications

Reset com\.ibm\.rcp\.platform\.personality/resetPerspective

group marker

group marker

Install com\.ibm\.eswe\.installupdate\.launcher/install

Application Management com\.ibm\.eswe\.installupdate\.launcher/management

Preferences... preferences com\.ibm\.rcp\.platform\.personality/preferences

separator

Close All closeAllTabs com\.ibm\.rcp\.platform\.personality/closeAllTabs

© Copyright IBM Corp. 2004, 2008 503

[

[[

[[[[

[[[[[[

[[[[

[[[[[

[[[[[

[[[[

[[[[

[[[[

[[[[[

[[[[[

[[[[[

[[[[

[[[[[

Page 516: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 50. File menu (continued)

Menu Item Sub-menu Item Menu ID Activity Pattern

Exit quit com\.ibm\.rcp\.platform\.personality/com\.ibm\.rcp\.ui\.filemenu\.exit

View menu

The menu items, markers, and separators defined for the View menu are defined in the following table.

Table 51. View menu

Menu Item Sub-menu Items Menu ID

Toolbar >

Show > com.ibm.rcp.ui.showmenu

sidebar 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 52. Help menu, 6.1.2

Menu Item Menu ID Activity Pattern

com\.ibm\.rcp\.platform\.personality/help

Help Contents helpContents com\.ibm\.rcp\.platform\.personality/helpContents

Search helpSearch com\.ibm\.rcp\.platform\.personality/helpSearch

Support com.ibm.esupport.client.Browser

About <product

name>...

about com\.ibm\.rcp\.platform\.personality/about

OSGi specific information

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.2 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.

504 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[[[[

[[[[[[[

[

[

[[

[[[

[[[

[[[[

[[[[

[[[

[[[[

[

[

Page 517: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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 509 for conventions to solve this problem.

Note: In order for your bundles/plug-ins to run on non-Eclipse versions of RCP or eRCP, they must

adhere to the OSGi standard for manifests. Eclipse does not always require strict adherence. For

instance, you might be able to use OSGi 4 properties without specifying ″Bundle-ManifestVersion:

2″. However, this will not work on strict OSGi implementations, such as Nokia’s eRCP.

Reference information 505

Page 518: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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.

506 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 519: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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:

Reference information 507

Page 520: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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 ){

508 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 521: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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();

}

Reference information 509

Page 522: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

/*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.

// 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.

510 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 523: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Refer to the following tables for a description of the options and their default values.

Table 53. 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

This is followed by the Client Services Content page:

Table 54. 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-Bundle or

Import-Package.

Import-Package

This is followed by the Target Definition page:

Table 55. Target definition 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

Reference information 511

Page 524: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 55. Target definition options (continued)

Option Description Default value

Target Features Check the Target Definition Features that your Client

Services Project requires from this tree of Target Features.

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 user may also

select any user defined features from this tree. These features

display on top of the tree with a label of ″User Defined

Features″. If this entry is not found on the tree, then either

the option is disabled in the preference page or the toolkit

did not find any features and plug-ins in the configured

location.

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 56. Client Services Fragment Project page

Option Description Default value

Project name Enter a name for your new Client Services fragment project. None

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 57. 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

512 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 525: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 57. Fragment Content page (continued)

Option Description Default Value

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

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 58. Target Definition 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 Features Check the Target Definition Features that your Client

Services Project requires from this tree of Target features. 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 user may also

select any user defined features from this tree. These features

display on top of this tree with a label of ″User Defined

Features″. If this entry is not found on the tree, then either,

this option is disabled in the preference page or the toolkit

did not find any features and plug-ins in the configured

location.

The ″Core OSGi

Interfaces″ Target

Feature is required by

all Target Definitions.

Reference information 513

Page 526: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 59. 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 60. 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 Features Check the Target Definition Features that your Client

Services Project requires from this tree of Target features. 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 user may also

select any user defined features from this tree. These features

display on top of the tree with a label of ″User Defined

Features″. If this entry is not found on the tree, then either

this option is disabled in the preference page or the toolkit

did not find any features and plug-ins in the configured

location.

The ″Core OSGi

Interfaces″ Target

Feature is required by

all Target Definitions.

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 61. Target Definition tab

Option Description Default Value

Target Definition Select a Target definition this Client

Services project will target.

None

514 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 527: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 61. Target Definition tab (continued)

Option Description Default Value

Target Features Check the Target Definition Features

that your Client Services Project

requires from this tree of Target

features. 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 user may

also select any user defined features

from this tree. These features display

on top of the tree with a label of

″User Defined Features″. If this entry

is not found on this tree, then either

this option is disabled in the

preference page or the toolkit did not

find any features and plug-ins in the

configured location.

The “Core OSGi Interfaces” Target

Feature is required by all Target

Definitions.

Table 62. 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.

Reference information 515

Page 528: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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 Plug-ins

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 451.

Lotus Expeditor Toolkit Preference Dialog

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

of two places.

The current configuration settings for the Lotus Expeditor Toolkit are displayed in the Test Environment

section of the preferences. These values were selected using the configuration dialog for the toolkit, and

can be accessed by selecting Window > Preferences > Client Services. Selecting Configure on this

preference page allows you to change your Lotus Expeditor Toolkit configuration. The dialog initially

populates with the current settings, and the Restore Defaults button can be used to reset the contents of

the dialog to the default values shipped with Lotus Expeditor Toolkit.

The Auto-Configuration Preference option can also be selected on this page. This preference option

controls when the configuration dialog for the toolkit is displayed. It can be displayed each time a

workspace opens, the first time a workspace opens, or not at all.

Refer to the following tables for a description of the options and their default values of the resulting

dialog screens:

Auto-Management Preferences

516 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 529: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Table 63. 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

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.

Select the Targets to be available for development Selection

If the Targets are selected, they will be available in the development environment during a new Client

Services project creation or a new Client Services launch configuration. The unselected targets will not be

shown in the development environment. The default is all Targets selected.

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.

User-Defined Features

v Enable

Reference information 517

Page 530: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

This selection enables or disables this function. If it is enabled the toolkit will try to find any

user-defined or third party features and plug-ins in the location specified. If it is disabled the toolkit

will bypass the function.

v Use Configured Location

If this function is enabled the user may specified the location, other than default, where these

user-defined features and plug-ins are located.

This location is where the Lotus Expeditor Toolkit looks for user-defined or third party features and

plug-ins. The default location is <platform location>\com.ibm.pvc.tools.bde\xpdt. Under this path,

an eclipse folder with two children (features and plugins) should have been created. The features

and plugins folders should contain these user-defined features and plug-ins respectively.

v Browse

The Browse button will enabled if the “Use Configured Location” selection is unchecked/unselected.

The browse button will open the system folder dialog so the user can locate the installed location of

these user-defined features.

Web

The Web specific preferences for the Lotus Expeditor Toolkit are provided here.

JSP preference

v Enable incremental JSP translation

This selection enables or disables the incremental JSP translation for web projects at the workspace

level. Disabling this option causes JSP translation to occur every time a web project is run or exported,

regardless of whether the JSP has been modified or not.

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

518 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

[

[

[

[

[[[

Page 531: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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 519

Page 532: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

v insert

Description - This tag calls the render method of the portlet and retrieves the content as well as its title.

The content and title of the specified portlet can optionally be placed into variables using the

contentVar and titleVar attributes.

Attributes

– url=”/” (mandatory) Identifies the portlet for this tag by using the context and portlet-name to

address the portlet windowId=”” (optional) Defines the window id of the portlet content

– Var=”” (optional) If defined the portlet’s content is not written to the output stream but 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 written into a variable with the given scope and name.

– titleVar=”” (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

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.

520 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 533: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

Reference information 521

Page 534: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

522 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 535: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

Reference information 523

Page 536: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

524 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 537: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

Reference information 525

Page 538: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

526 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 539: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Reference information 527

Page 540: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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.

528 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 541: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Reference information 529

Page 542: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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

530 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 543: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

Reference information 531

Page 544: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

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

532 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 545: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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

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 533

Page 546: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

534 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 547: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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, 2008 535

Page 548: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

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.

536 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 549: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

Each copy or any portion of these sample programs or any derivative work, must include a copyright

notice as follows:

© (your company name) 2004, 2007. Portions of this code are derived from IBM Corp. Sample Programs.

© Copyright IBM Corp. 2004, 2007 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 Linus 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 537

Page 550: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

538 Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1.x

Page 551: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1
Page 552: Lotus Expeditor: Developing Applications for Lotus Expeditor 6.1

����

Printed in USA


Recommended