my tutorial

460
ibm.com/redbooks WebSphere Commerce Line-of-Business Tooling Customization Rufus Credle Jeff Coster Steffen Eckardt Girish Gopinathan Vani Mittal Juha Nevalainen Ramya Rajendiran Customizing Management Center for WebSphere Commerce Optimizing the day-to-day activities of the business users Demonstrating customization scenarios

Upload: narendar-reddy

Post on 25-Apr-2015

819 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: My Tutorial

ibm.com/redbooks

WebSphere Commerce Line-of-Business ToolingCustomization

Rufus CredleJeff Coster

Steffen EckardtGirish Gopinathan

Vani MittalJuha Nevalainen

Ramya Rajendiran

Customizing Management Center for WebSphere Commerce

Optimizing the day-to-day activities of the business users

Demonstrating customization scenarios

Front cover

Page 2: My Tutorial
Page 3: My Tutorial

WebSphere Commerce Line-of-Business Tooling Customization

November 2008

International Technical Support Organization

SG24-7619-00

Page 4: My Tutorial

© Copyright International Business Machines Corporation 2008. All rights reserved.Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADPSchedule Contract with IBM Corp.

First Edition (November 2008)

This edition applies to IBM WebSphere Application Server Network Deployment V6.0.2, IBM WebSphere Commerce V6.0.0, WebSphere Commerce Developer V6.0.0, and IBM WebSphere Commerce Feature Pack 3 Version 3.0.1

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

Page 5: My Tutorial

Contents

Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ixTrademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiThe team that wrote this book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiiBecome a published author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xivComments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv

Part 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Chapter 1. IBM Management Center for WebSphere Commerce . . . . . . . . 31.1 Why Management Center was introduced . . . . . . . . . . . . . . . . . . . . . . . . . 41.2 Management Center capabilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.2.1 Functional capabilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2.2 Usability capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.2.3 Finding detailed information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.3 Comparing the Management Center to other WebSphere Commerce line-of-business tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.4 Management Center technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.4.1 Client-side technology. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.4.2 Server-side technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.1 High-level SOA architecture for the Management Center . . . . . . . . . . . . . 162.2 Presentation layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.2.1 Overview of the Presentation layer . . . . . . . . . . . . . . . . . . . . . . . . . . 172.2.2 The OpenLaszlo application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.3 The Mediation layer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.3 Business Logic layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.3.1 Components of the Business Logic layer . . . . . . . . . . . . . . . . . . . . . 232.3.2 Business Object Mediators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

Part 2. IBM Management Center for WebSphere Commerce customization . . . . . . . . . . . 27

Chapter 3. Customization overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293.1 Development assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.1.1 Management Center user interface. . . . . . . . . . . . . . . . . . . . . . . . . . 303.1.2 Management Center Web application. . . . . . . . . . . . . . . . . . . . . . . . 43

© Copyright IBM Corp. 2008. All rights reserved. iii

Page 6: My Tutorial

3.1.3 WebSphere Commerce services . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Chapter 4. Planning and designing customizations . . . . . . . . . . . . . . . . . 494.1 Who should read this chapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504.2 Knowledge prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 504.3 Overview of this chapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514.4 Customization methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514.5 Solution Outline phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

4.5.1 Gathering requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534.5.2 Defining the application model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

4.6 Macro Design phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564.6.1 Refining the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 564.6.2 Setting up the environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574.6.3 Defining the processes and guidelines . . . . . . . . . . . . . . . . . . . . . . . 574.6.4 Defining the test specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

4.7 Micro Design phase. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594.8 Build Cycle phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

4.8.1 Coding and unit testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614.8.2 Performing system testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 624.8.3 Developing support materials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

4.9 Deployment phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634.9.1 Setting up the production environment . . . . . . . . . . . . . . . . . . . . . . . 634.9.2 Deploying the customizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

4.10 Locating Management Center customization within a WebSphere Commerce project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

Chapter 5. Development tools and extension deployment . . . . . . . . . . . . 675.1 Development tools. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

5.1.1 WebSphere Commerce Developer . . . . . . . . . . . . . . . . . . . . . . . . . . 685.1.2 Management Center assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

5.2 Deploying the extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 705.2.1 Exporting the extension code from the development environment . . 715.2.2 Backing up the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715.2.3 Deploying the WAR module to the target WebSphere Commerce server

725.2.4 Testing the changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73

5.3 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745.3.1 Tracing your own components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

5.4 Debugging server communication with the TCP/IP Monitor . . . . . . . . . . . 785.4.1 Creating the TCP/IP monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

5.5 Hints and tips. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 795.5.1 Turning automatic build off . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 795.5.2 Using a version control system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

iv WebSphere Commerce Line-of-Business Tooling Customization

Page 7: My Tutorial

5.5.3 Increasing the Management Center inactivity time-out . . . . . . . . . . . 825.5.4 Customizing your Workbench perspective . . . . . . . . . . . . . . . . . . . . 835.5.5 Using the XML editor for OpenLaszlo files . . . . . . . . . . . . . . . . . . . . 835.5.6 Disabling the tools that you are using . . . . . . . . . . . . . . . . . . . . . . . . 83

5.6 Problem determination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 845.6.1 What to do if your changes are not appearing? . . . . . . . . . . . . . . . . 845.6.2 What to do if the server fails to start successfully . . . . . . . . . . . . . . . 85

Part 3. Customization scenario examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

Chapter 6. Enabling the merchandising associations’ Semantic Attribute . 89

6.1 Understanding the extension requirement . . . . . . . . . . . . . . . . . . . . . . . . 916.2 Checking if the semantic specifier element was provided. . . . . . . . . . . . . 916.3 Defining an extended resource bundle and properties file . . . . . . . . . . . . 92

6.3.1 Registering the new properties in the resource bundle. . . . . . . . . . . 946.4 Adding the extensions to the tool extension library . . . . . . . . . . . . . . . . . . 956.5 Adding the Semantic property to the Merchandising Association class . . 966.6 Implementing a Validator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 986.7 Including the semantic specifier in the JSP. . . . . . . . . . . . . . . . . . . . . . . 1006.8 Populating database tables with custom semantics . . . . . . . . . . . . . . . . 1016.9 Testing the extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

Chapter 7. Adding a new service action . . . . . . . . . . . . . . . . . . . . . . . . . . 1077.1 Defining the properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1087.2 Customizing the product list view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1087.3 Updating the catalog entry grid view . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1117.4 Providing the buyable property value definitions. . . . . . . . . . . . . . . . . . . 1127.5 Defining the Struts action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

7.5.1 Providing the response JSP files . . . . . . . . . . . . . . . . . . . . . . . . . . 1147.6 Testing the extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

Chapter 8. Advanced search for merchandising associations . . . . . . . . 1198.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1208.2 Building the customization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

8.2.1 Customizing the Management Center user interface . . . . . . . . . . . 1238.2.2 Customizing the Management Center Web application . . . . . . . . . 1298.2.3 Customizing WebSphere Commerce services . . . . . . . . . . . . . . . . 134

8.3 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Chapter 9. Price comparison mashup . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1439.1 Understanding the requirement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1449.2 Price comparison service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1459.3 Building the customization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

Contents v

Page 8: My Tutorial

9.3.1 Resource bundle definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1489.3.2 Price comparison class definition . . . . . . . . . . . . . . . . . . . . . . . . . . 1509.3.3 Property component definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1569.3.4 Updating the product properties view . . . . . . . . . . . . . . . . . . . . . . . 1599.3.5 Updating the library file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

9.4 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

Chapter 10. Customizing user preferences . . . . . . . . . . . . . . . . . . . . . . . 16510.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16610.2 Building the customization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

10.2.1 Customizing the client side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16810.2.2 Customizing the server side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17610.2.3 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Chapter 11. Spell Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17911.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18011.2 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

11.2.1 Meeting requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18311.2.2 CDYNE service detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18411.2.3 Component design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18511.2.4 Visual Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188

11.3 Deploying the complete or staged examples . . . . . . . . . . . . . . . . . . . . 19011.4 Staged development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193

11.4.1 Explaining the visual prototype stage (example 1) . . . . . . . . . . . . 19411.4.2 Viewing the visual prototype stage (example 1) . . . . . . . . . . . . . . 20411.4.3 Explaining the static XML prototype stage (example 2) . . . . . . . . 20611.4.4 Viewing the static XML prototype stage (example 2) . . . . . . . . . . 20911.4.5 Explaining the static XML prototype stage (example 3) . . . . . . . . 20911.4.6 Viewing the static XML prototype stage (example 3) . . . . . . . . . . 21011.4.7 Explaining the property provided prototype stage (example 4) . . . 21111.4.8 Testing the property provided prototype stage (example 4) . . . . . 21311.4.9 Explaining the CDYNE service prototype stage (example 5) . . . . 21611.4.10 Viewing the CDYNE service prototype stage (example 5) . . . . . 21811.4.11 Explaining the highlighted text prototype stage (example 6). . . . 21911.4.12 Viewing the highlighted text prototype stage (example 6). . . . . . 22211.4.13 Explaining the final stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22311.4.14 Testing the final stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

11.5 Possible enhancements and changes. . . . . . . . . . . . . . . . . . . . . . . . . . 23511.5.1 Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23511.5.2 Replace /skip single occurrence . . . . . . . . . . . . . . . . . . . . . . . . . . 23611.5.3 Using a different service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

11.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Chapter 12. Custom Application Configuration Management tool. . . . . 239

vi WebSphere Commerce Line-of-Business Tooling Customization

Page 9: My Tutorial

12.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24012.2 Overview of the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241

12.2.1 Architectural overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24612.3 Customizing the Management Center user interface . . . . . . . . . . . . . . 248

12.3.1 Main tool definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24912.3.2 Object definitions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25012.3.3 Search definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25912.3.4 List definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26112.3.5 Filter definition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26512.3.6 Property view definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26512.3.7 Resource bundle definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27512.3.8 Image files for Custom Application Configuration Management tool .

27612.3.9 Library file definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27612.3.10 Adding the Custom Application Configuration Management tool to

Management Center . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27712.4 Customizing the WebSphere Commerce services . . . . . . . . . . . . . . . . 280

12.4.1 Preparing your development environment . . . . . . . . . . . . . . . . . . 28212.4.2 Generating the CustomAppProperties service module projects . . 28312.4.3 Defining the CustomAppProperties noun . . . . . . . . . . . . . . . . . . . 28612.4.4 Generating the SDOs for the CustomAppProperties noun . . . . . . 29812.4.5 Generating the Persistence layer for the CustomAppProperties service

module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30312.4.6 Understanding the assets of the CustomAppProperties-Server project

30912.4.7 Updating the Data Service configuration. . . . . . . . . . . . . . . . . . . . 31312.4.8 Implementing the Business Object Mediators to mediate logical and

physical SDOs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31312.4.9 Configuring the Data Service layer for the CustomAppProperties

service module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34612.4.10 Implementing the Business Logic layer. . . . . . . . . . . . . . . . . . . . 35612.4.11 Implementing the client library . . . . . . . . . . . . . . . . . . . . . . . . . . 36212.4.12 Implementing access control. . . . . . . . . . . . . . . . . . . . . . . . . . . . 36312.4.13 Implementing unit tests using the CustomAppProperties client library

37112.4.14 Deploying to the WebSphere Commerce server. . . . . . . . . . . . . 392

12.5 Customizing Management Center Web application . . . . . . . . . . . . . . . 39312.5.1 Configuring the client-service-mapping. . . . . . . . . . . . . . . . . . . . . 39412.5.2 Configuring the client-service-mapping for Get commands . . . . . 39612.5.3 Configuring views and commands . . . . . . . . . . . . . . . . . . . . . . . . 39912.5.4 Implementing object mapping JSPs for Get commands . . . . . . . . 40412.5.5 Implementing object mapping JSPs for Process and Change

commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

Contents vii

Page 10: My Tutorial

12.5.6 Deploying the customization to the WebSphere Commerce Test Server411

12.6 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41112.6.1 Testing the CustomAppProperties service using unit tests . . . . . . 41112.6.2 Testing the Management Center customizations . . . . . . . . . . . . . 413

Appendix A. Additional material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419Locating the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419Using the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

How to use the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420Importing the Redbook.LOBTools.zip file. . . . . . . . . . . . . . . . . . . . . . . . . . . . 420

Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423Online resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423How to get Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432Help from IBM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433

viii WebSphere Commerce Line-of-Business Tooling Customization

Page 11: My Tutorial

Notices

This information was developed for products and services offered in the U.S.A.

IBM may 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 may have patents or pending patent applications covering subject matter described 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.

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 publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication 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.

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.

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.

© Copyright IBM Corp. 2008. All rights reserved. ix

Page 12: My Tutorial

Trademarks

IBM, the IBM logo, and ibm.com are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. These and other IBM trademarked terms are marked on their first occurrence in this information with the appropriate symbol (® or ™), indicating US registered or common law trademarks owned by IBM at the time this information was published. Such trademarks may also be registered or common law trademarks in other countries. A current list of IBM trademarks is available on the Web at http://www.ibm.com/legal/copytrade.shtml

The following terms are trademarks of the International Business Machines Corporation in the United States, other countries, or both:

BladeCenter®ClearCase®Cloudscape®DB2®developerWorks®

IBM®Lotus Notes®Lotus®Notes®Rational®

Redbooks®Redbooks (logo) ®System x™WebSphere®

The following terms are trademarks of other companies:

Adobe Flash, Adobe, and Portable Document Format (PDF) are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States, other countries, or both.

Oracle, JD Edwards, PeopleSoft, Siebel, and TopLink are registered trademarks of Oracle Corporation and/or its affiliates.

EJB, J2EE, Java, JavaScript, JSP, and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.

Windows, and the Windows logo 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.

x WebSphere Commerce Line-of-Business Tooling Customization

Page 13: My Tutorial

Preface

The Management Center for WebSphere® Commerce is the next generation business user tool for managing online business tasks. It was introduced with WebSphere Commerce Version 6, Feature Pack 3, for example, catalog tasks, marketing tasks, and promotion tasks.

In this IBM® Redbooks® publication, we give you a broad understanding of the features and capabilities of the Management Center for WebSphere Commerce. In addition, you learn how the Management Center fits into the service-oriented architecture (SOA) framework of IBM WebSphere Commerce.

In this book, we:

� Help you to install, tailor, and configure Management Center to optimize the day-to-day activities of the business users who manage merchandising and marketing tasks for stores that use the consumer direct and Business-to-Business (B2B) business models.

� Discuss the assets that make up the Management Center and what assets you can customize.

� Share some of the common customization scenarios.

� Demonstrate how to plan and perform customizations to the Management Center and how to understand the use of development tools for creating Management Center customizations.

� Provide examples of the customization scenarios that we developed and tested in the International Technical Support Organization labs and WebSphere Commerce labs, which are available for you to use.

The target audience for this book is Commerce Architects, Commerce Developers, Project Managers, and Deployment Managers.

© Copyright IBM Corp. 2008. All rights reserved. xi

Page 14: My Tutorial

The team that wrote this book

Figure 1 Left to Right: Rufus Credle, Steffen Eckardt, Vani Mittal, Ramya Rajendiran, Jeff Coster, Girish Gopinathan, Juha Nevalainen

This book was produced by a team of specialists from around the world working at the International Technical Support Organization, Raleigh Center.

Rufus Credle is a Certified Consulting IT Specialist at the ITSO, Raleigh Center. In his role as Project Leader, he conducts residencies and develops IBM Redbooks publications and IBM Redpaper publications about network operating systems, enterprise resource planning (ERP) solutions, voice technology, high availability, and clustering solutions, Web application servers, pervasive computing, IBM and OEM e-business applications, System x™, and IBM BladeCenter®. Rufus' various positions during his IBM career include assignments in administration and asset management, systems engineering, sales and marketing, and IT services. He has a BS degree in business management from Saint Augustine's College. Rufus has been employed at IBM for 28 years.

Jeff Coster is a Senior IT Specialist, IBM Certified Application Developer - WebSphere Commerce Version 6.0, IBM Certified System Administrator - WebSphere Commerce Version 6.0 in IBM Hursley UK.

xii WebSphere Commerce Line-of-Business Tooling Customization

Page 15: My Tutorial

Steffen Eckardt is an Advisory IT Architect from IBM Germany working for IBM Global Business Services. He has over eight years of experience in planning, building, and running WebSphere Commerce applications. Steffen worked in many customer projects as an Application Architect, a Consultant, Technical Project Leader, Lead Developer, and Reviewer. He has a Diploma Degree in Commercial Information Technology from the Technical University of Ilmenau, Germany.

Girish Gopinathan is an Advisory Software Engineer in IBM US. He has 12 years of experience in software design and development and has performed WebSphere Commerce customization for IBM.com since 2002. He has a Bachelor of Engineering degree in Electronics and Communication from Karunya Institute of Technology, Comibatore, India.

Vani Mittal is an IBM accredited IT Specialist working at IBM India in the India Software Labs. She works as a consultant in the IBM Software Services for WebSphere (ISSW) team. She has over five years of experience in consulting, design, and development of WebSphere Commerce engagements. She has a Master of Computer Applications degree from Jawaharlal Nehru University, New Delhi, India.

Juha Nevalainen is a Consulting IT Specialist from the IBM WebSphere Tech Sales team in Finland. He has 12 years of experience with WebSphere Commerce in Finland and in the UK. He has a M.Sc. degree in Computer Science from Helsinki University of Technology. Juha’s areas of expertise include WebSphere Commerce deployments, WebSphere Business Process Management, and some of the IBM Rational Application Developer tools. Juha contributed to the RAD Version 6 Programmers Guide Redbook publication.

Ramya Rajendiran is a Software Engineer in the IBM India Software Labs, Bangalore. She has two years of experience in the software field with WebSphere Commerce. Her working areas include WebSphere Commerce Content and Catalog Management and Management Center. She has a Bachelor's degree in Engineering in the Computer Science stream from the College of Engineering, Guindy, Anna University.

Thanks to the following people for their contributions to this project:

Tamikia Barrow, Margaret TicknorInternational Technical Support Organization, Raleigh Center

Scott Guminy, WebSphere Commerce Architect, IBM Software Group, Application and Integration Middleware SoftwareIBM Canada

Preface xiii

Page 16: My Tutorial

Daniel Cooper, Software Development - WebSphere CommerceIBM Canada

Jacob Vandergoot, IBM Software Group, Application and Integration Middleware SoftwareIBM Canada

Rob Leroux, WebSphere Commerce Software DeveloperIBM Canada

Become a published author

Join us for a two- to six-week residency program! Help write a book dealing with specific products or solutions, while getting hands-on experience with leading-edge technologies. You will have the opportunity to team with IBM technical professionals, Business Partners, and Clients.

Your efforts will help increase product acceptance and customer satisfaction. As a bonus, you will develop a network of contacts in IBM development labs, and increase your productivity and marketability.

Find out more about the residency program, browse the residency index, and apply online at:

ibm.com/redbooks/residencies.html

xiv WebSphere Commerce Line-of-Business Tooling Customization

Page 17: My Tutorial

Comments welcome

Your comments are important to us!

We want our books to be as helpful as possible. Send us your comments about this book or other IBM Redbooks in one of the following ways:

� Use the online Contact us review Redbooks form found at:

ibm.com/redbooks

� Send your comments in an e-mail to:

[email protected]

� Mail your comments to:

IBM Corporation, International Technical Support OrganizationDept. HYTD Mail Station P0992455 South RoadPoughkeepsie, NY 12601-5400

Preface xv

Page 18: My Tutorial

xvi WebSphere Commerce Line-of-Business Tooling Customization

Page 19: My Tutorial

Part 1 Introduction

In part 1 of the book, you will learn about:

� The IBM Management Center for WebSphere Commerce

� Why the Management Center was introduced

� The capabilities of the Management Center

� How the Management Center fits into the SOA framework of IBM WebSphere Commerce

Part 1

© Copyright IBM Corp. 2008. All rights reserved. 1

Page 20: My Tutorial

2 WebSphere Commerce Line-of-Business Tooling Customization

Page 21: My Tutorial

Chapter 1. IBM Management Center for WebSphere Commerce

In this chapter, we discuss the IBM Management Center for WebSphere Commerce and explain why it was introduced, what technologies it is built on, and what capabilities it offers. We also explain how IBM Management Center for WebSphere Commerce fits into the landscape of the IBM WebSphere Commerce line of business tooling.

This chapter can be most helpful to the following readers:

� Executives who want to become familiar with IBM Management Center for WebSphere Commerce

� Line-of-business users who perform daily work with the Management Center

� Project Managers who lead a WebSphere Commerce project, and make use of Management Center

� IT Architects and Software Developers who are designated for Management Center customization tasks but are completely new to the tool

1

© Copyright IBM Corp. 2008. All rights reserved. 3

Page 22: My Tutorial

1.1 Why Management Center was introduced

Since the major release of version 5.1 in 2001, all WebSphere Commerce line-of-business tools were based on the WebSphere Commerce Tools framework. This framework provides the line-of-business users with a consistent user interface, which includes a common look and feel and a set of user-interface components that use standard HTML elements, such as text input fields, selection fields, and buttons, to name a few.

The user interaction is mainly form-driven and request-response-based, which causes a full client-server-cycle with a complete page reload on any user submit action. Although user interface is improved by some client-side enhancements, such as user input validation to increase the tool’s responsiveness, the user interface is still a traditional style Web application, sometimes referred to as a Web 1.0 application.

With the Web 2.0 evolution in the past few years, the requirements of Web applications changed significantly. The use of advanced browser technologies, such as AJAX, enabled software developers to close the gap between browser-based and desktop applications, with respect to usability and user interface richness. A new kind of Web application evolved with powerful client-side functions that speed up your work and offer powerful user interface components and immediate action response.

IBM recognized the importance and value of the Web 2.0 approach to help you do your work quicker and more intuitively. The IBM Management Center for WebSphere Commerce is designed and built to bring the Web 2.0 principles to the WebSphere Commerce line-of-business tooling, which offers a more enjoyable user experience through a state-of-the-art user interface.

Another important reason for introducing Management Center is to make customizing and extending the WebSphere Commerce line-of-business tooling easier and more flexible.

The underlying technologies were carefully selected to ensure that the new tooling is based on a long-term sustainable platform that supports a wide range of user clients, depending mainly on open standards, and offering a maximum of flexibility in application design.

The application framework of the Management Center ensures a consistent application design, while it offers defined extension points to customize existing functions or to extend the tool by new functions and even new applications. A rich and well-documented application programming interface (API), for client and server side, helps software developers quickly adapt or enhance the tool’s functions to fulfill any customer requirement.

4 WebSphere Commerce Line-of-Business Tooling Customization

Page 23: My Tutorial

Compared to the existing WebSphere Commerce Tools framework, the number of touch points is significantly reduced. The extensions are now easier to build because they are more constricted by the Management Center framework, which makes the development of artifacts more straightforward. Together with logging, tracing, and debugging support, the effort is less in comparison.

The extensive documentation that is available in the WebSphere Commerce Information Center enables IT architects and software developers to get familiar with the correlations behind the scenes because the tutorials give a jump start on the customization road of Management Center.

This Redbooks publication is the ultimate guide to Management Center customization work. We recommend that you read this book before you start planning, designing, and implementing any non-simple customization scenario.

1.2 Management Center capabilities

In this section, we provide an overview of the capabilities of IBM Management Center for WebSphere Commerce. We describe functions and features at a high level to give you an idea of the Management Center’s primary intended use. Executives and project managers can use this information as an input to decide if Management Center is applicable to meet their specific business needs.

1.2.1 Functional capabilities

The IBM Management Center for WebSphere Commerce offers comprehensive functions covering the following areas:

� Product management� Catalog management� Marketing management� Promotions management

Product and catalog management main featuresThe Management Center contains catalog tools that allow you to create and manage catalog assets, such as products, catalogs, and categories. It has the following features:

� Browse master catalog and sales catalogs� Find any type of catalog entries, such as products, items, bundles, and kits� View and edit catalog entries� Find categories in master catalog and sales catalogs� View and edit categories

Chapter 1. IBM Management Center for WebSphere Commerce 5

Page 24: My Tutorial

� Manage descriptive and defining attributes of catalog entries� Manage merchandising associations of catalog entries� Manage sales catalogs, including creation, update, and deletion

Marketing management main featuresUse the marketing tool to manage your campaigns, campaign activities, and content. The following features are available:

� Manage campaigns

Use the campaigns to efficiently organize your campaign activities.

� Manage Web activities

Use the activity builder to define: the schedule and conditions of the targeted content to specific users.

� Manage e-mail activities

Use e-mail transport channel to deliver the content to users, similar to the Web activity management.

� Manage e-mail templates

Use a rich text editor to define e-mail templates. You can add several placeholders to personalize the content, which is accessible from a selection list. These placeholders are replaced by content after the e-mail gets created and sent.

Promotion management main featuresUsing the promotions tool, you can define discounts to give your customers an extra motivation for buying. Managing the promotions includes these features:

� Define discounts on the level of products, orders, or shipping

� Select from a list of predefined promotion types, and use the discount calculation rule that you want to apply

� Choose to bind the promotion redemption to a promotion code or a coupon, if desired

� Optionally, constrain the combination of multiple promotions

� Set the conditions for a user to be eligible for the promotion

� Define the promotion’s reward

� Optionally, set redemption limits

� Optionally, set date and time boundaries on which the promotion is effective

� Optionally, filter the eligible customers by defining customer segments

6 WebSphere Commerce Line-of-Business Tooling Customization

Page 25: My Tutorial

To help you create new promotions that are similar to existing ones, there is a copy and paste function that creates a promotion with the same data set as your promotion blueprint.

1.2.2 Usability capabilities

IBM Management Center for WebSphere Commerce offers a new, state-of-the-art and Web 2.0-aware user interface with excellent usability.

A consistent user-interface paradigm helps you to intuitively navigate through data and functions. Advanced user-interface components form a true rich interface application that contains drag-and-drop areas, zoomable GANTT charts, rich text editor, and editable tables, to name a few.

Moreover, you can work on several tasks in several tools concurrently, for example, you can work on a Web activity in the marketing tool using your catalog tool with a product, currently in edit mode, still open and accessible through the tools tab navigation. You can switch at any time between these tasks to complete them in any order, at your convenience.

Within a tool, all items currently being edited are listed under the Active Work folder in the Explorer view. Thus, you can edit multiple products simultaneously in any order that you want.

The application window and the various view and editor parts are fully resizable, taking advantage of all of the desktop space that you provide to the Management Center.

A major pain in WebSphere Commerce Accelerator is the handling of large data sets. IBM Management Center for WebSphere Commerce enhances WebSphere Commerce Accelerators ability to handle large data sets by giving better search capabilities, the ability to sort on any column in the list view, and the ability to rearrange, enable, and disable columns.

To improve performance and responsiveness, WebSphere Commerce server fetches only the data that is currently needed for display. The local browser cache is used for data caching and only data that changed is stored. Due to the given technology, the user interface code is loaded only once at startup and does not inflate the data transmission.

To speed up the work for you experienced users, many functions are accessible through keyboard shortcuts.

Chapter 1. IBM Management Center for WebSphere Commerce 7

Page 26: My Tutorial

1.2.3 Finding detailed information

For a complete list of all of the functional and usability capabilities, refer to the, which covers the following topics:

� Generic information about how to work with IBM Management Center for WebSphere Commerce

� Information about the:

– Catalogs tool– Promotions tool– Marketing tool

The WebSphere Commerce Information Center is available at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp

New features and functionality are frequently introduced through Feature Packs and releases. Check the latest documentation on the IBM WebSphere Commerce home page at:

http://www-306.ibm.com/software/genservers/commerceproductline/

1.3 Comparing the Management Center to other WebSphere Commerce line-of-business tools

IBM WebSphere Commerce offers a number of tools for line-of-business users. The following tools are available:

� WebSphere Commerce Accelerator

WebSphere Commerce Accelerator allows you to maintain online stores, hubs, and catalogs by completing various store operations, from managing the look and feel of your store to creating and maintaining orders to tracking store activities. You can, for example, manage the catalogs, create marketing campaigns, and view operational reports.

The Accelerator provides most of the functions that Management Center offers too. However, it does not provide the same rich and high-performance user experience that the Management Center provides, but is a matured and widely used tool.

While the future direction of the WebSphere Commerce line-of-business tooling will move toward the Management Center, the Accelerator is still fully supported. A number of functions are only available in Accelerator and there will be no replacement within WebSphere Commerce Version 6.

8 WebSphere Commerce Line-of-Business Tooling Customization

Page 27: My Tutorial

To learn more about WebSphere Commerce Accelerator, visit the WebSphere Commerce Information Center, specifically the WebSphere Commerce Accelerator section:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.user.doc/concepts/ctfmc.htm

� IBM Management Center for WebSphere Commerce

The Management Center is the next generation line-of-business tool for managing business tasks for online businesses.

The Management Center allows business users to perform merchandising and marketing tasks to create, update, and maintain merchandising and marketing assets.

The Management Center will be the successor of the Accelerator over time. New capabilities introduced in later versions of WebSphere Commerce will be managed using the Management Center.

� IBM Sales Center for WebSphere Commerce

The IBM Sales Center for WebSphere Commerce helps you accomplish your customer-service tasks easily and efficiently. You can work with orders and quotes for many customers and in many stores at the same time. In addition, you can quickly find information and compare products.

The IBM Sales Center is the preferred solution for Customer Sales Representatives who require a highly-efficient user interface for day-to-day call center tasks. You can also use it for in-store customer service tasks, where in-store staff can use it to quickly find a user account and work with a customer’s privileges, for example, promotions and coupons.

The Management Center and IBM Sales Center address different tasks, different user roles, in different work locations. Management Center addresses mainly planning and content management tasks on the level of headquarter or departments, while IBM Sales Center is about customer relationship management and order capture near the point-of-sale, either remotely in a call center or locally in a store.

To learn more about IBM Sales Center for WebSphere Commerce, visit the WebSphere Commerce Information Center, specifically the Getting started with the IIBM Sales Center section:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.telesales.tsr.doc/misc/welcome.htm

Alternatively, you can review the Redbooks publication Deploying and Customizing IBM Sales Center for WebSphere Commerce V6, SG24-7249.

Table 1-1 on page 10 provides a side-by-side comparison of all of the tools that we discussed in this section.

Chapter 1. IBM Management Center for WebSphere Commerce 9

Page 28: My Tutorial

Table 1-1 Comparison of the WebSphere Commerce Accelerator, IBM Management Center for WebSphere Commerce, and IBM Sales Center

Category WebSphere Commerce Accelerator

IBM Management Center for WebSphere Commerce

IBM Sales Center

Audience Line-of-business users performing the following roles:� Operational roles� Business relationship

roles� Product

management and merchandising roles

� Marketing roles� Customer service

roles

Line-of-business users performing the following roles:� Product

management and merchandising roles

� Marketing roles

Line-of-business users performing the following roles:� Customer service

roles

Typical environment Headquarter and departments

Headquarter and departments

Call center and point-of-sale locations

Main application Maintain online stores and hubs that support all aspects of settings, content management, and operations, which includes managing:� Hubs � Stores � Products and

catalogs� Content� Marketing and

promotions� Business

relationships� Users� Orders� Inventory� Logistics� Auctions� Payments� RFQs� Tax� Shipping

Supports content management, which includes managing:� Products and

catalogs� Content� Marketing and

promotions

Supports operations, which includes managing:� Users� Orders

10 WebSphere Commerce Line-of-Business Tooling Customization

Page 29: My Tutorial

Client technology Traditional browser-based Web application. Uses DHTML, JavaScript™ code, and CSS.

Flash-based rich interface application that runs in a browser.Uses the OpenLaszlo programming model that contains XML declarations and JavaScript code.

Eclipse-based rich client platform that is installed on a local machine.Uses the Eclipse programming model that contains XML and Java™ code.

Server technology WebSphere Commerce MVC architecture. Uses Struts framework, controller and task commands, EJBs, and JSPs.Accepts HTTP POST and GET requests containing structured name-value data.

WebSphere Commerce MVC architecture.Uses WebSphere Commerce Services, which includes OAGIS-based Web services, Business Object Document (BOD) commands, and Service Data Object (SDO)-based Data Service Layer persistence.

WebSphere Commerce MVC architecture.Uses WebSphere Commerce Services, which includes OAGIS-based Web services, BOD commands, and Service Data Object (SDO)-based Data Service Layer persistence.

User interface characteristics

Single-tasking user interface that employs standard HTML user controls.Performs a full request-response cycle to the server with a page reload on every action.

Multi-tasking user interface that employs sophisticated user controls.The user client interface is loaded only once.Action invocation and data transmission are separated from the user interface behavior.

Multi-tasking user interface that employs sophisticated user controls.The user client interface is loaded only once.Action invocation and data transmission are separated from the user interface behavior.

Category WebSphere Commerce Accelerator

IBM Management Center for WebSphere Commerce

IBM Sales Center

Chapter 1. IBM Management Center for WebSphere Commerce 11

Page 30: My Tutorial

1.4 Management Center technology

In this section, we provide an overview of the technology on which Management Center is built.

1.4.1 Client-side technology

The IBM Management Center for WebSphere Commerce is built on top of OpenLaszlo, which is an open source platform for creating Web applications with a desktop client-like user interface.

OpenLaszlo programs are written in XML and JavaScript and compiled to an Adobe® Flash program. While OpenLaszlo supports Flash and DHTML, the IBM

Performing customizations

Client-side and server-side customizations through changes or enhancements in JSP™ files, XML files, JavaScript files, and Java code.

Client-side customizations through changes or enhancements in Properties files and mainly OpenLaszlo files that contain XML and JavaScript code.Server-side customizations using the WebSphere Commerce Service framework through changes or enhancements in JSP files, XML files, Java code, and Query template files.

Client-side customizations through changes or enhancements in XML files, Properties files, and Java Code by using the Eclipse framework and Standard Widget Toolkit (SWT) or by using the Sales Center's own customization framework.Server-side customizations using the WebSphere Commerce Service framework through changes or enhancements in JSP files, XML files, Java code, and Query template files.

Availability in WebSphere Commerce

Available in WebSphere Commerce V5.6.1 and WebSphere Commerce V6.0

Available in WebSphere Commerce V6.0 with Feature Pack 3 or later

Available in WebSphere Commerce V6.0

Category WebSphere Commerce Accelerator

IBM Management Center for WebSphere Commerce

IBM Sales Center

12 WebSphere Commerce Line-of-Business Tooling Customization

Page 31: My Tutorial

Management Center for WebSphere Commerce only uses Flash; therefore, users need a supported Internet browser with an installed Flash plug-in.

Read Chapter 2, “Overview of the IBM Management Center for WebSphere Commerce environment” on page 15 for more details.

1.4.2 Server-side technology

On the server side, the Management Center utilizes WebSphere Commerce Services. Because WebSphere Commerce is transitioning to a service-oriented architecture (SOA), the business subsystems are decoupled so that different applications can better reuse WebSphere Commerce functions.

Instead of the name-value-pair URLs that represent a typical Web request, business components declare structured objects that represent services, implementing a well-defined service interface.

WebSphere Commerce service interfaces are defined using the OAGIS message structure, from The Open Applications Group.

The OAGIS standard provides a consistent message structure and model for messaging using XML. The OAGIS standards describe BODs as nouns and the services that interact with those nouns are called verbs.

More details are in Chapter 2, “Overview of the IBM Management Center for WebSphere Commerce environment” on page 15 or in the WebSphere Commerce Information Center at the following Web location:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.telesales.tsr.doc/misc/welcome.htm

Chapter 1. IBM Management Center for WebSphere Commerce 13

Page 32: My Tutorial

14 WebSphere Commerce Line-of-Business Tooling Customization

Page 33: My Tutorial

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment

In this chapter, we discuss how the Management Center fits into the overall service-oriented architecture (SOA) framework of IBM WebSphere Commerce.

2

© Copyright IBM Corp. 2008. All rights reserved. 15

Page 34: My Tutorial

2.1 High-level SOA architecture for the Management Center

The objective of this section is to provide an overview of how the Management Center fits into the SOA framework of WebSphere Commerce.

The Management Center makes wide use of the SOA model, in preference over the older model of name value pair commands and EJB™ persistence. The older model is called Service-Oriented Integration (SOI) because it just provides a service wrapper over the existing functionality. With SOA, the architecture of the application is constructed to facilitate the use of the components and logic as services. Figure 2-1 illustrates the difference between SOI and SOA. The SOI model is shown in grey.

Figure 2-1 Where the Management Center fits in the SOA model

The old style of using name value pair commands should only be used for Management Center customizations where:

� There is already a name value pair command that fits or is close to the requirements.

Management Center

Presentation layer

Business logic layer

Persistence layer

Data Service Layer

Business Object DocumentProcessing Commands

EJB 1.1

WebSphere Commerce Services

Name Value PairCommands

16 WebSphere Commerce Line-Of-Business Tooling Customization

Page 35: My Tutorial

� It is too much of an effort to create a new SOA-based command for the required Management Center changes.

For more information about WebSphere Commerce and its use of SOA for the Management Center, visit the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.developer.doc/concepts/csdsoa.htm

2.2 Presentation layer

In this section, we describe the presentation layer for the Management Center, specifically the architecture, components, and operation. We cover customization details in Chapter 3, “Customization overview” on page 29.

2.2.1 Overview of the Presentation layer

The Presentation layer consists of the OpenLaszlo application, which sits on the Web browser, and a Mediation layer. Figure 2-2 on page 18 illustrates the high-level components of the Presentation layer and the interaction between the OpenLaszlo application, the Mediation layer, and the Business Logic layer.

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment 17

Page 36: My Tutorial

Figure 2-2 Presentation layer and its interaction with the Business Logic layer

The Management Center, the OpenLaszlo Application, as seen in Figure 2-2, is a rich Internet application—a Web application that has rich user interface features and functionalities (of traditional desktop applications). This OpenLaszlo application introduces a layer of code between the user and the server. This layer of code is called the client engine, which you download as part of the instantiation of the Management Center. The client engine essentially takes care of maintaining the client-side data model, rendering the application’s user interface and the server communication. A data model is maintained on the client side that helps in transferring and processing the necessary to support the rich user interface features and functionalities to the Web client; however, the bulk of data is maintained on the server.

The OpenLaszlo application communicates in the Representational State Transfer (REST) style. It understands and communicates through incoming XML data and outgoing HTTP requests. WebSphere Commerce services understand only BOD requests and responses. The Mediation layer acts as a proxy server to the OpenLaszlo application and accepts the incoming HTTP requests from the OpenLaszlo application to build the appropriate BOD requests from the incoming HTTP requests. The Mediation layer acts on the BOD response from the services to build XML data that the OpenLaszlo application can understand.

Presentation layer

Web browser

httpRequest

XMLResponse

Business Logic layer

BODRequest

BODResponse

WebSphere Commerce services

Mediation layer

OpenLaszlo application

18 WebSphere Commerce Line-Of-Business Tooling Customization

Page 37: My Tutorial

2.2.2 The OpenLaszlo application

The OpenLaszlo application can be aligned to the Model-View-Controller architecture. In Figure 2-3:

� Model refers to the data model that is maintained on the client side.

� View refers to the user interface of the application.

� Controller renders the application’s user interface and maintains the data model and the server communication.

The Management Center core UI framework models the MVC components and their interactions. Figure 2-3 presents the OpenLaszlo application architecture on these lines.

Figure 2-3 OpenLaszlo application architecture

For more details about the OpenLaszlo application, visit the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.management-center_customization.doc/concepts/ctfcmcui.htm

Web browser

HTTPRequest

XMLResponse

OpenLaszlo Application

User Interaction

Data Model

Controller

View

Mediation Layer

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment 19

Page 38: My Tutorial

2.2.3 The Mediation layer

In this section, we describe how the Mediation layer mediates between the REST style requirements of the OpenLaszlo application and the Business Object Documents that can be used to service requests from a variety of external applications and systems.

For more information about the Mediation layer, visit the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.management-center_customization.doc/concepts/ctfmancenter.htm

The Mediation layer makes it easier to customize the Management Center than using Web services directly from the OpenLaszlo application. It also opens up the possibility of other clients using this REST style approach.

The Mediation layer is a Struts-based Web application (module) that is part of the WebSphere Commerce application (EAR). It is formed by four components, as shown in Figure 2-4 on page 21.

20 WebSphere Commerce Line-Of-Business Tooling Customization

Page 39: My Tutorial

Figure 2-4 Mediation layer and its interaction with the Presentation layer and Business Logic layer

The four components that comprise the Mediation layerThe Servlet Filter, Struts application, JSPs, and the Client layer make up the Mediation layer.

The Servlet Filter controls sessions using an Identity Token that is passed through a cookie to the OpenLaszlo application. This component is not meant for customization.

The Struts application mediates between the HTTP request, the BOD services, and the JSPs. The mediation is configured by the struts XML files, which are a customization point. We explain the mediation flow in the following sections: “The Mediation layer get request” on page 22 and “The Mediation layer’s create, update, and delete request” on page 22.

Presentation layer

Mediation layer

JSPsStrutsApplication

HTTPRequest

XMLResponse

BODRequest

BODResponse

Business Logic layer

WebSphere Commerce Services

Client Library

Servlet Filter

Web browser

OpenLaszlo Application

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment 21

Page 40: My Tutorial

The JSPs interact with the BODs to get the required data and to build the XML response in the form that the OpenLaszlo application requires. These JSPs are often a customization point.

The Client Library allows Java or JSP interactions with the BODs. This component is not for customization.

The Mediation layer get requestFigure 2-5 shows the flow of a get request through the Mediation layer. For more information, visit the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.management-center_customization.doc/concepts/ctfmancenter.htm

Figure 2-5 Flow of the get request through the Mediation layer

The Mediation layer’s create, update, and delete requestFigure 2-6 on page 23 shows the flow of a create, update, and delete request. For more information about this request, visit the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.management-center_customization.doc/refs/rtfprocessservices.htm

Line-of-BusinessResponse JSPs

Identity Token filter

Line-of-Business Struts Application

1

2

3

4 5

6

WebSphere Commerce Services

Management Center

Mediation layer

22 WebSphere Commerce Line-Of-Business Tooling Customization

Page 41: My Tutorial

Figure 2-6 Flow of the Mediation layer’s create, update, and delete request

2.3 Business Logic layer

In this section, we describe the Business Logic layer in the context of the Management Center. We cover the architecture, components, and operation. Figure 2-7 on page 25 provides an overview of the Business Logic layer.

2.3.1 Components of the Business Logic layer

The Business Logic layer consists of business components that have OAGIS services to return data or execute business processes. These OAGIS services are leveraged by the Presentation layer to display data or to invoke a business process. The business logic provides the data that the Presentation layer requires. The Business Object Document Processing Command is the entry point on the component facade where the business logic begins to process the Business Object Document. This layer works with the logical SDOs, which are abstracted from the actual physical representation of data.

The key objective for the Data Service Layer (DSL) is to provide a layer of abstraction for data access that is independent of the actual data store. It

Line-of-Business Response JSPs

Identity Token filter

Line-of-Business Struts Application

1

2

3 4

5

6

Management Center

WebSphere Commerce Services

Mediation layer

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment 23

Page 42: My Tutorial

provides a simple consistent interface for all data access, which makes the Business Logic layer independent from the persistence technology that is used.

The Data Service Facade is a thin layer that provides a single entry point into DSL. It enables interfaces to work with both physical and logical data model. It also allows each service module to register with the Data Service Layer and loads the service module-specific configuration files.

2.3.2 Business Object Mediators

The Business Object Mediators are classes that transform between the logical and physical representations of the domain model. They support create, read, update, and delete operations by interfacing with the logical SDOs to the Business Logic layer, which allows the Business Logic layer to deal only with the logical representation of the data. Each component provides its own mediators.

There are two kinds of mediators: Read and Change mediators. Change mediators handle the OAGIS Change, Process, and Sync requests. The most common approach is to call the Business Object Mediator to transform your logical SDOs to physical SDOs.

The Business Object Mediator uses the services of the Physical Data Container to fetch and save the physical data. The Physical Data Container supports create, read, update, and delete operations on the physical SDOs, which are mapped directly to the physical schema. It also enables the business logic to work with physical SDOs that are not mapped to the logical model.

Figure 2-7 on page 25 illustrates the Business Logic layer and the Persistence layer.

24 WebSphere Commerce Line-Of-Business Tooling Customization

Page 43: My Tutorial

Figure 2-7 Overview of Business Logic layer and the Persistence layer

For Management Center customizations, the Business Logic layer is typically less customized in comparison to the Presentation layer; therefore, we provide a limited amount of information about this layer. For detailed descriptions of the Business Logic layer and how to do more extensive customizations, visit:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.developer.soa.doc/concepts/csdsoaprogmodel.htm

Management Center

Presentation layer

Business logic layer

Persistence layer

Data Service

Layer

Business Object DocumentProcessing Commands

EJB 1.1

WebSphere Commerce Services

Name Value PairCommands

Logical SDOs

Business Object Mediator

Physical Data Container

Physical SDOsCommerce Database

Data Service Facade

Chapter 2. Overview of the IBM Management Center for WebSphere Commerce environment 25

Page 44: My Tutorial

26 WebSphere Commerce Line-Of-Business Tooling Customization

Page 45: My Tutorial

Part 2 IBM Management Center for WebSphere Commerce customization

In part 2 we:

� Provide an overview of the assets that make up the Management Center� Discuss what assets you can customize� Share some of the common customization scenarios

When planning to customize the Management Center, it is important to understand the framework and the components that make up the Management Center. In the upcoming chapters, you will learn how to plan and perform

Part 2

© Copyright IBM Corp. 2008. All rights reserved. 27

Page 46: My Tutorial

customizations to the Management Center and understand the use of development tools and assets for creating Management Center customizations.

28 WebSphere Commerce Line-of-Business Tooling Customization

Page 47: My Tutorial

Chapter 3. Customization overview

In this chapter, we provide an overview of the assets that make up the Management Center. We discuss which of these assets you can customize and also describe some common customization scenarios.

If you plan to customize the Management Center, it is important to understand the framework and the components that make up the Management Center. For an overview of the Management Center framework and development environment see Chapter 1, “IBM Management Center for WebSphere Commerce” on page 3 and Chapter 2, “Overview of the IBM Management Center for WebSphere Commerce environment” on page 15.

3

© Copyright IBM Corp. 2008. All rights reserved. 29

Page 48: My Tutorial

3.1 Development assets

From a customization perspective, the Management Center encompasses several development assets. These assets can be grouped into three categories:

� Management Center user interface � Management Center Web application� WebSphere Commerce services

We discuss all three types of assets in the subsequent sections.

3.1.1 Management Center user interface

The Management Center user interface is primarily divided into two parts:

� Management Center shell� Management Center tools

Management Center shellThe Management Center shell is a container in which all line-of-business tools reside. It provides the common elements of the user interface.

In this section, we describe the various shell assets and the customization scenarios that can cause these assets to be modified.

Main application areaAfter you successfully log on to the Management Center, the main application window is displayed. The main application window is defined in its own OpenLaszlo source file, MainWorkbench.lzx. The class wcfMainWorkbench defines the main application area. The application area is divided into three parts: banner area, main work area, and the status area.

Table 3-1 on page 31 lists the customization scenarios that require changes to the main application area.

Note: WebSphere Commerce services are not part of the Management Center. But for customizing the Management Center, we often need to customize services also; therefore, we include information about the services.

30 WebSphere Commerce Line-of-Business Tooling Customization

Page 49: My Tutorial

Table 3-1 Main application area customization scenarios

Status areaThe status area is the bottom area in the Management Center shell. By default, it consists of the message link and the progress indicator.

The status area is defined in its own OpenLaszlo source file ToolStatusArea.lzx. The class that defines the status area is wcfStatusArea.

Table 3-2 lists some customization scenarios for the status area.

Table 3-2 Status area customization scenarios

Banner areaThe banner area is defined in its own OpenLaszlo source file ToolBannerArea.lzx. By default, it is composed of the application menu, user identification area, logout link, and the branding logo.

Table 3-3 on page 32 lists the customization scenarios that require changes to the banner area.

Scenario Required changes Reference

Change the layout of the main page

Change the order of wcfBannerArea, wcfMainArea, and wcfStatusArea classes as desired.

WebSphere Commerce Information Center: Rearranging the layout of the Management Center main page:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfmainpagelayout.htm

Scenario Required changes Reference

Change the layout of the status area

Change the order of the wcfProgressIndicator and wcfMessageLink classes.

WebSphere Commerce Information Center: Rearranging the layout of the Management Center status area:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfstatusarealayout.htm

Chapter 3. Customization overview 31

Page 50: My Tutorial

Table 3-3 Banner area customization scenarios

Application menuThe application menu provides access to all tools that are built in the system, and items in the menu are visible to you based on the usages that are attached to the associated component. The application menu also provides hyperlinks to WebSphere Commerce Accelerator’s Getting Started and Preferences.

The application menu is defined in its own OpenLaszlo source file, ApplicationMenuItems.lzx. The class wcfApplicationMenuItems defines the menu items.

Table 3-4 on page 33 lists the customization scenarios that require changes to the application menu.

Scenario Required changes Reference

Change the layout of the banner area

Change the order of welcomeText, divider1, wcfLogoutLink, divider2, and headerLogo within bannerRightView.

WebSphere Commerce Information Center: Rearranging the layout of the Management Center banner:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfbannerlayout.htm

Change the welcome text in the user identification area

Modify the welcomeText element in ToolBannerArea.lzx to use a different resource bundle property.

None

Change the branding logo By default the IBM logo is displayed. You can change it to reflect your custom logo.

WebSphere Commerce Information Center: Changing the logo image:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangelogo.htm

32 WebSphere Commerce Line-of-Business Tooling Customization

Page 51: My Tutorial

Table 3-4 Application menu customization scenarios

Preferences dialogYou can set the following global preferences using the Preference Dialog, which you can open by selecting the Preferences menu item in the tool menu:

� Default store that is used when the tools are opened� Default language to be used in the tool UI� Default cultural locale that determines the number format in the tool� Whether to enable the Extended help feature in the application or not

The UI default language is persisted as the preferred language of the user in the USERS table in the database (USERS.LANGUAGE_ID), and the other preferences are persisted in the database as member attributes on a per user basis. So when you try to save the preferences by clicking the OK button in the preferences dialog, the member service is called to persist the preferences to the database.

Table 3-5 on page 34 lists all of the classes that are relevant to the Preferences feature.

Scenario Required changes Reference

Change the layout of the application menu

Change the order of the various wcfApplicationMenuItem classes.

WebSphere Commerce Information Center: Rearranging the layout of the Management Center menu:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfappmenulayout.htm

Change the icons that represent a tool

Change the activeIconSrc and inactiveIconSrc to use your custom icons.

WebSphere Commerce v6 Information Center: Changing the tool icon for the Management Center menu:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangeappmenuicon.htm

Change the access control for a tool

Authorize a new business role to access a tool.

WebSphere Commerce v6 Information Center: Changing access control for a Management Center tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfcreatelobrole.htm

Chapter 3. Customization overview 33

Page 52: My Tutorial

Table 3-5 User preferences API classes

Table 3-6 lists the services that the Preferences feature uses.

Table 3-6 Services used by Preferences

Table 3-7 on page 35 provides the various customization scenarios for user preferences.

Class Source file Description

wcfUserPreferenceDialog UserPreferenceDialog.lzx This is the user preference dialog that opens when you select Preferences from the application menu.

wcfUserPreferencePanel UserPreferencePanel.lzx This class contains all of the widgets that are in the user preference dialog.

wcfPreferenceManager PreferenceManager.lzx This class handles all of the preferences, stores them as attributes in the class, and persists them as member attributes to the database. It provides support for the tools to save and retrieve preferences for the user.

wcfConfigProperties ConfigProperties.lzx This class defines all of the configurable properties that are used in Management Center.

wcfUserPreferenceObject UserPreferenceObjects.lzx This is the base class that represents a user preference object. All preference objects in the Management Center should extend this class and implement the methods of this class.

Service Interface Description

GetPerson com.ibm.commerce.member.facade.client.MemberFacadeClient.findCurrentPerson()

This service is called to retrieve the user preferences from the database.

ChangePerson com.ibm.commerce.member.facade.client.MemberFacadeClient.updatePerson(Map parameters)

This service is called when you click OK in the Preferences dialog to save the preferences.

34 WebSphere Commerce Line-of-Business Tooling Customization

Page 53: My Tutorial

Table 3-7 User preferences customization scenarios

Management Center toolsEach Management Center tool is responsible for managing a set of business objects, for example, the Promotions tool manages promotions.

You can either customize an existing tool or create a new one to meet your requirements.

Scenario Required changes Reference

Change the layout of the preferences dialog

Change the order of the preference objects in wcfUserPreferencePanel (UserPreferencePanel.lzx.

None

Change the default values for preferences

The default values are defined in wcfConfigProperties (ConfigProperties.lzx).

WebSphere Commerce v6 Information Center: Changing default values for settings in the Preferences dialog:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangedefaultpref.htm

Add a new user preference 1. Create a new class that extends wcfUserPreferenceObject.

2. Insert the above new class to the list of existing preference objects in the dialog.

3. Create a new entry to the MBRATTR table in the database to register this new preference.

Refer to Chapter 10, “Customizing user preferences” on page 165 for an example.

Note: To add a new user preference, you must have at least Feature Pack 4 installed because wcfUserPreferenceObject class is declared private in previous versions.

Note: To customize the Promotions tool, you must have at least Feature Pack 4 installed.

Chapter 3. Customization overview 35

Page 54: My Tutorial

Each tool consists of a number of assets that you must modify in order to customize a tool. In this section, we describe the various tool assets and the customization scenarios that can cause the assets to be modified.

Business object editor definitionsThe business object editor is a high-level widget that provides all of the common features for creating and managing business objects. Each Management Center tool has to extend from the wcfBusinessObjectEditor class. The various Management Center tools are created by binding object definitions to the business object editor widget.

A business object editor class describes the characteristics and behavior of a Management Center tool. The class defines the object definitions, initialization services, filters, and search definitions for that tool.

Table 3-8 lists customization scenarios in which a business object editor requires changes.

Table 3-8 Customization scenarios for business object editor

Scenario Required changes Reference

Define a new tool Define a new class that extends from wcfBusinessObjectEditor. Define the required objects and artifacts for the new tool.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Define a new object Update the business object editor definition to include the new object definition.

Refer to “Object definitions” on page 37 for more information.

Define a new initialization service

Update the business object editor definition to include the new service definition.

Refer to “Service definitions” on page 41 for more information.

Define a new filter Update the business object editor definition to include the new filter definition.

Refer to “Filter definitions” on page 38 for more information.

Define a new search definition

Update the business object editor definition to include the new search definition.

Refer to “Search definitions” on page 38 for more information.

36 WebSphere Commerce Line-of-Business Tooling Customization

Page 55: My Tutorial

Object definitionsAn object definition class describes the characteristics of a Management Center object. The class defines the attributes, services, list definitions, property definitions, and client-side validators for an object.

Each object definition should extend from wcfObjectDefinition and should be defined in its own OpenLaszlo source file.

Table 3-9 lists possible customization scenarios for object definitions.

Table 3-9 Customization scenarios for object definitions

Scenario Required changes Reference

Define a new object Define a new class that extends from wcfObjectDefinition.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Add a new property or change an existing property

Update an object definition to include new user data or an attribute property.

WebSphere Commerce v6 Information Center: Adding new fields in the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadpcat.htm

Define a custom service or change an existing service

Update an object definition to include a new wcfCustomService definition.

Refer to Chapter 7, “Adding a new service action” on page 107 for an example.

Change an attribute of an object

Change the display name attribute of an object definition.

WebSphere Commerce v6 Information Center: Changing the display name for a Management Center object:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangedisplayname.htm

Define a new filter Update the object definition to include the new filter definition.

Refer to “Filter definitions” on page 38 for more information.

Define a new validator Define a new client-side validator

Refer to Chapter 6, “Enabling the merchandising associations’ Semantic Attribute” on page 89 for an example.

Chapter 3. Customization overview 37

Page 56: My Tutorial

Search definitionsA search definition class describes the characteristics of an object search type that is available from the search widget. The class defines the search service, the view that displays the search results, and an optional class to define the advanced search options.

Extend each search definition from wcfSearchDefinition, and define it in its own OpenLaszlo source file.

Table 3-10 lists possible customization scenarios for search definitions.

Table 3-10 Customization scenarios for search definitions

Filter definitionsYou can define a filter for an object, a list, or a business object editor. If you declare a filter as the child of an instance of wcfBusinessObjectEditor, the filter is selectable through a pull-down menu that is located at the top of the explorer view. If you declare the filter as a child of an instance of wcfObjectGrid, it is selectable through a pull-down menu that is located at the top of the list view.

Scenario Required changes Reference

Define a new search type Define a new class that extends from wcfSearchDefinition to search for a custom business object.

Refer to Chapter 8, “Advanced search for merchandising associations” on page 119 and Chapter 12, “Custom Application Configuration Management tool” on page 239 for examples.

Customize an existing search type

1. Change the display name

2. Change the view that displays the search results

None

Define an advanced search

Define a new advanced search class for a tool (for example, a custom tool) that does not support advanced search.

Refer to Chapter 8, “Advanced search for merchandising associations” on page 119 for an example.

Customize advanced search

Add new search conditions to an existing advanced search class.

WebSphere Commerce v6 Information Center: Adding new search conditions in the advanced search of the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadsca.htm

38 WebSphere Commerce Line-of-Business Tooling Customization

Page 57: My Tutorial

Define each filter in its own OpenLaszlo source file and extend it from one of the following classes:

� wcfObjectTypeFilter

It filters model objects based on an object type. You can define an object type filter for a business object editor, a primary object, or a list view of primary objects, for example, as a child of an instance of wcfBusinessObjectEditor, wcfPrimaryObjectDefinition, or wcfObjectGrid.

Another example is in the Catalog tool, the catalog entry list view defines filters to filter products that are based on the product type: products only, bundles only, kits only, SKUs only, and all except SKUs.

� wcfObjectPathFilter

It filters model objects based on the object path. You can define an object path filter only for a list view of primary objects, for example, as a child of a wcfOjbectGrid.

� wcfObjectPropertyFilter

It filters model objects based on the value of an object property. You can filter an object property filter only for a list view of primary objects, for example, as a child of a wcfObjectGrid.

Another example is in the Promotions tool, the promotion list view defines filters to filter the promotions based on the promotion group: order level promotions, product level promotions, and shipping promotions.

Table 3-11 lists possible customization scenarios for filter definitions.

Table 3-11 Customization scenarios for filter definitions

List view definitionsA list view lists objects in the form of a table. The Management Center also displays search results in a list view.

Define each business object list in its own OpenLaszlo library source file. The class of a list that displays primary objects should extend from wcfObjectGrid, and the class of a list that displays child objects should extend from wcfChildListEditor. The class defines its constituent columns and filters.

Scenario Required changes Reference

Define a new filter Define a new filter class that extends from one of the classes defined above.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Chapter 3. Customization overview 39

Page 58: My Tutorial

Table 3-12 lists some customization scenarios for a list view.

Table 3-12 Customization scenarios for a list view

Properties view definitionsThe properties view allows you to view and edit properties of a business object. You can display a properties view in the editor work area or in the details area that is associated with a list view.

Define each properties view in its own OpenLaszlo library source file. Primary business objects are required to provide a wcfObjectDefinition.propertiesClass attribute, which contains the name of a class that extends wcfObjectProperties.

Scenario Description Reference

Define the list view for a primary object

Define a new class that extends from wcfObjectGrid.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Define the list view for a child object

Define a new class that extends from wcfChildListEditor.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Define the list view for search results

Define a new class that extends from wcfObjectGrid.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Customize an existing list view

� Add a column to the list

� Delete a column from the list

� Reorder the default columns

� Change the default visibility of the columns

Refer to Chapter 6, “Enabling the merchandising associations’ Semantic Attribute” on page 89 and Chapter 7, “Adding a new service action” on page 107 for examples.

Change the attributes of a column of an existing list view

Change the attributes of a column as desired, for example, text, editable, visible, and so on.

WebSphere Commerce v6 Information Center: Changing a column name in a list view:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangecolumnlist.htm

Define a new filter Update the list view definition to include the new filter definition.

Refer to “Filter definitions” on page 38 for more information.

40 WebSphere Commerce Line-of-Business Tooling Customization

Page 59: My Tutorial

Table 3-13 lists some customization scenarios for the properties view.

Table 3-13 Customization scenarios for properties view

Calendar view definitionsA calendar view shows details about an object from a scheduling perspective, using a Gantt chart. Calendar views are available in the Promotions and Marketing tools.

Define each calendar view in its own OpenLaszlo library source file. It should extend from the wcfGanttGrid class. An instance of wcfGanttGrid is declared as the listClass for wcfChildListEditor, wcfSearchDefinition, and wcfReferenceList.

Calendar is a special type of list view; therefore, most of the customization scenarios that are described for a list view also hold good for the calendar view. For more information about customizing a list view, refer to “List view definitions” on page 39.

Service definitionsThe Management Center framework defines user interface services for actions, such as creating, updating, and deleting business objects. wcfService is the base class for all service types.

Table 3-14 on page 42 lists customization scenarios for service definitions.

Scenario Description Reference

Define a new properties view

Define a new class that extends from wcfObjectProperties for a custom business object.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Add a new property to the properties view

Update the properties view to include a new property. Create a new tab to include the new property.

WebSphere Commerce v6 Information Center: Adding new fields in the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadpcat.htm

Rearrange the contents of a properties view

Move tabs, sections, or widgets around as desired.

Refer to Chapter 9, “Price comparison mashup” on page 143 for an example.

Chapter 3. Customization overview 41

Page 60: My Tutorial

Table 3-14 Customization scenarios for service definitions

Scenario Required changes Reference

Define a new create, update, delete, or refresh service for a custom object

1. Define a new class that extends from wcfCreateService, wcfUpdateService, wcfDeleteService, or wcfRefreshService.

2. Declare it as a child object of the object definition.

3. Define a controller JSP to implement the service.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Define a new initialization service for a custom tool

1. Define a new class that extends from wcfInitService.

2. Declare it as a child of the business object editor instance of the new tool.

3. Define a controller JSP to implement the service.

None

Define a new search service

1. Define a new class that extends from wcfSearchService.

2. Declare it as a child of the search definition.

3. Define a controller JSP to implement the service.

Refer to Chapter 8, “Advanced search for merchandising associations” on page 119 and Chapter 12, “Custom Application Configuration Management tool” on page 239 for examples.

Define a new custom service

1. Define a new class that extends from wcfCustomService.

2. Declare it as a child of an object definition.

3. Define a controller JSP to implement the service.

Refer to Chapter 7, “Adding a new service action” on page 107 for an example.

Define a new get children service for a custom object

1. Define a new class that extends from wcfGetChildrenService.

2. Declare it as a child of the object definition.

3. Define a controller JSP to implement the service.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Define a new get references service for a custom primary object

1. Define a new class that extends from wcfGetReferencesService.

2. Declare it as a child of the primary object definition.

3. Define a controller JSP to implement the service.

None

42 WebSphere Commerce Line-of-Business Tooling Customization

Page 61: My Tutorial

WidgetsWidgets are UI elements that display and edit Management Center object properties. The Management Center framework provides a set of high-level widgets that provide all of the behaviors that are required for authoring business objects.

The main high-level widget that the framework provides is the Business Object Editor widget, which provides all of the behavior for a Management Center tool.

You can use or extend any of the widgets that are part of the OpenLaszlo API, which are defined at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.management-center_customization.doc/refs/rtfmain.htm

For information about how to create a new Management Center widget, refer to Creating a new Management Center widget at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfcreatenewwidgets.htm

For information about how to use or extend a Management Center widget, refer to Using or extending Management Center widget at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfuseexistingwidgets.htm

Chapter 9, “Price comparison mashup” on page 143 provides an example in which you create a new widget that is similar in behavior to the grid widget (wcfObjectGrid) that the Management Center framework provides.

Chapter 11, “Spell Checker” on page 179 provides an example in which you create a window dialog widget, which you can use to spell check a text property and make corrections.

3.1.2 Management Center Web application

The purpose of the Management Center Web application is to provide a Mediation layer between the Presentation layer (for example, the OpenLaszlo client) and the Business Logic layer (for example, WebSphere Commerce OAGIS services).

In this section, we describe the customization points that are defined for the Web application and how to customize the different assets. For more information

Chapter 3. Customization overview 43

Page 62: My Tutorial

about the Mediation layer architecture, refer to Section 2.2.3, “The Mediation layer” on page 20.

The line-of-business Web application contains the following customizable assets:

� OpenLaszlo source code

This is the source code for the Management Center user interface. Refer to 3.1.1, “Management Center user interface” on page 30 for details about customizing the OpenLaszlo code.

� Extension Struts configuration

The file path is /WEB-INF/struts-extension.xml. This is the struts configuration file where you add your custom URL mappings.

� Get controller JSPs

The Management Center sends a URL request to retrieve an object. The struts action forwards the request to a Get controller JSP that uses the wcf:getData tag to invoke the appropriate Get service to retrieve the list of Nouns from the WebSphere Commerce server.

� Serialization JSP fragments

When returning a response, these JSP fragments transform the OAGIS Noun into the appropriate XML representation that the Management Center expects. These JSP fragments are included by the Get controller JSP pages.

� get-data-config.xml

The Management Center framework uses the get-data-config.xml file to configure the wcf:getData tag that is defined in the Get controller JSPs.

� wc-componentname-clientobjects.xml

The Management Center object definition files contain information that is used to map URL requests to BOD requests and vice versa.

Table 3-15 lists some customization scenarios for the Management Center Web application.

Table 3-15 Customization scenarios for the Web application

Scenario Required changes Reference

Define a new retrieval service for a Management Center object

1. Create a new Get controller JSP.

2. Create a new serialization JSP.

3. Add a new forward action to struts-extension.xml.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

44 WebSphere Commerce Line-of-Business Tooling Customization

Page 63: My Tutorial

Define a new process service for a Management Center object

1. Define the mapping between the Noun elements and the Management Center object in a new XML file (wc-componentname-clientobjects.xml).

2. Add the XML file that you defined in the previous step to struts-extension.xml to the list of files that are specified in the config property of the BusinessObjectDocumentPlugin.

3. Create a new BusinessObjectDocument Struts action.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example.

Override a retrieval service for an existing Management Center object

The process to override an existing retrieval service is similar to creating a new one.

WebSphere Commerce v6 Information Center: Adding new search conditions in the advanced search of the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadsca3.htm

Override a process service for an existing Management Center object

The process to override an existing process service is similar to creating a new one.

None

Override an existing error message

WebSphere Commerce v6 Information Center: Mapping of validation error reason codes:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfmaperror.htm

Scenario Required changes Reference

Chapter 3. Customization overview 45

Page 64: My Tutorial

3.1.3 WebSphere Commerce services

In this section, we discuss the Business Logic layer, for example, the WebSphere Commerce services. We cover Management Center customization scenarios that require customization of the BOD command framework.

The BOD command framework (introduced in Feature Pack 3.0.1) is an implementation of the Business Logic layer that deals with business object documents and their Java representation.

In the following sections, we discuss possible scenarios for Management Center customization, which requires you to customize the WebSphere Commerce services.

Scenario: Creating a new Management Center toolCreating a new Management Center tool is an end-to-end scenario that involves customizing the Management Center user interface, Management Center Web application, and WebSphere Commerce services.

Refer to Chapter 12, “Custom Application Configuration Management tool” on page 239 for an example that shows how to create a new tool.

Note: For more information about the Business Logic layer and how it fits into the overall Management Center architecture, refer to Chapter 2, “Overview of the IBM Management Center for WebSphere Commerce environment” on page 15.

For information about the BOD command framework, refer to the WebSphere Commerce v6 Information Center:

� WebSphere Commerce BOD command framework

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdsoaprogmodel.htm

� Creating a new WebSphere Commerce BOD service module

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tutorial/tsdsoatutorial.htm

� Developing the Business Logic layer using the BOD command framework

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdcustomizesoasvc.htm

46 WebSphere Commerce Line-of-Business Tooling Customization

Page 65: My Tutorial

Scenario: Retrieval services for Management Center objectsThe retrieval service for a Management Center object corresponds to a BOD Get request. We can create a new Get service or customize an existing one to create a new retrieval service or override an existing retrieval service.

For information about customizing retrieval services, refer to 3.1.2, “Management Center Web application” on page 43.

For an example that shows how to create a retrieval service and a corresponding BOD Get request, refer to Chapter 12, “Custom Application Configuration Management tool” on page 239.

Scenario: Process services for Management Center objectsThe process services for Management Center objects correspond to Process BOD and Change BOD requests.

If the Management Center object represents a Noun, the Create and Delete services correspond to the Process BOD request with an action code of Create or Delete respectively.

If the Management Center object represents part of a Noun, the Create and Delete services correspond to the Change BOD request with an action code of Add or Delete respectively.

An Update service for a Management Center object always corresponds to the Change BOD request with an action code of Change.

For an example that shows how to create process services and corresponding Change and Process BOD services, refer to Chapter 12, “Custom Application Configuration Management tool” on page 239.

Chapter 3. Customization overview 47

Page 66: My Tutorial

48 WebSphere Commerce Line-of-Business Tooling Customization

Page 67: My Tutorial

Chapter 4. Planning and designing customizations

In this chapter, we focus on how to plan and perform customizations to the just the Management Center, as opposed to customizing the entire WebSphere Commerce product. For details about how to plan and manage a WebSphere Commerce project, which encompasses many other assets, refer to the IBM Redbooks publication, Planning and Managing the Deployment of WebSphere Commerce, SG24-7588, which you can download at:

http://www.redbooks.ibm.com/abstracts/sg247588.html?Open

The publication goes through all of the phases that a typical WebSphere Commerce project is divided into and highlights the major milestones of each phase.

In this chapter, we discuss the project life cycle phases that include work items that are related to Management Center customization. We cover the activities you must perform in each phase and the artifacts that you need to create, extend, or modify.

4

© Copyright IBM Corp. 2008. All rights reserved. 49

Page 68: My Tutorial

4.1 Who should read this chapter

In this chapter, we provide information about steps and tasks to customize the IBM Management Center for WebSphere Commerce. The information in this chapter is useful for readers in the following roles:

� Project managers who seek general guidance in customizing Management Center and who need to understand the activities to be accomplished.

� Lead developers and IT architects who plan the solution and are responsible for effort estimation, work task scheduling, and resource deployment.

� Developers who implement the solution and change, extend, or create development artifacts.

� Deployment managers who package, transfer, and install the application on a target environment.

4.2 Knowledge prerequisites

If you are a project manager, you need at least a basic understanding of the Management Center’s capabilities and technical fundamentals. You can find this information in Chapter 1, “IBM Management Center for WebSphere Commerce” on page 3.

IT architects, lead developers, and developers need a substantial understanding of the Management Center framework and programming model, which we provide in Chapter 2, “Overview of the IBM Management Center for WebSphere Commerce environment” on page 15.

Lead developers and developers also need an understanding of:

� WebSphere Commerce Developer environment

� WebSphere Commerce Services, including the BOD (Business Object Document) command framework and DSL (Data Service Layer)

� OpenLaszlo programming model

� Java programming language

� JSP programming

� JavaScript programming language

� XML

50 WebSphere Commerce Line-of-Business Tooling Customization

Page 69: My Tutorial

4.3 Overview of this chapter

In 4.4, “Customization methodology” on page 51, we explain the customization methodology, which is divided into different phases. We also point out the phases that are task specific to the Management Center.

In the remaining sections in this chapter, we go through the different customization methodology phases, in detail, and describe the activities that you perform in each phase and the work items that are relevant to the Management Center.

We close the chapter with an overview of the interdependencies between different WebSphere Commerce sub-projects.

For practical examples, refer to Part 3, “Customization scenario examples” on page 87.

4.4 Customization methodology

In this section, we include information about the general customization approach that we use in this book.

Following the project life cycle pattern of most project delivery methods, the life cycle is divided into several phases. Figure 4-1 provides a basic project life cycle that also serves as a base for common understanding of how to handle projects.

Figure 4-1 Basic project life cycle

Release

DeploymentBuildCycle

MicroDesign

MacroDesign

SolutionOutline

SolutionStartup

SolutionClose

Chapter 4. Planning and designing customizations 51

Page 70: My Tutorial

The project life cycle consists of the following phases:

� Solution Startup

Based on high-level business requirements, you investigate possible solutions, for example, if your company, needs to increase sales, the solution could be to introduce a new sales channel that reaches new customers. The decision might then be an online shop.

This phase is not specific to Management Center customization; therefore we do not discuss it here.

� Solution Outline

Based on specific business requirements, you build a global solution design and choose technology and products. In this phase, you define the main building blocks on a coarse-grained level, such as software packages, hardware, and networks. On a system level, you clarify the context and discover the main interfaces and use cases. You also elaborate on cost estimation, schedule, and risk assessment.

An important outcome of this phase is your decision to use Management Center.

In 4.5, “Solution Outline phase” on page 53, we describe the steps and work items that are in the Solution Outline phase.

� Macro Design

The purpose of the Macro Design phase is for you to develop a robust-architectural framework on which to build agile releases.

In this phase, you begin Management Center customization work. You fulfill several planning and high-level design tasks. The IT architect and lead developer are involved and are supported by the project manager.

In 4.6, “Macro Design phase” on page 56, we describe the steps and work items that you perform in the Macro Design phase.

� Micro Design

In this phase, you prepare for the build cycle of a specific release by driving the architecture and design to a release-specific and implementation-platform view.

The lead developer ensures that the developers understand the design they are considering and that the design is feasible to implement. IT architect supports and supervises.

In 4.7, “Micro Design phase” on page 59, we describe the steps and work items that you perform in the Micro Design phase.

52 WebSphere Commerce Line-of-Business Tooling Customization

Page 71: My Tutorial

� Build Cycle

In this phase, developers develop and test the system incrementally until the objectives of the release are achieved.

In 4.8, “Build Cycle phase” on page 61 we discuss the steps and work items that you need to take care of during the build cycle.

� Deployment

In this phase, the deployment manager performs the last phase of the release cycle. After the system is deployed successfully, the project team prepares for the next release.

In 4.9, “Deployment phase” on page 63, we cover the steps and work items regarding customizing the Management Center in the deployment phase.

� Solution Close

The Solution Close phase covers the required close activities, which includes gathering metrics and harvesting reusable assets. The Solution Close phase brackets the end of the engagement.

The Solution Close phase is not specific to Management Center customization; therefore, we do not discuss it here.

For details about each phase, we suggest that you refer to the IBM Redbooks publication, Planning and Managing the Deployment of WebSphere Commerce, SG24-7588, which is available at:

http://www.redbooks.ibm.com/abstracts/sg247588.html?Open

4.5 Solution Outline phase

Perform the following activities to complete the Solution Outline phase.

4.5.1 Gathering requirements

In this section, we discuss the various ways you can document business requirements.

Note: You conduct Solution Outline and Macro Design one time. The three phases that make up a release are grouped together and are performed many times, one time for each release of the system.

Chapter 4. Planning and designing customizations 53

Page 72: My Tutorial

Functional and non-functional requirementsTo gather functional requirements, build the use case model. Complete the requirements document and record all of the functional and non-functional requirements that are in the document.

Document any special usability requirements, such as the usage of hot keys or the need for accessibility features.

Document any other non-functional requirements that are specific to line-of-business user tooling, for example, average response time, number of concurrent users, or role-based authorization.

User interface requirementsTo model user interface requirements, perform the following activities:

� Create UI conceptual model

Ensures that the user interface matches the users’ vision and, by presenting familiar concepts and relationships, is easy to learn, adapt to, and use with little or no training.

� Create UI design guidelines

Ensures the user interface design’s consistency and gives the user the advantage of not having to learn a new way of interacting with the system.

� Create UI prototype

Creating an UI prototype clarifies user requirements, technical requirements, and feasibility. Discuss the prototype with end users and refine it iteratively. You can even use it for training purposes without having the full system implemented.

Because IBM has already invested a lot of work in collecting and implementing the UI requirements of business users who manage e-Commerce businesses, your job becomes a lot simpler.

Create wireframes for the user interface requirements because wireframes help you visually model the requirements and make sure that they are consistent with the established UI design guidelines of the Management Center.

Thanks to the OpenLaszlo base, the Management Center user interface is implemented declaratively. You can quickly build a prototype and decide how much of the function is mocked up.

Server-side servicesInvocating WebSphere Commerce services and building XML response documents is replaced by static XML response documents. The Management

54 WebSphere Commerce Line-of-Business Tooling Customization

Page 73: My Tutorial

Center Web application is the Mediation layer where you can place static data in the JSP files that create the response.

Client-side functions and server-side servicesIf you only need a visual prototype, then you might omit any dynamic behavior that would require writing JavaScript code. The prototype displays the initial state of the user interface, but it does not reflect user input if the function is beyond the out-of-the-box capabilities of the elements that are used.

4.5.2 Defining the application model

The main activity in this section is to perform a fit-gap-analysis. With the list of requirements that you documented in 4.5.1, “Gathering requirements” on page 53, decide if each requirement is a:

� Complete fit

You can meet the requirement with out-of-the-box features.

� Partial fit

You can meet the requirement, but you must customize it, partially meet the requirement, or even both.

� Gap

You must build a feature from scratch to meet the requirement.

The partial fits and gaps translate into the tasks that you must perform and the level of customization that is required, which helps you plan your customization items. Use a component diagram or another suitable design document to outline the building blocks and to describe the building blocks’ rough structure, behavior, and interactions.

To do the fit-gap analysis for business requirements that are related to the Management Center, you can check the WebSphere Commerce documentation for:

� Existing tools

The existing Management Center tools and WebSphere Commerce Accelerator offer a number of functions and flows for line-of-business users. Some of your requirements can be a complete fit if they are met by one of the existing tools.

� Customization options

Using the existing tools as a base, there are lot of options to change the behavior of the provided function and to include new functions. You can

Chapter 4. Planning and designing customizations 55

Page 74: My Tutorial

customize an existing Management Center tool to meet a requirement that you decide is a partial fit or maybe a gap.

� New tools that you can create

The Management Center framework is exposed to allow developers to create a completely new tool. You can create a new tool to meet requirements that you decide are gaps.

For all items, determine their default behaviors, capabilities, and limitations. Examine all of the available information sources in the following resources:

� Chapter 1, “IBM Management Center for WebSphere Commerce” on page 3

� Chapter 2, “Overview of the IBM Management Center for WebSphere Commerce environment” on page 15

� Chapter 3, “Customization overview” on page 29

� The WebSphere Commerce Information Center, which is at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp

4.6 Macro Design phase

The purpose of the Macro Design phase is to develop a robust architectural framework upon which you can build agile releases. Subsequent “Release” phases (Micro Design, Build Cycle, and Deployment) help to develop and deliver the specific release. In the following sections, we describe some of the activities that you must perform in the Macro Design phase.

4.6.1 Refining the requirements

The refining requirements activity builds on the work that you performed in the Solution Outline phase. Go deeper and document the happy paths and exception flows for each case. Based on the fit-gap analysis that you completed in the previous phase, document the Management Center assets that you need to create or customize. Do you need to create any new objects, views, and widgets? Do you need to create any new user interface services? Do you need to define new WebSphere Commerce services? Include answers to all of these questions in the Macro Design document, at a high level.

Include the wireframes and define all of the navigational and error routes for them. Document where each element of the page picks up the content from: a properties file, database, file system, and so on. Also, include the validation rules, if any, for the user interface elements and the corresponding error messages that need to be displayed in case a validation fails.

56 WebSphere Commerce Line-of-Business Tooling Customization

Page 75: My Tutorial

4.6.2 Setting up the environments

We recommend that you set up the build, development, and other environments in the Macro Design phase so that they are ready to use when you need them in the subsequent phases.

Set up the WebSphere Commerce Developer at the required fix pack and feature pack level for Management Center. To learn about the installation of WebSphere Commerce feature packs, refer to Installing WebSphere Commerce Enhancements at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.admin.doc/tasks/tigfepmaster1.htm

To use the Management Center, enable the feature soon after you complete the installation. Refer to Enabling the Management Center for the steps:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/tasks/ttfenablecmc.htm

For more information about the development tools that you can use to develop Management Center assets, refer to 5.1, “Development tools” on page 68.

4.6.3 Defining the processes and guidelines

You define the procedures for build and deployment in this phase. For more information about deploying Management Center customizations, refer to 5.2, “Deploying the extensions” on page 70.

Use a Software Configuration Management (SCM) tool for change control and to support the build and deployment cycle. A widely used SCM tool is CVS, but you can use any tool that supports IBM Rational Application Developer V6.

Also, create a document that contains coding guidelines, naming conventions, and so on and distribute them to the entire team. Refer to the following topics in the WebSphere Commerce Information Center for more information:

� Management Center modeling guidelines

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctfguidelines.htm

� Management Center file directory structure

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctfdirectorystructure.htm

Chapter 4. Planning and designing customizations 57

Page 76: My Tutorial

� Management Center file and class naming conventions

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctffilenaming.htm

4.6.4 Defining the test specification

In this activity, perform the following steps:

1. Select testing techniques and tools.2. Define conditions to test.3. Develop test cases.4. Combine test cases to test sets.5. Write test scripts, if necessary.6. Create test data.7. Define test execution procedures.

Prepare to test the functionality and do some non-functional testing. Testing for non-functional requirements includes usability testing and performance testing.

Functional testingFor functional testing, there are three general stages to test:

� OpenLaszlo client application

As of today, most of the GUI test automation tools cannot test OpenLaszlo applications. OpenLaszlo does not expose its run time through an interface to external programs, such as a remote debugger or other remote agents; therefore, testing is only possible from inside the run time.

LzUnit provides a unit test framework for OpenLaszlo. Similar to JUnit, LzUnit allows you to test units of code, but it is focussed on testing Laszlo classes and methods. Both test code and tested code are running inside the OpenLaszlo runtime. Refer to OpenLaszlo documentation to learn about LzUnit:

http://www.openlaszlo.org

� Management Center Web application

The communication between the client and the Web application uses the HTTP Post method. The request object is a URL with name-value-pair parameters, and the response object is an XML document. You can use one of the numerous Web test frameworks that are available to simulate an OpenLaszlo client request.

58 WebSphere Commerce Line-of-Business Tooling Customization

Page 77: My Tutorial

� WebSphere Commerce Services

The new BOD command framework uses the client library as a gateway for unit tests. When you create new components, the Design Pattern Toolkit (DPTK) generates a test unit project that contains some basic unit tests. You can use these JUnit-based tests as a starting point for your own set of tests.

However, if your custom services are used only in the Management Center, you might find it adequate to test them only through the Management Center Web application.

Performance testingThe performance testing strategy for Management Center needs to be different from the performance testing strategy of a regular Web 1.0 application. You can not think of the response time in the traditional terms of time taken between a single request and response. In the case of Management Center, when you click on something, the request might initiate a bunch of calls in the background, which might return responses asynchronously. So although we have an identified starting point, its difficult to see all of the end points.

Management Center is a search-intensive application. You can tune the database to improve the performance of the search queries. For details, refer to:

Management Center search tables at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/refs/rpmmctables.htm

Improving performance of case-insensitive searches in the Management Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/refs/rtforacleperform.htm

4.7 Micro Design phase

The purpose of the Micro Design phase is to prepare for the build cycle of a specific release of the system. This phase completes the analysis for a specific

Note: OpenLaszlo has a profiler that measures the time spent in each function. However, at the time of writing this book, this profiler is unsupported and does not work reliably on different operating system (OS) platforms. For more information, refer to:

http://wiki.openlaszlo.org/CallProfiler

Chapter 4. Planning and designing customizations 59

Page 78: My Tutorial

release. The Solution Outline and Macro Design phases take a release-independent view, whereas Micro Design drills down and focuses on a specific release.

The Micro Design focuses on laying out a complete coding framework, which includes all of the Management Center-specific assets, such as user interface definitions, user interface services, and component services that you need to develop. Create an object model or a class diagram to illustrate the relationship between different classes.

Management Center user interfaceFor each class, the design should answer questions, such as:

� Which class does the class extend from?

� Which services does the class define?

� What are the classes’ attributes?

� Which classes can declare an instance of this class as their child, for example, an instance of wcfCreateService might only be declared as a child of an instance of wcfObjectDefinition.

For the user interface elements, your design should answer the following questions at a minimum:

� What kind of widget does it use, for example, rich text editor, check box, or a custom one?

� What is the validation rule that is associated with the element, for example, the value should be a string of 25 characters maximum?

� What is the formatting associated with the element, if any (for example, Date format)?

For more information about the assets that you typically create or modify as you customize the Management Center user interface, refer to 3.1.1, “Management Center user interface” on page 30.

Management Center Web applicationFor the Management Center services, the design should cover details about the following assets:

� Get controller and Serialization JSPs� Struts actions� Mapping between the Noun and Management Center object

60 WebSphere Commerce Line-of-Business Tooling Customization

Page 79: My Tutorial

For more information about the assets that you typically create or modify as you customize the Management Center Web application, refer to 3.1.2, “Management Center Web application” on page 43.

WebSphere Commerce servicesEach component service that you need to create your design for should include the following details at a minimum:

� Expected behavior of the service� Supported Xpaths and access profiles� Supported actions� Error conditions

Your design should also include the following details:

� The data model with all of the new tables that you need to define, complete with the column and constraint details

� The logical data model, for example, definition of the new Nouns you need to create

� Details of BOD commands

� Client library interfaces

� Business object mediators

For more information about the assets that you typically create or modify as you customize the WebSphere Commerce services, refer to 3.1.3, “WebSphere Commerce services” on page 46.

4.8 Build Cycle phase

In the Build Cycle phase, you perform the programming and other development activities. The Build Cycle uses an incremental approach to development. Within each Build Cycle, there can be multiple programming cycles, each identified with specific objectives. A Build Cycle might not result in a Production Deployment. Testing the developed system is an integral part of this phase.

After the last Build Cycle iteration, package a Release Candidate of the system and associated configuration for subsequent deployment.

4.8.1 Coding and unit testing

In this activity, your team builds and tests the source code and executables.

Chapter 4. Planning and designing customizations 61

Page 80: My Tutorial

You can run multiple programming cycles serially, in parallel, or in combination. Often, separate development teams focus on a sequence of related programming cycles. These individual development teams work in parallel and independently from each other.

For Management Center customization, we recommend that a two-to-three week effort involves a small team of one-to-four developers for a single programming cycle. Larger projects that need customization in all areas (OpenLaszlo client, Management Center Web application and WebSphere Commerce services) might require a longer development cycle.

A team can work on a complete scenario and make changes to all areas in a cycle, which we call vertical programming. This approach is followed in most of the projects. Alternately, a team works only on a specific area (for example, the user interface) but on multiple scenarios during a cycle taking benefit from highly skilled experts (for example, developers skilled at OpenLaszlo and the Management Center framework). This approach is called horizontal programming.

With Management Center customization, both approaches are feasible and it is up to you to decide which way to go. The Management Center architecture allows decoupled development through interface mock-ups, decoupled server and client components, and the support for unit testing.

4.8.2 Performing system testing

System level tests verify proper execution of the system release candidate, such as:

� The interface and interdependencies of the output of the multiple programming cycles

� The combined release candidate with other applications

Verify that the system is functionally correct and operationally sound. Perform transaction flow, stress and volume, and regression tests.

If you pursue the vertical programming approach, you now need to ensure that the customizations made for each scenario work together, without errors and side-effects.

Teams that use the horizontal programming approach must replace the mock up interfaces with their real implementations and perform testing.

62 WebSphere Commerce Line-of-Business Tooling Customization

Page 81: My Tutorial

4.8.3 Developing support materials

Make sure that you develop various support materials, such as:

� User’s Guide� Help Text� Tutorials

The Management Center shell offers a menu bar with a Help menu. All items link to the WebSphere Commerce Information Center that runs on the server where Management Center also runs. Because the WebSphere Commerce Information Center is built on the Eclipse Platform, you can easily extend the online help with your own content. WebSphere Commerce does not support creating, deploying, and integrating WebSphere Commerce Information Center updates, so you must build your own procedures.

Furthermore, Management Center has a hover help feature that displays short help text when you hover the mouse pointer over various UI elements. You can add hover help messages to new or customized UI elements.

4.9 Deployment phase

The purpose of the Deployment phase is to roll-out the system and prepare for the next release.

This phase represents the shift from the development project team to the client (or out sourced) organization to begin the processes that are needed to operate, support, and maintain the system.

Install the packaged release of the system, and its hardware, in the planned production locations, and then go live with the system.

4.9.1 Setting up the production environment

Install the hardware and software infrastructure and set up the production environment. Refer to 4.6.2, “Setting up the environments” on page 57 for instructions about installing and enabling Management Center.

To learn more about WebSphere Commerce deployment, refer to Planning and Managing the Deployment of WebSphere Commerce, SG24-7588, which is available at:

http://www.redbooks.ibm.com/abstracts/sg247588.html?Open

Chapter 4. Planning and designing customizations 63

Page 82: My Tutorial

4.9.2 Deploying the customizations

Review the information about deploying WebSphere Commerce resources to a server environment on the WebSphere Commerce Information Center.

Because all assets of the Management Center user interface are packaged within the Management Center Web application (a WAR module), deploying all changes occurs within the same procedure. Review Customized WebSphere Commerce Enterprise Application (EAR) assets at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/concepts/cdpcustom_ear.htm

Also, refer to 5.2, “Deploying the extensions” on page 70 for more information about deploying Management Center customizations.

Review the WebSphere Commerce deployment checklist at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.samples.doc/refs/sddeploymentchecklist.htm

4.10 Locating Management Center customization within a WebSphere Commerce project

Customizing the IBM Management Center for WebSphere Commerce is typically embedded into a larger IBM WebSphere Commerce project. Therefore, there are other areas of customizing WebSphere Commerce components that take place in parallel.

Manage interdependencies to avoid conflicts because of the concurrently running customization work. Many components that could be subject to customization in Management Center might also be subject to customization in other WebSphere Commerce components; however, with proper planning and design, and by following the best practices on WebSphere Commerce customization, you can minimize the interdependencies.

Figure 4-2 on page 65 gives you an overview of frequently occurring WebSphere Commerce sub-projects and their dependent customization touch points. On every possible interdependency area, you should check if planned customizations will have an impact on one or more of the sub-projects.

64 WebSphere Commerce Line-of-Business Tooling Customization

Page 83: My Tutorial

Figure 4-2 Matrix of typical WebSphere Commerce sub-projects and customization items

Review the following example:

� Storefront customization typically requires that you customize the database schema, EJB Persistence layer, controller and task commands, and the customer user interface.

� If storefront implementation uses data that is not being stored in the default WebSphere Commerce database schema, extend the schema.

� If line-of-business users might manage this data, you must extend one of the tools. In this case, you must customize either Management Center or Accelerator, depending on the special requirement and the tools’ capabilities. Let us assume that the choice is Management Center.

� Now you discovered that there might be an interdependency between your Management Center customization sub-project and your storefront customization sub-project, by way of database schema customization.

InboundServices/OutboundServices

Storefront

Accelerator

Sales Center

ManagementCenter

WebSphereCommerceServices

LoadingUtilities

ManagementCenter

UI

SalesCenter

UI

ToolsUI

CustomerUI

BODCommands

Controller/Task

Commands

SDOPersistenceLayer (DSL)

EJBPersistence

Layer

DatabaseSchema

CustomizationArea

Web

Sphe

reC

omm

erce

Cus

tom

izat

ion

Sub-

proj

ect

Possible interdependencywithin a customization area

Chapter 4. Planning and designing customizations 65

Page 84: My Tutorial

66 WebSphere Commerce Line-of-Business Tooling Customization

Page 85: My Tutorial

Chapter 5. Development tools and extension deployment

In this section, we describe development tools and assets for creating Management Center customizations.

In this section, we describe the process and steps that are involved in deploying the Management Center extensions from the WebSphere Commerce development environment to a WebSphere Commerce runtime server.

5

© Copyright IBM Corp. 2008. All rights reserved. 67

Page 86: My Tutorial

5.1 Development tools

In this section, we describe development tools and assets for creating Management Center customizations.

5.1.1 WebSphere Commerce Developer

WebSphere Commerce Developer is the development toolkit for customizing WebSphere Commerce applications. All Management Center assets are developed using WebSphere Commerce development toolkit. These assets include the following:

� OpenLaszlo source files� JSP files� Struts action classes� Resource bundles� HTML pages� Images� ManagementCenter.swf file

To access the Management Center resources in your development environment, switch to Project Explorer view, and expand Dynamic Web Projects → LOBTools, as shown in Figure 5-1.

Figure 5-1 Project Explorer window

68 WebSphere Commerce Line-of-Business Tooling Customization

Page 87: My Tutorial

5.1.2 Management Center assets

Table 5-1 describes the Management Center assets and directory structure.

Table 5-1 Management Center assets and directory structure

Note: In the following table, the <component> tag indicates a Management Center component, for example, catalog, marketing, promotion.

Directorya Files in this directory

WebContent/WEB-INF/src/lzx/commerce/<component>

<component>ManagementToolDefinition.lzxTool definition file contains:� Context value definitions� Help link definition � Instantiation for:

– Init service

– Primary business objects

– Search definitions

– Filter definitions

– Objects from other components that this tool uses

<component>ExtensionsLibrary.lzxAdd entries in this file to include any OpenLaszlo files created for customization.

WebContent/WEB-INF/src/lzx/ commerce/<component>/restricted

Some components might have the following sub-directories under this restricted directory:� listViewDefinitions� objectDefinitions� propertiesViews� searchDefinitions

Note: Do not customize files in restricted folders. They are replaced when you apply fix packs or migrate to a new release.

<component>FilterDefinitions.lzxFilter definitions for component.

<component>Library.lzxLibrary file with inclusions for all OpenLaszlo files that the component uses.

<component>ResourceBundle.lzxDefines the resource bundle class and property keys that the component uses.

<component>Resources.lzxDefines image resources that the component uses.

WebContent/WEB-INF/src/lzx /commerce/<component>/listViewDefinitions

Chapter 5. Development tools and extension deployment 69

Page 88: My Tutorial

5.2 Deploying the extensions

In this section, we describe the process and steps that are involved in deploying the Management Center extensions from the WebSphere Commerce development environment to a WebSphere Commerce runtime server.

Because WebSphere Commerce Developer contains a fully functional test environment, including a runtime server, the developer can complete the new extension work locally on the dedicated development machine, which includes unit testing activity. When that work is completed, the extension is deployed to the server environment. This server environment is often the test server and eventually the production environment.

Files under this directory contain list and grid classes that the component uses.

WebContent/WEB-INF/src/lzx /commerce/<component>/objectDefinitions

Files under this directory contain primary, organizational, child, reference and common object definitions that the component uses.

WebContent/WEB-INF/src/lzx /commerce/<component>/propertiesViews

Files under this directory contain property view definitions that are used to create and edit objects.

WebContent/WEB-INF/src/lzx /commerce/<component>/searchDefinitions

Files under this directory contain search definitions that the component uses.

src/com.ibm.commerce.<component>.client.lobtools.properties

Note: When files are built, resource bundles are copied under WebContent/WEB-INF/classes/ directory

This package contains resource bundles for all user interface text, labels, and messages for component.

WebContent/jsp/commerce/<component>

JSP files that the Management Center Web application uses to mediate requests that are made between the client and the WebSphere Commerce services.

a. All directory paths are relative to LOBTools directory.

Directorya Files in this directory

70 WebSphere Commerce Line-of-Business Tooling Customization

Page 89: My Tutorial

Regardless of your WebSphere Application Server topology, the deployment tools work in the same way. Therefore, if you are working with a clustered environment, the process to deploy your extensions is the same if you were not working in a clustered environment.

If your extension is only touching the Management Center, which is stored under the LOBTools project, you can deploy your changes as a single WAR module file update. If you also made some other changes, for instance, extended the object model or the Data Service layer, then you must deploy those as usual as a Partial Application update.

5.2.1 Exporting the extension code from the development environment

Extensions to Management Center are deployed as a WAR file. The first step is to export the LOBTools project as a single WAR file. Follow the instructions that are in the WebSphere Commerce Info center for packaging Management Center files for deployment:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/tdecreatewar.htm

5.2.2 Backing up the application

Before you deploy the extension and changes, it is a good idea to make a backup of the assets that will be changed. This is especially important before you try the first deployment. An incorrect deployment can create a whole subdirectory structure somewhere other than where you intended, and manually recovering from that can be tiresome. Later on, when you become more familiar with the deployment process and understand how it works, the back-up step can be optional.

If there are many files and you do not have a detailed listing of all of them, it might be the simplest and safest option just to back up the entire J2EE™ application. The process of backing up the entire J2EE application is documented at the WebSphere Commerce Info center in the “Rolling back your J2EE asset changes” section:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/refs/rdptbear_rollback.htm

Another possibility to consider is to implement an automated deployment process that will take care of creating backups.

Chapter 5. Development tools and extension deployment 71

Page 90: My Tutorial

5.2.3 Deploying the WAR module to the target WebSphere Commerce server

At this point, we have a new Management Center WAR module to deploy, and the current application is backed up for safety. We are ready to deploy the changes.

You can deploy with the Web browser using the WebSphere Administrative Console or using the scripting tools from the command line. Both options are well documented in the Info center. The command line wsadmin tool currently supports both JACL and Jython type scripting.

Visit the following Web site, and follow the steps for deploying a WAR module:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/tasks/tdpdeploying_war_assets_entire.htm

Note: When you specify the application update options, the relative path to your module file is simply LOBTools.war, as shown in Figure 5-2 on page 73. The directory is located directly below the instance EAR path, so you can usually find it under here:

WAS_profiledir/installedApps/WC_instance_name_cell/WC_instance_name.ear/

72 WebSphere Commerce Line-of-Business Tooling Customization

Page 91: My Tutorial

Figure 5-2 Deploying the LOBTools WAR as a single module

5.2.4 Testing the changes

If deployment was successful, you will have a new version of the ManagementCenter.swf file on your target server, under the LOBTools.war directory.

You can test your Management Center extension without restarting the server. The application was actually restarted as part of the deployment process. If there were any errors, you can see them in the server console. If the application

Chapter 5. Development tools and extension deployment 73

Page 92: My Tutorial

started successfully, log out of any previous Management Center client sessions that you might have running, and then close the related browser Logon window. You can refresh the Management Center launch page (the one with the URL line), by pressing F5, to start a new session. Log back in and you should be able to verify the changes.

5.3 Debugging

OpenLaszlo proThankvides a powerful debugger hat can detect runtime errors, display debug information at many different detail levels, and inspect objects.

In a default WebSphere Commerce Developer installation, the Debugger window, shown in Figure 5-3, is displayed when you launch the Management Center for the first time.

Figure 5-3 Laszlo Debugger

In Figure 5-3, the three small buttons at the top right corner are Clear, Minimize and Close. The top portion of the window is the debugger log and this is where the debug messages appear. Use Debug.write() statements in your code to print to the debugger log. The method is variadic, which means that it takes any number of arguments.

You can inspect class instances directly from the console:

1. Enter the class name and press Enter. The instance comes back in blue and it is an object that you can click.

2. You can inspect the structure by clicking the blue elements.

You enable the Debug mode from the Laszlo compile process settings. Right-click LOBTools, and click Properties → OpenLaszlo Settings, as shown in Figure 5-4 on page 75.

74 WebSphere Commerce Line-of-Business Tooling Customization

Page 93: My Tutorial

When you change the debug mode, the settings become effective only after you rebuild the LOBTools project because the settings that you define here are Laszlo compiler settings, and the compiler is invoked as part of the build process.

Figure 5-4 OpenLaszlo settings in WebSphere Commerce Developer

The client-side Logging and Tracing settings control the information that is displayed and the detail level of the information. You can specify these settings in the Management Center URL or dynamically from the Logging and Tracing menu after Management Center is running.

To see the menu, launch the Management Center with the logger.display=true parameter. All of the target options might not appear unless you initially specify logger.target=debugger in the URL.

Chapter 5. Development tools and extension deployment 75

Page 94: My Tutorial

When we developed the samples in this Redbooks publication, we typically launched the Management Center with a URL similar to the following example, which enables the Logging and Tracing menu, shown in Figure 5-5, and specifies the Debugger window as the target. We added the host name jserver.com as an alias to localhost in the local HOSTS file so that the Web browser does not bother you with the SSL certificate mismatch messages any longer.

https://jserver.com:8000/lobtools/cmc/ManagementCenter?logger.display=true&logger.target=debugger

There is also a developmentMode=true setting, which causes XML and properties files to be reloaded if their timestamps change, which saves the time to restart the server. We found this of relatively little value because you still need to rebuild the LOBTools project and start a new browser session, and usually there were not that many changes to the properties files anyway.

See the Information Center for setting the Logging and Tracing details:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/tasks/ttflogtrace.htm

Figure 5-5 Logging and Tracing settings

76 WebSphere Commerce Line-of-Business Tooling Customization

Page 95: My Tutorial

Another nice bonus that comes from launching the Management Center with the Tracing and Logging parameters is that now the browser window shows the fully qualified server host name in the browser window title, as shown in Figure 5-6, which is helpful when you work with multiple WebSphere Commerce servers (test, development, and so on.) simultaneously.

Figure 5-6 Browser window title

5.3.1 Tracing your own components

You can also trace your own components, and it is pretty simple to do:

1. Give your component a descriptive name. We used com.Redbooks.components.

2. In your methods, call the wcfLogger class when entering and exiting the method, as shown in Example 5-1:

Example 5-1 Calling the wcfLogger class

<method name="updateText" args="txt"><![CDATA[

if (wcfLogger.enabled) {wcfLogger.entering("com.redbooks.components",

"extPropertyRTEwithSpellCheck", "updateText", [txt]);wcfLogger.log("com.redbooks.components", "INFO",

"extPropertyRTEwithSpellCheck", "updateText","updating text editor " + txt);

}

< your code >

if (wcfLogger.enabled) {wcfLogger.exiting("com.redbooks.components",

"extPropertyRTEwithSpellCheck", "updateText");

Note the wcfLogger.log call, which you can use to print additional details on any object or property values.

Chapter 5. Development tools and extension deployment 77

Page 96: My Tutorial

To see your trace:

1. Launch Management Center with the matching additional parameter: &logger.components=com.redbooks.components, as shown in Figure 5-7.

2. Set the detail levels as you want. You can set the default from the URL line, but unfortunately not for each component individually.

Figure 5-7 Tracing your own client-side OpenLaszlo components

5.4 Debugging server communication with the TCP/IP Monitor

The TCP/IP Monitor is a simple server that monitors all of the requests and responses between a Web browser and server, which is useful when you check that the WebSphere Commerce server BOD requests are well formed and processed correctly on the server side.

In connection with this, you can use JUnit to simulate those requests and to ensure that the data coming back is what you expected.

78 WebSphere Commerce Line-of-Business Tooling Customization

Page 97: My Tutorial

5.4.1 Creating the TCP/IP monitor

You can use the TCP/IP monitor to observe the request and response documents that are going to and from an existing WebSphere Commerce service or from a new one that you created. To create a TCP/IP Monitor to forward requests to WebSphere Commerce:

1. Select Window → Preferences → Internet → TCP/IP Monitor.

2. Click Add.

3. Type the following information:

– Local monitoring port: 81– Hostname: localhost– Port: 80

4. Click OK.

5. Select the created TCP/IP monitor, and click Start.

6. Click OK.

5.5 Hints and tips

In this section, we provide a collection of hints and tips that we found useful when working with Management Center extensions:

� Turn automatic build off� Use a version control system� Increase the Management Center inactivity time out� Customize your Workbench Perspective� Use the XML Editor for OpenLaszlo files� Disable the tools that you are not using

5.5.1 Turning automatic build off

The RAD build process executes the OpenLaszlo compiler at the end, which can take a lot of CPU cycles from your machine, if it is running continuously. Turn off automatic build, and build the LOBTools project manually. Use either the right-click Build Project option or the Ctrl + B keyboard shortcut. Many times when syntax errors occur, the LOBTools project requires a cleanup. In this case, select the LOBTools project, and click Project → Clean... → Clean selected project → LOBTools. Make sure that you select the Start a build immediately option.

Chapter 5. Development tools and extension deployment 79

Page 98: My Tutorial

5.5.2 Using a version control system

Use a supported version control system, such as Rational® ClearCase® or CVS, for keeping track of the changes. You update files in the single LOBTools project. In addition, when the next fix pack comes, it is useful to see what was changed.

We set up CVSNT version 2.5.03 for this small Redbooks publication projects team. Although there were occasionally some small hiccups that were related to file time stamps, in general this worked very well for us. CVSNT is open source and available for download from:

http://www.cvsnt.org

In a team environment such as ours, where many people are touching the same files, it is essential to have a fully-functional version control system in place.

80 WebSphere Commerce Line-of-Business Tooling Customization

Page 99: My Tutorial

There are a few things to note regarding CVS and OpenLaszlo. Make sure that you specify that the .lzx, .olsettings and .tpl file extensions refer to ASCII type files. The CVS default is binary. Although the binary default might still work, using ASCII makes better sense with these files:

1. Enable CVS support in WebSphere Commerce Developer. Click Window → Preferences → Workbench → Capabilities.

2. Expand the Team capability, select Core Team Support and CVS Support, and click OK.

3. Click Window → Preferences again. The Team menu should now appear in the navigation bar.

4. Click Team → CVS → File Content. Add lzx, olsettings, and tpl as the new ASCII type file extensions, and click OK.

We used the compatibility settings in Figure 5-8 on the CVS Server panel.

Figure 5-8 Compatibility settings window

After you install the software, all of the developers will already have the LOBTools project in their workspace. Importing this as a new project or replacing it completely is not a good idea with this type of pre-loaded project. What seemed to work well though was running Share Project after installation from every workstation, and then synchronizing changes when needed using the Synchronize with Repository option. The Team Synchronizing perspective can show both the incoming and outgoing changes clearly, as shown in Figure 5-9 on page 82. The developer always has control over what changes are brought in from the repository, and what changes are committed back to the repository. You can check the changes one-by-one. Alternately, you can copy all changes in using one click.

Chapter 5. Development tools and extension deployment 81

Page 100: My Tutorial

Figure 5-9 Bringing in the latest changes from the team repository

The only minor issue we encountered was that the Synchronize view also listed some files that were identical in content and only had a different time stamp. We went through all of these files with the Compare Editor to ensure that there were no other differences.

5.5.3 Increasing the Management Center inactivity time-out

By default, the Management Center session times out in 15 minutes, which is not necessary when you are working with the development environment. To adjust the time-out:

1. Open your instance configuration file:

drive:\<WCToolkitEE60\xml\config\wc-server.xml

2. Search for text ExpiryManagement.

3. Update the time-out value. The value is given in minutes, so you set it to 10 hours:

<ExpiryManagement ExpiryMgmtChannelId="-2,-4"InactivityTimeout="600" Threshold="15" enable="true"/>

4. Restart the server.

82 WebSphere Commerce Line-of-Business Tooling Customization

Page 101: My Tutorial

5.5.4 Customizing your Workbench perspective

Most of the typical Management Center development work occurs inside of the Java perspective; however, by default you still need to switch over to the J2EE perspective to access the WebSphere Commerce test server. A simple improvement is to add Servers view to your Java perspective because then all of the most used functions and features are handy, and you can avoid switching perspectives. Customizing your Workbench perspective also saves some memory. To add the Servers view to the Java perspective, click Window → Show View → Server → Servers. You can further customize through the Window → Customize Perspective menu.

5.5.5 Using the XML editor for OpenLaszlo files

The XML editor can color code your OpenLaszlo files, which makes it easier to spot closure mistakes in object definitions, quotations, and so on. To enable this feature, set up the XML editor as the default for OpenLaszlo files:

1. Click Window → Preferences → Workbench → File Associations, and click Add...

2. Enter *.lzx as the file type, and click OK.

3. Under the Associated Editors tab, click Add, and select the first XML Source Page Editor. Click OK twice.

5.5.6 Disabling the tools that you are using

This is a performance tip. If you work solely on one Management Center tool, making many changes and re-building, you can speed up the development cycle by temporarily disabling the other tools that you are not using, which makes the compiled ManagementCenter.swf smaller and quicker to load. To disable the tools that you are not using:

1. Navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell → restricted.

2. Open file ShellLibrary.lzx.

Note: A quicker way to open the ShellLibrary.lzx file is to:

1. Simultaneously press the Shift + Ctrl + R (for Open Resource) keys.

2. Type the filename, for example, Shell..., pick the file from the matching resources, and click OK.

Chapter 5. Development tools and extension deployment 83

Page 102: My Tutorial

3. At the end of the file, comment out the tools that you are not presently using. Figure 5-10 is an example of running with the Catalog tool only.

Figure 5-10 Commenting out tools that are not being extended

4. Rebuild the project.

Remember to uncomment this when you are done.

5.6 Problem determination

In this section, we provide some things for you to check for when your customization is not working as expected or is throwing an error.

5.6.1 What to do if your changes are not appearing?

Here are some common things to check if you are not seeing the changes you expected.

� Make sure you saved your changes, rebuilt the LOBTools project, and did not get any OpenLaszlo compilation errors. These errors appear in the Package Explorer navigation tree only after compilation.

� Make sure you restart the Web browser. Browser restart requires that you click Log Out, and close the Logon window (the one without the URL line).

84 WebSphere Commerce Line-of-Business Tooling Customization

Page 103: My Tutorial

Refresh (click the F5 key) the Management Center launch Web page, which is

https://jserver:8000/lobtools/cmc/ManagementCenter

You will have a new Management Center session going on right there.

� If you made changes to the Struts configuration or to the properties files, you must restart the server.

5.6.2 What to do if the server fails to start successfully

If the server fails to start successfully:

1. Check the server console and see what the error message is.

2. Check the Info Center for explanations and suggested corrective action.

3. Sometimes cleaning the LOBTools project helps to fix errors.

a. Select Project → Clean → Clean selected projects → LOBTools. b. Ensure that the immediate build option is selected.

4. Republish the project. By default the files in your project files are automatically copied to the target server directories, which is driven by the Smart publish setting that is enabled by default. See Window → Preferences → Server → Publish Method. You can verify that it is working by checking the State column in the Servers view, which should say Synchronized. However, sometimes the assets can get out of sync, and a manual Publish is required.

If the server is still failing to start successfully, try cleaning up the server configuration by removing the WC project from the server configuration, and then adding it back again:

1. In the Servers view, right-click your server, and click Add and remove projects.

2. Click WC and Remove.

3. Restart your server. Make sure there are no errors coming up in the server console.

4. Go back to Add and Remove Projects, and add the WC project back in again.

5. Check the server console.

Chapter 5. Development tools and extension deployment 85

Page 104: My Tutorial

86 WebSphere Commerce Line-of-Business Tooling Customization

Page 105: My Tutorial

Part 3 Customization scenario examples

In part 3, we present examples of the customization scenarios that we developed and tested in our labs and made available for you to use.

Part 3

© Copyright IBM Corp. 2008. All rights reserved. 87

Page 106: My Tutorial

88 WebSphere Commerce Line-of-Business Tooling Customization

Page 107: My Tutorial

Chapter 6. Enabling the merchandising associations’ Semantic Attribute

Merchandising associations allow the merchant to suggest additional products based on a selected catalog entry. The merchandising associations are used as a product recommendation strategy to increase store sales.

By default, WebSphere Commerce includes four merchandising association semantics: comes_with, none, requires, or temp. However, you might want to define additional semantics that map more directly to your catalog, such as:

� Compatible power adapters or cables for an electronic device� Compatible headsets for a mobile phone� Compatible tires and brake pads for a car

Among other things, the semantic attribute can be very useful in letting us define what type of accessory we are dealing with, which we can use on the storefront to group the compatible accessories together under meaningful accessory headings accordingly.

6

© Copyright IBM Corp. 2008. All rights reserved. 89

Page 108: My Tutorial

To learn more about merchandising associations and the semantic specifiers, see the Info Center documentation:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.user.doc/concepts/cpnmamass.htm

In this scenario, you enable the semantic specifier, and then define two compatible accessories for a master cylinder in the AdvancedB2BDirect catalog. Ideally the brake pads and tires would be mapped to a car, but this sample catalog does not come with such products, so we simply used the already existing racing master cylinder. The same idea still applies, and this works just as well for our illustration purposes. The result will appear similar to Figure 6-1.

Figure 6-1 Enabling the semantic attribute for merchandising associations

90 WebSphere Commerce Line-of-Business Tooling Customization

Page 109: My Tutorial

6.1 Understanding the extension requirement

The background is that our customer has a wide range of product specific accessories to offer. They want a richer capability for specifying the accessory, and they want to use the information that is on the product page by filtering and categorizing the matching accessories more meaningfully.

Studying the WebSphere Commerce Information Center, it turns out that the core capability for this extension is already included in the product in the form of the semantic specifier, and the required work is primarily about enabling it in the Management Center. We need a way to define the additional semantic detail of the association between two catalog entries. In particular, we would like to extend the accessory relationship, and be able to state what kind of accessory it is.

Another design option is to store the accessory type in the target catalog entry as a descriptive attribute. However, there is an additional benefit that we gain from specifying this at the association level, which is that it implicitly indicates that the accessory meets the compatibility requirement for that particular combination, which makes the selected option more desirable.

The implementation steps are:

1. Check if the data element is already available in the client model.2. Extend the Catalog tool with the semantic column.3. Add support for input validation.4. Populate the MASSOC table with additional semantic entries.5. Include the semantic specifier to the JSP response.6. Test the extension.

The MASSOC table that holds the semantic specifiers is documented in the Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.database.doc/database/massoc.htm

6.2 Checking if the semantic specifier element was provided

Logging in to the Management Center, we can see that the semantic information is not available in the Catalog tool. An obvious place is to add it as a column

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 91

Page 110: My Tutorial

under the Merchandising Associations tab, which is located next to the Association column.

We know that the WebSphere Commerce schema already includes the semantic attribute, and the semantic attribute specifiers are persisted in the MASSOC table. The next task is to determine if the semantic specifier is already provided in the object model:

1. Open WebSphere Commerce Developer, and navigate to LOBTools → WebContent → WEB-INF → config → com.ibm.commerce.catalog.

2. Open the wc-catalog-client-objects.xml file, and search for “semantic”. We can see that the merchandising association definition already contains a parameter named ‘semantic’:

<_config:URLParameter name="semantic"nounElement="/Association/@semantic" />

This is what we will refer to from the merchandising association grid.

6.3 Defining an extended resource bundle and properties file

Additional text definitions are required for the Semantic column to store the column heading and the possible semantic values. An extended properties file is the best place for holding this text, and makes migration tasks easier later on. To define an extended resource bundle and properties file:

1. In the Package Explorer, navigate to LOBTools → src.

2. Right-click src, and select New → Package.

3. In the Name field, enter com.redbooks.commerce.client.lobtools.propertiesas the package name, and click Finish. The new package is created.

92 WebSphere Commerce Line-of-Business Tooling Customization

Page 111: My Tutorial

Right-click the com.redbooks.commerce.client.lobtools.properties package, and click New → Other → Simple → File.

4. In the File name field, enter CatalogLOB.properties. Use this general file name without the locale specification when there is no match for a locale-specific version. In your project, you might need to provide language-specific texts, and then add the locale to the properties filename like this: <basename>_<locale>.properties. Explore the other existing packages, and note the use of the en_US locale in there as an example.

5. Click Finish. The CatalogLOB.properties file opens.

6. Define the following properties:

merchandisingAssociationSemantic_ColumnHeader=SemanticmerchandisingAssociationSemantic_REQUIRES=REQUIRESmerchandisingAssociationSemantic_COMES_WITH=COMES_WITHmerchandisingAssociationSemantic_TEMP=TEMPmerchandisingAssociationSemantic_NONE=NONEmerchandisingAssociationSemantic_BRAKE_PAD=BRAKE_PADmerchandisingAssociationSemantic_TIRE=TIRE

merchandisingAssociationSemanticValidationWarning=This semantic applies to ACCESSORY type merchandising associations only.

The last two semantic entries are the additional semantics for the AdvancedB2BDirect store catalog with the intent of identifying compatible brake pads and tires as an accessory. Although in this implementation all of your semantics need to be listed in the properties file, the mechanism is quite flexible, and you can use it for many different kinds of merchandising relationships that can be imagined between the source and target catalog entry.

Note: You decide the naming structure here depending on your needs. For larger multi-language extensions, you could define tool specific packages following the same naming convention that is used within WebSphere Commerce Developer itself, for example, the com.ibm.commerce.catalog.client.lobtools.properties package holds all properties files for the Catalog tool, and you could set up a similar structure for your larger extension projects too.

For the relatively small set of extensions in this book, we decided to use a single package and hold all properties under there.

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 93

Page 112: My Tutorial

Another more advanced approach is to pull this information directly from the MASSOC table:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.database.doc/database/massoc.htm

6.3.1 Registering the new properties in the resource bundle

You must tag and register the new properties in a resource bundle file. It is a good practice to organize and store our own Laszlo extension file assets under a separate folder structure. We will create a new sub-folder for this purpose:

/LOBTools/WebContent/WEB-INF/src/lzx/redbooks/catalog

This same folder is a good starting point for any other new Laszlo files that you might create for the Catalog tool later on. To tag and register the new properties in a resource bundle file:

1. In the Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx.

1. Right-click lzx, and select New → Folder.

2. In the File name field, enter redbooks, and click Finish.

3. Create the catalog sub-folder underneath in the same way.

4. Right-click catalog, select New → Other → Simple → File, and click Next.

5. In the File name field, enter extCatalogManagementResourceBundle.lzx.

6. Click Finish. The extCatalogManagementResourceBundle.lzx file opens.

7. Add the code in Example 6-1 to the file.

Example 6-1 Registering the custom properties in the resource bundle

<library><class name="extCatalogResourceBundle"

extends="wcfResourceBundle"baseName="com.redbooks.commerce.client.lobtools.

properties.CatalogLOB">

<!-- Merchandising Association Semantic properties --><wcfResourceBundleKey

name="merchandisingAssociationSemantic_ColumnHeader" /><wcfResourceBundleKey

name="merchandisingAssociationSemantic_REQUIRES" /><wcfResourceBundleKey

name="merchandisingAssociationSemantic_COMES_WITH" />

94 WebSphere Commerce Line-of-Business Tooling Customization

Page 113: My Tutorial

<wcfResourceBundleKeyname="merchandisingAssociationSemantic_TEMP" />

<wcfResourceBundleKeyname="merchandisingAssociationSemantic_NONE" />

<wcfResourceBundleKeyname="merchandisingAssociationSemantic_BRAKE_PAD" />

<wcfResourceBundleKeyname="merchandisingAssociationSemantic_TIRE" />

<!-- Merchandising Association Semantic Validator Warning --><wcfResourceBundleKey

name="merchandisingAssociationSemanticValidationWarning"/></class><extCatalogResourceBundle id="extCatalogResources"/>

</library>

8. Save and close the file.

6.4 Adding the extensions to the tool extension library

The Management Center contains an extension library class for the purpose of including your new class files. There is a separate library file for each of the Management Center tools. You must include any new class files that you created in this file.

For the Catalog tool, this library file is CatalogExtensionsLibrary.lzx, and we need to add our new resource bundle class definition in there:

1. In the Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog.

2. Open the CatalogExtensionsLibrary.lzx file.

3. Update the file to point to the new resource bundle file:

<library><!-- File to add customer libraries --><!-- Catalog resource bundle extension -->

Tip: When you know the file name, a quicker way to open the CatalogExtensionsLibrary.lzx file is to simultaneously press the Shift + Ctrl + R keys (for Open Resource). Start typing the name, for example, catalogext, and then pick the file from the Matching Resources listing.

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 95

Page 114: My Tutorial

<includehref="../../redbooks/catalog/extCatalogManagementResourceBundle.lzx" />

<!-- Merchandising Semantic Validator --><include

href="../../redbooks/catalog/objectDefinitions/MerchandisingSemanticValidator.lzx" />

</library>

4. Click Save.

For more details about working with the library class files, see this Information Center page:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfaddlibrary.htm

6.5 Adding the Semantic property to the Merchandising Association class

We already set the ground work of setting the properties, and we can now focus on extending the object and view definitions that are responsible for handling merchandising associations. This part of the Catalog tool is open for direct customization, and we can edit the provided Laszlo class files directly.

1. In the Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog → listViewDefinitions.

2. Open the MerchandisingAssociationGrid.lzx file.

3. The semantic column will be placed between the name and quantity columns. Search for quantity, and locate the property definitions for the catMerchandisingAssociationGrid class, starting like this:

<class name="catMerchandisingAssociationGrid"extends="wcfObjectGrid">...

Note: We also included another extension file here, MerchandisingSemanticValidator.lzx, which will be our validation class for checking correct user input. We discuss this further in the next section.

96 WebSphere Commerce Line-of-Business Tooling Customization

Page 115: My Tutorial

4. Add the following definition between the name and quantity definitions:

<wcfGridComboBox propertyName="semantic" required="false" editable="true" text="${extCatalogResources.merchandisingAssociationSemantic_ColumnHeader.string}" width="120"/>

5. Save and close the file.

6. Add the property definition to the catMerchandisingAssociation class. In Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog → objectDefinitions.

7. Open the CatalogCommonObjectDefinitions.lzx file.

8. Locate the catMerchandisingAssociation class, and add the code in Example 6-2 to it before the quantity definition.

Example 6-2 Adding the semantic specifier property to the object class definition

<class name="catMerchandisingAssociation" ...<!-- This property definition represents the options for the semantic specifier available between two catalog entries. --><wcfPropertyDefinition

propertyName="semantic" required="false"displayName="${extCatalogResources.

merchandisingAssociationSemantic_ColumnHeader.string}"><wcfPropertyValue

displayName="${extCatalogResources.merchandisingAssociationSemantic_REQUIRES.string}"value="REQUIRES"/>

<wcfPropertyValuedisplayName="${extCatalogResources.

merchandisingAssociationSemantic_COMES_WITH.string}"value="COMES_WITH"/>

<wcfPropertyValuedisplayName="${extCatalogResources.

merchandisingAssociationSemantic_TEMP.string}"value="TEMP"/>

<wcfPropertyValuedisplayName="${extCatalogResources.

merchandisingAssociationSemantic_NONE.string}"value="NONE"/>

<wcfPropertyValuedisplayName="${extCatalogResources.

merchandisingAssociationSemantic_BRAKE_PAD.string}"value="BRAKE_PAD"/>

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 97

Page 116: My Tutorial

displayName="${extCatalogResources.merchandisingAssociationSemantic_TIRE.string}"value="TIRE"/>

</wcfPropertyDefinition>

9. A few lines below this, add a default value for the Display Sequence, which corrects a tiny defect in the FEP 3.0.1 code:

<!-- By default, quantity is set to 1, and sequence is set to 0 --><dataset name="template">

<quantity>1</quantity><sequence>0</sequence>

</dataset>

10.While you edit the Merchandising Association class, you can also include a reference to our future validator class here. Right before the class definition closure, include the following line (in bold):

<extMerchandisingSemanticValidatorerrorMessage="${extCatalogResources.merchandisingAssociationSemanticValidationWarning.string}" />

</class>

11.Save and close the file.

12.Build your project. This action invokes the Laszlo compiler and eventually generates a new copy of the ManagementCenter.swf file for you.

6.6 Implementing a Validator

To enhance our customization, we want to state that our additional semantics are only meaningful for the accessory type associations. Using an input validator, we can improve the quality of the catalog data. A Validator can check the user selections and provide the appropriate feedback.

In this case, you are adding a validator that ensures that the BRAKE_PAD and TIRE semantics can only be defined for the accessory type merchandising associations.

98 WebSphere Commerce Line-of-Business Tooling Customization

Page 117: My Tutorial

To create the following new sub-folder, and put our custom Validator class in the new sub-folder:

/LOBTools/WebContent/WEB-INF/src/lzx/redbooks/catalog/objectDefinitions

1. In the Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → redbooks → catalog.

2. Create a new sub-folder, and name it objectDefinitions.

3. Right-click objectDefinitions, select New → Other → Simple → File, and click Next.

4. In the File name field, enter MerchandisingSemanticValidator.lzx.

5. Click Finish. The MerchandisingSemanticValidator.lzx file opens.

6. Enter the code in Example 6-3 or, import the code from the provided solution package.

Example 6-3 Validator for checking the semantic assignment

<library><class name="extMerchandisingSemanticValidator"

extends="wcfValidator"><attribute name="errorMessage" value=""

type="string"/><method name="validate" args="o"><![CDATA[

if(this.validateMerchandisingSemantic(o)){o.clearValidationError(this);

}else{o.addValidationError(this, this.errorMessage);

}]]>

</method>

<method name="validateMerchandisingSemantic"args="o"><![CDATA[var semantic = o.getProperty("semantic").value;var name = o.getProperty("name").value;var accessory = catalogResources

["merchandisingAssociationName_ACCESSORY"].string;var brake_pad = extCatalogResources

["merchandisingAssociationSemantic_BRAKE_PAD"].string;var tire = extCatalogResources

["merchandisingAssociationSemantic_TIRE"].string

if (semantic == brake_pad && name != accessory)return false;

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 99

Page 118: My Tutorial

else if (semantic == tire && name != accessory)return false;

elsereturn true;

]]></method>

</class></library>

7. Click Save.

The logic is that if the Brake Pad or Tire semantic are selected, but the selected association type is not accessory, the validation method returns false,and we return the errorMessage. In all other cases the validation returns true.

6.7 Including the semantic specifier in the JSP

One more necessary step is to include the semantic field in the JSP that retrieves the actual data for the Merchandising Association tab. The Management Center JSPs are provided in the restricted folder. You must create your own copy of any files that you need to change in there, and then update the Struts configuration to point to the extended versions. To include the semantic specifier in the JSP:

1. In the Package Explorer, navigate to LOBTools/WebContent/jsp/commerce/catalog/restricted/serialize

2. Open the GetMerchandisingAssociations.jsp file. Note that the semantic specifier is not included.

3. Create a suitable sub-folder structure for your copy, as follows:LOBTools/WebContent/jsp/redbooks/catalog

4. Copy the GetMerchandisingAssociations.jsp file into the new folder.

5. Navigate to LOBTools/WebContent/jsp/redbooks/catalog/.

6. Open the file GetMerchandisingAssociations.jsp, and locate the generic object definition in the middle of the file that starts like this:

<object objectType="${objectType}">...

7. Insert a line for the semantic specifier (in bold), so that the block now reads as follows:

<object objectType="${objectType}"><associationId>${association1.uniqueID}</associationId>

100 WebSphere Commerce Line-of-Business Tooling Customization

Page 119: My Tutorial

<assocId>${association1.uniqueID}</assocId><name><![CDATA[${association1.name}]]></name><originalName><![CDATA[${association1.name}]]></originalName><semantic><![CDATA[${association1.semantic}]]></semantic>

...

8. Save the file.

The next step is to update the Struts configuration so that the new version will be used.

9. In the Package Explorer, navigate to LOBTools/WebContent/WEB-INF/.

10.Open the struts-extension.xmlfile.

There are actually four different action definitions for retrieving the association data for product, SKU, dynamic kit, and bundle respectively. You can forward them all to the same generic JSP. Insert the definitions as follows:

<!-- Action Mappings --><action-mappings>

<action path="/GetProductChildren-MerchandisingAssociations"forward="/jsp/redbooks/catalog/GetMerchandisingAssociations.jsp" />

<action path="/GetSKUChildren-MerchandisingAssociation"forward="/jsp/redbooks/catalog/GetMerchandisingAssociations.jsp" />

<action path="/GetKitChildren-MerchandisingAssociations"forward="/jsp/redbooks/catalog/GetMerchandisingAssociations.jsp" />

<action path="/GetBundleChildren-MerchandisingAssociation"forward="/jsp/redbooks/catalog/GetMerchandisingAssociations.jsp" />

</action-mappings>

11.Save the file.

6.8 Populating database tables with custom semantics

In this section, you insert the new semantics into the commerce database.

Semantics are stored in the MASSOC table, and each additional semantic requires a new row in this table. Because we used Cloudscape® as our development database, we used the handy database access URL for performing this simple update.

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 101

Page 120: My Tutorial

To insert the new semantics into the commerce database:

1. Open the database access URL:

https://localhost:8002/webapp/wcs/admin/servlet/db.jsp

2. List the currently defined semantics by entering the following SQL:

SELECT * FROM MASSOC;

You should see the four predefined semantics listed in this table.

For the two new semantics, enter the following two SQL statements:

INSERT INTO MASSOC VALUES (‘BRAKE_PAD’, ‘Brake pad semantic’,NULL, NULL);

INSERT INTO MASSOC VALUES (‘TIRE’, ‘Tire semantic’, NULL, NULL);

3. Click Submit Query.

While you access the database, you might also want to explore the contents of the two other tables that deal with merchandising associations. They are MASSOCTYPE and MASSOCCECE. The MASSOCCECE table holds the actual associations for each source and target catalog entry pair.

6.9 Testing the extension

To test our changes in Management Center:

1. Start the WebSphere Commerce server.

2. Open the Management Center, and open the AdvancedB2BDirect store.

3. Navigate to the racing master cylinder. In the Search field, enter A0000462, and click the Find button.

4. Open the Merchandising Associations tab.

5. Add two new accessories for this product. Some good candidates for racing purposes are product codes A0000327 and A0000597. Enter these product codes in the available entry field, and click Find and Add, as shown in Figure 6-2 on page 103. Alternately, you can use the Utilities View (click Next button), and from there you can drag-and-drop some other products to the target area as well.

102 WebSphere Commerce Line-of-Business Tooling Customization

Page 121: My Tutorial

Figure 6-2 Defining the accessories with the semantic specifier

6. Set the association type to ACCESSORY for both, and set the semantic to BRAKE_PAD and TIRE, accordingly. Increase the quantity to four.

7. Click Save. There should be no error messages. Click Reload. The same information should still appear. This is a good test to see that your JSP is rendering correctly.

8. Try assigning the BRAKE_PAD or TIRE semantic for some other association type, such as XSELL or UPSELL. Error messages should appear.

Using the database access URL, you might also want to verify that the new associations were stored in the MASSOCCECE table.

9. Login to the AdvancedB2BDirect storefront, and navigate to the Racing Master Cylinder.

10.Verify that the accessory recommendation is made on the product page, as shown in Figure 6-3 on page 104.

Note: You can see that the RANK column is not populated and receives a NULL value. A further extension task is to add a new entry field for this in the Management Center UI, right after the semantic specifier. We will leave this to you as an extra challenge to try out, following the same ideas that we presented in this chapter.

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 103

Page 122: My Tutorial

Figure 6-3 Displaying an accessory recommendation

Having defined the semantics, the next customizing task for this storefront is to create meaningful groups for the various recommendations. On the product page, you could now list the compatible brake pads under a Brake Pads heading, tires under Tires, and so on. This is a JSP customizing task that is outside of the scope of this chapter.

Another more sophisticated version could use data services and retrieve the possible values from the MASSOC table. You can use the same approach for the association types too, based on the MASSOCTYPE table, which would require more work, but it could be a better option if there are many different types that continuously change.

104 WebSphere Commerce Line-of-Business Tooling Customization

Page 123: My Tutorial

For further study, see the MASSOC and MASSOCTYPE table definitions here:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.database.doc/database/massoc.htm

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.database.doc/database/massoctype.htm

This extension touched some of the basic extension points of modifying a view definition, providing additional properties, writing a validator class, and following best practices for extending the JSP files.

Chapter 6. Enabling the merchandising associations’ Semantic Attribute 105

Page 124: My Tutorial

106 WebSphere Commerce Line-of-Business Tooling Customization

Page 125: My Tutorial

Chapter 7. Adding a new service action

In this scenario, we cover the steps for adding a new object-specific service action to the Management Center UI. You can then invoke the action from the context menu, from the menus, or with a keyboard shortcut.

In the scenario, we show you how to add Make buyable and Make not buyable actions to the Product list view. The action is conditional, based on the current state. We only suggest the Make buyable option for a product that you cannot presently buy.

The product list view is additionally customized by column filtering.

7

© Copyright IBM Corp. 2008. All rights reserved. 107

Page 126: My Tutorial

7.1 Defining the properties

We will use the following text for the new menu actions. Refer to 6.3, “Defining an extended resource bundle and properties file” on page 92 for details about how to define these values in the properties and resource bundle files.

# Make Buyable menusbuyable=BuyablenotBuyable=Not buyablemakeBuyable=Make buyablemakeNotBuyable=Make not buyable

For reference, we also provide the related resource bundle definitions here. Note also the resource definitions for the buyable and non-buyable icons.

<library><class name="extCatalogResourceBundle"...<!-- Make Buyable properties --><wcfResourceBundleKey name="buyable"/><wcfResourceBundleKey name="notBuyable"/><wcfResourceBundleKey name="makeBuyable"/><wcfResourceBundleKey name="makeNotBuyable"/></class>

<resource name="buyableIcon"src="../../commerce/foundation/restricted/resources/active.png"/>

<resource name="nonBuyableIcon"src="../../commerce/foundation/restricted/resources/

deactive.png"/></library>

7.2 Customizing the product list view

The first challenge is to determine which Laszlo file is responsible for object services for a Product type object. In the Info Center, we found the Product Primary Object definition, where we can see the available services that are defined at the product level, and also that the file ProductPrimaryObjectDefinition.lzx should contain the respective service definitions:

108 WebSphere Commerce Line-of-Business Tooling Customization

Page 127: My Tutorial

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/catalog/objectDefinitions/ProductPrimaryObjectDefinition.lzx/catProductPrimaryObjectDefinition.html

To open the file:

1. In the Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog → objectDefinitions.

2. Open the ProductPrimaryObjectDefinition.lzx file.

There are many services that are already defined. We will add our two new services at the end. Locate the definition for wcfDeleteService, and insert the definitions in Figure 7-1 on page 116 after it:

Example 7-1 Adding a new custom service action

<!--- Make the selected products buyable --><wcfCustomService url="/cmc/MakeBuyable"

displayName="${extCatalogResources.makeBuyable.string}"toolbarIcon="activateToolbarIcon">

<wcfEnablementCondition conditionId="not_buyable"propertyName="xprop_buyable" enablementValue="0"objectPath="CatalogEntryExtraProperties" />

<wcfServiceParam name="storeId"/><wcfServiceParam name="catentryId" propertyName="catentryId" /><wcfServiceParam name="extraPropertiesId"

propertyName="extraPropertiesId" objectPath="CatalogEntryExtraProperties" />

<wcfServiceParam name="xprop_buyable" value="1"/></wcfCustomService> <!--- Make the selected products not buyable --><wcfCustomService url="/cmc/MakeNotBuyable"

displayName="${extCatalogResources.makeNotBuyable.string}"toolbarIcon="deactivateToolbarIcon">

<wcfEnablementCondition conditionId="buyable"propertyName="xprop_buyable" enablementValue="1" objectPath="CatalogEntryExtraProperties" />

<wcfServiceParam name="storeId"/><wcfServiceParam name="catentryId" propertyName="catentryId" /><wcfServiceParam name="extraPropertiesId"

propertyName="extraPropertiesId" objectPath="CatalogEntryExtraProperties" />

<wcfServiceParam name="xprop_buyable" value="0"/></wcfCustomService>

Chapter 7. Adding a new service action 109

Page 128: My Tutorial

Let us discuss the definition in Example 7-1 on page 109 for a moment. Note the use of the wcfCustomService API class here. This class is the entry point for mapping new actions to the Management Service UI. See the Information Center documentation for this class here:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/foundation/restricted/CustomService.lzx/wcfCustomService.html

This definition maps the two new services to Struts actions. We will add those actions to our extended Struts configuration soon. We are referring to the previously defined resource bundle for the menu text and the link to the menu icon is in place. The icon resources are actually defined in the .../foundation/restricted/Resources.lzx file. We are not extending this restricted file, but only referring to an existing icon resource in there. Alternately, you can copy the resource files to your own resource folder. For this simple scenario, we just link to the existing resources, which happens to be quite suitable for our purposes.

If you want to explore what other icons are available in the tool, navigate to the .../foundation/restricted/resources/normal folder (or other subfolders there), and open the Thumbnails view in WebSphere Commerce Developer.

Another important point in this definition is to identify the actual buyable property. The Information Center contains the buyable information that is available in the xprop_buyable property, but that is part of the extended properties definition and is accessible behind another object path. See the Catalog Entry browse grid definition in the Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/catalog/listViewDefinitions/CatalogEntryGrid.lzx/catCatalogEntryBrowseGrid.html

To address that property, we need to pass the extraPropertiesId in the service request as well.

Since no additional user input is required, passing the new value is really simple.

One last point about this definition, the wcfEnablementCondition, which declares the condition when the service will be available to user. This is a useful feature in this particular instance and using it makes the UI appear less cluttered also.

3. Close and save the file.

110 WebSphere Commerce Line-of-Business Tooling Customization

Page 129: My Tutorial

7.3 Updating the catalog entry grid view

Next we change the way the buyable information is presented to the user. Rather than the check box, perhaps the green and red icons might work more effectively. The wcfGridPropertyImage class seems to be suitable for that purpose.

Also, let us explore the column filtering capability so that the user can more easily work with a subset of products only.

1. In the Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog → listViewDefinitions.

2. Open the CatalogEntryGrid.lzx file, and notice that the file contains the class definitions for several different catalog entry grids, which includes products, child SKUs, and search results. Make sure that you are make the changes inside of the correct class.

3. Inside the wcsObjectGrid class, search for xprop_buyable. This should be the first occurrence of that string in this file. Add the new definition above it, and comment out the existing definition, as shown in Example 7-2.

Example 7-2 New definition

<class extends="wcfObjectGrid" .........<wcfGridPropertyImage name="xprop_buyable"

objectPath="CatalogEntry/CatalogEntryExtraProperties" propertyName="xprop_buyable" text="${catalogResources.productBuyable_ColumnHeader.string}" editable="false" enableFilter="true" imageResourceMap="${{0: 'nonBuyableIcon', 1: 'buyableIcon'}}">visible="true" width="70"

</wcfGridPropertyImage><!-- <wcfGridCheckbox trueValue="1" falseValue="0"

name="xprop_buyable" objectPath="CatalogEntry/CatalogEntryExtraProperties" propertyName="xprop_buyable" text="${catalogResources.productBuyable_ColumnHeader.string}" visible="true" width="90" alignment="center"/>

-->

Chapter 7. Adding a new service action 111

Page 130: My Tutorial

7.4 Providing the buyable property value definitions

To make the example more complete, let us also provide meaningful value mappings in the UI. For display purposes, rather than showing the true value (1), something like buyable makes more sense. We can make this change using the wcfValueDefinition class.

1. In Package Explorer, navigate to LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog → listViewDefinitions.

2. Open the CatalogCommonObjectDefinitions.lzx file.

3. At the end of the catCatalogEntryExtraProperties class definition, add the definition for the buyable property in Example 7-3.

Example 7-3 Definition for buyable property

<class name="catCatalogEntryExtraProperties" extends="wcfChildObjectDefinition"......</wcfPropertyDefinition><!-- Buyable flag --><wcfPropertyDefinition propertyName="xprop_buyable"

displayName="xprop_buyable"><wcfPropertyValue

displayName="${extCatalogResources.notBuyable.string}"value="0"/><wcfPropertyValue displayName="${extCatalogResources.buyable.string}" value="1"/>

</wcfPropertyDefinition></class>

As you can see, for most of the properties a definition is already provided, and you can further customize it. However, in the case of xprop_buyable, by default there is no definition provided. Fortunately, adding one of our own is still effective, which you will see in the testing phase soon.

112 WebSphere Commerce Line-of-Business Tooling Customization

Page 131: My Tutorial

7.5 Defining the Struts action

The last extension step left is to map the service URLs to the service module that will carry out the work, which is configured in our extended Struts configuration file:

1. In Package Explorer, navigate to LOBTools → WebContent → WEB-INF. 2. Open the struts-extension.xml file.3. Insert the two action mappings in Example 7-4.

Example 7-4 Updating the Struts extension file

<!-- Make buyable / not buyable --><action path="/MakeBuyable" parameter="CatalogEntry"

type="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentAction"

className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentActionMapping">

<set-property property="contextParameters" value="storeId,langId" /><set-property property="verb" value="Change" /><set-property property="documentRootFactory"

value="com.ibm.commerce.catalog.facade.datatypes.CatalogFactory"/>

<set-property property="clientLibrary"value="com.ibm.commerce.catalog.facade.client.

CatalogFacadeClient" /><set-property property="clientLibraryMethod"

value="changeCatalogEntry" /><set-property property="actionCode" value="Change"/><forward name="success"

path="/jsp/redbooks/catalog/RespondMakeBuyable.jsp"/> </action>

<action path="/MakeNotBuyable" parameter="CatalogEntry"type="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.

BusinessObjectDocumentAction"className="com.ibm.commerce.foundation.client.facade.bod.servlet.

struts.BusinessObjectDocumentActionMapping"><set-property property="contextParameters" value="storeId,langId" /><set-property property="verb" value="Change" /><set-property property="documentRootFactory"

value="com.ibm.commerce.catalog.facade.datatypes.CatalogFactory"/>

Chapter 7. Adding a new service action 113

Page 132: My Tutorial

<set-property property="clientLibrary"value="com.ibm.commerce.catalog.facade.client.

CatalogFacadeClient" /><set-property property="clientLibraryMethod"

value="changeCatalogEntry" /><set-property property="actionCode" value="Change"/>

<forward name="success"path="/jsp/redbooks/catalog/RespondMakeNotBuyable.jsp"/>

</action>

The mappings in Example 7-4 on page 113 are naturally very similar. They are modeled after the UpdateCatalogEntryExtraProperties action in the original Struts configuration, which is stored in the struts-ibm-tools.xmlfile. For more details about transforming the URL request to a BOD service, see the Information Center page here:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/refs/rtfprocessservices.htm

In this case, we are simply mapping our new action to an existing Change BOD service class. This class is responsible for performing the requested xprop_buyable flag update action on the server side.

A possible more advanced extension can include writing your own custom service module as well, for example, a custom BOD Process service could additionally make the child catalog entries (SKUs) buyable.

7.5.1 Providing the response JSP files

Here is a question. Now that the buyable flag change is executed on the server side and persisted to the database, how exactly does the Management Center client get to know about the change? The answer is through the response JSP files. The response JSPs are responsible for sending back an XML response that communicates to the UI what actual changes were performed, and what information should be updated in the view. To provide the response JSP files:

1. In Package Explorer, navigate to LOBTools → WebContent → jsp → redbooks → catalog.

2. Create a new JSP file and name it RespondMakeBuyable.jsp.

3. Insert the following code:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><?xml version="1.0" encoding="UTF-8"?><object objectType="Product">

114 WebSphere Commerce Line-of-Business Tooling Customization

Page 133: My Tutorial

<catentryId>${param.catentryId}</catentryId><object objectType="CatalogEntryExtraProperties">

<extraPropertiesId>${param.extraPropertiesId}</extraPropertiesId>

<xprop_buyable>1</xprop_buyable></object>

</object>

This JSP will return an <object> document that refers to the subject catalog entry ID and the new buyable value.

4. Save and close the file.

5. Create the other response JSP file, RespondMakeNotBuyable.jsp.

6. Insert the following code:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><?xml version="1.0" encoding="UTF-8"?><object objectType="Product">

<catentryId>${param.catentryId}</catentryId><object objectType="CatalogEntryExtraProperties">

<extraPropertiesId>${param.extraPropertiesId}</extraPropertiesId>

<xprop_buyable>0</xprop_buyable></object>

</object>

7.6 Testing the extension

To test the extension:

1. Restart the WebSphere Commerce server, which is necessary because we updated the Struts configuration.

2. Open the Management Center, and then open the ConsumerDirect store.

3. Open the Catalog tool, and navigate down the Category tree to the product level.

4. Select multiple products while simultaneously pressing down the Ctrl or Shift keys.

5. In the selected blue area, shown in Figure 7-1 on page 116, right-click, and notice the new menu actions.

6. Check the new menu icons also, and the new actions under the Edit menu option.

Chapter 7. Adding a new service action 115

Page 134: My Tutorial

Figure 7-1 Testing the Make buyable extension

A nice surprise here is that the new action is automatically enabled for multiple objects. The framework does all of the hard work that is related to that; therefore, we did not have to write any special code for dealing with multiple input objects.

We also enabled the Manufacturer column for filtering, which is easy to turn on and off. The feature is quite useful, for instance, when the business user needs to update products from certain manufacturer(s) only.

As a quick summary, this particular scenario was really quick to implement, but we also encountered some limitations in the FEP 3.0.1 version in this area. If we want to ask the user for additional input, for example, provide a new name for the

116 WebSphere Commerce Line-of-Business Tooling Customization

Page 135: My Tutorial

Manufacturer, there is no simple way of doing that. The custom action is mapped to the BOD service directly, and at the time of writing this book, the action could not be intercepted by additional client side dialogs. However, this is likely to change in future Management Center releases, allowing more flexible customized services to be built, while still maintaining the capability to target multiple objects as easily as in this example.

Chapter 7. Adding a new service action 117

Page 136: My Tutorial

118 WebSphere Commerce Line-of-Business Tooling Customization

Page 137: My Tutorial

Chapter 8. Advanced search for merchandising associations

In this chapter, we discuss how to add an advanced search facility for searching for catalog entries on merchandising association types. We add a new tab in the advanced search panel of the Management Center, build a new search service for the same, and also build their mediation assets.

8

© Copyright IBM Corp. 2008. All rights reserved. 119

Page 138: My Tutorial

8.1 Understanding the requirements

The Management Center supports building simple and advanced search facility on objects. While simple search facility accepts only one input search criterion, advanced search allows you to search on one or more input search criteria. Both simple and advanced searches can accept only wcfPrimaryObjectDefinitions as search results.

Out-of-the-box, the simple search facilities that are supported, for example, in the Catalog Management tool, are for Catalog Entries, Categories, Products, Kits, Bundles, and SKUs. The simple search box is available in the top-right corner of the tool. The same is available from the utility pane’s Find tab option. Figure 8-1 shows the options that are available out-of-the-box in the Management Center.

Figure 8-1 Management Center simple search options

The advanced search facility that is supported out-of-the-box is for searching Catalog Entries and Categories.The advanced search is available as one of the options from the simple search pull-down menu. Figure 8-2 on page 121 is an example of an advanced search panel.

120 WebSphere Commerce Line-of-Business Tooling Customization

Page 139: My Tutorial

Figure 8-2 Management Center advanced search example

The requirement that we describe in this chapter is to include a new advanced search functionality for searching catalog entries on merchandising associations. The search parameters are the Code or the part number of the source catalog entry and the merchandising association type. It returns the list of catalog entries that have the specific code and at least one merchandising association to another catalog entry of the association type that is specified. The Code of the source catalog entry supports wild card search.

In this chapter, we also include building a simple search facility for the same. The input for the simple search is the merchandising association type, which returns the list of catalog entries that have at least one merchandising association of the specified type. Simple search is included only for the completeness of the scenario and does not support wild card search.

Chapter 8. Advanced search for merchandising associations 121

Page 140: My Tutorial

The advanced panel for merchandising association looks like Figure 8-3.

Figure 8-3 Merchandising Association Advanced Search panel

122 WebSphere Commerce Line-of-Business Tooling Customization

Page 141: My Tutorial

8.2 Building the customization

This scenario needs customization on the Management Center user interface, the Management Center Web application, and the Commerce services.

8.2.1 Customizing the Management Center user interface

In this section, we discuss the customization that involves changing the user interface, for example, mainly the OpenLaszlo class files. The Management Center Framework provides some classes that you can extend for component-specific search implementations. The classes are:

� wcfSearchDefnition: An abstract class that you must extend to declare a type of business object search. wcfSearchDefnition retrieves values for one or more objects or object types. You can use one search type to return more than one type of objects. The search widget, the utility pane, or the predefined search nodes in the navigation view use these search definitions. You can only declare instances of this class as direct child nodes of an instance of wcfBusinessObjectEditor. Search definitions must include one child instance of wcfSearchService that describes the service to be used when performing the search. This class is defined in SearchDefinition.lzx

� wcfSearchService: A service that searches for one or more business objects based on user-specified criteria. You can only declare a search service as a child of an instance of wcfSearchDefinition.This class is defined in SearchService.lzx

� wcfAdvancedSearchContent: An abstract class that needs to be extended. The extending class can be a free form view that captures all user input for performing the advanced search. All instances of this class must implement the setSearchOptions method, which is in charge of creating the searchOptions map. The searchOptions map determines the name/value pairs that get passed to the search service. Search definitions that need an advanced facility can declare any class that extends the wcfAdvancedSearchContent class. This class is defined in AdvancedSearchWidget.lzx.

To create a search definition for merchandising associations:

1. Open Java perspective in WebSphere Commerce Developer from the menu Window → Open Perspective → Java.

2. Select File → New → Other → Simple → File.

3. Enter the parent folder as LOBTools/WebContent/WEB-INF/src/lzx/redbooks/catalog/searchDefinitions (the folder will be created if it does not already exist)

Chapter 8. Advanced search for merchandising associations 123

Page 142: My Tutorial

4. Type in the File Name as FindMerchandisingAssociationsSearchDefinition.lzx.

5. In FindMerchandisingAssociationsSearchDefinitions.lzx, define the class as in Example 8-1.

Example 8-1 Merchandising associations search class definition

<class name="catFindMerchandisingAssociationsSearchDefinition"

extends="wcfSearchDefinition"

searchType="FindMerchandisingAssociations" displayName="${extCatalogResources.merchandisingAssocia-

tionsSearchDisplayName.string}" listClass="catCatalogEntrySearchGrid" listTitle="${extCatalogResources.merchandisingAssocia-

tionsSearchListTitle.string}"advancedSearchContentClass="catMerchandisingAssociation-

sAdvancedSearchContent"><wcfSearchService name="findAllMerchandisingAssocia-

tions" url="/cmc/FindMerchandisingAssociations"><wcfServiceParam name="storeId"/><wcfServiceParam name="masterCatalogId"/>

</wcfSearchService></class>

Here we extend the wcfSearchDefinition to define a new search type for Catalog Entries:

searchType Defines the name of the business object search type.

displayName The display name for this search type in the simple and advanced search options.

listClass The grid class that displays the result of business objects that are returned from the service.

listTitle The title for the search results that are displayed in the grid.

advancedSearchContentClassA free form view class that captures all of the advanced search user inputs.

We specify a wcfSearchService to define our new search service call. The struts layer of the Management Center Web application maps the URL to a

124 WebSphere Commerce Line-of-Business Tooling Customization

Page 143: My Tutorial

jsp. wcfServiceParams are used to specify the parameters that will be passed as part of the service call, which are resolved at the level of the business object or at the context level.

6. Save and close the file.

7. Select File → New → Other → Simple → File.

8. Enter the parent folder as LOBTools/WebContent/WEB-INF/src/lzx/redbooks/catalog/searchDefinitions

9. Type the File Name as MerchandisingAssociationsAdvancedSearchContent.lzx

10.Define the advanced search content class, as shown in Example 8-2.

Example 8-2 Merchandising associations advanced search content class

<class name="catMerchandisingAssociationsAdvancedSearchContent" extends="wcfAdvancedSearchContent">

<simplelayout axis="y"/><view name="section1" width="100%" height="15">

<simplelayout axis="y"/><view name="filler1" height="15"/><!-- Instructional text to the user --><text

text="${catalogResources.searchInstructionalText.string}" width="100%" fontstyle="italic"/>

<view name="filler2" height="15"/></view><view name="section2" width="410" height="52">

<simplelayout axis="x"/><view name="section2_1" width="56%" height="100%">

<simplelayout axis="y"/><view name="filler1" height="30"/><view name="section2_1_1" width="100%"

height="30%"><text

text="${extCatalogResources.catalogEntrySourceCodeSearchPrompt.string}" width="177"/>

</view><view name="section2_1_2" width="97%" height="70%">

<!-- Text field for the catalogEntryCode search parameter -->

<wcfInputText name="sourceCatalogEntryCode" width="177"/>

Chapter 8. Advanced search for merchandising associations 125

Page 144: My Tutorial

</view></view><view name="section2_2" width="56%" height="100%">

<simplelayout axis="y"/><view name="filler2" height="30"/><view name="section2_2_1" width="100%"

height="30%"><text

text="${extCatalogResources.associationNameSearchPrompt.string}" width="180"/>

</view><wcfBaseComboBox name="associationName"

width="180"><handler name="oninit">

this.addItem(catalogResources.merchandisingAssociationName_ACCESSORY.string,catalogResources.merchandisingAssociationName_ACCESSORY.string);

this.addItem(catalogResources.merchandisingAssociationName_XSELL.string,catalogResources.merchandisingAssociationName_XSELL.string);

this.addItem(catalogResources.merchandisingAssociationName_UPSELL.string,catalogResources.merchandisingAssociationName_UPSELL.string);

this.addItem(catalogResources.merchandisingAssociationName_REPLACEMENT.string,catalogResources.merchandisingAssociationName_REPLACEMENT.string);

this.selectItem(catalogResources.merchandisingAssociationName_ACCESSORY.string);

</handler> </wcfBaseComboBox>

</view></view>

<method name="setSearchOptions"><![CDATA[

super.setSearchOptions();var newSearchOptions = {};newSearchOptions.sourceCatalogEntryCode =

this.section2.section2_1.section2_1_2.sourceCatalogEntryCode.getText();

newSearchOptions.associationName = this.section2.section2_2.associationName.getValue();

126 WebSphere Commerce Line-of-Business Tooling Customization

Page 145: My Tutorial

this.searchOptions = newSearchOptions;]]>

</method></class>

The catMerchandisingAssociationsAdvancedSearchContent is a free form view class that uses different widgets to elicit user input; however, it needs to extend from wcfAdvancedSearchContent. In this example, we have wcfInputText to provide a text box for the user to specify the catalog entry code, and we have wcfBaseComboBox for the user to choose from the merchandising association types. We must override the setSearchOptions method to specify the search parameters and their values that will be passed as part of the service call, for example, we specify that the search parameter sourceCatalogEntryCode takes the text from the sourceCatalogEntryCode widget.

11.Save and close the file.

12.In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog.

13.Open the CatalogManagementToolDefinition.lzx for editing.

14.For the Management Center to recognize our new search definition, add the class definition to the CatalogManagementToolDefinition.lzx. Include the line in Example 8-3 in the lzx file.

Example 8-3 Merchandising associations class definition declaration

<catFindMerchandisingAssociationsSearchDefinition/>

15.Save and close the file.

16.In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog.

17.Update the catalog extensions library file, as shown in Example 8-4 to point to the new search files.

Example 8-4 Including merchandising associations search files to the library

<include href="../../redbooks/catalog/searchDefinitions/FindMerchandisingAssociationsSearchDefinition.lzx"/>

<include href="../../redbooks/catalog/searchDefinitions/MerchandisingAssociationsAdvancedSearchContent.lzx"/>

Chapter 8. Advanced search for merchandising associations 127

Page 146: My Tutorial

In this section, we create a new resource bundle and a corresponding properties file to hold translatable text. We advise you to create your own resource bundles and not modify the ones that come out-of-the box.

1. Create a properties file:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → Java Resources → src.

b. Right-click src, and select New → Package.

c. In the Name field, enter com.redbooks.commerce.client.lobtools.properties as the package name, and click Finish. The package is created.

d. Right-click the com.redbooks.commerce.client.lobtools.properties package, select New → Other → Simple → File, and click Next.

e. In the File Name field, enter CatalogLOB.properties, and click Finish. The CatalogLOB.properties file opens.

f. Define the properties, as shown in Example 8-5.

Example 8-5 Merchandising associations search properties

merchandisingAssociationsSearchListTitle=Source Catalog EntriesmerchandisingAssociationsSearchDisplayName=Merchanding AssociationscatalogEntrySourceCodeSearchPrompt=Catalog Entry Source CodeassociationNameSearchPrompt=Association Name

g. Save and close the file.

2. Register the new properties file in the resource bundle:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → redbooks → catalog.

b. Right-click catalog, select New → Other → Simple → File, and click Next.

c. In the File name field, enter extCatalogManagementResourceBundle.lzx.

d. Click Finish. The extCatalogManagementResourceBundle.lzx file opens.

Note: The package might already exist if you went through any of the other examples that we gave in this book. If that is the case, ignore the steps a to c and proceed to the step d.

128 WebSphere Commerce Line-of-Business Tooling Customization

Page 147: My Tutorial

e. Add the code in Example 8-6 to the file.

Example 8-6 Merchandising associations Search Resource Bundle

<class name="extCatalogResourceBundle" extends="wcfResourceBundle"

baseName="com.redbooks.commerce.client.lobtools.properties.CatalogLOB">

<wcfResourceBundleKey name="merchandisingAssociationsSearchDisplayName"/>

<wcfResourceBundleKey name="merchandisingAssociationsSearchListTitle"/>

<wcfResourceBundleKey name="catalogEntrySourceCodeSearchPrompt"/>

<wcfResourceBundleKey name="associationNameSearchPrompt"/></class>

<extCatalogResourceBundle id="extCatalogResources"/>

f. Save and close the file.

3. Include extCatalogManagementResourceBundle.lzx in the extension library so that the Management Center recognizes that it is available for use:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → catalog.

b. Open the CatalogExtensionsLibrary.lzx file.

c. Update the file to point to the new resource bundle file, as shown in Example 8-7.

Example 8-7 Including the resource bundle in the library

<include href="../../redbooks/catalog/extCatalogManagementResourceBundle.lzx"/>

d. Save and close the file.

8.2.2 Customizing the Management Center Web application

In this section, we describe the customizations that you must make to the Management Center Web application. The changes at this level are to primarily define a new controller jsp to define the new search service and to include a struts action element to direct to this jsp.

Chapter 8. Advanced search for merchandising associations 129

Page 148: My Tutorial

To create a new controller jsp for the new search service:

1. Navigate to LOBTools → WebContent → jsp.

2. To create the JSP extension folder, right-click jsp, and select New → Other → Simple → Folder.

3. In the Folder name field, type redbooks, click Next, and then click Finish.

4. Repeat steps 2 and 3 to create a catalog folder in the redbooks directory.

5. To create the extension controller JSP file, right-click the catalog folder, and select New → Other → Simple → File. In the File name field, type FindMerchandisingAssociations.jsp, and then click Finish.

6. Define the JSP, as shown in Example 8-8.

Example 8-8 Merchandising associations search jsp

<c:choose><c:when test="${! (empty param.searchText )}">

<c:set var="expressionBuilderName" value="findSourceMerchandisingAssocationsAdvancedSearch"/>

<c:set var="sourceCatentryCode" value="*"/><c:set var="associationName"

value="${param.searchText}"/></c:when><c:when test="${empty param.searchText}">

<c:set var="expressionBuilderName" value="findSourceMerchandisingAssocationsAdvancedSearch"/>

<c:set var="sourceCatentryCode" value="${param.sourceCatalogEntryCode}"/>

<c:set var="associationName" value="${param.associationName}"/>

</c:when></c:choose>

<c:set var="catalog" value="${param.masterCatalogId}"/>

<wcf:getData type="com.ibm.commerce.catalog.facade.datatypes.CatalogEntryType[]"

var="catentries"expressionBuilder="${expressionBuilderName}"

Note: If you went through any of the other examples that we gave in this book, the package might already exist; therefore, ignore steps 2 to 4, and proceed to step 5.

130 WebSphere Commerce Line-of-Business Tooling Customization

Page 149: My Tutorial

varShowVerb="showVerb"recordSetStartNumber="${param.recordSetStartNumber}"recordSetReferenceId="${param.recordSetReferenceId}"maxItems="${param.maxItems}"><wcf:contextData name="storeId" data="${param.storeId}"/><wcf:contextData name="catalogId" data="${catalog}"/><wcf:param name="sourceCatentryCode"

value="${sourceCatentryCode}"/><wcf:param name="associationName"

value="${associationName}"/></wcf:getData>

<jsp:directive.include file="../../commerce/catalog/restricted/serialize/SerializeCatalogEntries.jspf"/>

The getData tag is part of the WebSphere Commerce foundation tag library. It allows us to retrieve service data objects from any WebSphere Commerce service and associate them with scripting variables:

type Specifies the type of business object that the service returns. Here the returning BusinessObjectDocument contains an array of com.ibm.commerce.catalog.facade.datatypes.CatalogEntryType in its data area.

var Specifies the name of the exported scripting variable to which the array of CatalogEntryType returned is bound. This variable is then used elsewhere in the jsp to access the returned result.

expressionBuilder An expression builder constructs an XPath expression to retrieve data.

varShowVerb Specifies the name of the exported scripting variable. This variable holds the Show verb object that is retrieved from the services.

recordSetStartNumber, recordSetReferenceId, maxItems These parameters are used for pagination.

The SerializeCatalogEntries.jspf is then used to build the XML response that is sent back to the OpenLaszlo application in the Web browser.

Chapter 8. Advanced search for merchandising associations 131

Page 150: My Tutorial

7. Save and close the file.

To extend the struts file to include an action element for the jsp that we defined earlier:

1. Navigate to LOBTools → WebContent → WEB-INF, and double-click the struts-extension.xml file to open it in the default editor.

2. Include the element in Example 8-9 under the <action-mapping> tag.

Example 8-9 Merchandising associations search struts action

<action path="/FindMerchandisingAssociations" forward="/jsp/redbooks/catalog/FindMerchandisingAssociations.jsp" />

This forwards the control to the JSP when the URL is as specified in the path element.

3. Save and close the file.

To build an expression builder that makes the new search request to the server:

1. Right-click the LOBTools\WebContent\WEB-INF\config folder.

2. Click New → Package. In the Name field, enter com.redbooks.commerce.catalog as the package name, and click Finish. The package is created.

3. Right-click the com.redbooks.commerce.catalog folder.

4. Click New → Other → Simple → File. Enter the file name as get-data-config.xml.

5. Define the XML file, as shown in Example 8-10.

Example 8-10 Merchandising associations search expression builder

<data-type><name>CatalogEntry</name>

<type>com.ibm.commerce.catalog.facade.datatypes.CatalogEntryType</type>

</data-type>

Note: If you went through any of the other examples that we gave in this book, the package might already exist; therefore, ignore steps 2, and proceed to step 5.

132 WebSphere Commerce Line-of-Business Tooling Customization

Page 151: My Tutorial

<client-facade><data-type-name>CatalogEntry</data-type-name>

<class>com.ibm.commerce.catalog.facade.client.CatalogFacadeClient</class>

<method>getCatalogEntry</method></client-facade>

<expression-builder> <name>findSourceMerchandisingAssocationsAdvancedSearch</name> <data-type-name>CatalogEntry</data-type-name>

<class>com.ibm.commerce.catalog.internal.client.taglib.util.CatalogSearchExpressionBuilder</class>

<method>formatExpression</method> <param>

<name>template</name>

<value>/CatalogEntry[Association[(Name='$associationName$')] and search(CatalogEntryIdentifier/ExternalIdentifier/PartNumber='$sourceCatentryCode$')]</value> </param> <param> <name>accessProfile</name> <value>Redbooks_CatalogEntry_MerchandisingAssociationsSearch</value> </param> </expression-builder>

All expression builders are defined in files that are named as get-data-config.xml (WebSphere Commerce getData action searches for configuration files that are named get-data-config.xml in the WEB-INF/config directory):

– The data-type element declares a supported data type for the getData action.

– The client-facade element declares the component client facade that invokes the service to fetch the data.

– The expression builder handles building the XPath expression with the published input parameters.

6. Save and close the file.

Chapter 8. Advanced search for merchandising associations 133

Page 152: My Tutorial

8.2.3 Customizing WebSphere Commerce services

In this section, we define a new search service as an extension to the catalogs component. Primarily, we talk about introducing a new query template for searching for catalog entries on merchandising associations.

The XPath key and the access profile of a logical object are related to a template SQL query to select the data using a query template. We define query template files (tpl files) that contain this mapping in a predefined syntax.

For this scenario, we must define our tpl file to perform a search on merchandising associations. This separation of SQLs from the runtime code avoids the need to recompile java code during such customizations.

To create a new search query template:

1. Right-click the WC\config\com.ibm.commerce.catalog-ext folder. If you do not find the folder, use the following steps to create one:

a. Right-click the WC project, and click New → Other → Simple → Folder → Next → Advanced.

b. Under Folder name, select Link to folder in the file system.

c. Click Browse, and navigate to <WCDE_installdir>/xml/config.

d. Name the folder com.ibm.commerce.catalog-ext.

e. Click Finish.

2. Click New → Other → Simple → File, and click Next.

3. Name the file: wc-query-RedbooksCatalogEntry-get.tpl. The name is important because it must begin with wc-query- and end with the suffix .tpl.

4. Click Finish.

5. Copy and paste the symbol definitions from Example 8-11 into the file.

Example 8-11 Merchandising associations search symbol definitions

BEGIN_SYMBOL_DEFINITIONS

<!-- CATENTRY table -->COLS:CATENTRY=CATENTRY:*COLS:CATENTRY_ID=CATENTRY:CATENTRY_IDCOLS:CATENTRY:MARKFORDELETE=CATENTRY:MARKFORDELETE

<!-- CATALOG table -->COLS:CATALOG=CATALOG:*COLS:CATALOG_ID=CATALOG:CATALOG_ID

134 WebSphere Commerce Line-of-Business Tooling Customization

Page 153: My Tutorial

<!-- CATGROUP table -->COLS:CATGROUP=CATGROUP:*COLS:CATGROUP_ID=CATGROUP:CATGROUP_ID

<!-- CATENTDESC table -->COLS:CATENTDESC=CATENTDESC:*

<!-- Other tables -->COLS:CATENTREL=CATENTREL:*COLS:MASSOCCECE=MASSOCCECE:*COLS:CATENTRY_ID_TO=MASSOCCECE:CATENTRY_ID_TOCOLS:CATENTRY_ID_FROM=MASSOCCECE:CATENTRY_ID_FROM

END_SYMBOL_DEFINITIONS

This section defines the tables our query template to use. The column symbol definitions are used and referenced in the SELECT list of our SQL template statements. Physical schema changes require changes only to this section of the tpl file.

6. Copy and paste the SQL definitions in Example 8-12 after the symbol definitions into the same file.

Example 8-12 Merchandising associations search SQL definitions

BEGIN_XPATH_TO_SQL_STATEMENTname=/CatalogEntry[Association[(Name=)] and search()]

base_table=CATENTRYsql=

SELECT MASSOCCECE.$COLS:CATENTRY_ID_FROM$

FROMCATENTRY

JOIN MASSOCCECE ON (CATENTRY.CATENTRY_ID = MASSOCCECE.CATENTRY_ID_FROM AND MASSOCCECE.STORE_ID IN ($STOREPATH:catalog$)), $ATTR_TBLS$ WHERE MASSOCCECE.MASSOCTYPE_ID IN (?Name?) AND ( $ATTR_CNDS$ )

ORDER BY

Chapter 8. Advanced search for merchandising associations 135

Page 154: My Tutorial

CATENTRY.CATENTRY_ID $DB:UNCOMMITTED_READ$

END_XPATH_TO_SQL_STATEMENT

This section directly maps the logical and physical layers, that is, the XPath key directly to a SQL statement. Here for our XPath, we do a join on CATENTRY and MASSOCCECE in the SQL statement.

7. Copy and paste the associated SQLs in Example 8-13 to the same file after the SQL definitions.

Example 8-13 Merchandising associations search associated SQLs

BEGIN_ASSOCIATION_SQL_STATEMENTname=IBM_CatalogEntryDescriptionWithPriceAssocSQLbase_table=CATENTRYadditional_entity_objects=truesql=

SELECT CATENTRY.$COLS:CATENTRY$,CATENTDESC.$COLS:CATENTDESC$,LISTPRICE.$COLS:LISTPRICE$

FROMCATENTRY LEFT OUTER JOINCATENTDESC ON

(CATENTDESC.CATENTRY_ID = CATENTRY.CATENTRY_ID AND CATENTDESC.LANGUAGE_ID IN ($CONTROL:LANGUAGES$))

LEFT OUTER JOINLISTPRICE ON

(CATENTRY.CATENTRY_ID = LISTPRICE.CATENTRY_ID)WHERE

CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$)END_ASSOCIATION_SQL_STATEMENT

BEGIN_ASSOCIATION_SQL_STATEMENTname=IBM_CatalogEntryToCatalogGroupRelationshipbase_table=CATENTRYadditional_entity_objects=truesql=

SELECT CATENTRY.$COLS:CATENTRY$,CATGPENREL.$COLS:CATGPENREL$,CATGROUP.$COLS:CATGROUP$

136 WebSphere Commerce Line-of-Business Tooling Customization

Page 155: My Tutorial

FROMCATENTRY,CATGPENREL JOINCATGROUP ON

(CATGROUP.CATGROUP_ID = CATGPENREL.CATGROUP_ID AND CATGPENREL.CATALOG_ID = $CTX:CATALOG_ID$)

WHERE CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$) AND CATGPENREL.CATENTRY_ID =CATENTRY.CATENTRY_ID AND CATGROUP.MARKFORDELETE = 0END_ASSOCIATION_SQL_STATEMENT

BEGIN_ASSOCIATION_SQL_STATEMENTname=IBM_ParentCatalogEntryForRootRelationshipsbase_table=CATENTRYadditional_entity_objects=truesql=

SELECT CATENTRY.$COLS:CATENTRY$,CATENTDESC.$COLS:CATENTDESC$,CATENTREL.$COLS:CATENTREL$,CATENTRY_PARENT.$COLS:CATENTRY_ID$,

CATENTRY_PARENT.$COLS:CATENTRY:MEMBER_ID$,CATENTRY_PARENT.$COLS:CATENTRY:ITEMSPC_ID$,

CATENTRY_PARENT.$COLS:CATENTRY:CATENTTYPE_ID$,CATENTRY_PARENT.$COLS:CATENTRY:PARTNUMBER$

FROMCATENTRY,CATENTRELJOIN CATENTRY CATENTRY_PARENT ON

CATENTRY_PARENT.CATENTRY_ID = CATENTREL.CATENTRY_ID_PARENTLEFT OUTER JOIN CATENTDESC ON CATENTDESC.CATENTRY_ID =

CATENTREL.CATENTRY_ID_PARENT AND CATENTDESC.LANGUAGE_ID IN ($CONTROL:LANGUAGES$)

WHERECATENTRY.CATENTRY_ID IN ($ENTITY_PKS$) AND

CATENTREL.CATENTRY_ID_CHILD = CATENTRY.CATENTRY_ID AND CATENTRY.MARKFORDELETE = 0 AND CATENTRY_PARENT.MARKFORDELETE = 0END_ASSOCIATION_SQL_STATEMENT

The associated SQL statements define a specific SQL query. These queries are then reused to build our access profiles in the PROFILE section.

Chapter 8. Advanced search for merchandising associations 137

Page 156: My Tutorial

Here we have three associated SQL statements:

– IBM_CatalogEntryDescriptionWithPriceAssocSQL (joins on CATENTRY, CATENTDESC and LISTPRICE)

– IBM_CatalogEntryToCatalogGroupRelationship (joins on CATENTRY, CATGPENREL and CATGROUP)

– IBM_ParentCatalogEntryForRootRelationships (joins on CATENTRY, CATENTDESC and CATENTREL)

8. Copy and paste the profile definitions in Example 8-14, after the associated SQL definitions, in the same file.

Example 8-14 Merchandising associations search profile definitions

BEGIN_PROFILE name=Redbooks_CatalogEntry_MerchandisingAssociatonsSearchBEGIN_ENTITY base_table=CATENTRY

className=com.ibm.commerce.foundation.internal.server.services.dataaccess.graphbuilderservice.DefaultGraphComposer associated_sql_statement=IBM_CatalogEntryDescriptionWithPriceAssocSQL associated_sql_statement=IBM_CatalogEntryToCatalogGroupRelationship associated_sql_statement=IBM_ParentCatalogEntryForRootRelationships END_ENTITYEND_PROFILE

Here we use the associated SQL statements to define our access profile.

9. Save and close the file.

8.3 Testing the customization

To test the search function:

1. Start the WebSphere Commerce server, and launch the Management Center.

2. Test the merchandising associations’ advanced search:

a. Launch the Advanced Search panels from the simple search drop-down menu.

138 WebSphere Commerce Line-of-Business Tooling Customization

Page 157: My Tutorial

b. Click the Merchandising Associations tab.

c. Enter a value in the Catalog Entry Source Code field (use '*' to indicate wild card search), for example, type FUCO*.

d. From the Association Name combo box, choose a value for the merchandising associations type value, for example, choose ACCESSORY from the combo box, as shown in Figure 8-4.

Figure 8-4 Merchandising associations search advanced search tab

e. Click Search.

A grid with all of the catalog entries whose part number starts with FUCO and with one or more merchandising associations with another catalog entry of type ACCESSORY are displayed.

3. Test the merchandising associations simple search function:

a. From the drop-down menu on the simple search box, choose the Merchandising Associations option, as shown in Figure 8-5 on page 140.

Chapter 8. Advanced search for merchandising associations 139

Page 158: My Tutorial

Figure 8-5 Merchandising associations simple search select

b. Type the merchandising association type for which you want to search, for example, type in X-SELL. Wild cards are not accepted here.

c. Click the Search button.

A grid with all of the catalog entries that have one or more merchandising associations with another catalog entry of type 'X-SELL' are displayed, as shown in Figure 8-6.

Figure 8-6 Merchandising associations simple search result

140 WebSphere Commerce Line-of-Business Tooling Customization

Page 159: My Tutorial

Chapter 8. Advanced search for merchandising associations 141

Page 160: My Tutorial

142 WebSphere Commerce Line-of-Business Tooling Customization

Page 161: My Tutorial

Chapter 9. Price comparison mashup

In this chapter, we demonstrate how to create a client-side mashup for the Management Center. We integrate the Management Center catalog tool with an external Web service.

9

© Copyright IBM Corp. 2008. All rights reserved. 143

Page 162: My Tutorial

9.1 Understanding the requirement

In this scenario, we have a business requirement to integrate an external price comparison service with the Management Center catalog tool. To view competitor pricing for a product that is being edited, the Management Center user has to visit a third-party price comparison Web site, and search for the product. Adding a client-side mashup simplifies this task.

The Management Center user wants to see competitor pricing information listed in the catalog tool’s Product properties view, next to list price and offer price. The pricing section is currently displayed in the Manage Product tab, as shown in Figure 9-1. To reduce clutter, we move the pricing section to a new property tab.

Figure 9-1 Product properties view - Pricing section

144 WebSphere Commerce Line-of-Business Tooling Customization

Page 163: My Tutorial

9.2 Price comparison service

Many Web sites provide price comparison services, for example:

http://www.PriceGrabber.comhttp://www.Shopzilla.comhttp://www.CNET.com

For this example, we use the free service from CNET.com, which requires a developer ID that is provided after registering for membership at the CNET Web site (See step 1 in section 9.4, “Testing the customization” on page 162).

The CNET API is a REST-based service that supports XML and JSON response formats. We use the XML response format. The general structure of the CNET request URL is:

http://api.cnet.com/restApi/v1.0/[resourceName]?[requiredParam1]=[value]&[optionalParam1]=[value]&partKey=[yourDeveloperKey]

In the CNET request URL:

� [resourceName] is the resource path. For this example we use techProduct as the resource name.

� [requiredParam1]=[value]&[optionalParam1]=[value] are required and they are optional parameters for the resource.

� partKey is the developer ID, which is a required parameter.

Example 9-1 and Example 9-2 on page 146 provides a sample XML responses for the techProduct search.

Example 9-1 Sample XML response for a successful request

<CNETResponse version="1.0"> <TechProducts start="0" numReturned="1" numFound="145"> <TechProduct id="32069546" xlink:href="http://api.cnet.com/restApi/v1.0/techProduct? productId=32069546&iod=hlPrice"> <Name>Lenovo ThinkPad T61</Name> <ImageURL width="60"></ImageURL> . . .

Note: For more detailed information about the CNET API, refer to the following URL:

http://api.cnet.com/

Chapter 9. Price comparison mashup 145

Page 164: My Tutorial

<LowPrice>$925.50</LowPrice> <HighPrice>$1,738.00</HighPrice> <PreferredNode id="6490"/> <Category id="6490" xlink:href="http://api.cnet.com/restApi/v1.0/category? categoryId=6490"/>

<PreferredNode id="6490"/> <Offers start="0" numReturned="3" numFound="3"> <Offer> <Merchant id="6274490"> <Name>Lenovo</Name> <Rating outOf="5">5.0</Rating> <ImageURL> http://i.i.com.com/cnwk.1d/sc/6274490-4-3-9-0-0.gif </ImageURL>

</Merchant> <MerchandiseType/> <OfferDate>2008-06-12 15:44:50.0</OfferDate> <Price lowest="false">$925.50</Price> <Availability>Yes</Availability>

</Offer> <Offer>

. .

</Offer> </Offers> </TechProduct> </TechProducts></CNETResponse>

Example 9-2 Sample error response

<CNETResponse version="1.0"> <Error code="401"> <ErrorMessage>A developer key is required to access the CNET API. To get your FREE developer key, go to this URL: http://membership.cnet.com/1383-4_1-172.html?path=http%3A%2F%2Fapi.cnet.com%2Fdashboard.html

</ErrorMessage> <Error></CNETResponse>

146 WebSphere Commerce Line-of-Business Tooling Customization

Page 165: My Tutorial

9.3 Building the customization

The price comparison widget communicates with the CNET API and displays pricing information from the response XML. We present the following data from the CNET response to the Management Center user:

� Total number of prices (offers) returned� Price range (Lowest price to highest price)� For each offer, we display the following:

– Merchant logo– Merchant name– Price

This data is displayed using a custom grid widget. The offer details are listed as rows in the grid. The number of offers and price range are displayed in the status bar of this custom grid.

Figure 9-2 shows a proposed design of the price comparison grid.

Figure 9-2 Price comparison grid

In the following sections, we step through the customizations that you must perform to implement the price comparison widget.

Chapter 9. Price comparison mashup 147

Page 166: My Tutorial

9.3.1 Resource bundle definition

We use a resource bundle for translatable labels and messages that the price comparison widget uses. In addition, a couple of non-translatable inputs, serviceKey and serviceURL (See section 9.3.2, “Price comparison class definition” on page 150), which the widget requires, are also stored in the resource bundle properties file.

The resource bundle class, extCatalogResourceBundle, shown in Example 9-3, defines the fully qualified resource bundle name using the baseName attribute. All of the property keys that are used in the resource bundle are declared using the wcfResourceBundleKey class.

This class is defined in the extCatalogManagementResourceBundle.lzx file under the LOBTools/WebContent/WEB-INF/src/lzx/redbooks/catalog directory.

Example 9-3 Resource bundle class definition

<library><class name="extCatalogResourceBundle"

extends="wcfResourceBundle" baseName="com.redbooks.commerce.client.lobtools.properties.CatalogLOB">

<!-- Price Comparison component resource bundle keys --><wcfResourceBundleKey name="priceTab"/><wcfResourceBundleKey name="priceListTitle"/><wcfResourceBundleKey name="merchantColumnTitle"/><wcfResourceBundleKey name="priceColumnTitle"/><wcfResourceBundleKey name="noPriceFound"/><wcfResourceBundleKey name="numberOfPricesFound"/><wcfResourceBundleKey name="serviceError"/><wcfResourceBundleKey name="priceRange"/><wcfResourceBundleKey name="serviceKey"/><wcfResourceBundleKey name="serviceURL"/>

Note: The following sections include code snippets along with explanations for the main parts of this customization. For complete source code, refer to the zip archive that we provided for this example. The contents of the zip archive might be imported into your workspace under the LOBTools project.

Some of the files in this archive might already exist in your workspace if you did other examples in this Redbooks publication or if we are making changes to files that are part of the WebSphere Commerce product. In such cases, we recommend that you merge the changes manually instead of overwriting files in your workspace with the files that we provided for this example.

148 WebSphere Commerce Line-of-Business Tooling Customization

Page 167: My Tutorial

</class><extCatalogResourceBundle id="extCatalogResources"/></library>

The resource bundle file CatalogLOB.properties is created in the package com.redbooks.commerce.client.lobtools.properties, which is located under the LOBTools/src folder, as shown in Example 9-4.

Example 9-4 Resource bundle content

#--Price Comparison component labelspriceTab=PricepriceListTitle=Price ListmerchantColumnTitle=MerchantpriceColumnTitle=Price

#--Price Comparison component messagesnoPriceFound=No offers found.numberOfPricesFound={number} offers found.priceRange=Price range: {minimumPrice} to {maximumPrice}.serviceError=Unable to retrieve offers from service provider.

#--Price Comparison component CNET Developer key. Register with CNET to get a developer key and enter the value here.serviceKey=<ENTER YOUR KEY HERE>

#--Price Comparison component CNET Service URL. DO NOT CHANGE THIS.serviceURL=http://api.cnet.com/restApi/v1.0/techProductSearch?partKey={serviceKey}&query={partnumber}&criteria=minOffers%3D1%7ChasGoodBad%3Dtrue&iod=hlPrice%2Coffers%2CgoodBad&orderBy=price&sortDesc=true&start=0&results=10

Chapter 9. Price comparison mashup 149

Page 168: My Tutorial

9.3.2 Price comparison class definition

In this section, we review the price comparison widget class definition. This class, extCatalogProductPriceGrabber, extends from the OpenLaszlo view class. It is defined in the extPriceGrabber.lzx file, which is located under the LOBTools/WebContent/WEB-INF/src/lzx/redbooks/components directory.

This class requires the following inputs:

� property: This is a class attribute to hold a partnumber. The value of this attribute is used to build the CNET request URL.

� serviceKey: This is the developer ID, which is a required input for the CNET API. Define it in the resource bundle, CatalogLOB.properties.

� serviceURL: This is the CNET service URL, which is defined in the resource bundle, CatalogLOB.properties. The parameters {partnumber} and {serviceKey} in this URL are replaced with the property attribute and serviceKey values respectively, before issuing the request to CNET.

The price comparison class defines the following methods:

� resetCustomAttributes: Sets the message attributes to an empty string (see section “Status area” on page 153). This method is called before a request is made to the CNET API.

� setProperty: This is the setter method for the property attribute. When ever the property value is changed, this method calls the updateValue method.

� updateValue: This method formats the CNET request URL and issues an http request.

We break up the discussion of the price comparison class into the following components:

� An HTTP dataset (LzDataset) to communicate with CNET API.� A custom grid to display merchant pricing information in the CNET response.� A status area to display messages.� A datapointer to process CNET response and set status messages.

The following sections go through each of the components.

150 WebSphere Commerce Line-of-Business Tooling Customization

Page 169: My Tutorial

HTTP Dataset declarationThe OpenLaszlo dataset class, shown in Example 9-5, is declared with the following attributes:

� type: Set to HTTP to indicate that the src attribute is a URL to load dynamic data from, and not a static XML file location.

� request: Set to false because we do not want the dataset to issue a request when it initializes.

� querytype: HTTP request method that is set to get.

If the request fails or times out, we want to present the user with a service failure message. We use the handler class to define handler methods for onerror and ontimeout events of the dataset class. The handler methods set the service failure error message in the errorMessage attribute of the price comparison class. (See section “Status area” on page 153).

Example 9-5 Dataset definition

<!-- HTTP data set to issue requests to CNET service --><dataset name="extCatalogProductPriceGrabberData" type="http" request="false" querytype="get" >

<handler name="onerror" args="a"><![CDATA[

classroot.setAttribute("errorMessage", extCatalogResources.serviceError.string);

]]></handler><handler name="ontimeout" args="a"><![CDATA[

classroot.setAttribute("errorMessage", extCatalogResources.serviceError.string);

]]></handler>

</dataset>

Chapter 9. Price comparison mashup 151

Page 170: My Tutorial

Custom grid declarationWe extend OpenLaszlo basegrid, basegridcolumn, and basescrollbar classes to create a custom grid that has a WebSphere Commerce look. The custom classes are defined in the extPriceGrabberGrid.lzx and extPriceGrabberGridColumn.lzx files under the LOBTools/WebContent/WEB-INF/src/lzx/redbooks/components directory.

Example 9-6 shows the custom grid declaration that is inside of the price comparison class.

We bind the HTTP dataset to the custom grid extPriceGrabberGrid using its datapath attribute. The contentdatapath attribute specifies the datapath to be used for the contents of the grid. Each column of the grid is declared using the extPriceGrabberGridcolumn class. The merchant logo is displayed using an image class, and the merchant name and price are displayed using the text class.

The resource attribute of the image class and the datapath attribute of the text class use XPATH expressions to resolve data to be displayed from the XML response. Because we defined the contentdatapath of the grid to be “TechProducts/TechProduct[1]/Offers[1]/Offer”, the XPATH expressions that the image and text classes use are relative to the contentdatapath value.

Example 9-6 Grid definition

<extPriceGrabberGrid datapath="local:classroot.extCatalogProductPriceGrabberData:/CNETResponse/"

contentdatapath="TechProducts/TechProduct[1]/Offers[1]/Offer" rowheight="50" selectable="false"showhlines="true"showhscroll="false"width="${parent.width}"height="${parent.height-21}"><!-- Merchant logo column --><extPriceGrabberGridcolumn sortable="false" width="250">

<image resource="$path{ 'Merchant/ImageURL/text()' }" valign="middle" x="$once{parent.x+5}"></image>

</extPriceGrabberGridcolumn><!-- Merchant name column --><extPriceGrabberGridcolumn width="250"

text="${extCatalogResources.merchantColumnTitle.string}"><text visible="true"

width="${parent.width}" valign="middle"

152 WebSphere Commerce Line-of-Business Tooling Customization

Page 171: My Tutorial

resize="false"datapath="Merchant/Name/text()" />

</extPriceGrabberGridcolumn><!-- Offer price column --><extPriceGrabberGridcolumn width="200"

text="${extCatalogResources.priceColumnTitle.string}"><text visible="true"

width="${parent.width}" valign="middle"resize="false"datapath="Price/text()" />

</extPriceGrabberGridcolumn><extPriceGrabberGridcolumn width="900"></extPriceGrabberGridcolumn>

</extPriceGrabberGrid>

Status areaThe status area is displayed right below the custom grid. It uses two text classes: one to display the price range message or error message and another to display the offer count message, as shown in Example 9-7 on page 154. The message text that is displayed comes from the following attributes of the price comparison class:

� successMessage: This attribute holds the price range message for a successful request.

� offerMessage: This attribute holds the offer count message for a successful request.

� errorMessage: This attribute holds error message to be displayed (if any). If the errorMessage attribute has a value, both successMessage and offerMessage values are empty.

We use constraints to create a dependency between the text classes in the status area and the message attributes. The following constraints are defined on the text attribute of the status area text classes:

� The first text class has a constraint that checks the successMessage and errorMessage attribute lengths and displays the attribute that has a value. When either of these attributes is modified, this constraint is evaluated.

� The second text class has a constraint that displays the offerMessage attribute. This constraint is evaluated when the offerMessage attribute is modified.

The success/error message text class also defines a handler method for its ontext event. When the text value that is displayed is modified, this handler

Chapter 9. Price comparison mashup 153

Page 172: My Tutorial

method changes the text foreground color to red if the content is an error message.

Example 9-7 Grid status area

<!-- Status area, displays success/error message and offer count --><view width="${parent.width}"><view y="-1" width="${parent.width}" resource="gridFooterResource" stretches="width"></view>

<text x="${parent.x+5}" selectable="true" y="0" text="$always{classroot.successMessage.length > 0 ? classroot.successMessage : classroot.errorMessage}"> <handler name="ontext"> if (classroot.successMessage.length > 0) { this.setColor(0x000000); } else { this.setColor(0xff0000); } </handler> </text>

<text x="${parent.width-this.width-5}" y="0" text="$always{classroot.offerMessage}"></text>

</view>

Datapointer declarationWe create a data pointer to point to the root node of the XML response from the HTTP dataset, as shown in Example 9-8 on page 155. This datapointer inspects the response XML and sets the status message attributes successMessage, offerMessage and errorMessage.

The datapointer registers the method setResultSize to be called when the ondata event is fired. The setResultSize method uses the following XPATH expressions to format status messages:

� Error/ErrorMessage: Service error message (if any) from the CNET API. If a value is returned by this XPATH expression, we set the errorMessage attribute.

� TechProducts/@numReturned: This XPATH expression returns the number of products in the response XML. If the value of this expression is zero, then

154 WebSphere Commerce Line-of-Business Tooling Customization

Page 173: My Tutorial

product data does not exist in CNET. In this case, we set the errorMessage attribute.

� TechProducts/TechProduct[1]/Offers[1]/@numReturned: This XPATH expression returns the number of prices that are available for the product. If the value of this expression is zero, we set the error message attribute; otherwise, we set the offerMessage attribute.

� TechProducts/TechProduct[1]/LowPrice: This XPATH expression retrieves the lowest price.

� TechProducts/TechProduct[1]/HighPrice: This XPATH expression retrieves the highest price.

If both the lowest price and the highest price are available, we set the price range message in the successMessage attribute.

Example 9-8 Datapointer to set status message

<datapointer name="resultDataPointer" xpath="local:classroot.extCatalogProductPriceGrabberData:/CNETResponse" ondata="setResultSize()" ><method name="setResultSize"><![CDATA[ var error = this.xpathQuery( 'Error/ErrorMessage/text()' ); if (error != null && error.length > 0) { if (error.indexOf('.') != -1) error = error.substring(0, error.indexOf('.')); classroot.setAttribute("errorMessage", error); return; } var productCount = this.xpathQuery( 'TechProducts/@numReturned' ); var offerCount = this.xpathQuery( 'TechProducts/TechProduct[1]/Offers[1]/@numReturned' ); if (productCount != null && offerCount != null && productCount > 0 && offerCount > 0) { classroot.setAttribute("offerMessage", classroot.replaceStringValue(extCatalogResources.numberOfPricesFound.string, "{number}", offerCount)); var lowPrice = this.xpathQuery( 'TechProducts/TechProduct[1]/LowPrice/text()' ); var highPrice = this.xpathQuery( 'TechProducts/TechProduct[1]/HighPrice/text()' ); if (lowPrice != null && lowPrice.length > 0 && highPrice != null && highPrice.length > 0) { classroot.setAttribute("successMessage",

Chapter 9. Price comparison mashup 155

Page 174: My Tutorial

classroot.replaceStringValue( classroot.replaceStringValue(extCatalogResources.priceRange.string, "{minimumPrice}", lowPrice), "{maximumPrice}", highPrice)); } } else { classroot.setAttribute("errorMessage", extCatalogResources.noPriceFound.string); }]]></method></datapointer>

9.3.3 Property component definition

We create a property component to bind the new price comparison widget to the partnumber property of a Product object. This new property component is included in the pricing section property group (See section “Creating a new property pane” on page 159).

The property component class extCatalogProductPriceGrabberComponent is defined in the extPriceGrabberPropertyComponent.lzx file, which is located under the LOBTools/WebContent/WEB-INF/src/lzx/redbooks/components directory.

This class extends from the wcfPropertiesComponent and defines the following methods:

� createEditor: This is a method, shown in Example 9-9 on page 157, which all sub classes of wcfPropertiesComponent should implement. It creates an instance of the price comparison class, extCatalogProductPriceGrabber, and sets the property attribute of the price comparison widget to the partnumber of the current product that is being edited.

156 WebSphere Commerce Line-of-Business Tooling Customization

Page 175: My Tutorial

Example 9-9 createEditor method

<!-- Return PriceGrabber component as editor --><method name="createEditor" args="parentComponent"><![CDATA[ var availableWidth = parentComponent.width - parentComponent.promptWidth - parentComponent.xspacing;

new extCatalogProductPriceGrabber(parentComponent, { name: "pricelist", x: parentComponent.promptWidth + parentComponent.xspacing, enabled: parentComponent.enabled, width: availableWidth, property: this.o.getPropertyValue("partnumber","") });]]></method>

� setModelObject: Overrides setModelObject (Example 9-10) in the parent class to:

– Set the property attribute of the price comparison widget when the product object selection changes.

– Create and register a LzDelegate to listen to onvalue events for the partnumber property of the product object. When the partnumber value is changed, this delegate calls the updatePropertyObject method.

Example 9-10 setModelObject method

<method name="setModelObject" args="newObject"><![CDATA[ super.setModelObject(newObject); var newProperty = null; if (typeof(this.o) != "undefined" && this.o != null) { newProperty = this.o.getPropertyValue("partnumber",""); } if (this["pricelist"]) { this.pricelist.setAttribute("property", newProperty); } var newPropertyObject = this.o.getProperty("partnumber","",true); if (typeof(this["propertyObject"]) == "undefined" || newPropertyObject != this["propertyObject"]) { if (typeof(this.updatePropertyObjectDel) == "undefined") { this.updatePropertyObjectDel = new LzDelegate(this, "updatePropertyObject"); }

Chapter 9. Price comparison mashup 157

Page 176: My Tutorial

this.updatePropertyObjectDel.unregisterAll(); this.propertyObject = newPropertyObject; if (this.propertyObject != null) { this.updatePropertyObjectDel.register(this.propertyObject, "onvalue"); if (this.isinited) { this.updatePropertyObject(); } } }]]></method>

� updatePropertyObject: Called when the partnumber property of a product is modified. This method, shown in Example 9-11, sets the property attribute of the price comparison widget with the new partnumber value.

Example 9-11 updatePropertyObject method

<method name="updatePropertyObject"><![CDATA[ if (typeof(this.propertyObject) != "undefined" && this.propertyObject != null && typeof(this.pricelist) != "undefined") { this.pricelist.setAttribute("property", this.propertyObject.value); }]]></method>

� destroy: Deletes the LzDelegate that this class creates. See Example 9-12.

Example 9-12 destroy method

<method name="destroy"><![CDATA[ if (this["updatePropertyObjectDel"]) { this.updatePropertyObjectDel.unregisterAll(); delete this.updatePropertyObjectDel; } super.destroy();]]></method>

158 WebSphere Commerce Line-of-Business Tooling Customization

Page 177: My Tutorial

9.3.4 Updating the product properties view

In the following sections, we explain the customizations that were made to the WebSphere Commerce product files to integrate the new price comparison widget with the catalog tool product properties view.

Creating a new property paneThe property groups that the product properties view uses are defined in the CatalogPropertyPane.lzx file, which is located under the LOBTools/src/lzx/commerce/catalog/propertiesViews directory.

Create a new property group, extCatalogProductPricePropertyGroup, in this file, as shown in Example 9-13. Make sure that the new property group includes the following components:

� List price child list viewer� Offer price child list editor� Price comparison property component

Example 9-13 New property group for Pricing section

<class extends="wcfPropertyGroup" groupTitle="${catalogResources.pricingSection.string}" name="extCatalogProductPricePropertyGroup" open="true">

<!-- Child List Editor: A table to display list price for the catalog entry in different currencies. --> <wcfChildListViewer name="listPriceClv" listClass="catListPriceObjectGrid" objectTypes="CatalogEntryListPrice" promptText="${catalogResources.listPricePrompt.string}" extendedHelpText="${catalogResources.extendedHelpText_listprice.string}"/>

<!-- Child List Editor: A table to display different offers for the catalog entry in different currencies. --> <wcfPropertyChildListEditor name="offersCle" listClass="catOfferObjectGrid" objectTypes="CatalogEntryOffer" promptText="${catalogResources.offerPricePrompt.string}" extendedHelpText="${catalogResources.extendedHelpText_offerprice.string}"/>

<!-- Price Grab Component: Display competitor prices for product. --> <extCatalogProductPriceGrabberComponent

Chapter 9. Price comparison mashup 159

Page 178: My Tutorial

promptText="${extCatalogResources.priceListTitle.string}" /></class>

Create a property pane, as shown in Example 9-14, to use the new property group, extCatalogProductPricePropertyGroup.

Example 9-14 Price property pane definition

<class name="extCatalogProductPricePane" extends="wcfPropertyPane"> <extCatalogProductPricePropertyGroup /></class>

Updating the Manage Product tabThe property pane, catManageProduct, is defined in the CatalogPropertyPane.lzx file.

Comment out the property group catManagePricingInformation from the property pane catManageProduct, as shown in Example 9-15, which removes the pricing section from the Manage Product tab.

Example 9-15 Remove Pricing section from Manage product tab

<class name="catManageProduct" extends="wcfPropertyPane"> <catManageGeneralProductInformation/> <catManagePublishingInformation/> <catManageDisplayInformation/>

<!-- Redbooks customization: Disable Pricing section in Manage product tab, this is moved to the new Price tab --> <!-- <catManagePricingInformation/> -->

<!-- This tag is disabled by default. To enable it, uncomment the tag below --> <!-- <catManageAdditionalInformation/> --></class>

Creating the Pricing tabThe product properties view class, catProductProperties, is defined in the file ProductPropertiesView.lzx, which is located under the LOBTools/src/lzx/commerce/catalog/propertiesView directory.

Update this file to create a new tab pane, extManagePriceTab, as shown in Example 9-16 on page 161. This new tab displays the price property pane,

160 WebSphere Commerce Line-of-Business Tooling Customization

Page 179: My Tutorial

extCatalogProductPricePane (See section “Creating a new property pane” on page 159).

Example 9-16 Price tab pane

<class extends="wcfObjectProperties" name="catProductProperties"><!-- This is the set of tabs to display on the Product properties view --> <wcfPropertyTabs name="tabs"> <!-- Tab: Manage Product. This tab contains general information about the selected product such as name, and description. --> <wcfPropertyTabPane name="manageProductTab" text="${catalogResources.manageProductTab.string}"> <!-- Property Pane: Manage Product. This is an instantiation of the property pane class which contains general product details. --> <catManageProduct/> </wcfPropertyTabPane>

<!-- Redbooks customization: New price tab pane. --> <!-- Tab: Price. This tab contains list/offer prices and competitor pricing information (if available) --> <wcfPropertyTabPane name="extManagePriceTab" text="${extCatalogResources.priceTab.string}"> <!-- Property Pane: Price. This is an instantiation of the proprty pane class which includes Price Grabber component, and list/offer prices child list viewers previously in Manage product tab. --> <extCatalogProductPricePane /> </wcfPropertyTabPane> . . . </wcfPropertyTabs></class>

Note: Example 9-16 does not include the complete source of the catProductProperties class. Refer to the ProductPropertiesView.lzx file for the complete source code.

Chapter 9. Price comparison mashup 161

Page 180: My Tutorial

9.3.5 Updating the library file

We include all of the OpenLaszlo files that were created for this customization in the catalog extensions library file CatalogExtensionsLibrary.lzx, as shown in Example 9-17. This file is located under the WebContent\WEB-INF\src\lzx\commerce\catalog directory. The Management Center reads this file to recognize all OpenLaszlo files that were created to extend the catalog tool.

Example 9-17 Include new files in CatalogExtensionsLibrary.lzx

<!-- Catalog resource bundle extension --><include href="../../redbooks/catalog/extCatalogManagementResourceBundle.lzx" />

<!-- Price grabber component --><include href="../../redbooks/components/extPriceGrabberGrid.lzx" /><include href="../../redbooks/components/extPriceGrabberGridColumn.lzx" /><include href="../../redbooks/components/extPriceGrabber.lzx" /><include href="../../redbooks/components/extPriceGrabberPropertyComponent.lzx" />

9.4 Testing the customization

To test this customization:

1. Before you test the customization, register for a developer key with CNET.com. Use the following Web site to register with CNET:

http://membership.cnet.com/1383-4_1-172.html?path=http%3A%2F%2Fapi.cnet.com%2Fdashboard.html

2. Update the CatalogLOB.properties file, which is located under the package com.redbooks.commerce.client.lobtools.properties with the developer key from CNET.com, as shown in Example 9-18.

Example 9-18 Update developerKey property

#--Price Comparison component CNET Developer key. Register with CNET to get a developer key and enter the value here.serviceKey=<ENTER YOUR KEY HERE>

3. Build the LOBTools project, and start the WebSphere Commerce server.

162 WebSphere Commerce Line-of-Business Tooling Customization

Page 181: My Tutorial

4. Load the sample technology products to the ConsumerDirect catalog. A catalog import CSV file is provided in the zip archive file for this example. Use the Catalog Import tool in WebSphere Commerce Accelerator to load and publish this data. This creates a category that is named LCD Television and also creates products under this category.

5. Launch the Management Center.

6. Open the Catalog tool, select the ConsumerDirect store, and navigate to the LCD Television category, as shown in Figure 9-3.

Figure 9-3 Catalog tool - Product list

7. From the product list, open a product, and in the properties view, select the Price tab. This tab, shown in Figure 9-4 on page 164 should include the list price grid, offer price grid, and the new price comparison grid.

Note: For detailed information about loading the catalog data using WebSphere Commerce Accelerator, refer to the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.user.doc/tasks/tcacsvld.htm

Chapter 9. Price comparison mashup 163

Page 182: My Tutorial

Figure 9-4 Price tab - Includes new price comparison grid

164 WebSphere Commerce Line-of-Business Tooling Customization

Page 183: My Tutorial

Chapter 10. Customizing user preferences

In this chapter, we discuss how to add a new user preference to the Management Center. We add an option to enable or disable the Price Comparison feature that we built in Chapter 9, “Price comparison mashup” on page 143.

10

© Copyright IBM Corp. 2008. All rights reserved. 165

Page 184: My Tutorial

10.1 Understanding the requirements

Using the Preferences dialog in the Management Center, you can set preferences, such as default store name, language, locale, and so on. The dialog is available from the Management Center menu, as shown in Figure 10-1.

Figure 10-1 Management Center menu

Figure 10-2 illustrates the default Preferences dialog.

Figure 10-2 Preferences dialog

You can set the following global preferences using the Preferences dialog:

� Default store to be used when a tool is opened� Default language to be used when a tool is opened� Default cultural locale that determines the number format in the tool� Whether to enable the Extended Help feature or not

166 WebSphere Commerce Line-of-Business Tooling Customization

Page 185: My Tutorial

The default language is persisted as the preferred language of the user in the USERS table (USERS.LANGUAGE_ID), which is located in the database. Other preferences are persisted in the database as custom member attributes on a per user basis.

In Chapter 9, “Price comparison mashup” on page 143, we built a price comparison feature to compare product prices from different service providers. The requirement is to allow the business user to enable or disable the feature and, when required, without any IT intervention. To satisfy this requirement, we must customize the Preferences dialog and add a new user preference.

Figure 10-3 shows how the customized Preferences dialog should appear.

Figure 10-3 Customized Preferences dialog

10.2 Building the customization

The first step in building the customization is to determine the assets that we must customize to support this requirement. We need to ascertain if it requires user interface changes, server side changes, or both.

Note: To add a new user preference, you should have at least Feature Pack 4 installed because the wcfUserPreferenceObject class is declared private in previous versions.

Chapter 10. Customizing user preferences 167

Page 186: My Tutorial

10.2.1 Customizing the client side

In this section, we identify the OpenLaszlo classes that implement the Preferences dialog. To customize the client side:

1. Open a Java perspective in WebSphere Commerce Developer, and from the menu select Window → Open Perspective → Java.

2. Simultaneously press the Control + Shift + R keys, or from the menu, select Navigate → Open Resource.

3. In the Open Resource dialog, type *Preference*.lzx, as shown in Figure 10-4.

Figure 10-4 Open Resource dialog

The following list provides information about the matching resources files from Figure 10-4:

� PreferenceManager.lzx: This file contains the wcfPreferenceManager class, which is the base class for storing and managing preferences. This class

168 WebSphere Commerce Line-of-Business Tooling Customization

Page 187: My Tutorial

handles all preferences that are captured in the Management Center, stores them as attributes in the class, and persists them as custom member attributes to the database. wcfPreferenceManager is a private class that we cannot modify.

� UserPreferenceDialog.lzx: This file contains the user preference dialog, which is opened when we select Preferences from the Management Center menu. The private class, wcfUserPreferenceDialog, contains the user preference panel and the OK and Cancel buttons.

� UserPreferenceObjects.lzx: This file contains the wcfUserPreferenceObject class, which is the base class that represents a user preference object. All preferences that are in the Management Center extend from this class, for example, wcfStorePreference defines the default store preference. For the new user preference, we create a new class that extends from wcfUserPreferenceObject and implement the methods that belong to this class.

� UserPreferencePanel.lzx: This file defines all of the widgets that are in the user preference dialog box. We include a widget to represent the option to enable or disable the price comparison feature.

Extending the resource bundle and properties filesIn this section, we create a new resource bundle and corresponding properties files to hold the translatable text. Create your own resource bundles, and do not modify the ones that come out of the box.

1. Create a properties file:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → Java Resources → src.

b. Right-click src, and select New → Package.

c. In the Name field, enter com.redbooks.commerce.client.lobtools.properties as the package name, and click Finish. The package is created.

d. Right-click the com.redbooks.commerce.client.lobtools.properties package, choose New → Other → Simple → File, and click Next.

Note: Some of the files and directories that we use in the following sections might already exist if you worked through any of the previous examples in this book. If that is the case, ignore the steps to create those directories and files.

Chapter 10. Customizing user preferences 169

Page 188: My Tutorial

e. In the File name field, enter extShellLOB.properties, and click Finish. The extShellLOB.properties file opens.

f. Define the properties, as given in Example 10-2.

Example 10-1 Defining the properties file

userPreferencePriceComparisonPrompt=Enable price comparison feature

2. Register the new properties file in the resource bundle:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx.

b. Right-click lzx, and select New → Folder.

c. In the File name field, enter redbooks, and click Finish.

d. Right-click redbooks, and select New → Folder.

e. In the File name field, enter shell, and click Finish.

f. Right-click shell, select New → Other → Simple → File, and click Next.

g. In the File name field, enter extShellResourceBundle.lzx.

h. Click Finish. The extShellResourceBundle.lzx file opens.

i. Add the code in Example 10-3 on page 171 to the file.

Example 10-2 Defining the resource bundle

<library><class name="extShellResourceBundle"

extends="wcfResourceBundle" baseName="com.redbooks.commerce.client.lobtools.properties.extShellLOB">

<wcfResourceBundleKey name="userPreferencePriceComparisonPrompt" />

</class><extShellResourceBundle id="extShellResources"/>

</library>

j. Save and close the file.

170 WebSphere Commerce Line-of-Business Tooling Customization

Page 189: My Tutorial

3. Include extShellResourceBundle.lzx in the extension library so that it is recognized by Management Center and available for use:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell.

b. Open the ShellExtensionsLibrary.lzx file.

c. Update the file, as shown in Example 10-4 on page 172 to point to the new resource bundle file.

Example 10-3 Including the resource bundle in the library

<library><include href=”../../redbooks/shell/extResourceBundle.lzx” />

</library>

d. Save the file.

Defining the new user preferenceIn this section, we create a class that defines the new user preference option. This class extends from wcfUserPreferenceObject and implements a set of methods that are available in wcfUserPreferenceObject. To define the new user preference:

1. Define a default value for the preference:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell.

b. Open the ConfigProperties.lzx file. This file contains the class wcfConfigProperties that defines the default values of all globally

Note: If you are using Feature Pack 3.0.1, edit ShellLibrary.lzx to fix a minor issue:

1. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell → restricted.

2. Open the ShellLibrary.lzx file.

3. Move the following entry to the end of the file just before the closing </library> tag: <include href=”../ShellExtensionsLibrary.lzx” />

This issue is fixed in Feature Pack 4.

Chapter 10. Customizing user preferences 171

Page 190: My Tutorial

configurable properties that are used in Management Center, which includes the user preferences as well.

c. Include the following attribute in Example 10-5 just before the closing </class> tag.

Example 10-4 Defining a default value for the preference

<attribute name=”defaultPriceComparisonEnabled” type=”string” value=”true” />

This value is the default for a user who does not have the user preferences set.

d. Save the file.

2. Create the new class extPriceComparisonPreference:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → redbooks → shell.

b. Right-click shell, select New → Other → Simple → File, and click Next.

c. In the File name field, enter extUserPreferenceObjects.lzx.

d. Click Finish. The extUserPreferenceObjects.lzx file opens.

e. Paste the code in Example 10-5 into the file.

Example 10-5 Defining the new user preference object

<library><class name="extPriceComparisonPreference"

extends="wcfUserPreferenceObject"><!--- Name of the preference. --><attribute name="preferenceName" type="string"

value="CMCPriceComparisonEnabled" />

<!---This method returns the value of this preference.@returns string: value of this preference

--><method name="getValue">

<![CDATA[return

this.priceComparisonEnabled.getValue().toString();]]>

</method>

<!---

172 WebSphere Commerce Line-of-Business Tooling Customization

Page 191: My Tutorial

This method sets the value of this preference from the map object in preference manager

to the object in the user interface.--><method name="loadValue">

<![CDATA[if

(preferenceManager.getPreference(this.preferenceName) == undefined) {

preferenceManager.setPreference(this.preferenceName, configProperties.defaultPriceComparisonEnabled);

}

this.priceComparisonEnabled.setValue(preferenceManager.getPreference(this.preferenceName));

]]></method>

<wcfBaseCheckbox name=”priceComparisonEnabled” text="${extShellResources.userPreferencePriceComparisonPrompt.string}" />

</class></library>

f. Save the file.

wcfUserPreferenceObject defines the following methods, which you can override to provide your own implementation:

oninit This handler is called an initialization of the user preference.

applyValue This method applies the preference value to the global preference setting.

getValue This method returns the value of the preference. By default it returns null. We implement this method to return the value of the check box.

loadValue This method loads the preference value from the preference manager to the object in the user interface. By default this method does nothing. We implement this method to load the saved value of the preference. If the logged-in user does not have this preference set, we load the default value from wcfConfigProperties.

Chapter 10. Customizing user preferences 173

Page 192: My Tutorial

validateValue This method validates the value of the preference that the user enters. By default this method returns true. We do not implement this method in our example because the user input is just a check box; however, it can be implemented if the user’s input is some text or a numerical value.

3. Include extUserPreferenceObjects.lzx in the extension library so that it is recognized by Management Center and available for use:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell.

b. Open the ShellExtensionsLibrary.lzx file.

c. Include extUserPreferenceObjects.lzx, as shown in Example 10-6.

Example 10-6 Including the resource bundle in the library

<library><include

href=”../../redbooks/shell/extUserPreferenceObjects.lzx” /></library>

d. Save the file.

4. Include the new preference widget in the Preferences dialog. The file UserPreferencesPanel.lzx defines the Preferences dialog. We include the newly created preference object (created in Step 2) here so that it shows up on the Preferences dialog:

a. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell.

b. Open the UserPreferencePanel.lzx file.

c. At the end of the file, the class wcfUserPreferencePanel is defined, as shown in Example 10-8.

Example 10-7 Original wcfUserPreferencePanel

<class name="wcfUserPreferencePanel"><wcfStorePreference /><wcfLanguagePreference listClass="wcfLanguageList"

enabled="false" /><wcfLocalePreference listClass="wcfLocaleList" /><wcfStylePreference listClass="wcfStyleList"

visible="false" /><wcfExtendedHelpPreference />

174 WebSphere Commerce Line-of-Business Tooling Customization

Page 193: My Tutorial

<simplelayout axis="y" spacing="15" /></class>

Include the extPriceComparisonPreference class, as shown in bold in Example 10-9.

Example 10-8 Customized wcfUserPreferencePanel

<class name="wcfUserPreferencePanel"><wcfStorePreference /><wcfLanguagePreference listClass="wcfLanguageList"

enabled="false" /><wcfLocalePreference listClass="wcfLocaleList" /><wcfStylePreference listClass="wcfStyleList"

visible="false" /><wcfExtendedHelpPreference /><extPriceComparisonPreference /><simplelayout axis="y" spacing="15" />

</class>

Using the new preference in the price comparison codeIn this section, we use the new user preference option to control the visibility of the price comparison widget. For more information regarding the price comparison feature, refer to Chapter 9, “Price comparison mashup” on page 143.

To use the new user preference:

1. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → redbooks → components.

2. Open the extPriceGrabberPropertyComponent.lzx file.

3. In the class extCatalogProductPriceGrabberComponent, add the init method, as shown in Example 10-10 on page 176.

Example 10-9 The init method

<method name="init"><![CDATA[

super.init();var pref =

preferenceManager.getPreference("CMCPriceComparisonEnabled");if (pref == "true") {

this.setAttribute("visible", true);}else {

this.setAttribute("visible", false);

Chapter 10. Customizing user preferences 175

Page 194: My Tutorial

}]]>

</method>

In the init method, we use the Preference Manager to retrieve the value of the user preference. If the value is “true” we set the “visible” attribute of extCatalogProductPriceGrabberComponent to true; otherwise, we set it to false. So if the user selected the check box against ‘Enable price comparison feature’ in the Preferences dialog, the price comparison feature is enabled; otherwise, it is disabled.

4. When a user changes the preference, the Management Center should automatically update the price comparison widget to reflect the change. To achieve this we use an event handler. When a user preference changes, the Preference Manager sends an event called preferenceChanged. Any object that wants to be notified of a change of preferences can handle this event. To handle the event, add the code in Example 10-11 on page 177 to extCatalogProductPriceGrabberComponent just after the init method that we added in step 3.

Example 10-10 The event handler

<handler name="preferenceChanged" reference="preferenceManager" args="preference">

<![CDATA[//if this event is for the CMCPriceComparisonEnabled

preferenceif (preference == "CMCPriceComparisonEnabled") {

this.init();}

]]></handler>

In the event handler, we check if CMCPriceComparisonEnabled is the preference for which the current event was generated and call the init method in case it is. The init method will again check the preference and enable or disable the price grabber accordingly.

10.2.2 Customizing the server side

In the previous section, we covered the user interface changes that are required for adding a new user preference. In this section, we look at the required server-side customizations.

As we discussed in the previous section, wcfPreferenceManager (in PreferenceManager.lzx) stores and manages the user preferences. The

176 WebSphere Commerce Line-of-Business Tooling Customization

Page 195: My Tutorial

Preference Manager calls the service /cmc/SavePreferences to save the user preferences in the submitSavePreferences method. The file struts-ibm-foundation.xml contains all of the predefined URLs that the shell requires. The SavePreferences URL is mapped to the updatePerson method of MemberFacadeClient, as shown in Example 10-11.

Example 10-11 Service mapping in struts-ibm-foundation.xml

<action path="/SavePreferences" parameter="Person"

type="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentClientLibraryAction"

className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentActionMapping">

<set-property property="clientLibrary"

value="com.ibm.commerce.member.facade.client.MemberFacadeClient" /><set-property property="clientLibraryMethod"

value="updatePerson" /></action>

The updatePerson method is mapped to the UserRegistrationUpdateCmd.

The UserRegistrationUpdateCmd stores the user preferences as custom member attributes in the MBRATTR and MBRATTRVAL tables. We need to define a custom attribute for the price grabber option. Execute the SQL statement in Example 10-12 to define the custom attribute.

Example 10-12 Defining the custom member attribute

insert into MBRATTR (MBRATTR_ID, ATTRTYPE_ID, NAME, DESCRIPTION) values (1,'STRING','CMCPriceComparisonEnabled','Default flag for Price Comparison feature in CMC');

CMCPriceComparisonEnabled is the name of the attribute that we defined in ConfigProperties.lzx in step 1 on page 171.

Note: For more information about the Member services, refer to the WebSphere Commerce V6 Information Center:

ChangePerson

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.component-services.doc/refs/rmschangeperson.htm

Chapter 10. Customizing user preferences 177

Page 196: My Tutorial

10.2.3 Testing the customization

To test our customization:

1. Build the LOBTools project:

a. Right-click LOBTools.b. From the Context menu, select Build Project.

2. Restart the WebSphere Commerce server. This is necessary because we inserted a record into a database table.

3. Open the Management Center.

4. From the Management Center menu, select the Preferences menu item.

5. Notice the check box against the text ‘Enable price comparison feature’. The check box should be selected by default because we set the default value of the preference to true in ConfigProperties.lzx.

6. Open the Catalog tool, and select the ConsumerDirect store.

7. In the Explorer view, navigate to the LCD Television category.

8. Right-click a product, from the Context menu, select Open.

9. Click the Price tab. The price comparison widget is visible.

10.From the Preferences dialog, disable the price comparison feature. The price comparison widget should disappear from the Price tab of the product that you have open.

Note: For more information about defining custom member attributes, see Defining custom attributes for member URLs in the WebSphere Commerce Information Center.

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.developer.doc/tasks/tmsdfatt.htm

178 WebSphere Commerce Line-of-Business Tooling Customization

Page 197: My Tutorial

Chapter 11. Spell Checker

In this chapter, we build a spell checking feature that you can use to spell check and correct the text fields of the properties panels of the Management Center. The customizations for this feature are almost entirely within the OpenLaszlo code of the Presentation layer.

We explore the capabilities of OpenLaszlo as a prototyping environment, followed by a progression, in example stages, to a final solution. We describe those stages in this section.

This example, and the example in Chapter 9, “Price comparison mashup” on page 143, are both examples of a client-side mashup, which is where an external service is used to augment the functionality that is available within the client application.

OpenLaszlo has some powerful features for handling the XML is returned from the type of external service that is used in a Mashup. You can easily filter the XML that is returned and bound to display widgets, and the example in this chapter demonstrates the use of these features.

The dynamic nature of the spell checker scenario provides examples of how to use JavaScript code within OpenLaszlo to handle events, which is one of the more complex topics of OpenLaszlo programming.

11

© Copyright IBM Corp. 2008. All rights reserved. 179

Page 198: My Tutorial

11.1 Understanding the requirements

In this section, we describe some typical high-level requirements for a spell checker, which a customer might propose as a change to the standard behavior of the Management Center, which we expand on to evolve some more detailed requirements.

It is common for content and catalog management tools to have a spell check and correction facility for textual descriptions, can often work with rich (formatted) text, in addition to plain text. This type of feature is typically implemented in a manner that is similar to the spell-check facility of a word processor or e-mail application.

Because this is a common feature, it has been requested by a number of customers of WebSphere Commerce.

The requirement, in general terms, is to spell check any text field. An example of where it is particularly useful is for the long and short descriptions of catalog entries. Figure 11-1 shows a product property panel that contains a long and short description field, which a user might want to spell check and correct.

Figure 11-1 Product properties panel (before modification)

The customer can edit the long description field using the rich text property editor, but the short description uses a plain text editor.

180 WebSphere Commerce Line-of-Business Tooling Customization

Page 199: My Tutorial

In a typical fit-gap analysis phase of a project, it is common to show the customer what facilities WebSphere Commerce has by default. For this example, we assume that, during this phase, the customer saw the window (Figure 11-1 on page 180), and said that they want to have:

� A spell check and correction feature.� To check and correct short and long description fields. � Capabilities that are similar to a word processing spell checker.

Normally, there would be an analysis and cos of what this feature would take to implement. In this case, as it often is, there are considerations to be made on cost, time scale, and features, which we discuss in 11.2.1, “Meeting requirements” on page 183.

Solution architects add detail to the requirements, discuss them with the customer, and get approval that the requirements include what they want. At this stage, it is important to point out to the customer that analysis is needed to determine what the cost, time scale, and feasibility implications are. Without investigation, we are unlikely to know this.

A more detailed list of requirements would be something like this:

� Spell check and correction for any of the text fields of the property editor page, for all catalog entry types

� The ability to view and correct both plain and rich text

� Similar to Lotus® Notes®, in terms of capabilities, for a screen shot, as seen in Figure 11-2 on page 182. We want the ability to:

– Highlight unknown words

– Suggest corrections that we can select and use for replace

– Edit and replace the word

– Replace one occurrence of the misspelled word

– Replace all occurrences of the misspelled word within the text field

– Skip one occurrence

– Skip all occurrences

– View unknown words that are highlighted in the context of the original text

– Process the text field, one unknown word at a time, and the ability to click accept or cancel the changes that were made

– Add the unknown word to a dictionary of words, so that it will no longer be an unknown word in the results of a spell check

� Ability to spell check and correct multiple languages

Chapter 11. Spell Checker 181

Page 200: My Tutorial

Figure 11-2 Lotus Notes spell check window

For the purposes of this publication, there was also an important non-functional requirement, which is that the service that we use for the spell check must be free and readily available. We also want to use a service that fits in well with the objective of demonstrating how to customize the Management Center; therefore, an externally hosted service will be better than a service that we have to download, deploy, and configure ourselves.

Note: A customer often has a specific list of required languages.

182 WebSphere Commerce Line-of-Business Tooling Customization

Page 201: My Tutorial

11.2 Design

This section provides an overview of the main aspects of the design.

The first thing you must do, as explained in 11.2.1, “Meeting requirements” on page 183, is to decide on what service to use, and which requirements are to be met within the time-scale constraints. For our example, we chose the service from the CDYNE Corporation which we describe in more detail in 11.2.2, “CDYNE service detail” on page 184.

The second design task we had was to decide on the best design that could use the service. This is described in 11.2.3, “Component design” on page 185.

11.2.1 Meeting requirements

A key aspect of the design for the spell checker, that we considered, was which spell check service we should use for the example. There was also the possibility of:

1. Using an external 3rd party service, via Web services or REST

2. building in a service using a library, preferably Java based.

After researching, and considering many options; we decided to use the spell check service of the CDYNE Corporation. We felt that this would meet the needs of this example.

At the time of writing, this service is free to use. It provides a simple REST interface, using a http put or get request. The service response is in XML, which fits nicely in with the data binding capabilities of OpenLaszlo. The service does not meet all of the capabilities of the requirements list of 11.1, “Understanding the requirements” on page 180, but is sufficient for the purposes of this book.

The requirements from the desired features list, that would be difficult to meet with this service, are the ability to:

1. Add the unknown word to a dictionary of words

2. Spell check and correct multiple languages.

It should be noted that, the dictionary requirement could be met by building this capability outside of the service, for example, within WebSphere Commerce. Some approaches to this are discussed in the 11.5.1, “Dictionary” on page 235. This capability was left out of the example due to the time constraints and priorities of this book.

Chapter 11. Spell Checker 183

Page 202: My Tutorial

Other requirements, that were pushed out of scope for this book, for example, were the ability to skip or replace a single occurrence of an unknown word. Again, this is due to time constraints and priorities.

11.2.2 CDYNE service detail

In this section, we explain the operation of the CDYNE service in more detail, which we need to explain before we move on to the design of our solution.

The CDYNE service has a number of usage options, which include Web services and RESTful interfacing using a put or get request. For a description of RESTful services, see:

http://en.wikipedia.org/wiki/Representational_State_Transfer

We use the RESTful option because it is simpler and fits in well with the standard features of OpenLaszlo. Using the put or get for the http request is not particularly important because both work. We chose to use put because it is not as restrictive on data volumes.

For a demonstration of the CDYNE service in action, see: http://ws.cdyne.com/SpellChecker/check.asmx?op=CheckTextBody

Enter some text into a form on that Web page, and you should see the XML result back from the service.

Alternatively, you can use the following address in your browser address bar:

http://ws.cdyne.com/SpellChecker/check.asmx?CheckTextBody?BodyText=WebSphere%20eCommerce&LicenseKey=any

After you reach the Web destination from the previous paragraph, the service should do a spell check on WebSphere Commerce and display the XML. The result, in this case, should be the same as in Example 11-1 on page 185, which you can see from the XML that this request returns:

� The total count of misspelled words� Each misspelled word � A list of suggestions for each misspelled word

Attention: At the time of writing, the CDYNE Corporation provided the Spell Check service to the specification that is outlined in this document. It was also free to use at the time of writing. There are no guarantees that CDYNE Corporation continues to operate this service to this specification, or that they will continue to offer the service on free or fee based terms.

184 WebSphere Commerce Line-of-Business Tooling Customization

Page 203: My Tutorial

Example 11-1 XML returned from CDYNE service

<?xml version="1.0" encoding="utf-8" ?> <DocumentSummary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://ws.cdyne.com/"> <MisspelledWord> <Suggestions>web sphere</Suggestions> <word>WebSphere</word> <SuggestionCount>1</SuggestionCount> </MisspelledWord> <MisspelledWord> <Suggestions>e commerce</Suggestions> <Suggestions>commerce</Suggestions> <word>eCommerce</word> <SuggestionCount>2</SuggestionCount> </MisspelledWord> <ver>1.0</ver> <body>WebSphere eCommerce</body> <MisspelledWordCount>2</MisspelledWordCount> </DocumentSummary>

11.2.3 Component design

Deciding to use the CDYNE service was one part of the design; however, we also had to decide how to implement the new feature. An important aspect of this was to minimize the development effort without breaking any of the implementation rules for Management Center customization. One particular rule is that we cannot extend any private classes or methods of the Management Center. Many of the Management Center widgets fall into this private category.

To explain how these restrictions affect the design, we first need to understand the relationship that the property panels and property editors have with the display widgets.

There are many types of Property panels. An example of one is the Product Properties Panel in Example 11-1. This panel contains a number of property editors, one for each property that we see displayed, for example, it creates a property editor for the Long Description Property.

Figure 11-3 on page 186 shows a specific example of the Product Properties Panel and highlights the displayed product’s Long Description Property. It is the responsibility of the Product Properties Panel object, to create the wcfRichTextPropertyEditor for the product property. In turn, it is the responsibility

Chapter 11. Spell Checker 185

Page 204: My Tutorial

of the wcfRichTextPropertyEditor to create the wcfRichTextEditor, which binds a local attribute to the specified property of the model. In this case, that binding would be to the Long Description model property of the product.

The binding is bi-directional, so updates to the property are reflected in the display, and edits that you make are propagated to the model property. The wcfRichTextEditor is the widget that gives you the ability to view and edit the property.

The model property can be shared so that a number of bound editors can work with the same property. You can also save the model property back to the database using standard features of the Management Center.

Figure 11-3 Properties Panel, rich text editor relationship

Given that this is how it works, then a design option that we might have thought of taking would be to extend the existing widget or the property editor to add our new behavior.

Product Properties Panel <class = wcfPropertyGroup>

Property Editor <class = wcfRichTextPropertyEditor >

Widget <class = wcfRichTextEditor>

creates edit facility

Model (Product){long description property}

binds

Widget <class = wcfRichTextEditor>

Model (Product){long description property}

186 WebSphere Commerce Line-of-Business Tooling Customization

Page 205: My Tutorial

We could not take this approach because these classes are private, and we are not allowed to:

� Extend them

� Wrap the objects

� Construct using them

� Include buttons within the existing widgets, for example, to invoke the spell checking

The decided to create a new Property Editor that binds a button widget to the required model property. When you click the button, a new dialog window opens to spell check the property and to make corrections. You can set up the completed corrections in the model property through the binding, when the user selects the OK button of the dialog. This approach follows the recommended patterns of the Management Center. Figure 11-4 shows that the Spell Check Editor’s basic pattern is the same as the out-of-the box Property Editor of Figure 11-3 on page 186.

Figure 11-4 Spell Check Editor Relationship

Product Properties Panel <class = wcfPropertyGroup>

Property Editor <class = extPropertySpellCheck>

Widget <class =extSpellCheckButton>

creates

Model (Product){long description property}

binds

<class = wcfDialog>

displays opensreturnscorrectedtext

Chapter 11. Spell Checker 187

Page 206: My Tutorial

With this design, the extPropertySpellCheck class extends wcfPropertyEditor, which is the base class for all Property Editors. This is not a private restricted class because customizations extend this class when developing property editors.

The extSpellCheckButton extends the button class, which is a standard component of OpenLaszlo. As previously stated, the widgets of the Management Center are generally in the restricted directory and are private. In our case, we only need the button click to open the new dialog window, which performs the spell check and allows the user to correct the text. For the dialog, we decided to use the wcfDialog class, which was on the recommendation of the Development team who took action to make this class public.

We use the Spell Check window object to invoke the spell check service of CDYNE and display the results. When the user clicks the OK button of that window, the correction process ends, and the corrected text is set in the extSpellCheckButtonWidget. Because this widget is bound to the model property, that property gets updated too.

It is standard behavior for any model properties that are updated or created to be listed in the active work display as being changed. The user can save all active work at any time, which results in the database being updated with the active work.

The process and classes that are needed for the short description property, which is unformatted text, remain the same, which was a design decision that was made because the process is very similar. In practice, the code that was developed for rich text can handle the spell check and correction of the unformatted text. A benefit of this is that it does not matter if the property is rich or unformatted or how large it is because you can easily include the spell check facility by adding a few lines of simple declarative XML to a property panel.

11.2.4 Visual Design

In this section, we describe the visual design of the spell checker. We used a wire frame to describe the layout and to help refine the behavioral requirements.

Before you build a visual prototype, it is common to draw and specify a wire frame mock up. A key part of the wire frame design, which we quickly decided on, was a pop-up window to show the unknown words and to allow corrections. This decision obviously had an impact on the wire frame’s appearance and its behavior. We based the wire frame design on the Lotus Notes spell check window, which is shown in Figure 11-2 on page 182.

188 WebSphere Commerce Line-of-Business Tooling Customization

Page 207: My Tutorial

Figure 11-5 shows the wire frame for our pop-up window, which is useful for discussions with the customer, and the wire frame helps to define the requirements that are needed to allow the designing and building of the visual prototype.

Figure 11-5 Spell check window wire frame, showing suggested corrections

The display areas of Figure 11-5, are all numbered and the following descriptions correspond with those numbers:

1. Title of the window, within the title bar of the window

2. Information text field, which shows:

– How many unknown words the spell check returned (can show zero)– Waiting for spell check service indication– All words processed indication– Error status message

3. Highlight view shows the full text that was spell checked and with occurrences of the unknown word highlighted. The purpose is to show the unknown word in the context of the sentence. This is to aid correction decisions. With many spell check features, you can use the originating widget to do the highlighting. Because of the restrictions with using the existing widget, see 11.2.3,

Spell Check

With suggested corrections

OK Cancel

There are 2 unknown words

A [spellin] misteak or two

Unknown word Skip

Replace with

spellin

spelling Replace

Suggestions spell inspellingspleenspline

2 information

1 title

3 highlight

5 labels

4 unknown word

6 skip / replacebuttons

7 corrected word

8 suggestions list

9 OK / CancelButtons

Chapter 11. Spell Checker 189

Page 208: My Tutorial

“Component design” on page 185, the design approach we used is to handle this within the pop-up window.

4. The current unknown word for the user to process. Information only. Not editable.

5. Labels to explain display areas 4, 7, and 8.

6. A Skip button to accept the unknown word as it is without changes. In this case, the dialog moves on to the next unknown word, if there is one. Also a Replace button to replace all occurrences of the unknown word with the contents of the edit field (7).

7. An edit field that initially shows the unknown word, which you can replace with a selection from the suggestions list (8), or the user can edit the word to correct it. After this field is changed, the Replace button becomes enabled to allow this corrected word to replace the unknown word.

8. The list of suggestions returned in the spell check results. We decided that this will scroll if there were more than 10 suggestions.

9. A Cancel Button, which ends the dialog and no changes occur, at any time. An OK button. As soon as a user makes a change, the button is enabled, and selecting it transfers the changes made using this window to the panel field that holds the property text that is being spell checked and corrected.

The corrections area of the display (areas 3 to 8 of the wire frame of Figure 11-5 on page 189), must not display when:

� There are no unknown words� The window is waiting for results� There is a service error

In other words, the corrections area only displays when there are corrections to the process.

11.3 Deploying the complete or staged examples

In this section, we provide a description of the Spell Checker files, which are provided in the zip that accompanies this book (“Locating the Web material” on page 419). We also provide notes about how you can deploy the full Spell Checker or the staged examples.

190 WebSphere Commerce Line-of-Business Tooling Customization

Page 209: My Tutorial

We deal with this subject now because you need to know this if you:

� Want to skip examples and move on to deploy the completed solution.

� Intend to deploy the example stages that follow on from this section.

� Want to open and look at the code of the completed solution or the example stages.

The zip file contains code for the completed solution and each example stage of the Spell Checker.

The files in the zip that you need for the Spell Checker can be described as fol-

lows:

� Directory: LOBTools\WebContent\WEB-INF\src\lzx\redbooks\components

– File: extSpellChecker.lzx, which contains the final versions of both the pop-up window dialogue panel and the extSpellCheckButton widget class.

– The following _EXn files are alternatives for the extSpellChecker.lzx class that you can compile in to demonstrate the example development stages that we describe in the progression of the Spell Checker:

• SpellCheck_EX1_extSpellChecker.lzx• SpellCheck_EX2_extSpellChecker.lzx• SpellCheck_EX3_extSpellChecker.lzx• SpellCheck_EX4_extSpellChecker.lzx• SpellCheck_EX5_extSpellChecker.lzx• SpellCheck_EX6_extSpellChecker.lzx• SpellCheck_EX7_extSpellChecker.lzx

– File: extHighlightRichText.lzx, which contains the class extHighlightRichText that is used to highlight the misspelled words in the text that was spell checked.

– File: extSpellCheckerPropertiesComponent.lzx contains the extPropertySpellCheck class that binds the editor to the model property.

– File: extUtils.lzx, which contains some utility classes

� Directory: LOBTools\WebContent\WEB-INF\src\lzx\commerce\catalog\propertiesViews

– File: CatalogPropertyPane.lzx, which was an out of the box customizable file that we modified to include the Spell Checker editors into the Product Properties Panel. This file also includes some edits that we did for other examples of this book.

Chapter 11. Spell Checker 191

Page 210: My Tutorial

� Directory: LOBTools/src/com/redbooks/commerce/client/lobtools/properties

– File: CatalogLOB.properties, which we created to contain the properties that we used for the catalog examples of this book, including the Spell Checker.

� Directory: LOBTools\WebContent\WEB-INF\src\lzx\redbooks\catalog

– File: extCatalogManagementResourceBundle.lzx, which we created to map the properties that we defined in our new property files to the wcfResourceBundleKey objects needed to let our OpenLaszlo code use the properties.

� Directory: LOBTools\WebContent\WEB-INF\src\lzx\commerce\catalog

– File: CatalogExtensionsLibrary.lzx, which was an out the box customizable file that we modified to include the new libraries that we needed to compile. The modifications that we made for the Spell Checker include a commented out section and a listing of each stage example.

Deploying the Spell Checker: If you want to deploy the Spell Checker, on its own, you can just deploy the files that we listed from the zip. However, the CatalogPropertyPane.lzx file and the CatalogExtensionsLibrary.lzx file include modifications from other examples of this book. It should be easy enough to identify these, and comment them out if you find compile errors. The comments in these files indicate where we made changes in this book and the examples that they pertain to.

Clean and compile the LOBTools project, and restart the server after you deploy the files.

192 WebSphere Commerce Line-of-Business Tooling Customization

Page 211: My Tutorial

11.4 Staged development

We developed the Spell Checker example in incremental stages. For each stage, we describe:

� Aspects of the design � Snippets of code� How to deploy� How to view and test

Viewing the results of the example stages: By default, the supplied zip compiles to the final completed version of the Spell Checker. To view the results of any of the example stages, modify the CatalogExtensionsLibrary.lzx file, and recompile the LOBTools project.

The modification is to replace the following line:

<include href="../../redbooks/components/extSpellChecker.lzx" />

Replace the line with the version that you want to compile and view, for example, to view the stage, Example 1, replace the line with:

<include href="../../redbooks/components/SpellCheck_EX1_extSpellChecker.lzx" />

The _EXn_ in the filename describes the example stage, where n is the stage number.

Note 3: Whenever you recompile the LOBTools project, we recommend that you clean and build the selected project (LOBTools), which ensures that it is all fully compiled. After this, do not restart the WebSphere Commerce server; instead, start a new browser session, and log into the Management Center, which ensures that the changed LOB tools files are loaded at the browser.

For the Spell Checker example, restart the server only if the property file changes are made to ensure that the property file changes are picked up on the server. As an alternative to restarting the server for this, you can refresh the WebSphere Commerce registry. See:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/refs/rmsrefreshregistry.htm

Chapter 11. Spell Checker 193

Page 212: My Tutorial

11.4.1 Explaining the visual prototype stage (example 1)

In this section, we describe the prototype that we built to demonstrate the GUI. You can use this prototype to:

� Demonstrate to the customer how the display appears� Walk through the operational scenarios� Build the presentation part of the solution

The Presentation stage that we developed needs some refactoring, but much of it we can reuse. Developing in this manner also helps us to ensure that the visual aspect of the display are kept separate from the display logic, the model, and the dynamic aspects of the presentation code. The declarative nature of OpenLaszlo helps with these aspects of development, as we demonstrate in this section.

After we had create the wire frame, as described in 11.2.4, “Visual Design” on page 188, we design and build the prototype for the wire frames.

The first part of the development is to design the view hierarchy, as depicted in Figure 11-6. We base this on the wire frame and specification of 11.2.4, “Visual Design” on page 188.

Figure 11-6 Spell Checker panel-view hierarchy

Spell Check

OK Cancel

There are 2 unknown words

A [spellin] misteak or two

Unknown word Skip

Replace with

spellin

spelling Replace

Suggestions spell inspellingspleenspline

3

1

2a

2b 2d

2

2c

194 WebSphere Commerce Line-of-Business Tooling Customization

Page 213: My Tutorial

The numbered areas of Figure 11-6 on page 194 correspond with the numbers in the following list that describes each area:

1. messageView: This non editable text component contains status messages, such as error states, number of unknown words, and waiting for service response.

2. correctionsView: We use this view to hide or show its sub views, which are required to make corrections. The only time this is set to visible, and hence its sub-views are visible, is when there are corrections to be made.

a. highlightedText: This sub-view highlights occurrences of the misspelled word in the source text. For the prototype examples, we just use a richinputtext component. In the later examples, where we implement the functionality for the highlighted text, we replace this with a custom extend version of the richinputtext component.

b. labelsView: A sub-view that we use to contain and layout the non-editable text components that show the labels for the widgets of view 2c. This needs to be a separate view, to aid layout, because 2b, 2c, and 2d are spaced along the X axis.

c. textView: This sub view contains and lays out the:

• Non editable “text” component that shows the unknown word that can be corrected if desired.

• Edittext component, which allows the user to edit the unknown word so that it can be replaced.

• List component, which displays the suggested corrections that the user might select and use to replace the unknown word.

d. rightButtonsView: We use this view to contain and layout the Skip and Replace button components.

3. okCancelView: We use this view to contain and layout the OK and Cancel button components.

After we have a design that has the view hierarchy and the component types to use, we implement the prototype. The declarative XML nature of OpenLaszlo makes this a relatively intuitive task, which you can see from the code that we developed in the Example 11-2 on page 196. The code is mainly a hierarchy of

Component types: The component types that we mentioned are all standard OpenLaszlo components. To learn more about these, and other component types, see the components section of:

http://www.openlaszlo.org/lps4.1/docs/reference/

Chapter 11. Spell Checker 195

Page 214: My Tutorial

XML that declares the views and components in the same hierarchy as the design of Figure 11-6 on page 194.

Example 11-2 Example 1, view hierarchy code

<wcfDialog id="spellCheckWindow" width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >

<!-- Some example text that would give the results of the example dataset.The first mispelled word is highlighted in [] and bold

--><attribute name="highlightedTextStr" type="string"

value="&lt;b&gt;[e commerce]&lt;/b&gt; with WebSphere Commerce" />

<simplelayout axis="y" spacing="10" />

<!-- view at top part of window used to display status messages --><view name="messageView">

<simplelayout axis="y" spacing="5" /><text>There were [2] unknown words</text>

</view> <!--

View containing all correction widgets, hidden when there are no corrections to process

--><view name="correctionsView"> <simplelayout axis="x" spacing="5" />

<!-- original text with unknown word highlighted, this is to show it in the context of its sentence

--><richinputtext name="highlightedText" options="ignorelayout" bgcolor="0xdddddd" multiline="true" width="${parent.width}"><method name="init" ><![CDATA[

196 WebSphere Commerce Line-of-Business Tooling Customization

Page 215: My Tutorial

this.setHTML(true); this.setEnabled(false); this.setText(spellCheckWindow.highlightedTextStr); super.init();]]></method></richinputtext>

<view name="labelView" y="${parent.highlightedText.y +parent.highlightedText.height}"

><simplelayout axis="y" spacing="12" /><text text="${extCatalogResources.spellCheckUnknownWordLabel.string}" /><text text="${extCatalogResources.spellCheckReplaceWithLabel.string}" /><text

text="${extCatalogResources.spellCheckSuggestionsLabel.string}" /> </view>

<!-- word for correction, correction editing field, and suggestions selection list --><view name="textView"

y="${parent.highlightedText.y +parent.highlightedText.height}"><simplelayout axis="y" spacing="10" />

<!-- an unknown word returned from the spell check service --><text>eCommerce</text>

<!--

edit field for correcting the unknown word, initially populatedwith unknown word, returned from the spell check service.The user can populate this field with a selected suggestion,or edit the text.

--><edittext>eCommerce</edittext> <!-- the suggestions list, populated with suggestions for the unknown word as returned by the spell check service -->

Chapter 11. Spell Checker 197

Page 216: My Tutorial

<list id="suggestions_SC" shownitems="10" > <textlistitem>eCommerce</textlistitem> <textlistitem>commerce</textlistitem>

</list> </view>

<!-- buttons to the right of user correction widgets --><view name="rightButtonsView"

y="${parent.highlightedText.y +parent.highlightedText.height}"><simplelayout axis="y" spacing="10" />

<!-- skip button: i.e. do not change, the unknown word --><button id="skipButton_SC" enabled="true"

text="${extCatalogResources.spellCheckSkipLabel.string}" ></button>

<!-- replace: i.e. replace the unknown word with the word in the corrected word edit field --><button id="replaceButton_SC" enabled="false"

text="${extCatalogResources.spellCheckReplaceLabel.string}" ></button></view>

</view>

<!-- The OK and cancel buttons at the bottom of the spell check window --><view name="okCancelView" placement="footer"><simplelayout axis="x" />

<button id="applyButton_SC" enabled="false"text="${extCatalogResources.spellCheckDoUpdateLabel.string}" >

</button>

<button id="cancelButton_SC" enabled="true"text="${extCatalogResources.spellCheckCancelLabel.string}"

><handler name="onclick">

spellCheckWindow.close();</handler>

</button>

198 WebSphere Commerce Line-of-Business Tooling Customization

Page 217: My Tutorial

</view>

</wcfDialog>

Some points to note about the code in Example 11-2 on page 196 are:

� The simplelayout components that control the spacing in either the x or y axis.

� The init method that we declared for the highlightedText object. It overrides the default and gets called on initialization. We needed to set some attribute values here because we cannot declare them in XML in the same way as many of the other components. It is essential here that we call the super init method to ensure that we did not break the standard behavior.

� A handler is included on the Cancel button that contains the JavaScript to close the window. This handler is associated with the onclick event of the button object that it is declared within.

� The ${} declarations declare a constraint, for example width=”{parent.width}”. In this case, which occurs for the highlightedText component of the example, the constraint contains the width of the view to the width of the parent view. If the parent width changes, so will the child that has this constraint declared.

� The ${} are also used to allow property text strings to be substituted, for example, text="${extCatalogResources.spellCheckCancelLabel.string}". This occurs in the example to set the Cancel button label to a property value. This approach is needed because we declared the button in XML, but the text is in a property file that we must dynamically set at a later time.

� The highlightedText object has its options attribute set, for example, options="ignorelayout". This is because we need this component to span the width of the window by getting it to ignore the simplelayout that is declared for the x axis of its parent view, for example, the correctionsView.

For our first prototype, we also include:

� The new button widget class, extSpellCheckButton, which controls the editing of the property.

� The new Property Editor class, extSpellCheck, which binds the button widget property to the model property.

� The modification of the Product Property Panel, which declares the instances of the Property Editor that are needed to create a Spell Checker for the short and long description properties

Chapter 11. Spell Checker 199

Page 218: My Tutorial

This code is enough to allow the buttons to display in the Property Panel, and to allow the Spell Checker window to display when the users click a button. It is also enough to complete the required code for the Product Property Panel and the Property Editor because they are fairly simple pieces of code.

Example 11-3 shows the code for the extSpellCheckButton class.

Example 11-3 extSpellCheckButton class

<class name="extSpellCheckButton" extends="button">

<attribute name="property" value="null"setter="setProperty(property)"

/>

<!---Set the {@link wcfModelProperty} to be associated with this spell check.@param wcfModelProperty newProperty: New Property associated with this spell check.-->

<method name="setProperty" args="newProperty">if (typeof(this["property"]) == "undefined" || newProperty != this["property"]) {

this.property = newProperty;

Tracing: The trace code is in the Spell Checker files of the zip that accompanies this book. We removed the trace code from the example code that we show in the spell check code snippets of this book to improve clarity. For a description of how to do tracing see:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/foundation/restricted/Logger.lzx/wcfLogger.html

Note: Generally, we follow the good practice of enclosing the JavaScript within methods and handlers with <![CDATA[ ...the JavaScript ... ]]> to avoid compile errors when comments are put in to the JavaScript. The // that we use to declare a comment is seen as invalid XML by the compiler. For short simple methods that have no comments, we did leave the CDATA declarations out.

For brevity, we removed the CDATA statements from the Spell Checker code that we show in this book.

200 WebSphere Commerce Line-of-Business Tooling Customization

Page 219: My Tutorial

}</method>

<handler name="onclick">if (this['property']) {

spellCheckWindow.open();}

</handler></class>

Some points to note about the code in Example 11-3 on page 200 are:

� The setProperty method sets a local copy of the property, which is bound to the required model property. Any subsequent changes to the model property are reflected in the value of this local property. Any change to this local property value are reflected back into the model property.

� For this prototype, the onclick handler has a simple implementation that just opens the spellCheckWindow. We include the code to start the spell check process in the later examples of this book.

Example 11-4 shows the new Property Editor class, extSpellCheck, which binds the button widget property to the model property.

Example 11-4 extPropertySpellCheck class

<class name="extPropertySpellCheck" extends="wcfPropertyEditor">

<attribute name="doSpellCheckButtonLabel"value="${extCatalogResources.spellCheckWindowLabel.string}"type="string"

/>

<!-- create the spell check editor "extSpellCheckButton" for the property --><method name="createEditor" args="parentComponent">

new extSpellCheckButton(parentComponent, {name: "editor",x: parentComponent.promptWidth + parentComponent.xspacing,property: parentComponent.property,enabled: parentComponent.enabled,text: doSpellCheckButtonLabel

});

</method>

Chapter 11. Spell Checker 201

Page 220: My Tutorial

</class>

Some points to note about the code in Example 11-4 on page 201 are:

� The new property editor class extPropertySpellCheck extends from the standard property editor base class wcfPropertyEditor.

� The createEditor method, which needs to be implemented by classes that extend wcfPropertyEditor, is responsible for creating the editing widget. In this case, this is an extSpellCheckButton object. The values that are supplied to the new extSpellCheckButton object constructor constrain the position of the button, set an appropriate label for it, and bind the editable property of the widget to the model property.

We also change the Product Property Panel code to include and initialize the property editors for the long and short descriptions. Example 11-5 shows the changes we made. Note that some we left some code out to highlight what we changed.

Example 11-5 wcfPropertyGroup class

<class extends="wcfPropertyGroup"groupTitle=

"${catalogResources.generalProductInformationSection.string}"name="catManageGeneralProductInformation" open="true"

>...

<!--Redbooks customization:Include new wcfPropertyEditor buttons after the short and longdescription edit fields. These buttons will invoke a spellcheck and correction window

--> <!-- Property: Short Description. A long input box

for the short description property. --><wcfPropertyInputLongText

objectPath="CatalogEntryDescription"promptText="${catalogResources.shortDescriptionPrompt.string}"propertyName="sDesc"

/> <!-- new button to invoke the spell check

202 WebSphere Commerce Line-of-Business Tooling Customization

Page 221: My Tutorial

on the short description model property --><extPropertySpellCheck

objectPath="CatalogEntryDescription"propertyName="sDesc"

/>

<!-- Property: Long Description. A rich text editor

for the long description property --><wcfPropertyRichTextEditor

objectPath="CatalogEntryDescription"promptText="${catalogResources.longDescriptionPrompt.string}"propertyName="lDesc"

/> <!-- new button to invoke the spell check

on the long description rich text property --><extPropertySpellCheck

objectPath="CatalogEntryDescription" propertyName="lDesc"

/>...

Some important points to note about the code in Example 11-5 on page 202 are:

� The property panels are declared in the file LOBTools/WebContent/WEB-INF/src/lzx/commerce/catalog/propertiesViews/CatalogPropertyPane.lzx. We distribute the modified version of this file in the zip file that accompanies this book. Within the file there are a number of property panel instances. The one we modified was for the Product Property Panel because it is for products that we want the buttons to appear. The name="catManageGeneralProductInformation" indicates that this is the panel instance we need to modify.

� We declared a new instance of our extPropertySpellCheck class just after the short description property editor declaration that was already in the file, which means that our button will appear in the row just below the short description editor, which is what we wanted. We also followed this approach for the long description property.

� The objectPath and propertyName attributes need to be set respectively to the required values for the model object and model property to allow the Property Editor base behavior to bind the editor to the model property.

Chapter 11. Spell Checker 203

Page 222: My Tutorial

� This is all the code that we need to add to the panel to include the Spell Checker. We did not modify this file in the subsequent examples for the Spell Checker.

� The Spell Checker can be included for other text properties of this and other Property Panels. To do this, add in declarative code that follows the pattern of Example 11-5 on page 202.

11.4.2 Viewing the visual prototype stage (example 1)

In this section, we explain how to deploy and view example stage 1 and the visual prototype. We also explain what you should see.

To view example 1:

1. recompile for example 1, as we explain in the “Viewing the results of the example stages Note in 11.3, “Deploying the complete or staged examples” on page 190.

2. Log into the Management Center, and select the catalog tool, Management Center -> Catalogs.

3. Search or browse for products, and open the Product Property panel for a product.

You should see the Spell Check buttons displayed, similarly to Figure 11-7 on page 205.

204 WebSphere Commerce Line-of-Business Tooling Customization

Page 223: My Tutorial

Figure 11-7 Product Property Panel with Spell Check buttons

4. Click either of the Spell Check buttons to see our prototype panel pop-up, as shown in Figure 11-8 on page 206.

Chapter 11. Spell Checker 205

Page 224: My Tutorial

Figure 11-8 Example 1, Spell Check window

At this stage, the text that displays is often hard coded, and in all cases is not relevant to the product of the properties panel.

The Cancel button is the only button that is implemented, and clicking that should close the window.

Clicking the other Spell Check button should re-open the window again.

11.4.3 Explaining the static XML prototype stage (example 2)

In this section, we explain the second example stage, where we still have the basic look and feel of the layout, but use a static included XML dataset to show the spell check and correction window. The state developed is where unknown words are, but not corrected yet.

The purpose of this stage is to prototype using data in the real XML format, but without the real CDYNE service being needed. This example stage shows how we can easily bind OpenLaszlo display widgets to the XML data. Because we use XML in the required format, this binding can stay the same when we use the real service of CDYNE in the subsequent examples.

The first step we take is to include some static example XML into our code, which we declared within an OpenLaszlo dataset. In the later examples, you will see how easy it is to change this dataset to use the CDYNE service.

206 WebSphere Commerce Line-of-Business Tooling Customization

Page 225: My Tutorial

Example 11-6 shows the code for the dataset. You can see from the example how the wcfDialog had its datapath attribute set to use the dataset as its source for data. Setting it at this level means that all sub-views can use this dataset.

Example 11-6 Static XML dataset

<dataset name="spellCheckDS"><DocumentSummary

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns="http://ws.cdyne.com/"><MisspelledWord>

<Suggestions>e commerce</Suggestions> <Suggestions>commerce</Suggestions> <word>eCommerce</word> <SuggestionCount>2</SuggestionCount>

</MisspelledWord><MisspelledWord>

<Suggestions>web sphere</Suggestions> <word>WebSphere</word> <SuggestionCount>1</SuggestionCount>

</MisspelledWord><ver>1.0</ver> <body>WebSphere eCommerce</body> <MisspelledWordCount>2</MisspelledWordCount>

</DocumentSummary></dataset>

<!-- This is the pop up modal window allowing the user to make spelling corrections, there is only one instance of this --><wcfDialog id="spellCheckWindow" datapath="spellCheckDS:/"

width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >...

The sub-views are needed to navigate the XML to get to the data they require. To do this, we use the OpenLaszlo approach of using XPath statements to navigate the XML, and bind the subview to the required path within the XML.

Note: In OpenLaszlo, the navigation and selection of the XML of a dataset can be set using XPath. For more information, visit:

http://www.openlaszlo.org/lps/docs/guide/data-structures.html

Chapter 11. Spell Checker 207

Page 226: My Tutorial

Example 11-7 shows the snippets of declarative XML that we used to do the navigation and binding. We omitted some code for clarity.

Example 11-7 Xpath navigation and binding

<!-- This is the pop up modal window allowing the user to make spelling corrections, there is only one instance of this --><wcfDialog id="spellCheckWindow" datapath="spellCheckDS:/"

width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >...

<!-- View containing all correction widgets, hidden when there are no corrections to process --><view name="correctionsView"

datapath="spellCheckDS:/DocumentSummary/MisspelledWord[1]">

<!-- word for correction, correction editing field, and suggestions selection list --><view name="textView" y="${parent.highlightedText.y

+parent.highlightedText.height}">

<!-- an unknown word returned from the spell check service --> <text id="wordForCorrection_SC" datapath="word/text()" > </text> <!-- edit field for correcting the unknown word --> <edittext id="correctedWord_SC" datapath="word/text()"> </edittext>

<!-- the suggestions list --> <list id="suggestions_SC" shownitems="10" > <textlistitem datapath="Suggestions/text()" /> </list>

Some points to note about the code in Example 11-7 are:

� The correctionsView datapath is set using XPath to navigate down to the first misspelled word element of the XML. This path is then set for all subviews of the corrections view.

� The wordForCorrection_SC text component navigates further down this path to the word element within the first misspelled word. The body data within this

208 WebSphere Commerce Line-of-Business Tooling Customization

Page 227: My Tutorial

element is bound to the text component, by nature of the declared text() of the XPath, which causes the body text of that element to be displayed.

In a similar fashion, the edit field gets bound to, and displays, that same word for correction text.

� The suggestions list is similarly bound to the suggestions. But in this case, multiple suggestion elements result in multiple list items being displayed.

� If there are no misspelled words in the XML, then the path for the corrections view evaluates to null; therefore, the corrections view, and its children, are hidden, which is what we want to happen. We demonstrate this behavior in 11.4.5, “Explaining the static XML prototype stage (example 3)” on page 209.

11.4.4 Viewing the static XML prototype stage (example 2)

In this section, we explain how to deploy and view example 2, the static XML prototype and stage.

To view example 2:

1. Recompile for example 2, as we explained in the “Viewing the results of the example stages” Note in 11.3, “Deploying the complete or staged examples” on page 190.

2. Login to the Management Center with a new browser session, and open a Product Properties (product details) page.

3. Click any of the Spell Check buttons, and you should see the spell check window, as shown in Figure 11-8 on page 206, which is the same as in Example 1, but now we are deriving the data from the XML.

11.4.5 Explaining the static XML prototype stage (example 3)

In this section, we explain the third example stage, where we still have the basic look, feel, and layout, and use a static included XML dataset to show the spell check and correction window; however, for this stage we changed the XML to reflect the state where no unknown words were found.

The purpose of this stage is to build on the previous example by showing that the corrections view is hidden correctly when there are no unknown words.

The change we make to the code is just to the dataset to match the case where the CDYNE service returns no misspelled words. Example 11-8 on page 210 shows the new dataset declaration.

Chapter 11. Spell Checker 209

Page 228: My Tutorial

Example 11-8 spellCheckDS

<!-- xml that would be returned from the spell check serviceif the text to check was "No misspelled words" in this case there are zero misspelled words, resulting in the

correction facility being hidden.--><dataset name="spellCheckDS">

<DocumentSummaryxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns="http://ws.cdyne.com/"><ver>1.0</ver> <body>No misspelled words</body> <MisspelledWordCount>0</MisspelledWordCount>

</DocumentSummary></dataset>

11.4.6 Viewing the static XML prototype stage (example 3)

In this section, we explain how to deploy and view example 3, the static XML prototype and stage with no unknown words. We also explain what you should see.

To view example 3:

1. Recompile for example 3, as we explained in the “Viewing the results of the example stages” Note in 11.3, “Deploying the complete or staged examples” on page 190.

2. Log into the Management Center with a new browser session, and open a Product Properties (product details) page.

3. Click any of the Spell Check buttons, and you should see the spell check window, as shown in Figure 11-9.

Figure 11-9 No misspelled words to display

210 WebSphere Commerce Line-of-Business Tooling Customization

Page 229: My Tutorial

11.4.7 Explaining the property provided prototype stage (example 4)

In this section, we explain the fourth example stage.

The purpose of this stage is to build on the previous examples by feeding through the real property value on to the spell check window. For this example, the doSpellCheck method just prints out some debug text for testing. The actual text for correction is still not displayed.

Example 11-4 on page 201 shows the interactions between the button widget property editor extSpellCheckButton and the spell check dialog window wcfDialog. The extSpellCheckButton is responsible for opening the dialog window and instigating the spell check. To do this, we added a doSpellCheck method to our spell check window. After corrections are all made, and the OK button is clicked, the spell check window has to return the corrected result to the extSpellCheckButton, so we added an update method to the extSpellCheckButton to do that.

Example 11-9 highlights the most significant changes that we made to the extSpellCheckButton class.

Example 11-9 Example 4, extSpellCheckButton code

<class name="extSpellCheckButton" extends="button">

<attribute name="property" value="null"setter="setProperty(property)"

/>

...

<!--- Set the {@link wcfModelProperty} to represent the spell correctedvalue. This method is called when the user clicks OK/APPLY toapply the changesfrom the dialog to the model

--><method name="updateText" args="correctedText">

if (this['property']) {this.property.change(correctedText);

}</method>

<handler name="onclick">if (this['property']) {

spellCheckWindow.doSpellCheck(this,this.property.value);}

Chapter 11. Spell Checker 211

Page 230: My Tutorial

</handler>

</class>

Some points to note about the code in Example 11-9 on page 211 are:

� We changed the onclick handler so that it calls the new doSpellCheck method of the spell check window. It passes in:

– A reference to this instance of the extSpellCheckButton, which the spell check window needs to return the corrected text.

– The text to be spell checked, from the property.

� The updateText method uses the change method for the property, which causes the model property to be updated so that it can be saved back to the database.

Example 11-10 highlights the main code changes that we made to the spell check window wcfDialog object.

Example 11-10 Example 4, spellCheckWindow code

<wcfDialog id="spellCheckWindow" datapath="spellCheckDS:/" width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >

<!-- formattedText is the text, that gets corrected and returned, for unfromatted text this gets set to the same as the textToCheckparameter

--><attribute name="formattedText" type="string" />

<!-- the source object which contains the actual editor that we return the corrected text to -->

<attribute name="sourceObjectToCorrectSpelling" />

....

<!-- Do a spell check on the supplied "newTextToCheck" using thespell check window and service.Note: newTextToCheck can be with or without formatting (html).The supplied sourceObj must implement method "updateText"args="correctedText".This is used by this spell checker to apply the corrected textwhen the user clicks the OK button after making corrections.

212 WebSphere Commerce Line-of-Business Tooling Customization

Page 231: My Tutorial

Note: this example version is incomplete, it just logs the textto check for testing purposes

--><method name="doSpellCheck" args="sourceObj, newTextToCheck">

if (wcfLogger.enabled) wcfLogger.log("com.redbooks.components", "INFO", "spellCheckWindow","doSpellCheck","Text to check is:" +newTextToCheck);

// to keep compatability with formatted text spell checking, // the check is always done using unformatted text, but

// corrections are always applied to // the this.formattedText attribute this.formattedText = newTextToCheck; this.sourceObjectToCorrectSpelling = sourceObj; this.open(); </method>

....</wcfDialog>

Some points to note about the code in Example 11-10 on page 212 are:

� The doSpellCheck method saves the supplied arguments to some new attributes of the wcfDialog spell check window object.

� The doSpellCheck method uses wcfLogger to output a trace statement to test the input text string that is being spell checked.

� The strategy we had was to save the text being spell checked in its formatted form and to make corrections by string replacement. Before the text was sent to the spell checker service, or used in the highlighted unknown words view, the formatting html would be removed. If the input text, to spell check, did not have any formatting, then this strategy would still work.

11.4.8 Testing the property provided prototype stage (example 4)

In this section, we explain how to deploy and test example 4, the property provided prototype stage.

Chapter 11. Spell Checker 213

Page 232: My Tutorial

To view example 4:

1. Recompile for example 4, as explained in Note 2 of 11.3, “Deploying the complete or staged examples” on page 190.

2. Log into the Management Center with a new browser session, but this time ensure that you have the following debug parameters on the end of the URL:

https://localhost:8000/lobtools/cmc/ManagementCenter?logger.display=true&logger.target=debugger&logger.components=com.redbooks.components

This is to ensure that you can trace our Redbooks components. For a detailed description of debugging, see 5.3, “Debugging” on page 74.

3. Use the Management Center to open a product properties (product details) page.

At this point, we want to enable the tracing of our Spell Checker. Select the top bar menu option: Management Center→ Logging and Tracing. At this point, you should see the logging and tracing options window and be able to select the following items, as shown in Figure 11-10 on page 215:

– Send Immediately– com.redbooks.compoonents = ALL

After you select the options, click the Enable button of that window to enable the tracing.

214 WebSphere Commerce Line-of-Business Tooling Customization

Page 233: My Tutorial

Figure 11-10 Logging and Trace configuration window

4. Click any of the Spell Check buttons to view the spell check window, as shown in Figure 11-9 on page 210.

5. Look in the debug window to see text similar to the following:

Thu Aug 14 13:26:17 GMT+0100 2008 com.redbooks.components FINER extSpellCheckButton doSpellCheck ENTRY Thu Aug 14 13:26:17 GMT+0100 2008 com.redbooks.components FINER spellCheckWindow doSpellCheck ENTRY Thu Aug 14 13:26:17 GMT+0100 2008 com.redbooks.components INFO spellCheckWindow doSpellCheck Text to check is:A cute giraffe print. Thu Aug 14 13:26:17 GMT+0100 2008 com.redbooks.components FINER spellCheckWindow doSpellCheck RETURN Thu Aug 14 13:26:17 GMT+0100 2008 com.redbooks.components FINER extSpellCheckButton doSpellCheck RETURN

The text in bold confirms that the text to spell check correctly passed through to the spell check window. In your case, the debug text of A cute giraffe print, should match the source text of the property that you selected to spell check.

Chapter 11. Spell Checker 215

Page 234: My Tutorial

11.4.9 Explaining the CDYNE service prototype stage (example 5)

In this section, we explain how example 5 builds on the previous examples by replacing the static XML dataset with a dataset that uses the spell check service of CDYNE.

In this example, we include the real CDYNE dataset and supply it with the text to spell check. The service then returns the resulting XML into the dataset. When this happens the binding that we set up in the previous example comes into action, and the views and components display the data that is returned in the dataset.

The following items are still not implemented in this example:

� Highlighted occurrences of the unknown word, in the context of the original text

� The correction process

Example 11-11 of the changed code demonstrates that not much code was added to achieve the replacement of the static dataset with the real service.

Example 11-11 Implementing the CDYNE dataset

<!-- Dataset using, cdyne service as an example spell check servicehttp://ws.cdyne.com/SpellChecker/check.asmx/CheckTextBody?

LicenseKey=anything&BodyText=stringnote: we set the changeable BodyText parameter dynamically, as this is the text to spell check.@see http://ws.cdyne.com/SpellChecker.Timeout set to 15 secs - default is 30, which is a bit long.

--><dataset name="spellCheckDS"

type="http" acceptencodings="true" request="false"querytype="put"timeout="15000"trimwhitespace="true"src="http://ws.cdyne.com/SpellChecker/check.asmx/CheckTextBody"ondata = "spellCheckWindow.handleData(this);"onerror = "spellCheckWindow.handleError(this);"ontimeout = "spellCheckWindow.handleTimeout(this);"

/>

216 WebSphere Commerce Line-of-Business Tooling Customization

Page 235: My Tutorial

Some points to note about the code of Example 11-11 on page 216 are:

� The request attribute was set to false to allow the request for the service to be invoked when the doSpellCheck method runs.

� The time-out was reduced to 15 seconds.

� The three handlers, for data, error and time-out were set to be methods of the spell check window wcfDialog object. This was to simplify and centralize this code.

Example 11-12 shows how we modified the doSpellCheck method to use a new utility method to remove any HTML formatting from the text to spell check. It then goes on to call a new method, callSpellCheckService, which:

� Sets the word that is to be spell checked as a query parameter for the service.� Actions the service by calling the doRequest method on the dataset.

Example 11-12 Using the CDYNE service

<wcfDialog id="spellCheckWindow" datapath="spellCheckDS:/" width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >......

<attribute name="textToCheck" value="" type="string" />.......

<method name="doSpellCheck" args="sourceObj, newTextToCheck">this.formattedText = newTextToCheck;

this.sourceObjectToCorrectSpelling = sourceObj;this.textToCheck = extStringUtil.removeTags(newTextToCheck);

// hide any previous results in the corrections view, for nowthis.correctionsView.setAttribute("visible", false);

this.setWaitForServiceMessage();this.open();this.callSpellCheckService();

</method>

<!-- use the spell check service --><method name="callSpellCheckService" >

spellCheckDS.setQueryParam("BodyText", this.textToCheck);spellCheckDS.setQueryParam("LicenseKey", "anything");

Chapter 11. Spell Checker 217

Page 236: My Tutorial

spellCheckDS.doRequest();</method>

For this example, we also made some changes that deal with the status messages and word count. We changed the way we implement that in the later examples, so we defer describing how that was done for now.

11.4.10 Viewing the CDYNE service prototype stage (example 5)

In this section, we explain how to deploy and view example 5, which is the first example to interface with the real CDYNE service.

For this and subsequent example stages to work, your browser needs access to the Internet.

To view example 5:

1. Recompile for example 5, as we explained in 11.4.2, “Viewing the visual prototype stage (example 1)” on page 204.

2. Log into the Management Center with a new browser session, and open a Product Properties (product details) page.

3. Check that the short description, for the product that you picked, has no spelling errors. If there are any spelling errors, correct them by editing the short description property in the panel. There is no need to save this change to the model.

4. Next, click the short description Spell Check button, and initially the spell check window pop-up is displayed in the waiting for service response state, as shown in Figure 11-11.

Figure 11-11 Waiting for service

Shortly after this, the spell check service should return an XML result declaring that there are no unknown words. At this point, the window changes to display, as shown in Figure 11-9 on page 210.

218 WebSphere Commerce Line-of-Business Tooling Customization

Page 237: My Tutorial

5. Click the Cancel button to close the window, and then edit the short description field that is on display in the property panel to introduce spelling errors in two words.

6. Click the spell check button for the short description, and results that are similar to Figure 11-12 are displayed. The unknown word that is displayed should match your first misspelled word of the short description. The number of suggestions that are displayed vary depending on what the misspelled word is.

Figure 11-12 With Spell Check Errors from CDYNE

7. Repeat the tests for the long description property, and you should receive similar results.

11.4.11 Explaining the highlighted text prototype stage (example 6)

In this section, we explain how example 6 builds on the previous examples by highlighting occurrences of the unknown word, within the context of the original text.

We still have not implemented the correction process in this example.

Chapter 11. Spell Checker 219

Page 238: My Tutorial

We extend the standard OpenLaszlo richinput text widget to provide the required functionality. Example 11-13 is from the extHighlightRichText file, and it shows our actions.

Example 11-13 New highlighting component

<class name="extHighlightRichText" extends="richinputtext">

<!-- html used to highlight text in [] bold and red, can be changedif required --><attribute name="prependHighlightHTML"

value="&lt;b&gt;&lt;font color=&quot;#FF0000&quot;&gt;["type="string"

/><attribute name="appendHighlightHTML"

value="]&lt;/font&gt;&lt;/b&gt;" type="string" />

<method name="init" >this.setHTML(true);this.setEnabled(false);super.init();

</method>

<!-- highlight all occurrences of the supplied "wordToHighlight" in the text of this widget, refereshes display --><method name="highlightWord" args="wordToHighlight">

if(! (extStringUtil.isBlankString(this.text) && extStringUtil.isBlankString(wordToHighlight) ) ) {

// first, remove highlighting that may be there from previousvar cleanedSentences = wcfStringUtil.replace(this.text,

this.appendHighlightHTML, "");var cleanedSentences = wcfStringUtil.replace(cleanedSentences,

this.prependHighlightHTML, "");

// finally, highlight occurences of the wordvar highlightedWordStr = this.prependHighlightHTML

+ wordToHighlight +this.appendHighlightHTML;var result = wcfStringUtil.replace(cleanedSentences,

wordToHighlight, highlightedWordStr);this.setAttribute("text", result);

}

220 WebSphere Commerce Line-of-Business Tooling Customization

Page 239: My Tutorial

</method>

<!-- replace all occurrences of the supplied "wordToChange" with "newWord" in the text of this widget

--><method name="replaceWord" args="wordToChange, newWord">

// replace the word so that it won't show uncorrected in// highlighted textthis.text = wcfStringUtil.replace(this.text,

wordToChange, newWord);

</method>

<!-- override of the normal datapath apply data method, this is to use the word returnedfrom the datapath to highlight the text in the widget

--><method name="applyData">

highlightWord(this.data);</method>

</class>

Some points to note about the code in Example 11-10 on page 212 are:

� The method, highlightWord, highlights the specified word in the display text of this object. It first removes any existing highlighting, and then replaces all occurrences of the word with a highlighted version of that word.

� There are local strings to control the style of the highlighting, which you can change to give a different style, if required.

� You can use the method, replaceWord, to replace a word in the text of this object. We need this in cases where there are a number of different words that are being corrected. The method clears a previous replaced word so that it is not highlighted after it is replaced.

� The applyData method is a standard OpenLaszlo method that is called when the datapath has new data. Normally, the richinputtext class that we extended uses the new data to set the display text. Our strategy, though, is to use the data from the datapath as the word to highlight. By overriding the applyData method we can do that.

Chapter 11. Spell Checker 221

Page 240: My Tutorial

� In order to use the new highlighting widget, we change the spell check window wcfDialog object code, as shown in the code snippet in Example 11-14.

Example 11-14 Using the highlighting component

<!-- original text with unknown word highlighted, this is to show it in the context of its sentence

--> <extHighlightRichText name="highlightedText" options="ignorelayout"

bgcolor="0xdddddd" multiline="true"width="${parent.width}">

</extHighlightRichText>.....

<!-- an unknown word returned from the spell check service --><text id="wordForCorrection_SC" datapath="word/text()" >

<handler name="ondata">

spellCheckWindow.correctionsView.highlightedText.setText(spellCheckWindow.textToCheck);

spellCheckWindow.correctionsView.highlightedText.highlightWord(this.data);

</handler> </text>

Some points to note about the code in Example 11-14 are:

� We changed the richinputtext widget declaration to declare our new widget type, extHighlightRichText.

� When the data loads into the displayed word for correction, we set the text to display for the widget to the unformatted text to check value. We then set the highlighted word to be the word for correction.

11.4.12 Viewing the highlighted text prototype stage (example 6)

In this section, we explain how to deploy and view example 6, which includes a view to highlight where the unknown word occurs in the original text.

Note: When we coded this example, we just invoked the highlightWord method from within a procedure. We decided later that the applyData approach is better, and we used it in the final solution, as we describe in 11.4.13, “Explaining the final stage” on page 223.

222 WebSphere Commerce Line-of-Business Tooling Customization

Page 241: My Tutorial

To view example 6:

1. Recompile for example 6, as we explained in 11.4.2, “Viewing the visual prototype stage (example 1)” on page 204.

2. Log into the Management Center with a new browser session, and open a Product Properties (product details) page.

3. Repeat the tests from 11.4.10, “Viewing the CDYNE service prototype stage (example 5)” on page 218, where you tested with misspelled words, but this time, the displayed spell check window should show the highlighting, similar to Figure 11-13. Occurrences of the unknown word are highlighted in red and are bracketed.

Figure 11-13 Highlighted unknown words

11.4.13 Explaining the final stage

In this section, we explain the design and code that we need for the final stage to complete the Spell Checker.

In this stage, we implement the correction process, and the model property is updated when the OK button is pressed. This is the first stage to really have

Chapter 11. Spell Checker 223

Page 242: My Tutorial

much dynamic event driven code and the JavaScript that is needed to implement that.

To help maintenance, we include a controller object to help centralize and control the states and transitions of the correction process. Figure 11-14 shows the states and transitions of the process. The ellipses are the states and the connections are the transitions.

Figure 11-14 State transition diagram

Using the states and transitions from the diagram as a guide, we implement our state controller object, as shown in Example 11-15.

Example 11-15 State controller

<!-- Single Object to record state and control the state transitions ofthe Spell Check Process. Changes to the currentState attribute willtrigger associated listeners and constraints.

-->

<node id="spellCheckerController_SC">

<attribute name="state" type="string" value="initial" /><attribute name="transition" type="string" />

initial

error

timedOut

checking

correctionsToDo

noCorrectionsNeeded

allProcessed wordEdited

closed

cancel

select/ edit

skip/ replace

skip/ replace

skip/ replace

ok/cancel

cancel

timeout

error

result[no unknown words]

result[unknown words]

cancel

cancel

ok/cancel

call service

224 WebSphere Commerce Line-of-Business Tooling Customization

Page 243: My Tutorial

<!-- Flags to indicate if a user has replaced a word using the spell check window

--><attribute name="wordReplaced" type="boolean" value="false" />

<handler name="ontransition" args="theTransition">switch (theTransition) {

case "to initial" :this.setAttribute("state", "initial");this.setAttribute("wordReplaced", false);break;

case "initial to checking" :this.setAttribute("state", "checking");break;

case "checking to correctionsToDo" :this.setAttribute("state", "correctionsToDo");break;

case "checking to noCorrectionsNeeded" :this.setAttribute("state", "noCorrectionsNeeded");break;

case "checking to error" :this.setAttribute("state", "error");break;

case "checking to timedOut" :this.setAttribute("state", "timedOut");break;

case "correctionsToDo to wordEdited" :this.setAttribute("state", "wordEdited");break;

case "to correctionsToDo" :this.setAttribute("state", "correctionsToDo");break;

case "to allProcessed" :this.setAttribute("state", "allProcessed");break;

default:// error due to undefined transition request // {programming error}if (wcfLogger.enabled)

wcfLogger.log("com.redbooks.components", "ERROR","spellCheckerController_SC", "ontransition","undefined transition request was: " +this.transition);

break;}

Chapter 11. Spell Checker 225

Page 244: My Tutorial

if (wcfLogger.enabled) wcfLogger.log("com.redbooks.components", "INFO","spellCheckerController_SC", "ontransition","transition = " +this.transition +" , new state = "+this.state);

</handler></node>

Some points to note about the code in Example 11-15 on page 224 are:

� The state attribute records the current state of the spell check and correction process. You can easily use this attribute in constraints to control what needs to happen to other objects when the state changes. Example 11-16 shows how this is achieved.

� A transition attribute is declared, which the spell check code can set whenever a transition is needed.

� A handler is listening for changes to the transition attribute, and it recognizes the transition that is requested and moves to the appropriate state.

As an illustration of how the spell check window code can use the state, look at the case of the messageView, which notifies the user of the status of the spell checking process, as shown in Example 11-16.

Example 11-16 Using the state controller

<wcfDialog id="spellCheckWindow" datapath="spellCheckDS:/" width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >.....

<!-- view at top part of window used to display status messages,message depends on state

-->

Benefits of the state controller object:

Using our state controller object:

� Simplified the spell checker code� Improved readability� Helped reduce the number of programmatic errors� Eased our aim of separating declarative XML from JavaScript code

Initially, we built the spell checker without it, then refactored the code to introduce it.

226 WebSphere Commerce Line-of-Business Tooling Customization

Page 245: My Tutorial

<view name="messageView"><simplelayout axis="y" spacing="5" /><state apply="${spellCheckerController_SC.state == 'checking'}">

<text text="${extCatalogResources.spellCheckWaitingMessage.string}"

/></state><state apply="${spellCheckerController_SC.state ==

'correctionsToDo'}"><text text="${spellCheckWindow.spellCheckResultsMsg}" />

</state><state apply="${spellCheckerController_SC.state ==

'noCorrectionsNeeded'}"><text text="${spellCheckWindow.spellCheckResultsMsg}" />

</state><state apply="${spellCheckerController_SC.state == 'error'}">

<text text="${extCatalogResources.spellCheckErrorGettingResultsMsg.string}"

/></state><state apply="${spellCheckerController_SC.state == 'timedOut'}">

<text text="${extCatalogResources.spellCheckTimedOutMsg.string}"

/></state>

<state apply="${spellCheckerController_SC.state =='allProcessed'}">

<text text="${extCatalogResources.spellCheckAllDoneMsg.string}"

/></state>

</view>

...

Some points to note about the code in Example 11-16 on page 226 are:

� We use state declarations for each state where we have a status information message to show.

� When a state apply condition is true, the declarations that are inside of those state tags will apply.

� Within each state, we declare a text component that contains resource bundle text that displays the applicable text message for that state.

Chapter 11. Spell Checker 227

Page 246: My Tutorial

� The state tags that are shown effectively form the equivalent of a case statement where only one text component at a time displays text in the information area of the window,

You might have noticed that the status information messages for no unknown words, and a number of unknown words, contains a word count message, for example, “There are [2] unknown words”. The unknown word count is returned in the XML message that the CDYNE service returns, which means that for two of the state sections of the Example 11-16 on page 226, we use a dynamically built attribute string spellCheckWindow.spellCheckResultsMsg rather than just a static resource bundle property. Example 11-17 shows how we built this dynamic message.

Example 11-17 Building the word count message

<wcfDialog id="spellCheckWindow" datapath="spellCheckDS:/" width="120" enabled="true" title="${extCatalogResources.spellCheckWindowLabel.string}" visible="false" modal="true" >.....

<!-- the number of unknown words returned from the spell checkservice --><text id="unknownWordCount_SC" visible="false" datapath=

"spellCheckDS:/DocumentSummary/MisspelledWordCount/text()"ondata="spellCheckWindow.handleUnknownWordCount(this.data);"

/>

<!-- The spell check results prompt message with [count] placeholder for the unknown word count

--><attribute name="spellCheckResultsTemplate"

value="${extCatalogResources.spellCheckSuggestionsPrompt.string}"type="string"

/>

<!-- The spell check results prompt message with the unknown word count

--><attribute name="spellCheckResultsMsg"

value="${extCatalogResources.spellCheckSuggestionsPrompt.string}"type="string"

/>

<!-- if no unknown words set controller state to no corrections to

228 WebSphere Commerce Line-of-Business Tooling Customization

Page 247: My Tutorial

do, otherwise set for corrections to do --><method name="handleUnknownWordCount" args="count" >

// first, replace the count placeholder with the count // in the prompt messagethis.spellCheckResultsMsg =

wcfStringUtil.replace(this.spellCheckResultsTemplate , "[count]", count);

// next, set the state, this event will update the message // view with the prompt messageif (count!="0") {

spellCheckerController_SC.setAttribute("transition", "checking to correctionsToDo");

} else {spellCheckerController_SC.setAttribute("transition",

"checking to noCorrectionsNeeded");}

</method>...

Some points to note about the code in Example 11-17 on page 228 are:

� We added a text component with an id of unknownWordCount_SC to hold the unknown word count. The datapath setting of this causes it to be populated with the misspelled word count that the CDYNE service returns.

� We set the ondata event of this text component to call a new method, handleUnknownWordCount, which:

– Replaces the place holder in the template message string with the unknown word count

– Sets the result of this into the spellCheckResultsMsg attribute that is used

– Sets the appropriate transition for our state controller. If the count is not zero, it is set to "checking to correctionsToDo"; otherwise, it is set to "checking to noCorrectionsNeeded". The transition setting then triggers the use of the dynamically formed string as the status message, as shown in Example 11-16 on page 226.

Next, we explain how we mapped button states to the process states. We take into account the states in the diagram of Figure 11-14 on page 224, and then consider how the states affect the buttons.

Chapter 11. Spell Checker 229

Page 248: My Tutorial

Table 11-1 outlines the button state control.

Table 11-1 Button state control

We show some snippets of the code to implement the button logic in Example 11-18. The constraints that enable or disable the Apply and Replace buttons, based on our controllers state, are shown in bold. Methods of the spell check widow are bound to the onclick events of the Skip, Replace, and Apply buttons. This approach helps us to reduce the quantity of the JavaScript code that was mixed in with the declarative XML.

Example 11-18 Button constraints

.... <!-- skip button: i.e. do not change, the unknown word --> <button id="skipButton_SC" text="${extCatalogResources.spellCheckSkipLabel.string}" onclick="spellCheckWindow.handleSkip();" /> <!-- replace: i.e. replace the unknown word --> <button id="replaceButton_SC" enabled="${spellCheckerController_SC.state == 'wordEdited'}" text="${extCatalogResources.spellCheckReplaceLabel.string}" onclick="spellCheckWindow.handleReplace();"

Button Enabled Disabled

Cancel Always Never

Skip Always Never (we hide corrections view when there are no unknown words)

Replace state = wordEdited (for example, a word is selected or edited, but no other action is taken yet)

state <> wordEdited

OK wordReplaced = true (for example, the replace button is used to replace a word)

wordReplaced = false

Note: We include a flag in our state controller for the wordReplaced state because we need to enable the OK button as soon as a first word is replaced, but we do not want to disable it until the user subsequently presses OK or the user ends the process with skip or cancel. We have no single state that achieves this.

230 WebSphere Commerce Line-of-Business Tooling Customization

Page 249: My Tutorial

/>

....

<button id="applyButton_SC" enabled="${spellCheckerController_SC.wordReplaced}" text="${extCatalogResources.spellCheckDoUpdateLabel.string}"onclick="spellCheckWindow.handleApply();"

/>

<button id="cancelButton_SC" enabled="true"text="${extCatalogResources.spellCheckCancelLabel.string}"

><handler name="onclick">

spellCheckWindow.close();spellCheckerController_SC.setAttribute

("transition", "to initial");</handler>

</button>

We also implemented the logic around selecting and editing the current unknown word. Example 11-19 shows snippets of code that we used for that.

Example 11-19 Suggestion selection and edit logic

...

<!-- an unknown word returned from the spell check service --><text id="wordForCorrection_SC" datapath="word/text()" />

<!-- edit field for correcting the unknown word, initially populated

with unknown word, returned from the spell check service.The user can populate this field with a selected suggestion, or edit the text.

--><edittext id="correctedWord_SC" datapath="word/text()"

onchanged="spellCheckWindow.handleUnknownWordEdited(this.text);"/> <!-- the suggestions list, populated with suggestions for the unknown

word, as returned by the spell check service --><list id="suggestions_SC" shownitems="10"

onselect=

Chapter 11. Spell Checker 231

Page 250: My Tutorial

"spellCheckWindow.handleSelectedSuggestion(this.getText());">

<textlistitem datapath="Suggestions/text()" /></list> ...

<!-- handle the case where a user has edited the word for correctioni.e. enable the replace button and set the controller state

--><method name="handleUnknownWordEdited" args="editedWord">

if((! extStringUtil.isBlankString(editedWord))) {

spellCheckerController_SC.setAttribute("transition","correctionsToDo to wordEdited");

}</method>

<!-- when the user selects a suggestions, replace the displayedcorrected word with it. Also, enable the replace button, as asuggestion has been selected

--><method name="handleSelectedSuggestion" args="selectedWord">

if (! extStringUtil.isBlankString(selectedWord)) {

correctedWord_SC.setText(selectedWord);spellCheckerController_SC.setAttribute("transition",

"correctionsToDo to wordEdited");}

</method>

Some points to note about the code in Example 11-19 on page 231 are:

� The user can edit the editable text field that is populated with the current unknown word. We bound the handleUnknownWordEdited method to its onchanged event so that this method is invoked when the user makes any kind of edit to that field.

� The handleUnknownWordEdited method sets our state controller transition so that the state moves on to wordEdited, which triggers activity that is bound to that particular state, for example, the Replace button becomes enabled.

� We took a similar approach for the suggestion list, but in this case we use the onselect event to invoke the handleSelectedSuggestion method.

� The handleUnknownWordEdited method also sets our state controller transition so that the state moves on to wordEdited. A selection of a suggestion moves the process onto the same state as though the user did a

232 WebSphere Commerce Line-of-Business Tooling Customization

Page 251: My Tutorial

manual edit. In this case though, the corrected word edit field is set to the suggestion.

The previous examples of the spell checker only use the first unknown word that the CDYNE service returns because the datapath is set to use the first occurrence of unknown word in the XML. To complete the spell checker implementation, we moved to the next occurrence of unknown word in the XML. To do this, we added a new moveToNextWord method to the spell check window object, as shown in Example 11-20.

Example 11-20 Move to next unknown word snippet

...<!-- moves the display on to the next misspelled word in the retrieved xml --><method name="moveToNextWord">

var dp = this.correctionsView.datapath;if (dp.selectNext()) {

// also need to check that we are still iterating through // Misspelled Word Elements.

// there are other element types at this level

var elementName = dp.getNodeName(); if (elementName == "MisspelledWord") { spellCheckerController_SC.setAttribute("transition",

"to correctionsToDo"); this.correctionsView.applyData(); } else { // hide corrections as all processed now this.correctionsView.setAttribute("visibility", "hidden");

spellCheckerController_SC.setAttribute("transition", "to allProcessed");

} } else { // hide corrections as all processed now this.correctionsView.setAttribute("visibility", "hidden");

spellCheckerController_SC.setAttribute("transition", "to allProcessed");

}</method>

...

Chapter 11. Spell Checker 233

Page 252: My Tutorial

Some points to note about the code in Example 11-20 on page 233 are:

� We moved to the next node by:

– Getting the datapath of the corrections view, which is initially set to the first unknown word node of the XML.

– Using the selectNext method of the datapath to move to the next node.

� We found that we could not just use the fact that there were no more nodes to determine when all unknown words were processed because there were other types of nodes at the same level of the XML. The iterations were passing down through those nodes too, which we fixed by adding in a check to make sure that the next node that was found was of the unknown word element type.

� Moving the datapath on to the next unknown word causes the child views of the corrections view to update, which is based on the relative XPath settings used for the child views.

� When all corrections are processed, the state is transitioned to allProcessed.

11.4.14 Testing the final stage

In this section, we explain how to deploy and test the final code, which includes the full dynamic behavior of the Spell Checker.

To compile to the final level of code:

1. Set the CatalogExtensionsLibrary.lzx file back to its original state, for example, as it was in the zip that accompanies this book. This compiles the extSpellChecker.lzx file, rather than the example stages.

2. Log into the Management Center with a new browser session, and open a Product Properties (product details) page.

Note: We used this section to explain some important points about how we designed and implemented the spell checker. To understand the full solution, you can look through the complete files of the zip that accompanies this book. The files that we use for the spell checker are described in 11.4.2, “Viewing the visual prototype stage (example 1)” on page 204.

234 WebSphere Commerce Line-of-Business Tooling Customization

Page 253: My Tutorial

You can now fully test the Spell Checker. Some things that we tested, that you might want to check are:

� Try out the Spell Checker for the rich text - long description and the short text unformatted text properties using cases of:

– Various misspelled words– Same word misspelled a number of times – No misspelled words– Various numbers of misspelled words

� The Replace button is only enabled after a suggested correction is selected or the unknown word is edited

� The OK button is only enabled after a word is replaced

� The highlight text area highlights all occurrences of the current unknown

� The Skip button skips to the next unknown word, if there is one

� Disconnect from the internet to see that error message

� Persistence: If the user clicks the OK button, the changed product should be listed in the active work section to the left of the window. Clicking the save button should persist the spell correction changes that you made, which you can confirm by: logging out, starting a new browser session, and opening the Product Properties panel for the product that was modified. The changes made should be seen.

11.5 Possible enhancements and changes

In this section, we discuss some possible enhancements that you can make to the spell checker. The discussions cover:

� Some short comings of the solution� Typical requirements that need enhancements� Suggestions on how to implement some of these enhancements

11.5.1 Dictionary

In this section, we discuss why a dictionary is a useful feature to have for the spell checker, and then we provide an overview of some ways that you can implement it.

A dictionary feature allows users to get the Spell Checker to stop reporting particular spellings as unknown words. In the eCommerce arena, this is particularly useful because things, such as brand names and domain specific terms, are often used and might be unknown to the Spell Checker.

Chapter 11. Spell Checker 235

Page 254: My Tutorial

The obvious approach, is to use a service that has a dictionary. We explore using a different service further in 11.5.3, “Using a different service” on page 237.

Another approach is to save and reuse a list of known words, perhaps in the WebSphere Commerce database. There are various ways that you can achieve this persistence. The current Spell Checker solution needs modifying to:

� Provide an add to the dictionary button to persist the current unknown word to the list of known words.

� Retrieve the list of known words and strip occurrences of them from the text that is sent to the Spell Check service for spell checking.

11.5.2 Replace /skip single occurrence

In this section, we discuss the usefulness of enabling the user to replace a single occurrence of an unknown word and discuss how to implement it, if needed. We have not tried or tested these suggestions.

We only implement the replacement of all occurrences of the unknown word for a few reasons:

� This is likely to be the most useful option for eCommerce, where the text is usually quite short, and it would be fairly unusual to need to only change one occurrence.

� The user can go back to the normal editor for the field and make corrections specific to particular occurrences of the word.

� We were limited on time as to what features we could include.

To implement this feature:

1. Change the current Replace button label to Replace All. 2. Add a new button titled Replace. The onclick event of this needs to invoke a

new method that implements similar functionality to the current method, handleReplace. The new method must not move on the next unknown word and needs to call a new replaceFirstWord method on the extHighlightRichText class.

3. Make the replaceFirstWord method similar to the current replaceWord method of that class. However, it needs to only replace the first occurrence of the changed word. After this, it also needs to refresh the highlighted text, using the highlightWord method of the same class.

236 WebSphere Commerce Line-of-Business Tooling Customization

Page 255: My Tutorial

11.5.3 Using a different service

In this section, we discuss using a different service than CDYNE. We cover why this might be a good thing to do, what additional features you might want from the new service, and what type of changes are needed to the existing solution.

The CDYNE service is currently free at the time of writing and working as specified in this book. However, that might not always be the case. It also has some limitations, in particular there is no dictionary or multiple language support.

For these reasons, you might want to use a different service, which can be hosted by a third party or one that you deploy on your own servers.

If you pick a service that is already capable of operating in a RESTful manner, returning XML results, the effort needed to change the existing solution might be limited to altering the following:

� The dataset to use the new URL

� The setting of the query parameters of the dataset

� The XPath statements that are used to set the datapaths appropriately

� The moveToNextWord method because the navigation of the XML might be different.

If you pick or deploy a service that does not work in a RESTful manner, you might need to implement a RESTful interface onto the service. If the service supports SOAP, you can change the current solution to support that. For documentation on the use of SOAP with OpenLaszlo, see:

http://www.openlaszlo.org/lps/docs/guide/rpc-soap.html

11.6 Summary

In this section, we summarize what we covered with the Spell Checker, including, the challenges we had and what was good. We also provide some tips.

The main challenges we had were:

� Finding an appropriate service. This proved to be harder than expected. This situation might change in the future as more service providers appear and there are less restrictions on usage.

� Working out the best approach. We spent a lot of time examining alternatives before we decided on using a new property editor, which was the only way to avoid issues with wanting to use the out of the box Management Center widgets.

Chapter 11. Spell Checker 237

Page 256: My Tutorial

The main things that we liked were:

� OpenLaszlo. It has the following features that we found to be particularly elegant and powerful:

– The declarative nature makes it easy to assemble the look and feel prototype

– This prototype can be taken forward with the final solution having similar construction code into that of the original prototype

– Ease of use of datasets for local static data and with minimal change for an external RESTful service

– Use of XPath to navigate the XML datasets, which is easy to understand and do

– The way that the viewable components can easily be bound to the XML of the dataset, which makes it easy to move from a static prototype to the use of dynamic data

– The ease with which events can be listened for and acted on using constraints

� The architecture of the Management Center made it easy to introduce a new property editor. It is easy to include a property editor in property panels. It should also be relatively easy to add a grid property editor.

The main tips we want to summarize are:

� Ensure that you follow the Management Center guidelines for customizing the Management Center

� Take small steps at a time, and build up from the look and feel prototype to the final solution. The less experience you have with Management Center customization, the smaller the steps you should take.

� Experiment with OpenLaszlo. Some of this can be done offline from WebSphere Commerce. One way to do this, is to use the OpenLaszlo site, where the documentation contains live editors that you can use to try out code snippets. For an example of this, go to the OpenLaszlo reference documentation, select a component, and then select the Edit button in one of the example panels. The reference documentation for version 4.1 is at:

http://www.openlaszlo.org/lps4.1/docs/reference/#

� Use declarative XML in preference to JavaScript

� Use JavaScript, and try to keep the bulk of JavaScript separate of the declarative XML.

238 WebSphere Commerce Line-of-Business Tooling Customization

Page 257: My Tutorial

Chapter 12. Custom Application Configuration Management tool

In this chapter, we build an end-to-end application that consists of customizations to all stages, a Management Center user interface (UI), a Management Center Web application, and IBM WebSphere Commerce services.

We build a tool that enables line-of-business users to manage settings of a custom WebSphere Commerce application. Custom WebSphere Commerce applications can use these settings to receive administrative settings that are not covered by existing WebSphere Commerce tools, such as WebSphere Commerce Accelerator or the Administration Console.

With the Custom Application Configuration Management tool (CACMT), line-of-business users can view, add, update, and delete settings for the store that is currently selected.

We only implement configuration management within the scenario that we describe in this chapter. There is no custom WebSphere Commerce application provided that uses the settings. However, you can integrate the configuration data from this example easily into one of the starter stores.

12

© Copyright IBM Corp. 2008. All rights reserved. 239

Page 258: My Tutorial

12.1 Understanding the requirements

There is a need to store configuration settings in every WebSphere Commerce application. Typical settings to be managed include data, such as:

� E-mail addresses for administrative purposes

� External URLs

� Number of categories, products, orders, and so on, shown in a list view (page size)

� Number of maximum order items that are allowed per shopping cart

More generally, these settings are in place to influence the behavior of the application’s customized user interface and customized business logic.

The WebSphere Commerce product has several tools, where configuration settings are managed, for example, the WebSphere Commerce Accelerator and the Administration Console. Unfortunately, there is no generic configuration management facility that allows line-of-business users to administer settings that custom WebSphere Commerce applications can easily pick up.

The Custom Application Configuration Management tool is a new tool for the Management Center that takes advantage of its state-of-the-art look-and-feel. For easier navigation, the configuration settings are grouped by categories.

After logging on to Management Center and selecting a store, the line-of-business users can manage all of the settings of the selected store, using the following action:

� Browse the configuration setting groups� Browse the configuration settings of a selected group� Change a configuration setting� Add a configuration setting� Delete a configuration setting

With limited functionality, there is already a tool to manage store-specific settings. Accelerator offers the Store flow feature that allows you to configure certain features in published stores. However, there are a number of issues, compared to Custom Application Configuration Management tool:

� The settings are persisted to file system and not to the database.

Take care when you deploy new releases of your WebSphere Commerce application because the store flow files are located within the Stores.war directory.

240 WebSphere Commerce Line-of-Business Tooling Customization

Page 259: My Tutorial

On a federated environment with multiple nodes, the changes of the store’s flow files must be somehow distributed to all nodes.

While you can enable staging support for the Custom Application Configuration Management tool, you cannot enable staging support for store flow.

� The store flow settings offer only the selection of predefined values.

The setting management is limited to disable/enable a specific setting, or to choice between a list of values. No data can be entered. No new settings can be added.

� Accessing the store flow settings is based on boolean value.

The <flow> tag library only allows you to check if a specific setting is enabled or disabled.

The store flow feature supports Extended Sites but the Custom Application Configuration Management tool does not.

Another approach is to misuse Content Spots to hold configuration settings, which might be a quick solution for very small applications but we do not recommend it at all because configuration settings would get mixed up with marketing content, and there is no possibility to protect configuration settings from changing by non-entitled users.

12.2 Overview of the customization

In this scenario, we create a tool for configuration settings management. Line-of-business users employ the Management Center to view, add, update, and delete settings. The settings are stored to a newly created, custom table that resides in the WebSphere Commerce instance database.

Figure 12-1 on page 242 shows the Custom Application Configuration Management tool user interface.

Chapter 12. Custom Application Configuration Management tool 241

Page 260: My Tutorial

Figure 12-1 Custom Application Configuration Management tool UI elements

The following UI elements are specific to the Custom Application Configuration Management tool:

� Explorer view

The Explorer view allows you to navigate through the configuration setting categories with which you want to work. Select a category to load all of its containing configuration settings that are in the List view.

The Explorer view always includes the Search Results node (to allow you to return to a list-of-results at any time) and Active Work node (to show the configuration settings that you currently have open).

� List view

The view is displayed in the main work area. The list view lists configuration settings in the form of a table. You can view the list and select a specific row to see more details. You can also reorder, hide, or show columns.

ListView

ExplorerView

Properties View

UtilitiesView

242 WebSphere Commerce Line-of-Business Tooling Customization

Page 261: My Tutorial

� Properties view

Also displayed in the main work area, the properties view shows details about the selected configuration setting, which you can also edit in this view. You access the properties view from either selecting to create a new instance of a configuration setting or by selecting an existing configuration setting from a list view.

� Utilities view

In the utilities view, you can locate and use configuration settings that you want to reference without navigating away from the current view. Use the utilities view to search for configuration settings. Browse and clipboard features are also provided.

The customization work is comprised of the following high-level steps:

� Customize the Management Center user interface:

– Define the main tool definition.

– Define the OpenLaszlo classes that are instantiated in the tool definition class.

– Define the UI text and images for the Management Center objects.

– Define the library class for all OpenLaszlo classes.

– Add the new tool to the Management Center menu.

– Authorize the new tool to the business role.

� Customize the WebSphere Commerce services

A new service module called CustomAppProperties is created:

– Define the CustomAppProperties noun.

– Generate the CustomAppProperties service module projects.

– Generate the logical Service Data Objects (SDOs) for the CustomAppProperties noun.

– Implement the Persistence layer for the WebSphere Commerce BOD programming model.

– Implement Business Object Mediators to transform logical SDOs and physical SDOs.

– Configure the Data Service layer for the CustomAppProperties service module.

– Implement the Business Logic layer.

– Implement the client library.

– Implement access control.

Chapter 12. Custom Application Configuration Management tool 243

Page 262: My Tutorial

– Deploy and validate the CustomAppProperties service module with JUnit.

� Customize the Management Center Web application:

– Define retrieval services for the new Management Center object. – Define process services for the new Management Center object.

Figure 12-2 shows the Project Explorer, which outlines all projects that are involved in the Custom Application Configuration Management tool scenario.

Figure 12-2 Projects involved in the CACMT scenario

You work on the following projects:

� Enterprise Applications

WebSphere Commerce

This project contains the asset definition of the WebSphere Commerce Enterprise Application Archive (EAR) that you must execute in the J2EE environment of the IBM WebSphere Application Server.

This project is a default WebSphere Commerce Developer project, and you will update its configuration.

244 WebSphere Commerce Line-of-Business Tooling Customization

Page 263: My Tutorial

� EJB Projects

CustomAppProperties-Server

This project contains all BOD commands, Business Object Mediators, and physical SDOs. It implements the component facade.

You generate this project during customization. You change the generated assets and update the project’s configuration.

� Dynamic Web Projects

– CustomAppPropertiesServicesHTTPInterface

This project serves as a remote access proxy and contains a Web services router servlet for the CustomAppProperties component.

You generate this project during customization. No updates on assets or configuration are required.

– LOBTools

This project contains all assets of the Management Center user interface and Management Center Web application.

This project is a default WebSphere Commerce Developer project and is created when you enable the Management Center feature from Feature Pack 3.0.1.

You create and update several assets, and you update the project’s configuration.

– WebServicesRouter

This project is intended to define all of the Web services that your WebSphere Commerce instance provides, which only applies to Web services using the functional architecture of WebSphere Commerce prior to Feature Pack 2. Therefore, this project is not used with Management Center, so we do not use it in this scenario.

This project is a default WebSphere Commerce Developer project. You only need to copy assets from this project to others.

� Other Projects

– ComponentProjects

This project stores the ComponentProjects design pattern. Together with the Design Pattern Toolkit (DPTK), these assets generate WebSphere Commerce services. All CustomAppProperties projects are generated from this toolkit.

Chapter 12. Custom Application Configuration Management tool 245

Page 264: My Tutorial

This project is a default WebSphere Commerce Developer project, but you have to download and import this project into your workspace before you use it.

You create a few assets, and then start the generation process.

– CustomAppProperties-Client

This project contains the service client library that acts as a facade to the CustomAppProperties service.

You generate this project during customization. You do not need to make any changes to the assets, but you do update the project’s configuration.

– CustomAppProperties-DataObjects

This project contains the logical Service Data Objects, represented as Java classes, the SDO data definition (XML Schema Definition - XSD), and the SDO service definition (Web Services Description Language - WSDL). Both CustomAppProperties-Server and CustomAppProperties-Client projects access this project and share the same assets. The reason to out source the logical SDOs is to keep <service>-Client and <service>-Server projects independent without adding redundancy on the code.

You generate this project during the customization, make changes to the assets, and update the project’s configuration.

– CustomAppProperties-UnitTests

This project contains JUnit-based unit tests to test the CustomAppProperties service operations. This project utilizes CustomAppProperties-Client and CustomAppProperties-DataObjects projects and is configured to access CustomAppProperties service by a Web service using HTTP.

You generate this project during the customization, make changes to the assets, and update the project’s configuration.

12.2.1 Architectural overview

In WebSphere Commerce Feature Pack 3.0.1, the Business Object Document command framework is introduced. This command framework centers on business objects, or nouns, as the value object that is used in all of your Java business logic. The introduction of the Data Service layer supports the persistence of these value objects.

WebSphere Commerce is transitioning to a service-oriented architecture (SOA) by decoupling business subsystems. Decoupling allows reuse in other environments, besides the WebSphere Commerce application. You can use

246 WebSphere Commerce Line-of-Business Tooling Customization

Page 265: My Tutorial

WebSphere Commerce services in WebSphere Portal applications, the IBM Sales Center, the Management Center, and any other custom applications.

The Management Center and a JUnit test application use the CustomAppProperties service that is built within this scenario.

Figure 12-3 shows an overview of the main building blocks of the Custom Application Configuration Management tool. The Management Center, WebSphere Commerce server, and CustomAppProp service test application are independent, not necessarily sharing a common environment and connected through HTTP-based interfaces. However, the customization steps that we describe in this chapter are all performed on your local workstation, running WebSphere Commerce Developer.

Figure 12-3 Architectural overview diagram of the Custom Application Configuration Management tool

The Management Center uses name-value-pair URLs to invoke services on the WebSphere Commerce server, through the mediation of the Management Center Web application. Returning documents are of simple-formatted XML.

WebSphere Commerce Server

CustomAppProperties service test application

JUnit Test Cases

BOD Commands

Business Object

Mediators

Physical Object

Persistence Service

Logical SDOs

IBM Management Center for WebSphere Commerce

Logical SDOs

HTTPPOST

XML

SOAP Request

EJB Call

EJB Call

Database ServerWebSphere Commerce Database

JDBC

CustomAppProperties-DataObjects

CustomAppProperties-UnitTests CustomAppProperties-Client

Remote usage (Call)

Local usage (Use)

Legend

LOBTools

Managament Center Web Application

OpenLaszlo Application

LOBTools CustomAppProperties-DataObjects

Client Library Web Service Router

CustomAppProperties-Server

CustomAppPropertiesServicesHTTPInterface

SOAP Response

Chapter 12. Custom Application Configuration Management tool 247

Page 266: My Tutorial

The CustomAppProperties service test application uses OAGIS messaging. Instead of the name-value-pair URLs that represent a typical Web request, business components declare structured objects that represent services. The components use OAGIS XSDs to define services. Technically, the communication is performed by Web services using the Simple Object Access Protocol (SOAP).

The applications that run inside of the WebSphere Commerce server employ local Enterprise Java Beans (EJBs) to perform fast and container-managed communication, which includes transaction handling.

The Data Access Service (DAS), which the Data Service layer provides accesses the WebSphere Commerce database.

12.3 Customizing the Management Center user interface

In this section, we explain how to make client-side customizations to add the new Custom Application Configuration Management tool to the Management Center.

All of the Management Center resources that are created for the new tool are under the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config

Note: In the following sections, we include code snippets along with explanations for the main parts of this customization. For a complete source code, refer to the LOBTools customization compressed archive that we provide for this example. You can import the contents of the archive into your workspace under the LOBTools project.

Some of the files in this archive might already exist in your workspace if you performed other examples in this IBM Redbooks publication, or if you are making changes to files that are part of the WebSphere Commerce product. In such cases, we recommend that you merge the changes manually instead of overwriting files in your workspace with the files that we provide in this example.

248 WebSphere Commerce Line-of-Business Tooling Customization

Page 267: My Tutorial

12.3.1 Main tool definition

The main tool definition file defines a business object editor, which is the starting point for any Management Center tool. The business object editor instantiates the following class definitions:

� Init service definition

Initializes one or more context values by invoking the URL that is specified in the url attribute. The response must be an XML document that contains context values.

� Object definitions

You can instantiate the following object definition types in the tool definition:

– Top object definition: Describes the root object for the business object editor. This object is the starting point for populating the Management Center explorer tree.

– Primary object definition: Describes a business object that the business object editor must manage.

– Organizational object definition: Describes a node in the Management Center explorer view. An organizational object has no representation on the WebSphere Commerce server. It is a client-side object that groups primary objects within the Explorer view.

� Filter definition

Describes a filter for objects in the Management Center Explorer view.

� Search definition

Describes an object search type. Search definitions allow business users to find Management Center objects within the new tool.

The file cfgConfigManagementToolDefintion.lzx has the main tool definition for the Custom Application Configuration Management tool. We define the class, extConfigManagement, which extends wcfBusinessObjectEditor and instantiates filter, object, and search definitions that the Custom Application Configuration Management tool uses, as shown in Example 12-1 on page 250.

Note: The Custom Application Configuration Management tool does not require any special context values. The only context value that is required is storeId, which is already available from the framework. Therefore, no Init service definition was created for the Custom Application Configuration Management tool.

Chapter 12. Custom Application Configuration Management tool 249

Page 268: My Tutorial

Example 12-1 Tool definition for the Custom Application Configuration Management tool

<class name="extConfigManagement" extends="wcfBusinessObjectEditor" >

<!-- Filter definitions --><extConfigCategoryFilter />

<!-- Primary object definitions --><extConfigTopObjectDefinition /><extConfigOrganizationalObjectDefinition/><extConfigPropertyPrimaryObjectDefinition /><extConfigCategoryPrimaryObjectDefinition />

<!-- Search definitions --><extFindConfigurations />

</class>

12.3.2 Object definitions

In this section, we go through all of the object definitions that were created for the new tool. The following objects are modeled for the Custom Application Configuration Management tool:

� ConfigurationTop: Organizational object for grouping configuration categories in the Explorer view.

� ConfigCategory: Primary object that represents a unique configuration category. These categories are displayed in the Explorer view as child nodes of the organizational object.

� ConfigProperty: Primary object that represents a custom configuration property. These categories are displayed in the list view when you select a ConfigCategory object in the Explorer view. You can perform Create, Update, and Delete actions on this object type.

� ChildConfigProperty: A reference object that links a parent ConfigCategory object to its child ConfigProperty object.

All OpenLaszlo files for Custom Application Configuration Management tool object definitions are under the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config/objectDefinitions

250 WebSphere Commerce Line-of-Business Tooling Customization

Page 269: My Tutorial

Top object definitionThe file, cfgConfigTopObjectDefinition.lzx, contains the top object definition for the Custom Application Configuration Management tool. This file defines the following classes:

� extConfigOrganizationalObjectDefinition: Defines an organizational object type, shown in Example 12-2. The attributes that this definition uses are:

– objectType: A string that identifies the object type as ConfigurationTop.

– organizedObjectTypes: A comma separated list of object types that are listed under this organizational object. In our case, we have only one object type to be listed: ConfigCategory.

– icon: Resource name for the icon to use in Explorer view for this organizational object.

– displayName: Displays the name to use in Explorer view. This value is retrieved from the resource bundle.

This class declares a child element, wcfGetChildrenService, with the URL /cmc/GetConfigCategories. This service returns a list of ConfigCategory business objects that are to be displayed in the Explorer view when the organizational object tree node is expanded.

Example 12-2 Organizational object definition

<class name="extConfigOrganizationalObjectDefinition" extends="wcfOrganizationalObjectDefinition" objectType="ConfigurationTop" organizedObjectTypes="ConfigCategory" icon="configTreeFolderIcon" displayName="${extConfigResource.configTopDisplayName.string}"> <wcfGetChildrenService url="/cmc/GetConfigCategories"> <wcfServiceParam name="storeId"/> </wcfGetChildrenService> </class>

� extConfigTopObjectDefinition: Top object definition for the Custom Application Configuration Management tool, which uses a child template data set, shown in Example 12-3 on page 252. When the business object editor is initialized, the Explorer view tree is populated using the object in the template data set, which, in this case, is the organizational object ConfigurationTop, which we defined in Example 12-2.

Chapter 12. Custom Application Configuration Management tool 251

Page 270: My Tutorial

Example 12-3 Top object definition

<!-- Top object definition. Template datadet defined to use ConfigurationTop organiational object. --><class name="extConfigTopObjectDefinition" extends="wcfTopObjectDefinition"> <dataset name="template"> <object objectType="ConfigurationTop"/> </dataset></class>

Based on this definition, the business object editor should display the organizational object, ConfigurationTop, with the display name, Configuration Categories (the display name value is taken from the resource bundle), and when expanded, list the available ConfigCategory objects as child nodes. See Figure 12-4 for a sample of the Custom Application Configuration Management tool Explorer view.

Figure 12-4 CACMT Explorer view

Reference object definitionTo create a parent-child relationship between the ConfigCategory and ConfigProperty object types, we create a reference object definition. The class extConfigCategoryPropertyReference, which is in the file cfgConfigObjectDefinitions.lzx, defines a parent-child relationship, which we show in Example 12-4 on page 253.

Note: If a wcfGetChildrenService element is defined as a child of the top object definition, then the Explorer tree root nodes are created based on the objects that this service returns. For the Custom Application Configuration Management tool, we use a single organizational object, ConfigurationTop, as the root node.

252 WebSphere Commerce Line-of-Business Tooling Customization

Page 271: My Tutorial

The primary object that owns this reference object is the parent, while the object type that is referenced is the child in this relationship. The following attributes are defined for this class:

� idProperty: Name of the object property that contains the unique ID for an instance of this object type.

� objectType: String that identifies the object type.

� referencedType: String that identifies the child object type in this relationship. In this case, the child object type is ConfigProperty.

Example 12-4 shows the reference object definition.

Example 12-4 Reference object definition

<class name="extConfigCategoryPropertyReference" extends="wcfParentReferenceObjectDefinition" idProperty="childConfigPropertyId" objectType="ChildConfigProperty" referencedType="ConfigProperty"></class>

Primary object definitionsTwo primary objects are modeled for the Custom Application Configuration Management tool, ConfigCategory and ConfigProperty.

Primary object definition for ConfigCategoryConfigCategory is a client-side object that is modeled to present all distinct configuration property categories in the Explorer view. This is not a business object on the WebSphere Commerce server; therefore, you cannot create it using the Custom Application Configuration Management tool.

The class, extConfigCategoryPrimaryObjectDefinition, which is in the file cfgConfigCategoryPrimaryObjectDefinition.lzx, defines the ConfigCategory primary object, which we show in Example 12-5 on page 254. This primary object represents a grouping of configuration properties by category name. The following list contains some of the important attributes that this class definition sets:

� objectType: String that identifies the object type as ConfigCategory.

� creatable: Set to false. This indicates that the ConfigCategory object type should not be visible in the create menu. Management Center user cannot create instances of this object type.

� displayNameProperty: Name of the object’s property whose value is used as the display name for an instance of this object type. In this case, the display

Chapter 12. Custom Application Configuration Management tool 253

Page 272: My Tutorial

name for an object is the value of its configCategoryName property, which is the value that is displayed in the Explorer’s tree view.

Example 12-5 Definition for ConfigCategory primary object

<class name="extConfigCategoryPrimaryObjectDefinition" extends="wcfPrimaryObjectDefinition" objectType="ConfigCategory" creatable="false" displayName="${extConfigResource.config_DisplayName.string}" displayNameProperty="configCategoryName" idProperty="configCategoryName" headerIcon="configurationHeaderIcon" icon="configurationIcon" newDisplayName="${extConfigResource.config_NewDisplayName.string}">..</class>

The following child elements are declared within the primary object class definition:

� wcfGetChildrenService is declared as a child of this primary object definition, as shown in Example 12-6. This service returns a list of ConfigProperty child objects. The parameters that are passed to the request are:

– storeId: Store ID from context.

– configCategoryName: Value of the configCategoryName property of the ConfigCategory object. This service returns all of the configuration properties with the given category name.

Example 12-6 Get children service definition for ConfigCategory object

<wcfGetChildrenService url="/cmc/GetConfigCategoryChildren"> <wcfServiceParam name="storeId"/> <wcfServiceParam name="configCategoryName" propertyName="configCategoryName" /></wcfGetChildrenService><extConfigCategoryPropertyReference />

Note: Example 12-5 does not have the complete class definition; instead, it displays parts of the class definition for reference. For the complete source code, refer to the cfgConfigCategoryPrimaryObjectDefinition.lzx file.

254 WebSphere Commerce Line-of-Business Tooling Customization

Page 273: My Tutorial

� To define a parent-child relationship between the ConfigCategory and ConfigProperty object types, we instantiate the reference object extConfigCategoryPropertyReference, as shown in Example 12-6 on page 254. We discussed this reference object“Reference object definition” on page 252.

� When the Management Center user selects a ConfigCategory object in the explorer view, we want to display the ConfigProperty child objects that the wcfGetChildrenService returns as a list view in the main work area, as shown in Figure 12-5, which occurs using a wcfNavigationListDefinition declaration, as shown in Example 12-7. The following attributes are set for this navigation list definition:

– listClass: Name of the class that displays the child objects. In this case, we use extConfigPropertyList (See section “Navigation list definition” on page 261).

– isDefault: Set to true to indicate that this is the default navigation list. The default navigation list is displayed in the main work area when a ConfigCategory object is selected in the Explorer view.

– listTitle: Title for the navigation list, which is displayed above the list in the main work area.

– displayName: Display name for the navigation list, which is displayed in the context menu for the ConfigCategory object in the Explorer view.

Example 12-7 Navigation list definition

<wcfNavigationListDefinition name="extConfigCategoryChildList" listClass="extConfigPropertyList" listTitle="${extConfigResource.propertyList.string}" displayName="${extConfigResource.propertyListDisplayName.string}" isDefault="true" />

Figure 12-5 Navigation list view

Chapter 12. Custom Application Configuration Management tool 255

Page 274: My Tutorial

Primary object definition for ConfigPropertyThe ConfigProperty object is the WebSphere Commerce business object that the Custom Application Configuration Management tool manages. The class extConfigPropertyPrimaryObjectDefinition, which is in the file cfgConfigPropertyPrimaryObjectDefinition.lzx, defines the ConfigProperty primary object.

The ConfigProperty object has the following properties:

� key: Name of the custom configuration property.� category: Category name for the custom configuration property.� type: Indicates the data type of the custom configuration property.� description: Description of the custom configuration property.� value: Value of the custom configuration property.

The following list contains the required attribute set that is in the primary object class definition (Example 12-8):

� objectType: Identifies object types as ConfigProperty.

� creatable: Set to true to indicate that this object type should be visible in the create menu.

� displayNameProperty: Name of the object’s property whose value will be used as the display name for an instance of this object type. In this case, the display name for an object is the value of its key property. This value is displayed in the Explorer view and Property view when an instance of this object is opened for update.

� idProperty: Name of the object’s property that holds a unique ID for an instance of this object.

� searchType: A search type that can be used to perform searches for objects of this type. The search type that you specify must be a searchType attribute from a wcfSearchDefinition. We use the search type, FindConfigProperties, which is defined in the search definition class extFindConfigurations (See 12.3.3, “Search definition” on page 259).

� propertiesClass: Name of the class that is used to display the Properties view for objects of this type. The Property view class that is used for the ConfigProperty object is extConfigurationProperties (See 12.3.6, “Property view definition” on page 265).

Example 12-8 Definition for ConfigProperty primary object

<class name="extConfigPropertyPrimaryObjectDefinition" extends="wcfPrimaryObjectDefinition" objectType="ConfigProperty" creatable="true" displayName="${extConfigResource.config_PropertyDisplayName.string}"

256 WebSphere Commerce Line-of-Business Tooling Customization

Page 275: My Tutorial

displayNameProperty="key" idProperty="configPropertyId" newDisplayName="${extConfigResource.config_PropertyNewDisplayName.string} " searchType="FindConfigProperties" propertiesClass="extConfigurationProperties" headerIcon="configPropertyHeaderIcon" icon="configPropertyIcon">

The following child elements are declared within this primary object definition class:

� An instance of extConfigPropertyValidator, which is an object-level validator that validates a ConfigProperty object. The class definition for this validator is in the cfgConfigPropertyObjectValidator.lzx file. It validates the value property of this primary object based on the following rules:

– If the type property is Integer, the value property should be an integer.

– If the type property is Float, the value property should be a float.

– If the type property is Date, the value property should be parsable, such as a date object.

– If the type property is DateTime, the value property should be parsable, such as a date object.

– If the type property is SimpleText, no validation occurs.

� The following service definitions, shown in Example 12-9 are declared for Create, Update, and Delete actions on the ConfigProperty object:

– wcfCreateService creates an object on the WebSphere Commerce server by invoking the URL that is specified in the url attribute.

– wcfUpdateService updates an object on the WebSphere Commerce server by invoking the URL that is specified in the url attribute.

– wcfDeleteService deletes an object on the WebSphere Commerce server by invoking the URL that is specified in the url attribute.

Example 12-9 Service definitions

<!-- Create service --><wcfCreateService url="/cmc/CreateCustomAppProperties"> <wcfServiceParam name="storeId"/></wcfCreateService><!-- Update service --><wcfUpdateService url="/cmc/UpdateCustomAppProperties">

Chapter 12. Custom Application Configuration Management tool 257

Page 276: My Tutorial

<wcfServiceParam name="storeId"/> <wcfServiceParam name="configId" propertyName="configPropertyId" /></wcfUpdateService><!-- Delete service --><wcfDeleteService url="/cmc/DeleteCustomAppProperties"> <wcfServiceParam name="storeId"/> <wcfServiceParam name="configId" propertyName="configPropertyId" /></wcfDeleteService>

� Property definitions (wcfPropertyDefinition instances) for each property of the ConfigProperty primary object. Property definitions are optional, and you can use them to define information that built-in validators use and also to add custom validators for a property.

For key, value, category, and description properties of the ConfigProperty object, we use property definitions, shown in Example 12-10, to set the following information:

– displayName: Display name for this property.

– propertyName: Name of the property being defined.

– required: Indicates if this is a required property. When set to true, the Management Center UI appends an asterisk to the display name. Setting this to true also enables a built-in validator, which ensures that the value of this property is not null or empty.

– type: Data type for this property. A built-in validator ensures that the value of this property can be converted to the specified type.

– maximumSize: Maximum size for this property. The built-in property size validator uses this value.

Example 12-10 Property definitions for key, value, category and description

<!-- Property definition for ConfigProperty.key --><wcfPropertyDefinition displayName="${extConfigResource.keyPropertyName.string}" propertyName="key" required="true"type="string" maximumSize="100"/>

<!-- Property definition for ConfigProperty.value --><wcfPropertyDefinition displayName="${extConfigResource.valuePropertyName.string}" propertyName="value" required="true" type="string" maximumSize="254"/>

<!-- Property definition for ConfigProperty.category --><wcfPropertyDefinition

258 WebSphere Commerce Line-of-Business Tooling Customization

Page 277: My Tutorial

displayName="${extConfigResource.categoryPropertyName.string}" propertyName="category" required="true" type="string" maximumSize="100"/>

<!-- Property definition for ConfigProperty.description --><wcfPropertyDefinition displayName="${extConfigResource.descPropertyName.string}" propertyName="description" type="string" maximumSize="254"/>

For the type property of ConfigProperty object, in addition to the attributes that we previously mentioned, we also create wcfPropertyValue instances to provide a list of selectable values for this property, as shown in Example 12-11. Attributes set for each wcfPropertyValue are:

– displayName: Displays the name for the property value.

– value: The value that is stored in the object. The possible values defined are SimpleText, Integer, Float, Date, and DateTime.

Example 12-11 Property definitions for type

<!-- Property definition for ConfigProperty.type --><wcfPropertyDefinition propertyName="type" displayName="${extConfigResource.typePropertyName.string}" maximumSize="50" required="true" type="string"> <wcfPropertyValue displayName="${extConfigResource.typeString.string}" value="SimpleText"/> <wcfPropertyValue displayName="${extConfigResource.typeInteger.string}" value="Integer"/> <wcfPropertyValue displayName="${extConfigResource.typeDecimal.string}" value="Float"/> <wcfPropertyValue displayName="${extConfigResource.typeDate.string}" value="Date"/> <wcfPropertyValue displayName="${extConfigResource.typeTimestamp.string}" value="DateTime"/></wcfPropertyDefinition>

12.3.3 Search definition

We add the FindConfigProperties search type to allow the Management Center users to search for configuration properties.

In this section, we explain the search definition that is created for the ConfigProperty object, as shown in Example 12-12 on page 260. The search

Chapter 12. Custom Application Configuration Management tool 259

Page 278: My Tutorial

definition class, extFindConfigurations, is defined in the cfgFindConfigSearchDefinition.lzx file, under the following directory: LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config/searchDefinitions

The following attributes are set for the search definition:

� searchType: A string that identifies the search type.

� displayName: Display name to be used for this search type.

� isDefault: Set to true, which indicates that this is the default search type.

� listClass: Name of the grid class to be used to display search results. In this case, extConfigPropertySearchGrid (See “Search list definition” on page 264).

� listTitle: Title to be displayed in the search results view.

An instance of the search service (wcfSearchService), which was created as a child of this search definition, specifies the search URL in its url attribute.

Example 12-12 Search definition

<class name="extFindConfigurations" extends="wcfSearchDefinition" searchType="FindConfigProperties" displayName="${extConfigResource.config_PropertyDisplayName.string}" isDefault="true" listClass="extConfigPropertySearchGrid" listTitle="${extConfigResource.propertySearchTitle.string}"> <wcfSearchService name="findConfigProperties" url="/cmc/FindConfigProperties"> <wcfServiceParam name="storeId" /> </wcfSearchService></class>

You can initiate this default search either from the Search bar in the right corner of the Management Center menu area, as shown in Figure 12-6 or from the Search bar in the Utilities view, shown in Figure 12-7 on page 261.

Figure 12-6 Search bar in menu area.

260 WebSphere Commerce Line-of-Business Tooling Customization

Page 279: My Tutorial

Figure 12-7 Search bar in utilities view

12.3.4 List definitions

In this section, we explain list definitions that were created for the new tool. The following two list definitions are created for the Custom Application Configuration Management tool:

� Definition for the navigation list to display the ConfigProperty objects when a ConfigCategory object is selected in the Explorer view.

� Definition for search result list that displays the ConfigProperty objects that the FindConfigProperties search type returns (See 12.3.3, “Search definition” on page 259).

All of the OpenLaszlo files that are for the Custom Application Configuration Management tool list definitions are under the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config/listViewDefinitions

Navigation list definitionNavigation list is defined in cfgConfigurationPropertiesGrid.lzx file. The following two classes are defined in this file:

� The Child list editor (wcfChildListEditor) class, extConfigPropertyList, as shown in Example 12-13. This class is referenced by The wcfNavigationListDefinition class references this and declares it for the ConfigCategory primary object, as shown in Example 12-7 on page 255. The following attributes are set for this class:

– listClass: Name of the object grid class that is used for viewing this list, in this case extConfigPropertyGrid.

– objectTypes: Child object types to be displayed in this list. We have only one object type, ChildConfigProperty, to display.

Example 12-13 Child list editor

<class extends="wcfChildListEditor" name="extConfigPropertyList"> <attribute name="listClass" value="extConfigPropertyGrid"/>

Chapter 12. Custom Application Configuration Management tool 261

Page 280: My Tutorial

<attribute name="objectTypes" value="ChildConfigProperty"/></class>

� Object grid (wcfObjectGrid) class extConfigPropertyGrid. This is the grid class used by navigation child list editor extConfigPropertyList to display ConfigProperty objects in the list view.

The object grid class definition sets its preferenceKey attribute, as shown in Example 12-14. When columns in this grid are reconfigured by a Management Center user, the new column settings are saved in the Preference Manager, only if the preferenceKey attribute value is set.

wcfGridText is used to display property values in each column of the grid, as shown in Example 12-14. The following grid column attributes are set for each wcfGridText element:

– editable: If set to true, the column allows in place editing.

– propertyName: Name of the object property to display in this column.

– objectPath: Used to specify the path to locate the property set in the propertyName attribute. The object type that this grid uses is the ChildConfigProperty reference object, as shown in Example 12-4 on page 253. Therefore, to resolve the value for the propertyName attribute from the child object, we use the ConfigProperty as the object path.

– datatype: The columns data type.

– text: Text to display in the column header.

– visible: If set to true, the column is visible. You can modify this setting by reconfiguring the grid.

– required: If set to true, it indicates that this is a required column. A Management Center user cannot hide required columns.

Example 12-14 Navigation list grid definition

<class extends="wcfObjectGrid" name="extConfigPropertyGrid" preferenceKey="extConfigPropertyBrowseGrid"><wcfGridText editable="false" name="configPropertyId" objectPath="ConfigProperty" propertyName="configPropertyId" text="${extConfigResource.configPropertyIdColumnHeader.string}" visible="false" width="90"/><wcfGridText editable="false" name="category" objectPath="ConfigProperty" propertyName="category" text="${extConfigResource.configCategoryColumnHeader.string}" visible="false" width="90"/> <wcfGridText editable="false" name="key" objectPath="ConfigProperty" propertyName="key" required="true"

262 WebSphere Commerce Line-of-Business Tooling Customization

Page 281: My Tutorial

datatype="string" text="${extConfigResource.keyColumnHeader.string}" visible="true" width="200"/> <wcfGridText editable="false" name="value" objectPath="ConfigProperty" propertyName="value" datatype="string" text="${extConfigResource.valueColumnHeader.string}" visible="true" width="220"/> <wcfGridText editable="false" name="type" objectPath="ConfigProperty" propertyName="type" datatype="string" text="${extConfigResource.typeColumnHeader.string}" visible="true" width="100"/><wcfGridText editable="false" name="description" objectPath="ConfigProperty" propertyName="description" datatype="string" text="${extConfigResource.descColumnHeader.string}" visible="false" width="300"/></class>

Figure 12-8 shows the default navigation grid display. The Management Center can change the columns that are displayed and their order.

Figure 12-8 Navigation grid

Chapter 12. Custom Application Configuration Management tool 263

Page 282: My Tutorial

Search list definitionThe search grid class, extConfigPropertySearchGrid, is defined in the cfgConfigurationPropertiesSearchGrid.lzx file, as shown in Example 12-15. This grid definition is similar to the navigation list definition that is shown in Example 12-14 on page 262 with the following differences:

� No objectPath attribute is specified because the search grid operates on the ConfigProperty primary object.

� Because the search can return ConfigProperty objects from multiple categories, the default visibility of the category property is set to true.

Example 12-15 Search list grid definition

<class extends="wcfObjectGrid" name="extConfigPropertySearchGrid" preferenceKey="extConfigPropertySearchGrid"><wcfGridText editable="false" name="configPropertyId" propertyName="configPropertyId" text="${extConfigResource.configPropertyIdColumnHeader.string}" visible="false" width="90"/><wcfGridText editable="false" name="category" propertyName="category" text="${extConfigResource.configCategoryColumnHeader.string}" visible="true" width="220"/> <wcfGridText editable="false" name="key" propertyName="key" required="true" datatype="string" text="${extConfigResource.keyColumnHeader.string}" visible="true" width="200"/> <wcfGridText editable="false" name="value" propertyName="value" datatype="string" text="${extConfigResource.valueColumnHeader.string}" visible="true" width="220"/> <wcfGridText editable="false" name="type" propertyName="type" datatype="string" text="${extConfigResource.typeColumnHeader.string}" visible="true" width="100"/><wcfGridText editable="false" name="description" propertyName="description" datatype="string" text="${extConfigResource.descColumnHeader.string}" visible="false" width="300"/> </class>

264 WebSphere Commerce Line-of-Business Tooling Customization

Page 283: My Tutorial

Figure 12-9 shows the default search result grid display. The Management Center can change the columns that are displayed and their order.

Figure 12-9 Search result grid

12.3.5 Filter definition

We add a filter to restrict the object types that are displayed in the Explorer view to the ConfigurationTop root object and the ConfigCategory primary object, as shown in Example 12-16. The default filter class extConfigCategoryFilter for the Explorer view is defined in the cfgConfigManagementFilterDefinitions.lzx file, which is located in the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config

Example 12-16 Filter definition

<class name="extConfigCategoryFilter" extends="wcfObjectTypeFilter" filterType="All" displayName="${extConfigResource.configCategoryFilter.string}" objectTypes="ConfigurationTop,ConfigCategory" isDefault="true"/>

12.3.6 Property view definition

We create a property view to define the editor that is presented to a Management Center user when an instance of the ConfigProperty object is opened or when a new instance needs to be created, as shown in Figure 12-10 on page 266.

Chapter 12. Custom Application Configuration Management tool 265

Page 284: My Tutorial

Figure 12-10 Property view

The property view definition class, extConfigurationProperties (Example 12-17), is defined in the cfgConfigurationPropertiesView.lzx file, which is located under the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config/propertiesViews

We need only one content pane to display all of the property editors, so we use a wcfPropertyPane. Inside the pane, property editors are grouped using the wcfPropertyGroup class, as shown in Example 12-17. All of the property editor classes set the following attributes:

� propertyName: Name of the ConfigProperty object’s property that this editor should bind to.

� required: If set to true, a value is required for this property.

� promptText: The label to be displayed for this property editor.

Example 12-17 Property view class definition

<class name="extConfigurationProperties" extends="wcfObjectProperties"> <wcfPropertyPane name="pane">

Note: Example 12-17 does not have the complete class definition. It displays parts of the class definition for reference. For the complete source code refer to the cfgConfigurationPropertiesView.lzx file.

266 WebSphere Commerce Line-of-Business Tooling Customization

Page 285: My Tutorial

<!-- Grouping for category, type key and description property editors --> <wcfPropertyGroup name="group" collapsable="false"> <extConfigCategoryPropertyInputText propertyName="category" required="true" promptText="${extConfigResource.categoryPropertyName.string}"/> <wcfPropertyCombobox propertyName="type" required="true" promptText="${extConfigResource.typePropertyName.string}" /> <wcfPropertyInputText propertyName="key" required="true" promptText="${extConfigResource.keyPropertyName.string}" /> <wcfPropertyInputMultiLineText propertyName="description" required="false" promptText="${extConfigResource.descPropertyName.string}" /> </wcfPropertyGroup> . . . </wcfPropertyPane></class>

Editors for the category, type, key, and description properties are defined in one property group. Editors for the value property are defined in separate groups, which we discuss in “Object property: value” on page 270.

In the following sections, we go through each of the properties and the editors that we provide for them.

Object property: CategoryThe object property, Category, is the configuration category. We want a text editor to be used to edit the category property, with the additional capability of pre-populating its value from the parent ConfigCategory object (if available). This is useful when a create action is initiated after the user selects an existing category in the Explorer view, as shown in Figure 12-11 on page 268.

Chapter 12. Custom Application Configuration Management tool 267

Page 286: My Tutorial

Figure 12-11 Create new configuration property for an existing category.

A custom editor class, extConfigCategoryPropertyInputText, is used to bind to the category property, as shown in Example 12-18.

Example 12-18 Custom editor for category property

<extConfigCategoryPropertyInputText propertyName="category" required="true" promptText="${extConfigResource.categoryPropertyName.string}"/>

This class extends from the wcfPropertyInputText class and is defined in the cfgConfigurationPropertyEditors.lzx file, which is located in the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config/propertiesViews

In this custom editor class, we override the setModelObject method to check if the category name can be resolved from the ConfigProperty object’s parent primary object. If available, we set the category property value, as shown in Example 12-19 on page 269.

268 WebSphere Commerce Line-of-Business Tooling Customization

Page 287: My Tutorial

Example 12-19 Custom editor for category property

<class name="extConfigCategoryPropertyInputText" extends="wcfPropertyInputText"> <method name="getConfigCategoryName"> <![CDATA[ var category = null; if (typeof(this.o) != "undefined" && this.o != null) { var topObj = this.o.getParentPrimaryObject("ConfigCategory"); if (topObj != null) { category = topObj.getPropertyValue("configCategoryName",""); } } return category; ]]> </method>

<method name="setModelObject" args="newObject"> <![CDATA[ super.setModelObject(newObject); var category = this.o.getPropertyValue("category", ""); if (category == null || category == "") { category = getConfigCategoryName(); if (category != null) this.o.setPropertyValue("category", "", category); } ]]> </method></class>

Note: In our scenario, ConfigCategory is modeled as a client-side parent object to the ConfigProperty object for presenting an Explorer view of all distinct configuration categories. There is no corresponding business object on the WebSphere Commerce server. If ConfigCategory was a real parent object on the server side, then we would model it as a creatable object and use a wcfReferenceEditor here instead of this custom editor.

Chapter 12. Custom Application Configuration Management tool 269

Page 288: My Tutorial

Object property: typeThe object property, type, is the custom configuration property type. We use a wcfPropertyCombobox editor to bind to the type property, as shown in Example 12-20. The values that are displayed inside the combo box are taken from the type property definition in the ConfigProperty primary object definition, as shown in Example 12-11 on page 259.

Example 12-20 Combo box for type property

<wcfPropertyCombobox propertyName="type" required="true" promptText="${extConfigResource.typePropertyName.string}" />

Object property: keyThe object property, key, is the configuration property name. We use a text input editor, wcfPropertyInputText, to bind to the key property, as shown in Example 12-21.

Example 12-21 Input text editor for key property

<wcfPropertyInputText propertyName="key" required="true" promptText="${extConfigResource.keyPropertyName.string}" />

Object property: descriptionThe object property, description, is a description of the configuration property. We use a multi-line text editor, wcfPropertyInputMultiLineText, to bind to the description property, as shown in Example 12-22.

Example 12-22 Multi line text editor for description property

<wcfPropertyInputMultiLineText propertyName="description" required="false" promptText="${extConfigResource.descPropertyName.string}" />

Object property: valueThe object property, value, is the value of the custom configuration property. For the value property, we want to display an editor that matches the property type. Depending on the type property that is selected in the combo box, we want to display an appropriate editor. Table 12-1 on page 271 lists the property types and the editors that we want to use for each type.

270 WebSphere Commerce Line-of-Business Tooling Customization

Page 289: My Tutorial

Table 12-1 value property editors

To selectively display editors based on the property type that is selected, we use the wcfEnablementCondition class, which is used to declare an enablement condition to indicate whether the parent object should be enabled. You can reach instances of this class as children of the wcfPropertyGroup class.

We define multiple property groups for the value property, one for each editor type that we support. Each property group declares a wcfEnablementCondition child. We use the following attributes of the wcfEnablementCondition class to selectively enable these property groups:

� propertyName: Name of the object’s property to be evaluated. In this case, this is the type property.

� enablementValue: This is the value that the type property must be set to for the property group to be enabled.

The property group “groupText”, shown in Example 12-23 declares a wcfEnablementCondition with the enablementValue attribute of SimpleText. This property group is displayed only if the type property value is SimpleText.

Example 12-23 Property group for SimpleText property type

<wcfPropertyGroup name="groupText" collapsable="false"> <wcfEnablementCondition propertyName="type" enablementValue="SimpleText" /> <wcfPropertyInputText propertyName="value" required="true" promptText="${extConfigResource.valuePropertyName.string}" /></wcfPropertyGroup>

We use the same approach to define property groups for Integer, Float, Date, and DateTime property types, as shown in Example 12-24 on page 272.

Property type Editor

SimpleText wcfPropertyInputText

Integer wcfPropertyNumericText

Float wcfPropertyNumericText

Date wcfPropertyDatePicker

DateTime wcfPropertyDateTimePicker

Any other type wcfPropertyInputText

Chapter 12. Custom Application Configuration Management tool 271

Page 290: My Tutorial

Example 12-24 Property groups for Integer, Float, Date and DateTime property types

<!-- Integer value editor group --><wcfPropertyGroup name="groupInteger" collapsable="false"> <wcfEnablementCondition propertyName="type" enablementValue="Integer" /> <wcfPropertyNumericText propertyName="value" required="true" numDecimalPlaces="0" showDecimals="false" promptText="${extConfigResource.valuePropertyName.string}" /></wcfPropertyGroup>

<!-- Decimal value editor group --><wcfPropertyGroup name="groupDecimal" collapsable="false"> <wcfEnablementCondition propertyName="type" enablementValue="Float" /> <wcfPropertyNumericText propertyName="value" required="true" numDecimalPlaces="2" showDecimals="true" promptText="${extConfigResource.valuePropertyName.string}" /></wcfPropertyGroup>

<!-- Date value editor group --><wcfPropertyGroup name="groupDate" collapsable="false"> <wcfEnablementCondition propertyName="type" enablementValue="Date" /> <wcfPropertyDatePicker propertyName="value" required="true" promptText="${extConfigResource.valuePropertyName.string}" /></wcfPropertyGroup>

<!-- DateTime value editor group --><wcfPropertyGroup name="groupDateTime" collapsable="false"> <wcfEnablementCondition propertyName="type" enablementValue="DateTime" /> <wcfPropertyDateTimePicker propertyName="value" required="true" promptText="${extConfigResource.valuePropertyName.string}" /></wcfPropertyGroup>

272 WebSphere Commerce Line-of-Business Tooling Customization

Page 291: My Tutorial

To declare a default editor, we add one more property group, as shown in Example 12-25. This property group uses a wcfEnablementAndCondition declaration. This class enables a parent object if all of the child wcfEnablementCondition are true.

Example 12-25 Default property group

<!--Default value editor group. --><wcfPropertyGroup name="groupDefault" collapsable="false"> <wcfEnablementAndCondition> <wcfEnablementCondition propertyName="type" enablementValue="SimpleText" negate="true" /> <wcfEnablementCondition propertyName="type" enablementValue="Date" negate="true" /> <wcfEnablementCondition propertyName="type" enablementValue="DateTime" negate="true" /> <wcfEnablementCondition propertyName="type" enablementValue="Integer" negate="true" /> <wcfEnablementCondition propertyName="type" enablementValue="Float" negate="true" /> </wcfEnablementAndCondition> <wcfPropertyInputText propertyName="value" required="true" promptText="${extConfigResource.valuePropertyName.string}" /></wcfPropertyGroup>

Figure 12-12 on page 274 shows the value editor displayed when the SimpleText property editor is selected.

Chapter 12. Custom Application Configuration Management tool 273

Page 292: My Tutorial

Figure 12-12 Value editor for SimpleText property type

Figure 12-13 shows the value editor displayed when the property type is changed to Date.

Figure 12-13 Value editor for Date property type

274 WebSphere Commerce Line-of-Business Tooling Customization

Page 293: My Tutorial

12.3.7 Resource bundle definition

The resource bundle class for the Custom Application Configuration Management tool extConfigResourceBundle is defined in the cfgConfigManagementResourceBundle.lzx file, which is located in the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config

The resource bundle class specifies the fully-qualified resource bundle name in the baseName attribute. All resource bundle property key names are declared using the wcfResourceBundleKey class, as shown in Example 12-26.

Example 12-26 Resource bundle definition

<library><class name="extConfigResourceBundle" extends="wcfResourceBundle" baseName="com.redbooks.commerce.client.lobtools.properties.ConfigLOB">

<wcfResourceBundleKey name="configTopDisplayName"/> <wcfResourceBundleKey name="config_DisplayName"/> <wcfResourceBundleKey name="config_NewDisplayName"/> <wcfResourceBundleKey name="config_PropertyDisplayName"/> <wcfResourceBundleKey name="config_PropertyNewDisplayName"/> <wcfResourceBundleKey name="propertyList"/> <wcfResourceBundleKey name="propertyListDisplayName"/> <wcfResourceBundleKey name="propertySearchTitle"/> <wcfResourceBundleKey name="configCategoryFilter"/> . . . </class><extConfigResourceBundle id="extConfigResource"/></library>

The properties file, ConfigLOB.properties, is created under the package com.redbooks.commerce.client.lobtools.properties, which is located in the LOBTools/src folder.

Note: Example 12-26 does not have the complete class definition; instead, it displays parts of the class definition for reference. For the complete source code, refer to the cfgConfigManagementResourceBundle.lzx file

Chapter 12. Custom Application Configuration Management tool 275

Page 294: My Tutorial

12.3.8 Image files for Custom Application Configuration Management tool

Image files that are used as Explorer view icons, list icons, Property view icons, and so on are defined as resources, as shown in Example 12-27, in the cfgConfigManagementResources.lzx file, which is located in the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config

We included image files in the zip archive that we provided for this scenario.

Example 12-27 Resource definitions

<library> <resource name="configTreeFolderIcon" src="resources/configroot.png" /> <resource name="configurationHeaderIcon" src="resources/descriptive_attr.png" /> <resource name="configurationIcon" src="resources/descriptive_attr_small.png" /> <resource name="configPropertyHeaderIcon" src="resources/defining_attr.png" /> <resource name="configPropertyIcon" src="resources/defining_attr_small.png" /></library>

12.3.9 Library file definition

The library file includes all of the OpenLaszlo files that were created for the new tool, as shown in Example 12-28. The Management Center uses this file to recognize all of the associated classes for the new tool.

The Custom Application Configuration Management tool library file, cfgConfigLibrary.lzx, is created in the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/redbooks/config

Example 12-28 Library file

<library><include href="cfgConfigManagementResources.lzx"/><include href="cfgConfigManagementResourceBundle.lzx"/><include href="objectDefinitions/cfgConfigPropertyObjectValidator.lzx"/>

276 WebSphere Commerce Line-of-Business Tooling Customization

Page 295: My Tutorial

<include href="objectDefinitions/cfgConfigObjectDefinitions.lzx"/><include href="listViewDefinitions/cfgConfigurationPropertiesGrid.lzx" /><include href="listViewDefinitions/cfgConfigurationPropertiesSearchGrid.lzx" /><include href="objectDefinitions/cfgConfigPropertyPrimaryObjectDefinition.lzx"/><include href="objectDefinitions/cfgConfigCategoryPrimaryObjectDefinition.lzx"/><include href="objectDefinitions/cfgConfigTopObjectDefinition.lzx"/><include href="propertiesViews/cfgConfigurationPropertyEditors.lzx" /><include href="propertiesViews/cfgConfigurationPropertiesView.lzx" /><include href="cfgConfigManagementFilterDefinitions.lzx" /><include href="searchDefinitions/cfgFindConfigSearchDefinition.lzx" /><include href="cfgConfigManagementToolDefintion.lzx"/></library>

12.3.10 Adding the Custom Application Configuration Management tool to Management Center

In the following sections, we explain customizations that you must make to add the new tool to the Management Center.

Defining the label and icon for the new menu itemTo define the new menu item label and icon, we create the following OpenLaszlo files under the LOBTools/WebContent/WEB-INF/src/lzx/redbooks/shell directory:

� extResources.lzx: This file defines all image resources that are used for menu icons, as shown in Example 12-29. We included image files for the new menu item icon in the zip archive for this scenario.

Example 12-29 Shell extension resources

<library> <resource name="configurationActiveTabIcon" src="resources/descriptive_attr_small.png" /> <resource name="configurationInactiveTabIcon" src="resources/descriptive_attr_small.png" /></library>

� extShellResourceBundle.lzx: Resource bundle definition for menu item labels (Example 12-30 on page 278).

Chapter 12. Custom Application Configuration Management tool 277

Page 296: My Tutorial

Example 12-30 Shell resource bundle extension

<library> <class name="extShellResourceBundle" extends="wcfResourceBundle" baseName="com.redbooks.commerce.client.lobtools.properties.extShellLOB">

<wcfResourceBundleKey name="configManagementDisplayName" /> </class>

<extShellResourceBundle id="extShellResources"/></library>

The resource bundle properties file, extShellLOB.properties, is created in the package com.redbooks.commerce.client.lobtools.properties, which is located in the LOBTools/src folder.

Updating the shell extension library

To pick up all of the OpenLaszlo resources that are created for the tool, we update the Management Center shell extension library file ShellExtensionsLibrary.lzx to include the Custom Application Configuration Management tool library file (See 12.3.9, “Library file definition” on page 276).

In addition, we also include the resource bundle file extShellResourceBundle.lzx and the image resource extension file extResources.lzx that we created (See “Defining the label and icon for the new menu item” on page 277).

Example 12-31 on page 279 shows the changes that we made to the ShellExtensionsLibrary.lzx file, which is located in the following file:

LOBTools/WebContent/WEB-INF/src/lzx/commerce/shell

Note: If you are using Feature Pack 3.0.1, edit the ShellLibrary.lzx to fix a minor problem:

1. In the Project Explorer, navigate to Dynamic Web Projects → LOBTools → WebContent → WEB-INF → src → lzx → commerce → shell → restricted.

2. Open the ShellLibrary.lzx file.

3. Move the following entry to the end of the file just before the closing </library> tag: <include href=”../ShellExtensionsLibrary.lzx” />

This problem was fixed in Feature Pack 4.

278 WebSphere Commerce Line-of-Business Tooling Customization

Page 297: My Tutorial

Example 12-31 Shell extension library updates

<library> <!-- Include shell resource bundle extension --> <include href="../../redbooks/shell/extShellResourceBundle.lzx" /> <!-- Include resources --> <include href="../../redbooks/shell/extResources.lzx" />

<!--- Include library for Configuration Management tool. --> <include href="../../redbooks/config/cfgConfigLibrary.lzx" /></library>

Updating the Application menuThe last step in adding the Custom Application Configuration Management tool to the Management Center is to add the CACMT to the Application menu, as shown in Figure 12-14.

Figure 12-14 Custom Application Configuration Management tool menu item

We update the ApplicationMenuItems.lzx file, which is located in the following directory:

LOBTools/WebContent/WEB-INF/src/lzx/commerce/shell

We add a new menu item for our new tool, as shown in Example 12-32 on page 280.

The objectClass attribute specifies the business object editor name extConfigManagement. The usage attribute specifies the role that is authorized to use the new tool. For this scenario, we used the existing IBM_CatalogTool role.

Chapter 12. Custom Application Configuration Management tool 279

Page 298: My Tutorial

Example 12-32 Menu item definition for CACMT

<wcfApplicationMenuItem id="configManagement" width="${parent.width}" height="25" activeIconSrc="configurationActiveTabIcon" inactiveIconSrc="configurationInactiveTabIcon" displayName="${extShellResources.configManagementDisplayName.string}" objectClass="extConfigManagement" usage="IBM_CatalogTool" actionName="openBusinessObjectEditor" />

12.4 Customizing the WebSphere Commerce services

The customization steps loosely follow the Creating a new WebSphere Commerce BOD service module tutorial, which is available at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tutorial/tsdsoatutorial.htm

After you complete the customization, you can use:

� Get services to retrieve configuration settings from the XAPPPROPS table

� Get services to retrieve configuration setting categories from the XAPPPROPS table

� Process services to create and delete configuration settings in the XAPPPROPS table

� Change services to update configuration settings in the XAPPPROPS table

The business objects are represented by OAGIS nouns, and you define and generate the CustomAppProperties noun.

Note: Information about changing access control for a Management Center tool is at the following Web site:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfcustomizeshell.htm

280 WebSphere Commerce Line-of-Business Tooling Customization

Page 299: My Tutorial

Figure 12-15 on page 282 represents the assets that you create during this scenario. As you progress through the scenario, you will see different versions of the diagram, with the relevant asset for the current step highlighted.

Note: To separate the logical representation of a configuration setting from a configuration setting category, two different nouns is the more sophisticated approach. However, Feature Pack 3.0.1 does not support multiple nouns that are mapped to a single table; therefore, we use only one noun that represents both the settings and the category.

Of course you can create a second table that holds the configuration setting categories, which enables you to introduce a separate noun for a configuration setting category.

Chapter 12. Custom Application Configuration Management tool 281

Page 300: My Tutorial

Figure 12-15 Overview of assets to be created for the Custom Application Configuration Management tool

12.4.1 Preparing your development environment

Before you begin this tutorial, ensure that you fulfill the following prerequisites:

� Installed WebSphere Commerce Developer.

CustomAppProperties-UnitTests

DPTK appdef

CustomAppProperties-Client

CustomAppProperties-Server

CustomAppProperties-DataObjects

RAD Projects:CustomAppProperties-ClientCustomAppProperties-UnitTestsCustomAppProperties-Server

CustomAppProperties-DataObjectsCustomAppPropertiesServicesJMSInterfaceCustomAppPropertiesServicesHTTPInterface

JUnit test cases

Commandregistration

Physical SDO Java classesQuery templates

Logical SDOs

NounXSD/WSDL

Ecore,genmodel

Physical objectpersistence service

BusinessObject Mediators

Business logic

Generate model code

Readmediators

Changemediators

Get commands Process commands

Change commands Sync commands

Client Library

text GeneratesConfiguresUses or Calls

Legend

Database

Object-relationalmetadata

Business objectmediator configuration

Service moduleconfiguration

Data ServiceLayer Wizard

Access controlpolicy XML

Value mapping

acpload

massload

282 WebSphere Commerce Line-of-Business Tooling Customization

Page 301: My Tutorial

� Installed WebSphere Commerce Feature Pack 3.0.1.

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.admin.doc/tasks/tigfepmaster.htm

� Enabled WebSphere Commerce services for Feature Pack 3.0.1

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvenableservices.htm

� Set up your development environment.

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvsetupdevenv.htm

� Installing the Design Pattern Toolkit and the ComponentProjects design pattern

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvdptk.htm

12.4.2 Generating the CustomAppProperties service module projects

The Design Pattern Toolkit (DPTK) is an Eclipse-enabled template engine for generating applications that are based on model-driven architecture transformations. WebSphere Commerce uses a DPTK plug-in to create WebSphere Commerce service modules from a simple XML file.

In the next steps, you will create the module service definition file customAppProperties.appdef by defining the name of the service module and the service operations (OAGIS verbs) that it supports. By applying the WebSphere Commerce Component Projects pattern, the service module projects are generated.

As outlined in Figure 12-16 on page 284, we create the following projects:

� CustomAppProperties-Server

� CustomAppProperties-Client

� CustomAppProperties-UnitTests

� CustomAppProperties-DataObjects

� CustomAppPropertiesServicesJMSInterface, which we do not use for CustomAppProperties service

� CustomAppPropertiesServicesHTTPInterface

Chapter 12. Custom Application Configuration Management tool 283

Page 302: My Tutorial

Figure 12-16 Generated projects from CustomAppProperties service module definition

To generate CustomAppProperties service module projects:

1. Start WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. Create the application definition file to create the base code for the CustomAppProperties service module:

a. Expand the Other Projects → ComponentProject → newServiceModule folder.

b. Right-click the components folder, and select New → Other → Simple → File. Click Next.

c. In the File name field, type customAppProperties.appdef, and click Finish.

d. Double-click the customAppProperties.appdef file to open it.

e. Paste the application definition from Example 12-33 into the file, and then save the file.

The definition indicates the name of the noun (CustomAppProperties) and the verbs that are enabled for the pattern (Get, Process, and Change but not Sync). This file determines the assets and code to be generated for you.

The meaning of the other attributes are described in Creating a WebSphere Commerce service module of the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvcreatecomponent.htm

Example 12-33 CustomAppProperties definition file customAppProperties.appdef

<commerce-componentname="CustomAppProperties"company="Redbooks"packagenameprefix="com.redbooks.commerce"namespace="http://www.redbooks.ibm.com/xmlns/prod/commerce/9"nlsprefix="redbooks"type="BOD"><noun

DPTK appdef RAD Projects:CustomAppProperties-ClientCustomAppProperties-UnitTestsCustomAppProperties-Server

CustomAppProperties-DataObjectsCustomAppPropertiesServicesJMSInterfaceCustomAppPropertiesServicesHTTPInterface

284 WebSphere Commerce Line-of-Business Tooling Customization

Page 303: My Tutorial

name="CustomAppProperties"get="true"process="true"change="true"sync="false" />

</commerce-component>

4. Right-click CustomAppProperties.appdef, and select Apply Pattern.

5. Select WebsphereCommerce Component Projects, as shown in Figure 12-17.

Figure 12-17 Apply WebSphere Commerce Component Projects pattern

6. Click OK. The pattern is applied.

7. Click OK to close the message box, and switch to the Navigator view to verify that the following projects are created:

– CustomAppProperties-Server– CustomAppProperties-Client– CustomAppProperties-UnitTests– CustomAppProperties-DataObjects– CustomAppPropertiesServicesJMSInterface– CustomAppPropertiesServicesHTTPInterface

Chapter 12. Custom Application Configuration Management tool 285

Page 304: My Tutorial

8. The DTPK pattern generates some code in the CustomAppProperties-Server project that you must move to the WebSphere Commerce installation. Using Windows® Explorer, copy the folder <workspace_dir>/CustomAppProperties-Server/TODO-MoveItToWCServerXMLFolder/xml from the CustomAppProperties-Server project into the <WCDE_installdir>/xml directory.

You created the service module projects, and you are now ready to implement specific logic to your service.

12.4.3 Defining the CustomAppProperties noun

Nouns define the name of each data element in the logical model, and assign that name to a data type. This data type might be a primitive XML schema type, or you can define a complex type. A complex type is a construct of data elements. WebSphere Commerce provides some predefined complex type constructs which are shared among all of the nouns. Figure 12-18 illustrates defining the CustomAppProperties noun.

Figure 12-18 Defining the CustomAppProperties noun

Note: Build errors will show up in the projects at this stage because the CustomAppProperties data objects are not yet generated from the CustomAppProperties noun. Continue the scenario to generate these objects and to resolve the build errors.

Note: Also, validation errors on XML and XSD files are shown, especially in the folder <workspace_dir>/CustomAppProperties-Server/TODO-MoveItToWCServerXMLFolder/xml. You might find it comfortable to either move the folder out of the workspace or to deactivate XML Schema Validation in WebSphere Commerce Developer for the concerning projects.

CustomAppProperties-DataObjects

Logical SDOs

NounXSD/WSDL

Ecore,genmodel

Generate model code

286 WebSphere Commerce Line-of-Business Tooling Customization

Page 305: My Tutorial

The noun that is used in this scenario is called the CustomAppProperties noun. This noun represents the logical data model of the new component that you are going to create. Remember, that the logical data model that the logical SDOs represent is shared across all clients who use your service. The generated code from the CustomAppProperties noun is stored in the CustomAppProperties-DataObjects project, which we outline in Figure 12-18 on page 286.

Before you define the noun, you must prepare the CustomAppProperties-DataObjects project:

1. The foundation data objects are provided in the WebServicesRouter project in the following directory:

<workspace_dir>\WebServicesRouter\WebContent\component-services

Figure 12-19 Foundation data objects folder

a. Copy \xsd to <workspace_dir>\CustomAppProperties-DataObjects\xsd.

b. Copy \ecore to <workspace_dir>\CustomAppProperties-DataObjects\ecore.

c. Copy \wsdl to <workspace_dir>\CustomAppProperties-DataObjects\wsdl.

Chapter 12. Custom Application Configuration Management tool 287

Page 306: My Tutorial

2. Right-click the CustomAppProperties-DataObjects project, and select Refresh.

Examining the generated default nounBefore building the noun, let us examine the default noun that was generated for you. Open the CustomAppProperties-DataObjects/xsd/OAGIS/9.0/Overlays/Redbooks/Commerce/Resources/Nouns/CustomAppProperties.xsd file.

Review Figure 12-20 on page 289 to get an overview. You find the following pre-built objects:

� Import of the CustomAppProperties-DataObjects\xsd\OAGIS\9.0\Overlays\IBM\Commerce\Resources\Components\BaseTypes.xsd file.

This XSD contains the definition of the UserDataType that is needed to extend an existing noun. We come back later to use the UserDataType. We recommend that you always import the BaseTypes.xsd.

In the same directory, there are a number of other XSDs that contain WebSphere Commerce base types. Whenever you need to refer to existing WebSphere Commerce data models, import the appropriate XSDs, and use their containing data types, which ensures a consistent data model between your custom service module and WebSphere Commerce.

� CustomAppPropertiesType type

This data type represents your logical business data model and is enhanced in the next step; therefore, it represents the configuration setting data model. The Custom Application Configuration Management tool basically relies on the CustomAppPropertiesType.

� CustomAppPropertiesIdentifierType type

This data type represents the identifier of your logical business data model. By default, it contains a UniqueID element and an ExternalIdentifier element of type CustomAppPropertiesExternalIdentifierType. The UniqueID is intended to serve as a primary key.

� CustomAppPropertiesExternalIdentifierType type

This data type represents an alternative identifier to your data object. Thinking in the ways of relational database tables, this identifier is a unique index. It can contain one or more fields.

By default it contains the element “Name” of type String.

� CustomAppPropertiesBODVersion element

288 WebSphere Commerce Line-of-Business Tooling Customization

Page 307: My Tutorial

In order for the WebSphere Commerce server to differentiate between different levels of client libraries, which might have different versions of the WebSphere Commerce nouns, the versionID attribute of the OAGIS BusinessObjectDocumentType is populated with the WebSphere Commerce version that is associated with the noun.

You always need to include this element. For more information, refer to the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdbodversion.htm

Figure 12-20 Basic structure of the generated CustomAppProperties default noun

Figure 12-21 on page 290 displays the structure of the pre-built noun in detail. The CustomAppProperties noun consists of the following elements:

� /CustomAppProperties/CustomAppPropertiesIdentifier

This element encapsulates all identifier elements that you want to provide. By default, the following identifiers are provided:

– /CustomAppProperties/CustomAppPropertiesIdentifier/UniqueID

Chapter 12. Custom Application Configuration Management tool 289

Page 308: My Tutorial

The UniqueID is mapped later on the primary key of the XAPPPROPS database table.

– /CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier/Name

You extend the ExternalIdentifier later by adding another field to reflect the unique index of the XAPPPROPS database table.

� Description

A pre-built field substitutional for all data fields you will later provide.

� UserData

A pre-built field that acts as an extension point for future extensions of the CustomAppProperties noun with additional data. This field is set of type UserData that BaseTypes.xsd imports.

We strongly recommend that you keep this field in every noun. For more information about extending a noun, refer to the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvextendnoun.htm

If you look for practical application for extending a noun, refer to the WebSphere Commerce Information Center, tutorial Adding new properties to a WebSphere Commerce service using the Data Service layer at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tutorial/twvfounduserdata.htm

Figure 12-21 Detailed structure of the generated CustomAppProperties default noun

Updating the default noun to the target structureNow you can define the target structure of the CustomAppProperties noun that represents the configuration settings.

290 WebSphere Commerce Line-of-Business Tooling Customization

Page 309: My Tutorial

After you apply all changes, your CustomAppProperties noun will have a structure similar to Figure 12-22 on page 291.

Figure 12-22 Updated CustomAppProperties noun

To update the default noun to the target structure:

1. Using the graphical editor of WebSphere Commerce Developer or by directly editing the XSD source code, add the following elements:

a. /CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier/Storeent_id

Together with Name, this element represents a unique index and an alternative identifier to UniqueID. It is populated with the unique identifier of the store to which this configuration setting belongs.

i. Add this type as int (Built-in simple type). ii. Update the minOccurs and the maxOccurs attributes to 1.

b. /CustomAppProperties/Value

Note: We decided to include a flat representation of foreign relationship to a WebSphere Commerce store. Alternatively, you can import CustomAppProperties-DataObjects\xsd\OAGIS\9.0\Overlays\IBM\Commerce\Resources\Components\IdentifierTypes.xsd and use the StoreIdentifierType type.

Chapter 12. Custom Application Configuration Management tool 291

Page 310: My Tutorial

This field represents the value of the configuration setting. The data stored in this field might need additional interpretation depending on the value that is stored in the ValueType field.

Add this value as type String (Built-in simple type).

c. /CustomAppProperties/ValueType

This field represents the value type of the configuration setting. It provides the client with information about how to interpret the data that is stored in the field Value. To enforce proper operation, this field cannot be empty or null and must have one of the following fixed values:

• SimpleText• Code• Date• Time• DateTime• Color• Integer• Float• Email• URL

Add this field as a Simple Type:

i. By using the Properties view of the XSD editor, name the newly created type ValueTypeEnum, then select atomic as the Variety, and select normalized String as the Base Type.

ii. From the Enumeration tab of the Properties view, add the list of fixed values to the ValueTypeEnum type, as shown in Figure 12-24 on page 294 and Figure 12-23 on page 293.

292 WebSphere Commerce Line-of-Business Tooling Customization

Page 311: My Tutorial

Figure 12-23 ValueTypeEnum simple type, General tab of Properties view

Chapter 12. Custom Application Configuration Management tool 293

Page 312: My Tutorial

Figure 12-24 ValueTypeEnum simple type, Enumerations tab of Properties view

iii. Select the ValueType field, and change the type to redbooks:ValueTypeEnum (User defined simple type).

iv. Update the minOccurs and maxOccurs attributes to 1.

d. /CustomAppProperties/Category

This field represents the category of the configuration setting:

i. Add this field as type String (Built-in simple type). ii. Update minOccurs attribute to 1, and maxOccurs attribute to 1.

2. Use the graphical editor of WebSphere Commerce Developer or directly edit the XSD source code, and update the following elements:

/CustomAppProperties/CustomAppPropertiesIdentifier/UniqueID

This field represents the primary key of the configuration setting. Change this field to type long (Built-in simple type).

The following elements remain in the noun definition and serve for the following purposes:

� /CustomAppProperties/CustomAppPropertiesIdentifier

This field represents the noun’s identifier.

� /CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier

This field represents the noun’s external identifier.

� /CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier/Name

Together with Storeent_id, this field represents a unique index and an alternative identifier to UniqueID.

294 WebSphere Commerce Line-of-Business Tooling Customization

Page 313: My Tutorial

� /CustomAppProperties/Description

This field holds an administrative description as a reminder for the line-of-business user.

� /CustomAppProperties/UserData

This field enables the extension of the CustomAppProperties noun by using userData extension.

You should end up with an XSD, as shown in Example 12-34.

Example 12-34 CustomAppProperties.xsd

<?xml version="1.0" encoding="UTF-8"?><schema xmlns="http://www.w3.org/2001/XMLSchema"

xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"xmlns:oa="http://www.openapplications.org/oagis/9"xmlns:_wcf="http://www.ibm.com/xmlns/prod/commerce/9/foundation"xmlns:redbooks="http://www.redbooks.ibm.com/xmlns/prod/commerce/9"attributeFormDefault="unqualified" elementFormDefault="qualified"targetNamespace="http://www.redbooks.ibm.com/xmlns/prod/commerce/9"ecore:nsPrefix="redbooks"ecore:package="com.redbooks.commerce.customappproperties.facade.datatypes"><annotation>

<documentation>This file contains all type definitions that make up aCustomAppProperties.

</documentation></annotation><import namespace="http://www.ibm.com/xmlns/prod/commerce/9/foundation"

schemaLocation="../../../../IBM/Commerce/Resources/Components/BaseTypes.xsd" /><complexType name="CustomAppPropertiesExternalIdentifierType">

<annotation><documentation>

The type definition of an external identifier for aCustomAppProperties.

</documentation></annotation><sequence>

<element maxOccurs="1" minOccurs="1" name="Name" type="string"><annotation>

<documentation>The name of the CustomAppProperties.

</documentation></annotation>

</element>

Chapter 12. Custom Application Configuration Management tool 295

Page 314: My Tutorial

<element name="Storeent_id" type="int" minOccurs="1" maxOccurs="1"><annotation>

<documentation>The reference to a store of the CustomAppProperties

</documentation></annotation>

</element></sequence><attribute name="ownerID" type="string" use="optional">

<annotation><documentation>The owner of a CustomAppProperties.</documentation>

</annotation></attribute>

</complexType><complexType name="CustomAppPropertiesIdentifierType">

<annotation><documentation>

The type definition of an CustomAppProperties identifier.</documentation>

</annotation><sequence>

<element maxOccurs="1" minOccurs="1" name="UniqueID" type="long"><annotation>

<documentation>The CustomAppProperties ID.</documentation></annotation>

</element><element maxOccurs="1" minOccurs="0" name="ExternalIdentifier"

type="redbooks:CustomAppPropertiesExternalIdentifierType"><annotation>

<documentation>The external identifier of the CustomAppProperties.

</documentation></annotation>

</element></sequence>

</complexType><element name="CustomAppPropertiesBODVersion" type="string" fixed="6.0.0.4">

<annotation><documentation>

The version of WebSphere Commerce when the CustomAppProperties nounwas last changed. The value is set as the versionID attribute in thecorresponding BODs.

</documentation></annotation>

</element>

296 WebSphere Commerce Line-of-Business Tooling Customization

Page 315: My Tutorial

<complexType name="CustomAppPropertiesType"><annotation>

<documentation>Type definition of a CustomAppProperties.</documentation></annotation><sequence>

<element maxOccurs="1" minOccurs="1" name="CustomAppPropertiesIdentifier"type="redbooks:CustomAppPropertiesIdentifierType"><annotation>

<documentation>The CustomAppProperties identifier.

</documentation></annotation>

</element><element maxOccurs="1" minOccurs="0" name="Description" type="string">

<annotation><documentation>

Description of the CustomAppProperties</documentation>

</annotation></element><element maxOccurs="1" minOccurs="0" ref="_wcf:UserData">

<annotation><documentation>The user data area.</documentation>

</annotation></element><element name="Value" type="string" minOccurs="0" maxOccurs="1">

<annotation><documentation>Value of the CustomAppProperties</documentation>

</annotation></element><element name="Category" type="string" minOccurs="1" maxOccurs="1">

<annotation><documentation>

Category of the CustomAppProperties</documentation>

</annotation></element><element name="ValueType" type="redbooks:ValueTypeEnum" minOccurs="1"

maxOccurs="1"><annotation>

<documentation>ValueType of the CustomAppProperties

</documentation></annotation>

</element>

Chapter 12. Custom Application Configuration Management tool 297

Page 316: My Tutorial

</sequence></complexType><element name="CustomAppProperties" type="redbooks:CustomAppPropertiesType">

<annotation><documentation>

Element definition of the CustomAppProperties.</documentation>

</annotation></element><simpleType name="ValueTypeEnum">

<annotation><documentation>

Represents the value type of the configuration setting. It providesthe client with information, how to interpret the data stored in thefield Value.

</documentation></annotation><restriction base="normalizedString">

<enumeration value="SimpleText"></enumeration><enumeration value="Code"></enumeration><enumeration value="Date"></enumeration><enumeration value="Time"></enumeration><enumeration value="DateTime"></enumeration><enumeration value="Color"></enumeration><enumeration value="Integer"></enumeration><enumeration value="Float"></enumeration><enumeration value="Email"></enumeration><enumeration value="URL"></enumeration>

</restriction></simpleType>

</schema>

You created the logical data model of the CustomAppProperties noun. Your next step is to generate the logical SDOs.

12.4.4 Generating the SDOs for the CustomAppProperties noun

Because you made changes to the schema, you must reload the genmodel and regenerate the SDO. Reloading the genmodel file creates the ecore files that are used to construct the SDO Java source for your messages.

298 WebSphere Commerce Line-of-Business Tooling Customization

Page 317: My Tutorial

To generate the SDOs for the CustomAppProperties noun:

1. Open the CustomAppProperties-DataObjects\ecore folder.

2. Right-click CustomAppProperties.genmodel, and select Reload.

3. Select Load from XML Schema. Click Next.

Be sure that no error message appears. The wizard checks the list of XSDs in the XML Schema URI field for validation errors, and when it finds an error, an error message window appears. If this happens, go back to your customAppProperties.xsd noun definition file and correct all errors.

Also be sure that customAppProperties.xsd is in the list of the XML Schema URI field. You might find it comfortable to copy the field content into an external text editor for better readability.

Figure 12-25 illustrates the XML Schema Import definition.

Figure 12-25 XML Schema Import definition

4. Click Next again, and then click Browse.

5. Expand the Workspace in the left pane, and navigate to the CustomAppProperties-DataObjects\ecore folder.

Note: In this step, you generate code for the CustomAppProperties-DataObjects project. The code generator takes note of already existing code and will not overwrite resources. To make sure that the code gets completely regenerated, repeat this step. We recommend that you delete all packages in CustomAppProperties-DataObjects/src before.

Chapter 12. Custom Application Configuration Management tool 299

Page 318: My Tutorial

6. Select Foundation.genmodel and Oagis9.genmodel, as shown in Figure 12-26.

Figure 12-26 Select genmodels to be applied to CustomAppProperties noun

7. Click OK.

8. In the Referenced generator models area, locate the Oagis9 model area, and select Oagis9CodeLists, Oagis9, and Oagis9UnqualifiedDatatypes, as shown in Figure 12-27 on page 301. Under Foundation model, select the CommerceFoundation model.

300 WebSphere Commerce Line-of-Business Tooling Customization

Page 319: My Tutorial

Figure 12-27 Select referenced generator models

9. Click Finish.

10.Open CustomAppProperties.genmodel.

11.Right-click the root element, and select Set SDO Defaults.

12.Save the model (Ctrl+S).

13.Under the CustomAppProperties root, right-click the CustomAppProperties element, and select Generate Model Code, which generates the CustomAppProperties-DataObjects code.

14.Verify that the CustomAppProperties-DataObjects project has no compilation errors.

Chapter 12. Custom Application Configuration Management tool 301

Page 320: My Tutorial

Take a moment to examine the most important assets that the current activity generated. Go to CustomAppProperties-DataObjects/src, and expand the packages:

� com.redbooks.commerce.customappproperties.facade.datatypes

This package mainly contains Java interfaces that represent the:

– Data types that are used in the CustomAppProperties noun.

– Data types that are used to form request and respond documents that cover the verbs Get, Change, and Process.

– Document root and a factory to generate CustomAppProperties noun, the request data types, and the response data types.

� com.redbooks.commerce.customappproperties.facade.datatypes.impl

This package contains the implementation classes for the data types that are defined in the following package: com.redbooks.commerce.customappproperties.facade.datatypes

� com.redbooks.commerce.customappproperties.facade.datatypes.util

This package contains several implementation classes that are used as factories of the noun, the request data types, and the response data types.

We need to update the class that represents the user-defined simple type, ValueTypeEnum, because as of the current implementation in Feature Pack 3.0.1 there is an error in type conversion. This error will be solved in the next Fix Pack. Follow these steps to implement a workaround:

1. Open CustomAppProperties-DataObjects/src.

2. Under the com.redbooks.commerce.customappproperties.facade.datatypes.impl package, open the CustomAppPropertiesTypeImpl.java file in the Java editor.

3. Navigate to the method public void eSet(EStructuralFeature eFeature, Object newValue).

4. Replace the following code with the code in Example 12-35:

case CustomAppPropertiesPackage.CUSTOM_APP_PROPERTIES_TYPE__VALUE_TYPE:

setValueType((ValueTypeEnum) newValue);return;

Example 12-35 Workaround ti fix wrong code conversion for ValueTypeEnum

case CustomAppPropertiesPackage.CUSTOM_APP_PROPERTIES_TYPE__VALUE_TYPE:

//Workaround for wrong type conversionif (newValue instanceof ValueTypeEnum) {

302 WebSphere Commerce Line-of-Business Tooling Customization

Page 321: My Tutorial

setValueType((ValueTypeEnum) newValue);} else {

setValueType(ValueTypeEnum.get((String) newValue));}return;

12.4.5 Generating the Persistence layer for the CustomAppProperties service module

The BOD command framework uses the Data Service layer that is independent of the actual physical schema.

WebSphere Commerce Developer provides a Data Service layer wizard to generate object-relational metadata and physical data objects that represent the database schema. Use this wizard to create all necessary assets, as shown in Figure 12-28.

Figure 12-28 Generating the Persistence layer for the CustomAppProperties service module

Note: If you need to regenerate the logical SDOs, you might need to re-apply the changes that we described here.

CustomAppProperties-Server

Physical SDO Java classes

Physical objectpersistence service

Database

Data ServiceLayer Wizard

Chapter 12. Custom Application Configuration Management tool 303

Page 322: My Tutorial

Creating the XAPPPROPS tableBecause you want to persist the configuration settings in the database, you first have to create the table to store them.

Execute the following SQL statements, shown in Example 12-36, to create the XAPPPROPS table. The SQL statements:

� Create the table XAPPPROPS.

� Define the XAPPPROPS_ID column as the primary key.

� Add a foreign key constraint on the STOREENT_ID column to the table STOREENT.

� Create an unique index on the columns NAME and STOREENT_ID.

� Insert a record into the KEYS table to enable the WebSphere Commerce key manager handling primary keys.

Example 12-36

ALTER TABLE "XAPPPROPS" DROP FOREIGN KEY "F_10001";DROP INDEX "X0000001";DROP TABLE "XAPPPROPS";

CREATE TABLE "XAPPPROPS" ("STOREENT_ID" INTEGER NOT NULL,"XAPPPROPS_ID" BIGINT NOT NULL,"OPTCOUNTER" SMALLINT,"NAME" CHARACTER(254) NOT NULL,"VALUE" VARCHAR(2000),"DESCRIPTION" VARCHAR(2000),"VALUETYPE" CHARACTER(254) NOT NULL,"CATEGORY" CHARACTER(254),"VERSION" INTEGER,"FIELD1" BIGINT,"FIELD2" FLOAT,"FIELD3" VARCHAR(2000),"FIELD4" VARCHAR(2000),"FIELD5" VARCHAR(2000)

);

ALTER TABLE "XAPPPROPS"ADD CONSTRAINT "XAPPPROPS_PK" PRIMARY KEY ("XAPPPROPS_ID");

ALTER TABLE "XAPPPROPS"ADD CONSTRAINT "F_10001" FOREIGN KEY ("STOREENT_ID")

304 WebSphere Commerce Line-of-Business Tooling Customization

Page 323: My Tutorial

REFERENCES "STOREENT"("STOREENT_ID")ON DELETE CASCADEON UPDATE NO ACTION;

CREATE UNIQUE INDEX X0000001 ON XAPPPROPS (

STOREENT_ID ASC,NAME ASC

); INSERT INTO KEYS

(KEYS_ID, TABLENAME, COLUMNNAME, COUNTER, PREFETCHSIZE, LOWERBOUND, UPPERBOUND)

values (5001, 'xappprops', 'xappprops_id', 10000, 1, 10000, 9223372036850000000);

Table 12-2, the XAPPPROPS table, provides the information that is related to a configuration setting.

Table 12-2 New custom table XAPPPROPS

Column name Column type Description

STOREENT_ID INTEGER NOT NULL The internal reference number that identifies the store entity. These columns and the NAME are a unique index.

XAPPPROPS_ID BIGINT NOT NULL The internal reference number of the configuration setting.

OPTCOUNTER SMALLINT For concurrency control. Currently unused.

NAME CHARACTER(254) NOT NULL

The external identifier that identifies the configuration setting. These columns and the STOREENT_ID are a unique index.

VALUE VARCHAR(2000) The value of the configuration setting.

DESCRIPTION VARCHAR(2000) An administrative description of the configuration setting.

Chapter 12. Custom Application Configuration Management tool 305

Page 324: My Tutorial

To execute this script, we recommend that you use the Database Access servlet that is provided with WebSphere Commerce Developer:

1. From the J2EE perspective, go to the Server view, and start Start WebSphere Commerce Test Server.

2. After start-up is completed, open a Web browser, and call this URL:

http://localhost/webapp/wcs/admin/servlet/db.jsp

3. Copy the script into the text area, and click Submit. If you execute this script the first time, you must omit the first three statements because they will lead to an error.

For later reference, store this SQL script in the CustomAppProperties-Server project:

1. Right-click the CustomAppProperties-Server project, and then select New → Other.

2. Select Simple → Folder, and then click Next.

3. In the Folder name field, type Scripts, and then click Finish.

4. Repeat Steps 1 to 3 to create a folder named “Data” under the folder Scripts.

VALUETYPE CHARACTER(254) NOT NULL

An identifier to define the type of data of the column VALUE. Valid entries are SimpleText, Code, Date, Time, DateTime, Color, Integer, Float, Email, or URL.

CATEGORY CHARACTER(254) A category description that is used to group configuration settings.

VERSION INTEGER Customizable.

FIELD1 BIGINT Customizable.

FIELD2 FLOAT Customizable.

FIELD3 VARCHAR(2000) Customizable.

FIELD4 VARCHAR(2000) Customizable.

FIELD5 VARCHAR(2000) Customizable.

Note: We did not test the SQL statements on Oracle®.

Column name Column type Description

306 WebSphere Commerce Line-of-Business Tooling Customization

Page 325: My Tutorial

5. Right-click the Scripts folder, and then select New → Other.

6. Select Simple → File, and then click Next.

7. In the File name field, type xappprops.ddl, and then click Finish.

8. Copy the code from Example 12-36 on page 304 into the file, and then save (Ctrl+S).

Generating the physical data objects and the object-relational metadata

If your development environment uses a Cloudscape database, ensure that there is no existing connection to it (for example, ensure that the WebSphere Commerce Test Server is stopped). To generate the physical data objects and the object-relational metadata:

1. Select File → New → Other → WebSphere Commerce → Data Service Layer, and click Next.

2. Select Work with a custom service module, and enter the following information, as shown in Figure 12-29:

– Service module: com.redbooks.commerce.customappproperties

– Extension class prefix: CustomAppProperties

– Extension Java package name: com.redbooks.commerce.customappproperties

Figure 12-29 Data Service layer Configuration wizard, Service module selection

3. Click Next.

Chapter 12. Custom Application Configuration Management tool 307

Page 326: My Tutorial

4. Select the XAPPPROPS table, as shown in Figure 12-30.

Figure 12-30 Data Service layer Configuration wizard, Table selection

5. Click Finish. Now the code generation for CustomAppProperties-Server project is performed.

6. Update the CustomAppProperties-Server build path:

a. Right-click the CustomAppProperties-Server project, and select Properties.

b. Select Java Build Path.

c. Under the Library tab, select Add External Jars, and add the following:

• Enablement-BaseComponentsData.jar from <WCDE_installdir>\wc.modules\ejbs\cloudscape

308 WebSphere Commerce Line-of-Business Tooling Customization

Page 327: My Tutorial

• Enablement-RelationshipManagementData.jar from <WCDE_installdir>\wc.modules\ejbs\cloudscape

• Enablement-BaseComponentsLogic.jar from <WCDE_installdir>\workspace\WC

7. Organize the imports for the CustomAppProperties-Server project:

a. Close all open Java files from the CustomAppProperties-Server project.

a. In WebSphere Commerce Developer, open the Java perspective.

b. Right-click the CustomAppProperties-Server\EJBModule folder, and select Source.

c. Select Organize Imports.

8. Ensure that there are no compilation errors remaining.

All generation steps are finished. You can now implement the service-specific logic and configuration.

12.4.6 Understanding the assets of the CustomAppProperties-Server project

Take a moment to familiarize yourself with the assets that we created so far:

� Physical SDOs for the XAPPPROPS table

The static physical SDOs provide a Java representation of the WebSphere Commerce schema. Each service module has a physical SDO for those tables that the service module reads, updates, or deletes. In our scenario, you created the physical SDO for the XAPPPROPS table.

The physical SDOs are independent of the logical SDOs. Mediation is needed to transform physical SDOs into logical SDOs and vice versa.

Like the logical SDOs, the physical SDOs contain similar resources: data types, document roots, and factories, which are all represented through a pair of Java interfaces and implementation classes. You will find these assets in the packages:

– com.redbooks.commerce.customappproperties.facade.server.entity.datatypes

– com.redbooks.commerce.customappproperties.facade.server.entity.datatypes.impl

– com.redbooks.commerce.customappproperties.facade.server.entity.datatypes.util

Chapter 12. Custom Application Configuration Management tool 309

Page 328: My Tutorial

Physical SDOs of the XAPPPROPS table are represented by the Xappprops class, which contains setter and getter methods to set each column of the table.

The classes and interfaces that are dedicated to the physical CustomAppProperties service module have names that start with CustomAppProperties”. They can handle multiple physical SDOs and support multiple tables per service module.

� Object-relational metadata

The object-relational metadata maps a physical SDO to the actual physical table in the WebSphere Commerce schema. The mapping is stored in the <WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties/wc-object-relational-metadata.xml file.

If you open the file, you will find a <_config:table name="XAPPPROPS" ...> element that holds information about all columns of the XAPPPROPS table; furthermore, the foreign relationship to the STOREENT table is covered in a <_config:relationship ...> element.

� Query templates

These templates map the WebSphere Commerce extended XPath notation expressions to one or more SQL template queries. These SQL template queries fetch the physical data from the database.

In the following directory, there are two prebuilt query templates:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

– wc-query-CustomAppProperties-get.tpl.sample

This query template contains queries to use with the Get verb. Because the generated query templates are not reflecting the updated logical and physical SDOs, you update this query template in a later step.

– wc-query-CustomAppProperties-update.tpl.sample

This query template contains queries to use with the Process and Change verbs. Because the generated query templates are not reflecting the

Note: Keep in mind that the Xappprops physical SDO is only an internal representation of the XAPPPROPS table records. You can think in terms of a cached object or a detached object. The physical SDO is populated automatically by object-relational mapping service, but changes to the physical SDO does not result in a change of the XAPPPROPS table by its own.

310 WebSphere Commerce Line-of-Business Tooling Customization

Page 329: My Tutorial

updated logical and physical SDOs, you update this query template in a later step.

� Logical SDO to physical SDO mapping

For each logical SDO, this mapping defines the physical SDO that contains the unique ID of the noun. The mapping is stored in the following file:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties/wc-business-object-mediator.xml

Open the file to view the <_config:object> element. The attribute logicalType defines the logical SDO, and the attribute physicalType defines the physical SDO. Because the mapping file does not reflect the actual physical SDO type, you update this mapping file in a later step.

The WebSphere Commerce Information Center has information that explains how to configure the Business object mediators in more detail:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdexposenewdata.htm

� Business object mediators

Build logical SDOs from physical SDOs, and build physical SDOs from logical SDOs. The mediator classes are defined in the wc-business-object-mediator.xml file too, using the <_config:mediator> element and the <_config:part-mediator> sub-element.

Because noun parts are not used in the CustomAppProperties service module, the definitions in <_config:part-mediator> have no effect.

All mediators are stored in the package com.redbooks.commerce.customappproperties.facade.server.services.dataaccess.bom.mediator:

– Read Mediators

Build a logical SDO out of the physical SDO.

The read mediator for Xappprops physical SDO is defined as ReadCustomAppPropertiesMediator class.

– Change Mediators

Take a logical SDO as input and either Create, Update, or Delete the appropriate physical SDOs. The modified physical SDOs are then saved back to the database using the PhysicalDataContainer.

The change mediator for the Xappprops physical SDO is defined in the ChangeCustomAppPropertiesMediator class.

Chapter 12. Custom Application Configuration Management tool 311

Page 330: My Tutorial

� EJB classes and interfaces

The package com.redbooks.commerce.customappproperties.facade.server contains code for EJB communication between based on Session Beans. We recommend that you not change this code.

� BOD commands that implement verbs and actions

The com.redbooks.commerce.customappproperties.facade.server.commands package contains BOD commands implementing Get, Process, and Change verbs and its actions.

To learn more about developing the Business Logic layer using the BOD command framework, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdcustomizesoasvc.htm

� Exceptions and language specific exception messages

The com.redbooks.commerce.customappproperties.facade.server.exception package contains service module specific Exceptions.

The following two packages contain message key definitions and language specific exception messages, which mediators and BOD commands use when throwing exceptions to the client:

– com.redbooks.commerce.customappproperties.logging– com.redbooks.commerce.customappproperties.logging.properties

In this scenario, you do not extend messages.

� Access control assets

The following package contains a service module-specific protectable proxy class that is the bridge between any Java object and the policy manager access control engine that is part of WebSphere Commerce:

com.redbooks.commerce.customappproperties.facade.server.authorization

The protectable proxy class is configured in the <WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties/wc-component.xml file using the <_config:protectable-proxy> sub-element of the <_config:authorization-configuration> element.

In this scenario, you implement access control.

Note: The read mediation always flows from physical SDO to logical SDO. You cannot have different mediators for the physical SDO depending on the logical SDO; therefore, you cannot map multiple nouns to a single table.

312 WebSphere Commerce Line-of-Business Tooling Customization

Page 331: My Tutorial

� CustomAppProperties service module meta data

The metadata configuration is stored in the wc-component.xml file too. The <_config:database> element defines the JNDI name to the WebSphere Commerce database, while the Data Service is configured with the <_config:dataservice> element, which defines the data mediator type and the metadata initialization class.

The com.redbooks.commerce.customappproperties.facade.server.metadata package contains the metadata initialization class CustomAppPropertiesMetadata that provides configuration information for the Data Service layer.

Because the CustomAppPropertiesMetadata class does not reflect actual CustomAppProperties service module settings, you update this class in the next step.

12.4.7 Updating the Data Service configuration

To update the Data Service configuration of the CustomAppProperties-Server project:

1. Open the CustomAppPropertiesMetadata class.

2. Implement the getRootEClass() method to return the root physical SDO object. Replace the body of the getRootEClass() method with the following:

return com.redbooks.commerce.customappproperties.facade.server.entity.datatypes.impl.CustomAppPropertiesEntityPackageImpl.eINSTANCE.getCustomAppPropertiesRoot();

3. Find the line following line:

private static final String PACKAGE_NAME = "";

4. Replace the line in step 3 with the following line:

private static final String PACKAGE_NAME = "com.redbooks.commerce.customappproperties.facade.server.entity.datatypes.impl.CustomAppPropertiesEntityPackageImpl";

5. Save the file.

12.4.8 Implementing the Business Object Mediators to mediate logical and physical SDOs

Mediators are needed for each changeable noun part. A noun part is either a part of a noun, or by definition, can be a noun itself.

Chapter 12. Custom Application Configuration Management tool 313

Page 332: My Tutorial

To simplify development and maintenance of mediators, one noun can be sectioned into multiple changeable parts. We recommend that you use one mediator for each complex element in the noun, excluding any user data elements.

In this scenario, we do not use noun parts. The CustomAppProperties noun is the only noun that we work on.

To provide a better understanding on noun parts, imagine, we enhance the CustomAppProperties noun with a noun part that is holding a list of additional attributes for every configuration setting. These attributes could be persisted in an additional table XAPPPRATTR. In this case you would need additional mediators to read and update the configuration setting attribute noun part.

Figure 12-31 outlines the steps.

Figure 12-31 Implementing Business Object Mediators and updating the service module configuration

CustomAppProperties-Server

BusinessObject Mediators

Readmediators

Changemediators

Business objectmediator configuration

Service moduleconfiguration

Value mapping

314 WebSphere Commerce Line-of-Business Tooling Customization

Page 333: My Tutorial

Implementing the read mediatorsCode generation pre-built the following read mediators for you:

� ReadCustomAppPropertiesMediator

A read mediator to build the CustomAppProperties noun when executing a Get verb.

� ReadCustomAppPropertiesNounPartMediator

A read mediator to build any CustomAppProperties noun parts when executing a Get verb. Because the CustomAppProperties service does not uses noun parts, you do not need to update this class.

To update the ReadCustomAppPropertiesMediator class that is located in the CustomAppProperties-Server project:

1. Open the ReadCustomAppPropertiesMediator class.

2. Navigate to the method public void buildNoun(Object aLogicalEntityType, Object aPhysicalEntityType).

3. There is already demo code provided between the comments // TODO: Demo code Begin and // TODO: Demo code End. Uncomment it.

The line Customappproperties aCustomAppPropertiesPhysicalDO = (Customappproperties) aPhysicalEntityType; contains a compile error because Customappproperties is unknown to the compiler. The code generator assumes that the physical SDO is named equal to the table’s name and the table name is equal to the name of the service module (that is CustomAppProperties).

But following the WebSphere Commerce database schema object naming considerations, the new table must start with an X, and the table name should be no longer than 10 characters. The table name was decided to be XAPPPROPS, and hereafter the Data Service layer wizard generated the physical SDO type named Xappprops. Hence, you must replace all of the occurrences of the generated Customappproperties type reference with the Xappprops type in the next steps.

To learn about database schema object naming considerations, visit the WebSphere Commerce Developer Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.database.doc/refs/rdbnamingconventions.htm

4. Replace the line Customappproperties aCustomAppPropertiesPhysicalDO = (Customappproperties) with Xappprops aCustomAppPropertiesPhysicalDO = (Xappprops) aPhysicalEntityType;

The compilation error on this line disappears, but other errors arise. Ignore them for now.

Chapter 12. Custom Application Configuration Management tool 315

Page 334: My Tutorial

5. The buildNoun() method has to fulfill three tasks:

– Build the CustomAppProperties identifier with the UniqueID and the External Identifier. This is out sourced to the buildCustomAppPropertiesIdentifier() method.

– Set all of the attributes in the CustomAppProperties noun.

– Build and populate userData of the CustomAppProperties noun. This is out sourced to the buildUserData() method.

Replace the buildNoun() method content between the “Demo code Begin” and “Demo code End” comments with the syntax in Example 12-37.

Example 12-37 buildNoun() method excerpt

CustomAppPropertiesType aCustomAppPropertiesLogicalDO = (CustomAppPropertiesType) aLogicalEntityType;Xappprops aCustomAppPropertiesPhysicalDO = (Xappprops) aPhysicalEntityType;

// build the id type with uid and namebuildCustomAppPropertiesIdentifier(aCustomAppPropertiesLogicalDO,

aCustomAppPropertiesPhysicalDO);

// set all attributesaCustomAppPropertiesLogicalDO.setDescription(aCustomAppPropertiesPhysicalDO

.getDescription());aCustomAppPropertiesLogicalDO

.setCategory(aCustomAppPropertiesPhysicalDO.getCategory());aCustomAppPropertiesLogicalDO.setValue(aCustomAppPropertiesPhysicalDO.getValue());String valueType = aCustomAppPropertiesPhysicalDO.getValuetype();if (valueType != null && !"".equals(valueType))

aCustomAppPropertiesLogicalDO.setValueType(ValueTypeEnum.get(valueType.trim()));

// build the userdata from logical DataObject into Physical DataObjectbuildUserData(aCustomAppPropertiesLogicalDO, aCustomAppPropertiesPhysicalDO);

6. Implement the buildCustomAppPropertiesIdentifier() method. Replace the method’s content between the “Demo code Begin” and “Demo code End” comments with the syntax in Example 12-38.

Example 12-38 buildCustomAppPropertiesIdentifier() method excerpt

// create the ID object and set to the logical data objectCustomAppPropertiesIdentifierType aCustomAppPropertiesIdentifier = getCustomAppPropertiesFactory()

.createCustomAppPropertiesIdentifierType();aCustomAppPropertiesLogicalDO

.setCustomAppPropertiesIdentifier(aCustomAppPropertiesIdentifier);

316 WebSphere Commerce Line-of-Business Tooling Customization

Page 335: My Tutorial

Xappprops aCustomAppPropertiesPhysicalDO = (Xappprops) aPhysicalEntityType;

// set the uid in ID objectaCustomAppPropertiesIdentifier.setUniqueID(aCustomAppPropertiesPhysicalDO

.getXappprops_id());

// set the name in ID objectCustomAppPropertiesExternalIdentifierType exId = getCustomAppPropertiesFactory()

.createCustomAppPropertiesExternalIdentifierType();aCustomAppPropertiesIdentifier.setExternalIdentifier(exId);exId.setName(aCustomAppPropertiesPhysicalDO.getName());exId.setStoreentId(aCustomAppPropertiesPhysicalDO.getStoreent_id());

The methods now set the complete CustomAppPropertiesIdentifierType, which includes UniqueId and CustomAppPropertiesExternalIdentifierType, with Name and Storeent_id.

7. To enable userData, find and uncomment the buildUserData() method. Replace the method’s content between the “Demo code Begin” and “Demo code End” comments with the syntax from Example 12-39.

Example 12-39 buildUserData() method

public void buildUserData(CustomAppPropertiesType aLogicalEntityType,Xappprops aPhysicalEntity) throws AbstractApplicationException {

final String METHODNAME = "buildUserData";

if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {LOGGER.entering(CLASSNAME, METHODNAME, new Object[] { aLogicalEntityType,

aPhysicalEntity });}Map attributes = new HashMap();populateNameValuePairType(attributes, aLogicalEntityType, aPhysicalEntity);UserDataType userData = getCommerceFoundationFactory().createUserDataType();aLogicalEntityType.setUserData(userData);Iterator anIter = attributes.entrySet().iterator();while (anIter.hasNext()) {

Map.Entry anEntry = (Map.Entry) anIter.next();if (anEntry.getKey() != null && anEntry.getValue() != null) {

aLogicalEntityType.getUserData().getUserDataField().put(anEntry.getKey().toString(), anEntry.getValue().toString());

}}if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {

LOGGER.exiting(CLASSNAME, METHODNAME);

Chapter 12. Custom Application Configuration Management tool 317

Page 336: My Tutorial

}}

The code copies all userData properties from the physical SDO to the logical SDO using the userData field in CustomAppProperties noun.

8. Organize the imports for the ReadCustomAppPropertiesMediator class:

a. Open the Java perspective in WebSphere Commerce Developer.

b. Right-click the ReadCustomAppPropertiesMediator class, and select Source.

c. Select Organize Imports.

9. Add the correct throws statement to the buildNoun() method:

a. Navigate to the buildNoun() method.

b. Replace the statement throws BusinessObjectMediatorException with the statement throws AbstractApplicationException

10.Save file. (Ctrl+s)

Implementing the change mediatorsThe code generation pre-built the following read mediators for you:

� ChangeCustomAppPropertiesMediator� ChangeCustomAppPropertiesBasePartMediator

Understanding the ChangeCustomAppPropertiesMediator classThe ChangeCustomAppPropertiesMediator class is a change mediator that creates and deletes the CustomAppProperties noun when executing a Process verb.

Table 12-3 on page 319 contains the methods that you will implement.

318 WebSphere Commerce Line-of-Business Tooling Customization

Page 337: My Tutorial

Table 12-3 ChangeCustomAppPropertiesMediator methods to be implemented

Method Description Implementation

validateCreate() Checks if the physical object can be created from a given logical noun.

Checks if: � The object to be

created is present in the physical data container.

� The external identifier fields are not empty or null.

� Mandatory fields are present.

Optionally performs other checks.

If one of the checks fail, a validation error is added to the return list.

Checks for already existing objects and checks on the prebuilt Name fields.

Other checks are up to you.

Chapter 12. Custom Application Configuration Management tool 319

Page 338: My Tutorial

create() Creates the physical entity that corresponds to the logical noun.

Uses physical data containers to create physical objects and to get a new primary key from the key manager.

Sets all fields from the logical noun to physical object.

Calls the updateNameValuePairType() method to set the userData field.

You do not need to call the save() method on the physical data container because the BOD command framework does it.

The pre-built code contains most of the code.

You must provide proper field population from the logical noun to the physical object. Use the example code as a guide.

updateNameValuePairType()

Updates the physical CustomAppProperties object with the user data that is set in the logical CustomAppProperties noun. The name value pair mapping is set in the wc-businessobject-mediator.xml file.

Changes are not necessary.

Method Description Implementation

320 WebSphere Commerce Line-of-Business Tooling Customization

Page 339: My Tutorial

validateDelete() Checks if the physical object can be deleted represented by the given logical noun.

Checks if the object to be removed is present in the physical data container.

If the entity is not present, a validation error is added to the return list.

Checks if the present object is pre-built.

Other checks are up to you.

delete() Deletes the logical noun. The delete action on the logical noun is copied to the physical implementation. Deleting the logical noun can result in an update of the physical entity in the form of a mark for delete or can result in an actual delete from the physical data store.

To physically remove the object, call the removePhysicalObject() method on the physical data container.

The code for physically removing an object is pre-built.

Method Description Implementation

Chapter 12. Custom Application Configuration Management tool 321

Page 340: My Tutorial

findPhysicalEntity() Finds the physical entity in the physical data container.

Because the physical data container might return a list of physical entities after initialization, the correct entity needs to be identified. Typically this is done by traversing all entities and comparing them by UniqueID with the given logical noun.

Remember, the physical entities are only cached objects, so iteration is performed in Java code, not on the database.

This method is used by validateDelete() and delete().

Prebuilt code uses a simple UniqueID comparison to find a physical entity that correlates to a given logical noun.

You can implement additional comparisons to identify the correct physical entity.

Method Description Implementation

322 WebSphere Commerce Line-of-Business Tooling Customization

Page 341: My Tutorial

initializePhysicalDataContainer()

Initializes the physical data container for this mediator. Obtains the physical entities from the list of given logical nouns.

The data from nouns that are present in the list is used to fetch the physical entities with the help of queries that are configured with the Data Service layer.

This method is called from the BOD command framework every time the superclass method getPhysicalDataContainer() is called, for example, in the findPhysicalEntity() method.

The code is prebuilt.

resolveByExternalIdentifier()

Resolves the noun part, which has only the external identifier. The noun parts with external identifiers should be resolved to set the UniqueID in the noun.

This method is called the fromvalidateCreate() method.

The pre-built code does not reflect the updated external identifier containing of Name and Storeent_id field. You must update the code appropriately.

validateChange() Because the Change verb is implemented by the ChangeCustomAppPropertiesBasePartMediator class this method is not implemented.

No action.

Method Description Implementation

Chapter 12. Custom Application Configuration Management tool 323

Page 342: My Tutorial

Understanding the ChangeCustomAppPropertiesBasePartMediator class

A change mediator’s task is to change any CustomAppProperties noun parts when executing a Change verb. Again, CustomAppProperties service does not uses noun parts; however, the Change verb is defined to be executed on noun parts and its mediators. So although we do not use noun parts, you nevertheless are required to implement change methods of the ChangeCustomAppPropertiesBasePartMediator to support update action on the CustomAppProperties noun.

Implement the methods that we describe in Table 12-4 on page 325.

change() Because the Change verb is implemented by the ChangeCustomAppPropertiesBasePartMediator class this method is not implemented.

No action.

Method Description Implementation

324 WebSphere Commerce Line-of-Business Tooling Customization

Page 343: My Tutorial

Table 12-4 ChangeCustomAppPropertiesBasePartMediator methods to implement

Method Description Implementation

validateChange() Checks if the physical object can be updated from the modified logical noun.

Checks if: � The object to be

updated is present in the physical data container.

� The external identifier fields are not empty or null.

� Mandatory fields are present.

Optionally performs other checks.

If the physical object cannot be updated, the appropriate error exception is added to thelist of exceptions to be returned to the caller.

Checks for already existing object and checks on Name field are pre-built. Update the check for existing physical objects, and add the Storeent_id field to the external identifier.

Other checks are up to you.

update() Updates the physical data container with the modified logical noun.

Sets all fields from logical noun to physical object.

Calls the updateNameValuePairType() method to set userData field.

You do not need to call the physical data container because the BOD command framework does this.

Pre-built code contains most of the code.

Provide proper field population from the logical noun to the physical object. Use the example code as a guide.

Chapter 12. Custom Application Configuration Management tool 325

Page 344: My Tutorial

updateNameValuePairType()

Updates the physical CustomAppProperties object with the user data set in the logical CustomAppProperties noun. The name value pair mapping is set in the wc-businessobject-mediator.xml file.

Does not need to be changed.

findPhysicalEntity() This method returns the physical SDO from the physical data container that was created in theChangeCustomAppPropertiesMediator by calling the getParentPhysicalDataContainer() method.

Function works similar to findPhysicalEntity() method in the ChangeCustomAppPropertiesMediator.

Is used by the validateChange() and update() methods.

Pre-built code uses a simple UniqueID comparison to find the physical entity that correlates to a given logical noun and noun part.

You can implement additional comparisons to identify the correct physical entity.

initializePhysicalDataContainer()

Initializes the physical data container for this mediator. It currently performs no actions because the physical data container from the ChangeCustomAppPropertiesMediator is used in this mediator.

Does not need to be changed.

resolveByExternalIdentifier()

Performs no actions because the ChangeCustomAppPropertiesMediator does the resolve.

Does not need to be changed.

Method Description Implementation

326 WebSphere Commerce Line-of-Business Tooling Customization

Page 345: My Tutorial

Updating the CustomAppPropertiesFacadeConstants classThe CustomAppProperties-Server project shares constants that are used throughout the whole service module with other service projects. These constants are located in the CustomAppProperties-Client project.

Update the CustomAppPropertiesFacadeConstants class in the CustomAppProperties-Client project according to Example 12-40 on page 328:

1. Open the CustomAppPropertiesFacadeConstants class.

2. Delete or comment out the ACCESS_PROFILE_DETAILS_INFORMATION constant, because we do not use the access profile Redbooks_Details.

3. Delete or comment out the ACCESS_PROFILE_SUMMARY_INFORMATION constant, because we do not use the access profile Redbooks_Summary.

4. Change the ACCESS_PROFILE_DEFAULT constant to ACCESS_PROFILE_ALL_INFORMATION value.

5. Add an additional constant ACCESS_PROFILE_CATEGORY to use for reading the list of custom setting categories.

6. Add an additional constant ACCESS_PROFILE_SEARCH to use for searching in custom settings.

validateCreate() Performs no checking because the ChangeCustomAppPropertiesMediator does the validation.

Does not need to be changed.

create() Performs no actions because the ChangeCustomAppPropertiesMediator creates the nouns.

Does not need to be changed.

validateDelete() Performs no checking because the ChangeCustomAppPropertiesMediator does the validation.

Does not need to be changed.

delete() Performs no actions because the ChangeCustomAppPropertiesMediator deletes the nouns.

Does not need to be changed.

Method Description Implementation

Chapter 12. Custom Application Configuration Management tool 327

Page 346: My Tutorial

7. Add an additional constant NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID that represents the Storeent_id field of the noun.

8. Add an additional constant NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_CATEGORY that represents the Category field of the noun.

9. Delete or comment out the XPATH_CUSTOMAPPPROPERTIES_NAME constant. We do not use this Xpath expression because it does not reflect the Storeent_id external identifier part.

10.Delete or comment out the XPATH_CUSTOMAPPPROPERTIES constant, because we do not use this Xpath expression.

11.Add an additional constant XPATH_EMPTY_CUSTOMAPPPROPERTIES that represents the Xpath statement to access an undefined noun. The Process and Change BOD commands use this XPath expression. For Process, action Delete processing, and for Change processing, the provided logical noun is used to identify the physical object, which Business Object Mediators do. For Process, action Create no identification is needed (except for checking of existing object with same identifier) because in this case a new physical object is created.

12.Add an additional constant XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID that represents the Xpath statement to read a noun by providing external identifiers.

13.Add an additional constant XPATH_CUSTOMAPPPROPERTIES_BY_CATEGORY_BY_STOREENT_ID that represents the Xpath statement to read a noun by a given Category and the Storeent_id.

14.Add an additional constant XPATH_PATTERN_CUSTOMAPPPROPERTIES_SEARCH_BY_STOREENT_ID that represents the Xpath statement to search nouns by a given Storeent_id using the search() expression builder.

15.Add an additional constant XPATH_CUSTOMAPPPROPERTIES_BY_STOREENTID that represents the Xpath statement to read all nouns by a given Storeent_id.

Example 12-40 CustomAppPropertiesFacadeConstants class

package com.redbooks.commerce.customappproperties.facade;

/** * This class defines the constants used to interact with the CustomAppProperties * facade. */public class CustomAppPropertiesFacadeConstants {

// =============================================================================

328 WebSphere Commerce Line-of-Business Tooling Customization

Page 347: My Tutorial

// The following is global constants names associated with the component.// =============================================================================/** * The component name for the CustomAppProperties component. */public static final String COMPONENT_NAME

= "com.redbooks.commerce.customappproperties";

// =============================================================================// The following is a predefined set of access profiles provided by the // component.// =============================================================================/** * This constants represents an access profile that returns all * information about the noun being returned. */public static final String ACCESS_PROFILE_ALL_INFORMATION = "Redbooks_All";

/** * This constants if the default access profile when one is not specified. * The default access profile is the all access profile. */public static final String ACCESS_PROFILE_DEFAULT

= ACCESS_PROFILE_ALL_INFORMATION;

/** * Access profile for updating a noun */public static final String ACCESS_PROFILE_UPDATE = "Redbooks_Update";

/** * Access profile for resolving a noun's ID */public static final String ACCESS_PROFILE_ID_RESOLVE = "Redbooks_IdResolve";

/** * Access profile for reading category related information from the noun */public static final String ACCESS_PROFILE_CATEGORY = "Redbooks_Category";

/** * Access profile for noun search */public static final String ACCESS_PROFILE_SEARCH = "Redbooks_Search";

Chapter 12. Custom Application Configuration Management tool 329

Page 348: My Tutorial

// =============================================================================// The following is a predefined set of XPATH provided by the component.// =============================================================================/** * The constanst for closing the <code>Xpath</code> with a backet. */public static final String CLOSE_XPATH = "]";

/** * The constanst for closing the <code>Xpath</code> with 2 backets. */public static final String DOUBLE_CLOSE_XPATH = ")]";

/** * The attribute name of UID in noun CustomAppProperties. */public static final String NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_UID

= "UniqueID";

/** * The <code>Xpath</code> of CustomAppProperties with UID. */public static final String XPATH_CUSTOMAPPPROPERTIES_UID

= "/CustomAppProperties/CustomAppPropertiesIdentifier[("+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_UID + "="+ CustomAppPropertiesFacadeConstants.DOUBLE_CLOSE_XPATH;

/** * The attribute name of Name in noun CustomAppProperties. */public static final String NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_NAME

= "Name";

/** * The attribute name of Storeent_id in noun CustomAppProperties. */public static final String NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID

= "Storeent_id";

/** * The attribute name of Category in noun CustomAppProperties. */public static final String NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_CATEGORY

= "Category";

330 WebSphere Commerce Line-of-Business Tooling Customization

Page 349: My Tutorial

/** * The <code>Xpath</code> for an empty, unresolved CustomAppProperties noun. */public static final String XPATH_EMPTY_CUSTOMAPPPROPERTIES =

"/CustomAppProperties[1]";

/** * The <code>Xpath</code> of CustomAppProperties with external ID. */public static final String XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID

= "/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[("+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_NAME+ "= and "+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID + "=" + DOUBLE_CLOSE_XPATH;

/** * The <code>Xpath</code> of CustomAppProperties with Category and * Storeent_id. */public static final String XPATH_CUSTOMAPPPROPERTIES_BY_CATEGORY_BY_STOREENT_ID

= "/CustomAppProperties[("+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_CATEGORY+ "=) and CustomAppPropertiesIdentifier[ExternalIdentifier[("+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID+ "="+ DOUBLE_CLOSE_XPATH+ CLOSE_XPATH + CLOSE_XPATH;

/** * The <code>Xpath</code> of searching CustomAppProperties for a given * Storeent_id. */public static final String XPATH_PATTERN_CUSTOMAPPPROPERTIES_SEARCH_BY_STOREENT_ID

= "/CustomAppProperties[CustomAppPropertiesIdentifier[ExternalIdentifier[("+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID+ "="+ DOUBLE_CLOSE_XPATH+ CLOSE_XPATH + " and search()"+ CLOSE_XPATH;

/** * The <code>Xpath</code> of getting CustomAppProperties by Storeent_id.

Chapter 12. Custom Application Configuration Management tool 331

Page 350: My Tutorial

*/public static final String XPATH_CUSTOMAPPPROPERTIES_BY_STOREENTID

= "/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[("+ NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID+ "="+ CustomAppPropertiesFacadeConstants.DOUBLE_CLOSE_XPATH;

// =============================================================================// The following is a list of actions that can be used for the process request.// =============================================================================/** * Constant for the Process Create action on CustomAppProperties */public static final String PROCESS_VERB_ACTION_CREATE_CUSTOMAPPPROPERTIES

= "Create";

/** * Constant for the Process Delete action on CustomAppProperties */public static final String PROCESS_VERB_ACTION_DELETE_CUSTOMAPPPROPERTIES

= "Delete";}

Updating the ChangeCustomAppPropertiesMediator classUpdate the ChangeCustomAppPropertiesMediator class, which is located in the CustomAppProperties-Server project:

1. Open the ChangeCustomAppPropertiesMediator class.

2. Navigate to method validateCreate().

3. Replace the validateCreate() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-41.

Example 12-41 validateCreate() method excerpt

CustomAppPropertiesType aCustomAppProperties = (CustomAppPropertiesType) aNoun;

// check the name (external id)if (aCustomAppProperties.getCustomAppPropertiesIdentifier() != null

&& aCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier() != null

&& aCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName() != null) {

Note: Declare all constants as public static final and be of type String.

332 WebSphere Commerce Line-of-Business Tooling Customization

Page 351: My Tutorial

String customapppropertiesName = aCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName();

if (customapppropertiesName == null || customapppropertiesName.length() == 0) {// name cannot be emptyApplicationError validateError = new ApplicationError(

ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_EMPTY,null, LOGGER.getResourceBundleName());

validationErrors.add(validateError);} else {

if (LoggingHelper.isTraceEnabled(LOGGER)) {LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME,

"validate customappproperties name: " + customapppropertiesName);}

// check for duplicate name existing in the database alreadyif (resolveByExternalIdentifier(aNoun)) {

ApplicationError validateError = new ApplicationError(ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_ALREADY_EXISTS,

new Object[] { customapppropertiesName }, LOGGER.getResourceBundleName());

validationErrors.add(validateError);}

// check for name length else if (CustomAppPropertiesMetadata.invalidStringLength(

customapppropertiesName,CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_NAME_LENGTH_LIMIT)) {

ApplicationError validateError = new ApplicationError(ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_TOO_LONG,null, LOGGER.getResourceBundleName());

validationErrors.add(validateError);}

}} else {

// check name cannot be empty

Chapter 12. Custom Application Configuration Management tool 333

Page 352: My Tutorial

ApplicationError validateError = new ApplicationError(ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_EMPTY,null, LOGGER.getResourceBundleName());

validationErrors.add(validateError);}

// Check descriptionString strDescription = aCustomAppProperties.getDescription();// check description's lengthif (CustomAppPropertiesMetadata.invalidStringLength(strDescription,

CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_DESCRIPTION_LENGTH_LIMIT)) {ApplicationError validateError = new ApplicationError(

ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_DESCRIPTION_TOO_LONG,

null, LOGGER.getResourceBundleName());validationErrors.add(validateError);

}

4. Navigate to the method create().

5. Replace the create() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-42.

Example 12-42 create() method excerpt

// Create the entityCustomAppPropertiesType logicalCustomAppProperties = (CustomAppPropertiesType) aNoun;PhysicalDataContainer pdc = getPhysicalDataContainer();

Xappprops physicalCustomAppProperties = (Xappprops) pdc.createPhysicalObject(null,Xappprops.class);

// get thd next available uid and then insert into the physical dataobjectLong uid = pdc.getNextPrimaryKey(Xappprops.class);physicalCustomAppProperties.setXappprops_id(uid.longValue());

logicalCustomAppProperties.getCustomAppPropertiesIdentifier().setUniqueID(uid.longValue());

if (LoggingHelper.isTraceEnabled(LOGGER)) {LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME,

"new CustomAppProperties unique id= " + uid);}

334 WebSphere Commerce Line-of-Business Tooling Customization

Page 353: My Tutorial

// set the name and storeent_idif (logicalCustomAppProperties.getCustomAppPropertiesIdentifier() != null

&& logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier() != null) {

physicalCustomAppProperties.setName(logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName());

physicalCustomAppProperties.setStoreent_id(logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getStoreentId());

}

// set all other attributesString description = logicalCustomAppProperties.getDescription();String value = logicalCustomAppProperties.getValue();String valueType = logicalCustomAppProperties.getValueType().getName();String category = logicalCustomAppProperties.getCategory();

if (description != null)physicalCustomAppProperties.setDescription(description);

if (value != null)physicalCustomAppProperties.setValue(value);

if (valueType != null)physicalCustomAppProperties.setValuetype(valueType);

if (category != null)physicalCustomAppProperties.setCategory(category);

// update the user data fieldupdateNameValuePairType(logicalCustomAppProperties, physicalCustomAppProperties);

6. Navigate to the validateDelete() method.

7. Replace the validateDelete() method content with Example 12-43.

Example 12-43 validateDelete() method

public List validateDelete(Object aNoun) throws DataMediatorException {

final String METHODNAME = "validateDelete";if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {

LOGGER.entering(CLASSNAME, METHODNAME, new Object[] { aNoun });}

List validationErrors = new ArrayList();if (findPhysicalEntity(aNoun) == null) {

ApplicationError validateError = new ApplicationError(

Chapter 12. Custom Application Configuration Management tool 335

Page 354: My Tutorial

ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NOT_FOUND,new Object[] { aNoun }, LOGGER.getResourceBundleName());

validationErrors.add(validateError);}

if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {LOGGER.exiting(CLASSNAME, METHODNAME, validationErrors);

}return validationErrors;

}

8. Navigate to the delete() method.

9. Replace the delete() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-44.

Example 12-44 delete() method excerpt

// Delete the entity; can either mean mark for delete, or deleteCustomAppPropertiesType logicalCustomAppProperties = (CustomAppPropertiesType) aNoun;long customapppropertiesId = logicalCustomAppProperties

.getCustomAppPropertiesIdentifier().getUniqueID();

// Get the physical data object with specific idXappprops physicalCustomAppProperties = (Xappprops) findPhysicalEntity(aNoun);

if (physicalCustomAppProperties != null) {if (LoggingHelper.isTraceEnabled(LOGGER)) {

LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME,"Delete Data Object CustomAppProperties with unqiue ID: "

+ customapppropertiesId);}getPhysicalDataContainer().removePhysicalObject(physicalCustomAppProperties);

} else {if (LoggingHelper.isTraceEnabled(LOGGER)) {

LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME,"Data Object CustomAppProperties with unqiue ID: "

+ customapppropertiesId + " doesn't exist");}

}

10.Navigate to the findPhysicalEntity() method.

11.Replace the findPhysicalEntity() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-45 on page 337.

336 WebSphere Commerce Line-of-Business Tooling Customization

Page 355: My Tutorial

Example 12-45 findPhysicalEntity() method excerpt

Xappprops aPhysicalEntity = null;PhysicalDataContainer pdc = getPhysicalDataContainer();

// if the PhysicalDataContainer is not null, loop it and compare the uid to find the DataObjectif (pdc != null) {

CustomAppPropertiesType aLogicalCustomAppProperties = (CustomAppPropertiesType) aNoun;

long customapppropertiesId = aLogicalCustomAppProperties.getCustomAppPropertiesIdentifier().getUniqueID();

if (LoggingHelper.isTraceEnabled(LOGGER)) {LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME, "Find CustomAppProperties: "

+ customapppropertiesId);}

List customapppropertiesList = pdc.getPhysicalObjects();if (customapppropertiesList != null && customapppropertiesList.size() > 0) {

Iterator customapppropertiesIter = customapppropertiesList.iterator();while (customapppropertiesIter.hasNext()) {

Xappprops tempPhysicalEntity = (Xappprops) customapppropertiesIter.next();// compare id to get the Physical DataObjectif (tempPhysicalEntity.getXappprops_id() == customapppropertiesId) {

aPhysicalEntity = tempPhysicalEntity;break;

}}

}}

if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {LOGGER.exiting(CLASSNAME, METHODNAME, aPhysicalEntity);

}

return aPhysicalEntity;

12.Navigate to the initializePhysicalDataContainer() method.

13.Replace the initializePhysicalDataContainer() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-46.

Example 12-46 initializePhysicalDataContainer() method excerpt

PhysicalDataContainer physicalEntities = null;

Chapter 12. Custom Application Configuration Management tool 337

Page 356: My Tutorial

// Get a list of extenal IDs from the nounsList customapppropertiesIdList = new ArrayList();Iterator customapppropertiesNounIterator = aListNoun.iterator();while (customapppropertiesNounIterator.hasNext()) {

CustomAppPropertiesType aCustomAppPropertiesType = (CustomAppPropertiesType) customapppropertiesNounIterator

.next();if (aCustomAppPropertiesType.getCustomAppPropertiesIdentifier() != null) {

long uniqueID = aCustomAppPropertiesType.getCustomAppPropertiesIdentifier().getUniqueID();

customapppropertiesIdList.add(String.valueOf(uniqueID));}

}

if (customapppropertiesIdList.size() > 0) {// if there is one or more noun, construct the query to get the physical data // containersSelectionCriteria query = new SelectionCriteria();query

.setXPathKey(CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_UID);query.setAccessProfile(CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_UPDATE);

query.setXPathParameter(new RelationalExpression(

CustomAppPropertiesFacadeConstants.NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_UID,customapppropertiesIdList));

physicalEntities = CustomAppPropertiesMetadata.getDataServiceFacade().getPhysicalDataContainer(query);

} else {//if no noun exist, return an empty PhysicalDataContainerphysicalEntities = CustomAppPropertiesMetadata.getDataServiceFacade()

.getEmptyPhysicalDataContainer();}

if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {LOGGER.exiting(CLASSNAME, METHODNAME, physicalEntities);

}

return physicalEntities;

14.Remove or comment out the return statement after the “Demo code End” comment.

15.Navigate to the resolveByExternalIdentifier() method.

338 WebSphere Commerce Line-of-Business Tooling Customization

Page 357: My Tutorial

16.Replace the resolveByExternalIdentifier() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-47.

Example 12-47 resolveByExternalIdentifier() method excerpt

boolean resolveStatus = false;long uniqueId;String name = null;long storeent_id = 0;CustomAppPropertiesType customapppropertiesNoun = (CustomAppPropertiesType) aNoun;

// get the uid and see whether it existsif (customapppropertiesNoun.getCustomAppPropertiesIdentifier() != null) {

uniqueId = customapppropertiesNoun.getCustomAppPropertiesIdentifier().getUniqueID();

}

if (LoggingHelper.isTraceEnabled(LOGGER)) {LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME, "need to resolve noun");

}

// get the external idif (customapppropertiesNoun.getCustomAppPropertiesIdentifier() != null

&& customapppropertiesNoun.getCustomAppPropertiesIdentifier().getExternalIdentifier() != null) {

name = customapppropertiesNoun.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName();

storeent_id = customapppropertiesNoun.getCustomAppPropertiesIdentifier().getExternalIdentifier().getStoreentId();

}

if (name != null) {// construct selectionCriteria to find the ID from extIDSelectionCriteria query = new SelectionCriteria();query

.setXPathKey(CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID);

query

.setAccessProfile(CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ID_RESOLVE);query

.setXPathParameter(new RelationalExpression(

Chapter 12. Custom Application Configuration Management tool 339

Page 358: My Tutorial

CustomAppPropertiesFacadeConstants.NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_NAME,name));

query.setXPathParameter(new RelationalExpression(

CustomAppPropertiesFacadeConstants.NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID,

String.valueOf(storeent_id)));PhysicalDataContainer physicalEntites = CustomAppPropertiesMetadata

.getDataServiceFacade().getPhysicalDataContainer(query);// if find the physical object of particular extIDif (physicalEntites.getPhysicalObjects().size() > 0) {

resolveStatus = true;Xappprops customapppropertiesEntity = (Xappprops) physicalEntites

.getPhysicalObjects().get(0);// set the id back to the Logical Business ObjectcustomapppropertiesNoun.getCustomAppPropertiesIdentifier().setUniqueID(

customapppropertiesEntity.getXappprops_id());

if (LoggingHelper.isTraceEnabled(LOGGER)) {LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL, CLASSNAME, METHODNAME,

"The external identifier "+ customapppropertiesEntity.getXappprops_id()+ " into the noun");

}}// if the external id is null

} else {if (LoggingHelper.isTraceEnabled(LOGGER)) {

LOGGER.logp(LoggingHelper.DEFAULT_TRACE_LOG_LEVEL, CLASSNAME, METHODNAME,"The external identifier is missing from the noun");

}}

if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {LOGGER.exiting(CLASSNAME, METHODNAME, new Boolean(resolveStatus));

}

return resolveStatus;

17.Remove or comment out the return statement after the “Demo code End” comment.

340 WebSphere Commerce Line-of-Business Tooling Customization

Page 359: My Tutorial

18.After you update the code, you might find some compilation errors because of unhandled exceptions. Use the Eclipse Quick Fix function to update the throw statement of methods as proposed.

19.Organize the imports for the ChangeCustomAppPropertiesMediator class:

a. Open the Java perspective in WebSphere Commerce Developer.

b. Right-click the ChangeCustomAppPropertiesMediator class, and select Source.

c. Select Organize Imports.

20.Save the file (Ctrl+S).

Updating the ChangeCustomAppPropertiesBasePartMediator classUpdate the ChangeCustomAppPropertiesBasePartMediator class, which is located in the CustomAppProperties-Server project:

1. Open the ChangeCustomAppPropertiesBasePartMediator class.

2. Navigate to the validateChange() method.

3. Replace the validateChange() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-48.

Example 12-48 validateChange() method excerpt

// check whether the noun exists by uidXappprops physicalCustomAppProperties = (Xappprops) findPhysicalEntity(aNoun,

aNounPart);

if (physicalCustomAppProperties != null) {CustomAppPropertiesType logicalCustomAppProperties = (CustomAppPropertiesType)

aNoun;

// Check whether the name is validif (logicalCustomAppProperties.getCustomAppPropertiesIdentifier() != null

&& logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier() != null

&& logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName() != null

&& !logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName().equals(

physicalCustomAppProperties.getName())) {

String name = logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName();

long storeent_id = logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier()

Chapter 12. Custom Application Configuration Management tool 341

Page 360: My Tutorial

.getStoreentId();if (name == null || name.length() == 0) {

// name cannot be emptyApplicationError validateError = new ApplicationError(

ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_EMPTY,null, LOGGER.getResourceBundleName());

validationErrors.add(validateError);} else {

// check whether the physical data object with the same name and storeent_id exists already

if (traceEnabled) {LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME,

"validate CustomAppProperties name: " + name);}

SelectionCriteria selectionCriteria = new SelectionCriteria();selectionCriteria

.setXPathKey(CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID);

selectionCriteria

.setAccessProfile(CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ID_RESOLVE);selectionCriteria

.setXPathParameter(new RelationalExpression(

CustomAppPropertiesFacadeConstants.NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_NAME,name));

selectionCriteria.setXPathParameter(new RelationalExpression(

CustomAppPropertiesFacadeConstants.NOUN_ATTRIBUTE_NAME_CUSTOMAPPPROPERTIES_STOREENTID,

String.valueOf(storeent_id)));PhysicalDataContainer pdc = CustomAppPropertiesMetadata

.getDataServiceFacade()

.getPhysicalDataContainer(selectionCriteria);

List physicalDOList = pdc.getPhysicalObjects();

// if there is physical data object existif (physicalDOList != null && physicalDOList.size() != 0) {

ApplicationError validateError = new ApplicationError(

342 WebSphere Commerce Line-of-Business Tooling Customization

Page 361: My Tutorial

ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_ALREADY_EXISTS,

new Object[] { name }, LOGGER.getResourceBundleName());validationErrors.add(validateError);

} else if (CustomAppPropertiesMetadata.invalidStringLength(name,CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_NAME_LENGTH_LIMIT)) {

// checked name lengthApplicationError validateError = new ApplicationError(

ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_TOO_LONG,null, LOGGER.getResourceBundleName());

validationErrors.add(validateError);}

}}

// Check whether the description is valid// Check the length of the descriptionif (CustomAppPropertiesMetadata.invalidStringLength(logicalCustomAppProperties

.getDescription(),CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_DESCRIPTION_LENGTH_LIMIT)) {

ApplicationError validateError = new ApplicationError(ApplicationError.TYPE_GENERIC_ERROR,

CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_DESCRIPTION_TOO_LONG,

null, LOGGER.getResourceBundleName());validationErrors.add(validateError);

}}

4. Navigate to the update() method.

5. Replace the update() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-49.

Example 12-49 update() method excerpt

Xappprops physicalCustomAppProperties = (Xappprops) findPhysicalEntity(aNoun,aNounPart);

// set values from logical data object into the query and run it

Chapter 12. Custom Application Configuration Management tool 343

Page 362: My Tutorial

// set the name and storeent_idif ((logicalCustomAppProperties.getCustomAppPropertiesIdentifier() != null)

&& (logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier() != null)

&& (logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName() != null)) {

physicalCustomAppProperties.setName(logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getName());

physicalCustomAppProperties.setStoreent_id(logicalCustomAppProperties.getCustomAppPropertiesIdentifier().getExternalIdentifier().getStoreentId());

}

// set all other attributesString description = logicalCustomAppProperties.getDescription();String value = logicalCustomAppProperties.getValue();String valueType = logicalCustomAppProperties.getValueType().getName();String category = logicalCustomAppProperties.getCategory();

if (description != null)physicalCustomAppProperties.setDescription(description);

if (value != null)physicalCustomAppProperties.setValue(value);

if (valueType != null)physicalCustomAppProperties.setValuetype(valueType);

if (category != null)physicalCustomAppProperties.setCategory(category);

// update the user data fieldupdateNameValuePairType(logicalCustomAppProperties, physicalCustomAppProperties);

6. Navigate to the findPhysicalEntity() method.

7. Replace the findPhysicalEntity() method content between the “Demo code Begin” and “Demo code End” comments with Example 12-50

Example 12-50 findPhysicalEntity() method excerpt

Xappprops aPhysicalEntity = null;PhysicalDataContainer pdc = getParentPhysicalDataContainer();

// if the PhysicalDataContainer is not null, loop it and compare the uid to find the DataObjectif (pdc != null) {

CustomAppPropertiesType aLogicalCustomAppProperties = (CustomAppPropertiesType) aNoun;

344 WebSphere Commerce Line-of-Business Tooling Customization

Page 363: My Tutorial

long customapppropertiesId = aLogicalCustomAppProperties.getCustomAppPropertiesIdentifier().getUniqueID();

if (LoggingHelper.isTraceEnabled(LOGGER)) {LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME, "Find CustomAppProperties: "

+ customapppropertiesId);}

List customAppPropertiesList = pdc.getPhysicalObjects();if (customAppPropertiesList != null && customAppPropertiesList.size() > 0) {

Iterator customAppPropertiesIter = customAppPropertiesList.iterator();while (customAppPropertiesIter.hasNext()) {

Xappprops tempPhysicalEntity = (Xappprops) customAppPropertiesIter.next();// compare id to get the Physical DataObjectif (tempPhysicalEntity.getXappprops_id() == customapppropertiesId) {

aPhysicalEntity = tempPhysicalEntity;break;

}}

}

}

if (LoggingHelper.isEntryExitTraceEnabled(LOGGER)) {LOGGER.exiting(CLASSNAME, METHODNAME, aPhysicalEntity);

}

return aPhysicalEntity;

8. Remove or comment out the return statement after the “Demo code End” comment.

9. After you update the code, you might find some compilation errors because of unhandled exceptions. Use the Eclipse Quick Fix Function to update the throw statement of methods as proposed.

10.Organize the imports for the ChangeCustomAppPropertiesBasePartMediator class:

a. Open the Java perspective in WebSphere Commerce Developer.

b. Right-click the ChangeCustomAppPropertiesBasePartMediator class, and select Source.

c. Select Organize Imports.

11.Save the file (Ctrl+S).

Chapter 12. Custom Application Configuration Management tool 345

Page 364: My Tutorial

12.4.9 Configuring the Data Service layer for the CustomAppProperties service module

Figure 12-32 outlines the next steps for customizing the new service module.

Figure 12-32 Configuring the Data Service layer

To configure the Data Service layer:

1. Define two query templates:

– wc-query-CustomAppProperties-get.tpl

A query template file that maps each get request XPath statement and access profile to a SQL template query.

– wc-query-CustomAppProperties-update.tpl

A query template file that maps each change request XPath statement to a SQL template query.

The pre-built sample query template files contain some sample queries and access profiles that are based on the assumption of the table name being equal to the component service name (CustomAppProperties), standard columns, and standard identifier. Neither the updated logical CustomAppProperties noun nor the used physical table XAPPPROPS are reflected, so update the template files in the upcoming steps.

CustomAppProperties-Server

Physical SDO Java classesQuery templates

Physical objectpersistence service

BusinessObject Mediators

Readmediators

Changemediators

Object-relationalmetadata

Business objectmediator configuration

Service moduleconfiguration

Value mapping

346 WebSphere Commerce Line-of-Business Tooling Customization

Page 365: My Tutorial

Detailed information about query templates is available in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdqtf.htm

2. Define the logical to physical SDO mapping.

Defines the wc-business-object-mediator.xml file to relate logical nouns to physical data objects.

Detailed information about the wc-business-object-mediator.xml file is available in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdexposenewdata.htm

3. Update the CustomAppProperties service configuration (wc-component.xml).

Detailed information about the wc-component.xml file is available in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdextendconfig.htm

Defining the wc-query-CustomAppProperties-get.tpl query template

On code generation, a sample query template file wc-query-CustomAppProperties-get.tpl.sample was pre-built. You can find this file in the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

Rename the file wc-query-CustomAppProperties-get.tpl.sample:

1. Using Windows Explorer, navigate to the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

2. There is already another sample file, wc-query-CustomAppProperties-get.tpl, which has no meaningful content. Delete it.

3. Rename the file wc-query-CustomAppProperties-get.tpl.sample to wc-query-CustomAppProperties-get.tpl.

Update the query template to reflect the correct table name:

1. Using a text editor, open the file wc-query-CustomAppProperties-get.tpl

2. Replace the content using the syntax in Example 12-51 on page 349.

Chapter 12. Custom Application Configuration Management tool 347

Page 366: My Tutorial

3. Review the section SYMBOL_DEFINITIONS, which defines the columns that are used in the subsequent queries.

4. Review the XPATH_TO_SQL_STATEMENT sections.

There is a configuration for all XPath expressions that are used for Get requests that you already defined in the CustomAppPropertiesFacadeConstants class in the CustomAppProperties-Client project.

5. Review the ASSOCIATION_SQL_STATEMENT and PROFILE section.

Using the search expression builder to perform parametric search queries requires a two-step query. In the following sections, we provide steps to implement a search on configuration settings:

– XPath-to-SQL statement /CustomAppProperties[CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=)]] and search()]

The statement returns only primary keys that the association SQL statement uses.

The search() expression is provided with parameters that form the search condition, when building the Get request.

– Association SQL statement Redbooks_XAPPPROPS_AllFields

The association statement returns all fields and uses the primary keys that are fetched by a XPath-to-SQL statement, which is defined by an access profile.

– Access profile Redbooks_Search

The access profile combines a XPath-to-SQL statement and an association SQL statement.

For more details about two-step queries, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdqueryexec.htm

Important: For some reason, the search() expression always needs to be on the end of the XPath-to-SQL statement. Otherwise, the XPath parser cannot match the XPath-to-SQL statement from the query template file with the XPath expression from a Data Service layer request.

348 WebSphere Commerce Line-of-Business Tooling Customization

Page 367: My Tutorial

Example 12-51 Query template file wc-query-CustomAppProperties-get.tpl

BEGIN_SYMBOL_DEFINITIONS<!-- The table for noun CustomAppProperties -->

<!-- getting all columns in the table-->COLS:XAPPPROPS = XAPPPROPS:* <!-- getting uid column in the table-->COLS:XAPPPROPS_ID = XAPPPROPS:XAPPPROPS_ID<!-- getting name column in the table-->COLS:XAPPPROPS_NAME = XAPPPROPS:NAME<!-- getting STOREENT_ID column in the table-->COLS:XAPPPROPS_STOREENT_ID = XAPPPROPS:STOREENT_ID<!-- getting CATEGORY column in the table-->COLS:XAPPPROPS_CATEGORY = XAPPPROPS:CATEGORY

END_SYMBOL_DEFINITIONS

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_All --><!-- Get the all information for CustomAppProperties with specified uid --><!-- All access profile includes all attributes --><!-- @param UniqueID Unique id of CustomAppProperties to retrieve. --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties/CustomAppPropertiesIdentifier[(UniqueID=)]+Redbooks_Allbase_table=XAPPPROPSsql=

SELECT XAPPPROPS.$COLS:XAPPPROPS$ FROM XAPPPROPS WHERE

XAPPPROPS.Id = ?UniqueID? END_XPATH_TO_SQL_STATEMENT

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_All --><!-- Get the all information for CustomAppProperties with specfified external ID --><!-- All access profile includes all the attributes --><!-- @param Name Name (External ID) of CustomAppProperties to retrieve --><!-- @param Storeent_id Storeent_id (External ID) of CustomAppProperties to retr --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[(Name= and Storeent_id=)]+Redbooks_All

base_table=XAPPPROPS

Chapter 12. Custom Application Configuration Management tool 349

Page 368: My Tutorial

sql=SELECT

XAPPPROPS.$COLS:XAPPPROPS$ FROM XAPPPROPS WHERE

XAPPPROPS.NAME = ?Name?AND XAPPPROPS.STOREENT_ID = ?Storeent_id?

END_XPATH_TO_SQL_STATEMENT

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_All --><!-- Get the all information for CustomAppProperties by given Category and --><!-- Storeent_id --><!-- All access profile includes all the attributes --><!-- @param Category Category of CustomAppProperties to retrieve --><!-- @param Storeent_id Storeent_id (External ID) of CustomAppProperties to retr --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties[(Category=) and CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=)]]]+Redbooks_All

base_table=XAPPPROPSsql=

SELECT XAPPPROPS.$COLS:XAPPPROPS$ FROM XAPPPROPS WHERE

XAPPPROPS.CATEGORY = ?Category?AND XAPPPROPS.STOREENT_ID = ?Storeent_id?

END_XPATH_TO_SQL_STATEMENT

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_Category --><!-- Get the all information for CustomAppProperties by given Storeent_id --><!-- Redbooks_Category access profile includes only basic information --><!-- Used to create the list of configuration setting categories --><!-- @param Storeent_id Storeent_id (External ID) of CustomAppProperties to retr --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[(Storeent_id=)]+Redbooks_Category

base_table=XAPPPROPSsql=

350 WebSphere Commerce Line-of-Business Tooling Customization

Page 369: My Tutorial

SELECT XAPPPROPS.$COLS:XAPPPROPS_ID$, XAPPPROPS.$COLS:XAPPPROPS_NAME$, XAPPPROPS.$COLS:XAPPPROPS_STOREENT_ID$, XAPPPROPS.$COLS:XAPPPROPS_CATEGORY$ FROM XAPPPROPS WHERE

XAPPPROPS.STOREENT_ID = ?Storeent_id?ORDER BYCATEGORY ASC

END_XPATH_TO_SQL_STATEMENT

<!-- ============================================================================ --><!-- AccessProfile: None --><!-- Get the UniqueID for CustomAppProperties by given search expression --><!-- and Storeent_id --><!-- @param search search expression of CustomAppProperties to retrieve --><!-- @param Storeent_id Storeent_id (External ID) of CustomAppProperties to retr --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties[CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=)]] and search()]

base_table=XAPPPROPSsql=

SELECT XAPPPROPS.$COLS:XAPPPROPS_ID$ FROM XAPPPROPS,$ATTR_TBLS$ WHERE

XAPPPROPS.STOREENT_ID = ?Storeent_id?AND ( $ATTR_CNDS$ )

END_XPATH_TO_SQL_STATEMENT

<!-- ============================================================================ --><!-- Association Statement --><!-- Adds all XAPPPROPS fields to the resultant data graph. --><!-- ============================================================================ -->BEGIN_ASSOCIATION_SQL_STATEMENT

name=Redbooks_XAPPPROPS_AllFieldsbase_table=XAPPPROPSadditional_entity_objects=truesql=

SELECT

Chapter 12. Custom Application Configuration Management tool 351

Page 370: My Tutorial

XAPPPROPS.$COLS:XAPPPROPS$ FROM XAPPPROPS WHERE

XAPPPROPS.XAPPPROPS_ID IN ($ENTITY_PKS$) END_ASSOCIATION_SQL_STATEMENT

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_Search --><!-- Search Profile using the Redbooks_XAPPPROPS_AllFields association statement --><!-- ============================================================================ -->BEGIN_PROFILE

name=Redbooks_SearchBEGIN_ENTITY

base_table=XAPPPROPS associated_sql_statement=Redbooks_XAPPPROPS_AllFields

END_ENTITYEND_PROFILE

6. Save the file.

Defining the wc-query-CustomAppProperties-update.tpl query template

On code generation, a sample query template file wc-query-CustomAppProperties-update.tpl.sample was pre-built. You can find this file in the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties.

Rename the file wc-query-CustomAppProperties-update.tpl.sample:

1. Using Windows Explorer, navigate to the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

2. There is already another sample file wc-query-CustomAppProperties-update.tpl that has no meaningful content. Delete it.

3. Rename the wc-query-CustomAppProperties-update.tpl.sample file to wc-query-CustomAppProperties-update.tpl.

Update the query template to reflect correct table name:

1. Using a text editor, open the wc-query-CustomAppProperties-update.tpl file, and replace the content with the syntax in Example 12-52 on page 353.

352 WebSphere Commerce Line-of-Business Tooling Customization

Page 371: My Tutorial

2. Review the SYMBOL_DEFINITIONS section, which defines the columns that are used in the subsequent queries.

3. Review the XPATH_TO_SQL_STATEMENT sections.

There is a configuration for all XPath expressions that are used for Process and Change requests, which you already defined in the CustomAppPropertiesFacadeConstants class, in the CustomAppProperties-Client project.

The section contains:

– An expression to read all of the data that the UniqueID identified (XAPPPROPS.XAPPPROPS_ID).

– An expression to resolve the UniqueID by external identifiers (XAPPPROPS.NAME and XAPPPROPS.STOREENT_ID).

Example 12-52 Query template file wc-query-CustomAppProperties-update.tpl

BEGIN_SYMBOL_DEFINITIONS<!-- The table for noun CustomAppProperties -->

<!-- getting all columns in the table-->COLS:XAPPPROPS = XAPPPROPS:* <!-- getting uid column in the table-->COLS:XAPPPROPS_ID = XAPPPROPS:XAPPPROPS_ID<!-- getting name column in the table-->COLS:XAPPPROPS_NAME = XAPPPROPS:NAME<!-- getting STOREENT_ID column in the table-->COLS:XAPPPROPS_STOREENT_ID = XAPPPROPS:STOREENT_ID

END_SYMBOL_DEFINITIONS

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_Update --><!-- Get the all information for CustomAppProperties with specified uid --><!-- All access profile includes all attributes --><!-- @param UniqueID Unique id of CustomAppProperties to retrieve. --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties/CustomAppPropertiesIdentifier[(UniqueID=)]+Redbooks_Updatebase_table=XAPPPROPSsql=

SELECT XAPPPROPS.$COLS:XAPPPROPS$ FROM XAPPPROPS WHERE

Chapter 12. Custom Application Configuration Management tool 353

Page 372: My Tutorial

XAPPPROPS.XAPPPROPS_ID = ?UniqueID? END_XPATH_TO_SQL_STATEMENT

<!-- ============================================================================ --><!-- AccessProfile: Redbooks_IdResolve --><!-- Get the information for CustomAppProperties with specfified Name and <!-- Storeent_id for ID resolving. --><!-- Access profile includes the attribute UniqueID, Name, and Storeent_id --><!-- @param Name Name (External ID) of CustomAppProperties to retrieve --><!-- @param Storeent_id Storeent_id (External ID) of CustomAppProperties to retr --><!-- ============================================================================ -->BEGIN_XPATH_TO_SQL_STATEMENT

name=/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[(Name= and Storeent_id=)]+Redbooks_IdResolve

base_table=XAPPPROPSsql=

SELECT XAPPPROPS.$COLS:XAPPPROPS_ID$, XAPPPROPS.$COLS:XAPPPROPS_NAME$, XAPPPROPS.$COLS:XAPPPROPS_STOREENT_ID$ FROM XAPPPROPS WHERE

XAPPPROPS.NAME = ?Name? and XAPPPROPS.STOREENT_ID = ?Storeent_id?END_XPATH_TO_SQL_STATEMENT

Defining the logical to physical SDO mappingYou define the logical to physical mapping in the wc-business-object-mediator.xml file. This file relates a logical type (noun) to the physical type (physical SDO) that contains its unique ID. The mapping is defined by the logicalType and physicalType Attributes of the <_config:object> element.

Update the wc-business-object-mediator.xml file:

1. Using Windows Explorer, navigate to the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

2. Using a text editor, open the wc-business-object-mediator.xml file.

3. Review the content of the file. There is a default mapping definition that defines a physicalType being that is not specific (and hence, being wrong) to the CustomAppProperties service module. A sample mapping is provided in

354 WebSphere Commerce Line-of-Business Tooling Customization

Page 373: My Tutorial

the comment line. However, this mapping also does not reflect the actual name of the physical type.

4. Replace the following mapping definition with the content in Example 12-53.

<_config:object logicalType="..." physicalType="...">

Example 12-53 Logical to physical SDO mapping definition

<_config:object

logicalType="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType"

physicalType="com.redbooks.commerce.customappproperties.facade.server.entity.datatypes.Xappprops">

5. Save the file.

Updating the CustomAppProperties service configuration

The wc-component.xml file is a generic configuration file for your WebSphere Commerce service module. Various internal components use this file to define their configuration properties.

If you want to add your own service module configuration, place it into this file. You have access to the configuration properties through the com.ibm.commerce.foundation.common.config.ComponentConfiguration class.

For detailed information about service module configuration, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdextendconfig.htm

Update the wc-business-object-mediator.xml file:

1. Using Windows Explorer, navigate to the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

2. Using a text editor, open the wc-component.xml file.

The pre-built content that is in this file is correct. Changes are not necessary; however, the search expression builder that we use needs some additional configuration settings.

Chapter 12. Custom Application Configuration Management tool 355

Page 374: My Tutorial

3. Inside of the <_config:dataservice> element, add an <_config:mapping> element. Add the content of Example 12-54 as a sub-element to the <_config:dataservice> element.

Example 12-54 Column mapping definition for the search expression builder

<!-- Mapping for xappprops search --><_config:mapping>

<_config:key name="CustomAppProperties" /><_config:basetable name="XAPPPROPS" useAllColumns="false">

<_config:columns name="NAME" caseSensitive="false" /><_config:columns name="VALUE" caseSensitive="false" /><_config:columns name="DESCRIPTION" caseSensitive="false" /><_config:columns name="VALUETYPE" caseSensitive="true" /><_config:columns name="CATEGORY" caseSensitive="false" />

</_config:basetable></_config:mapping>

4. Review the added code.

You enabled the listed columns for search, specifying the names and a flag to use or to not use a case-sensitive search.

5. Save the file.

12.4.10 Implementing the Business Logic layer

The Business Logic layer provides services to return data or to execute business logic, as shown in Figure 12-33 on page 357.

Building the search expression: When you build the search expression in a later step, use the exact values that you defined in the name attribute.

356 WebSphere Commerce Line-of-Business Tooling Customization

Page 375: My Tutorial

Figure 12-33 Implementing the Business Logic layer

The BOD programming that was introduced in Feature Pack 3 uses four BOD processing patterns: Get, Change, Process, and Sync:

� BOD Get processing pattern

The Business Object Document Get processing pattern describes the design pattern that searches for and retrieves data.

In this scenario, we use pre-built Get commands to read CustomAppProperties nouns from the XAPPPROPS table. We do not cover the implementation of new Get commands in this scenario.

� BOD Process processing pattern

The Business Object Document Process pattern performs a single action on a single noun. Based on the information within that noun, a Process controller will control the actions of the business logic. This Process controller reads common data across the actions within the request, instantiates the task command implementations for those actions, and executes them.

In this scenario, we use pre-built Process commands to create and delete CustomAppProperties nouns in the XAPPPROPS table. The implementation of new Process commands is not necessary, and we do not cover them within this scenario.

� BOD Change processing pattern

The business object document Change processing pattern adds, changes, or deletes a business object. The use of BOD processing commands enables

CustomAppProperties-Server

Commandregistration

Business logic

Get commands Process commands

Change commands Sync commands

Access controlpolicy XML

acpload

massload

Chapter 12. Custom Application Configuration Management tool 357

Page 376: My Tutorial

the Change requests to perform multiple actions in one request. While Process commands work on nouns, the Change commands work on noun parts; however, because Process processing pattern supports no update action, the update of a noun is implemented with a Change command too.

In this scenario, we use pre-built Change commands to update existing CustomAppProperties nouns in the XAPPPROPS table. It is not necessary to implement new Change commands; therefore, we do not cover this subject within this scenario.

� BOD Sync processing pattern

Systems that contain master data records to push out notifications when their data has changed use the Business Object Document Sync processing pattern. The Sync request contains the updated version of the business object, and the request is sent out to all other listening systems to update their version of the business object.

In this scenario, we use no Sync processing pattern.

Detailed information about BOD commands using the four BOD processing patterns are available in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csddesignpatterns.htm

BOD commands used in this scenarioWe do not implement new BOD commands because the pre-built BOD commands covers all necessary business logic we need in this scenario.

Take a moment to review the pre-built BOD commands using the following steps:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, navigate to the CustomAppProperties-Server project.

4. Open the ejbModule source folder.

5. The commands are located in the following package: com.redbooks.commerce.customappproperties.facade.server.commands Expand the package.

358 WebSphere Commerce Line-of-Business Tooling Customization

Page 377: My Tutorial

6. Open the GetCustomAppPropertiesCmd.java command interface, which contains the following methods:

– setGetCustomAppProperties()

Sets the GetCustomAppProperties Business Object Document representing a request. It contains an XPath expression to identify the CustomAppProperties nouns to be fetched.

– getShowCustomAppProperties()

Returns the Show Business Object Document, which represents the response to the Get request.

Review the GetCustomAppPropertiesCmdImpl implementation class, which is located in GetCustomAppPropertiesCmdImpl.java. Amongst others, it provides the name of the Fetch task commands interface through the getFetchCommandInterface() method.

7. Open the FetchCustomAppPropertiesCmd.java command interface.

This command interface contains the getCustomAppPropertiess() method that returns the list of CustomAppProperties nouns that were retrieved through the fetch based on an XPath expression.

Optionally, review the FetchCustomAppPropertiesCmdImpl implementation class, which is located in FetchCustomAppPropertiesCmdImpl.java.

8. Review the InsertMoreCustomAppPropertiesDataCmd.java command interface.

Sometimes you want to include more data in the nouns you return from a Get service. WebSphere Commerce provides a customization point called the InsertMoreData command, for this purpose.

To learn more about modifying a Get service to use business logic to insert more data for a specific access profile, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdworkmoredata.htm

9. Open the ProcessCustomAppPropertiesCmd.java command interface, which contains the following methods:

– setProcessCustomAppProperties()

Sets the ProcessCustomAppProperties Business Object Document representing a request. It contains the process type that represents the action code and a list of CustomAppProperties nouns to perform the action.

– getAcknowledgeCustomAppProperties()

Chapter 12. Custom Application Configuration Management tool 359

Page 378: My Tutorial

Returns the Acknowledge Business Object Document that represents the response to the specific Process request.

Optionally, review the ProcessCustomAppPropertiesCmd implementation class, which is located in ProcessCustomAppPropertiesCmdImpl.java.

10.Review action-specific Process commands.

The generated commands are more or less empty, acting as facade and extension point for your specific needs. You will find the following interfaces and implementation classes:

– ProcessCustomAppPropertiesActionCmd

Common interface for all CustomAppProperties Process commands.

– ProcessCustomAppPropertiesDeleteActionCmdImpl

Customizable Process command to execute the Delete action.

– ProcessCustomAppPropertiesCreateActionCmdImpl

Customizable Process command to execute the Create action.

11.Review the Change commands.

The Change processing pattern stipulates the splitting of the Change request into smaller tasks. Hence, the Change command calls a number of task commands to perform the several tasks.

The pre-built default implementation, which is located at ChangeCustomAppPropertiesCmdImpl.java, contains methods to return task-command interface names for actions on noun parts, as well as a method to build the BOD Respond document that represents the response to the Change request.

The following task commands are called:

– ChangeCustomAppPropertiesBasePartCmdImpl

This command modifies the noun's basic attributes. A list of nouns and action expressions are passed to this command to act upon.

– ChangeCustomAppPropertiesBasePartCmdImpl

This command is executed post the update of the nouns's basic attributes, hence after the execution of the Change mediators.

Registering the BOD commandsRegister the BOD commands with the command registration based on the CMDREG table. You must include all of the commands that we discussed in the preceding section in the command registration; otherwise, WebSphere Commerce cannot find and execute them.

360 WebSphere Commerce Line-of-Business Tooling Customization

Page 379: My Tutorial

Luckily, all needed assets are already generated and ready to use. Register the CustomAppProperties BOD commands using the next steps:

1. Using Windows Explorer, navigate to the following directory:

<WCDE_installdir>/xml/config/com.redbooks.commerce.customappproperties

2. Using a text editor, open the CustomAppProperties-cmdreg.xml file.

3. Review the existing content.

The file is an XML file that is formatted for import by the WebSphere Commerce Mass Load utility. The commands are registered to be valid for the WebSphere Commerce instance, not being tied on a specific store.

Notice the special syntax on some interface name attribute values, which take the format of:

package.commandInterface+XPathExpression, such as

interfacename="com.redbooks.commerce.customappproperties.facade.server.commands.ChangeCustomAppPropertiesPartPostActionCmd+/CustomAppProperties[]"

The BOD command framework interprets this special syntax. The syntax after the plus character “+” references an XPath key that is based on the CustomAppProperties logical model. When the client library API receives an XPath that is formatted in this way, there is logic to interpret which fetch command to call and where to place the values for the corresponding attributes in the XPath key.

To review detailed information, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdsoaget.htm

To review a more complex example, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tutorial/twvstep3.htm

This example is regarding a Feature Pack 2 tutorial, but the command interface interpretation is covered in detail and is also valid for Feature Pack 3.

4. Open a command prompt. In Windows XP, click Start > Run.

5. Enter cmd.exe.

6. On the command prompt, navigate to <WCDE_installdir>/bin directory with

cd <WCDE_installdir>\bin

Chapter 12. Custom Application Configuration Management tool 361

Page 380: My Tutorial

7. Use massload.bat to import CustomAppProperties-cmdreg.xml into your WebSphere Commerce database. If you are using a Cloudscape database, ensure that no application has a connection to the WebSphere Commerce database, such as the WebSphere Commerce Test Server.

8. On one line, type:

massload ..\xml\config\com.redbooks.commerce.customappproperties\CustomAppProperties-cmdreg.xml

Oracle and DB2® users need to adapt the import statement respectively.

9. Review the Mass Load utility logs in the <WCDE_installdir>\logs directory

12.4.11 Implementing the client library

The client library's primary purpose is to simplify and eliminate code on the client. The client library is essentially a Java layer that helps Java applications to integrate with your service architecture. The client library already has support for session and authentication and provides Java-based clients with a standardized mechanism to create the logical SDO objects to represent service requests.

The client library is located in the CustomAppProperties-Client project.

To familiarize yourself with the generated assets of the client library:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, navigate to the CustomAppProperties-Client project.

4. Open the src folder.

5. Expand the com.redbooks.commerce.customappproperties.logging package.

This package contains the CustomAppPropertiesClientApplicationMessageKeys interface, which holds constants to represent CustomAppProperties messages that CustomAppProperties clients commonly use.

6. Expand the com.redbooks.commerce.customappproperties.facade package.

This package contains the CustomAppPropertiesFacadeConstants class, which holds constants that the CustomAppProperties service module and clients commonly. You already added all necessary code in a preceding step.

7. Expand the com.redbooks.commerce.customappproperties.facade.client package.

362 WebSphere Commerce Line-of-Business Tooling Customization

Page 381: My Tutorial

This package contains the CustomAppProperties Facade Client, which provides common methods that are used as single point-of-contact to the CustomAppProperties service module. This class is a provider for a set of convenient Java APIs to represent particular CustomAppProperties operations or Java APIs for Web-based requests by transforming the name-value-pair request into the appropriate request BODs.

This class contains a code template for a method that the JSTL-enabled JSP uses.

The super class AbstractCustomAppPropertiesFacadeClient contains all code for the basic Get, Process, and Change operations that we use in our scenario, so no additional update of the CustomAppPropertiesFacadeClient class is needed.

You will use the CustomAppPropertiesFacadeClient class when we build the JUnit-based test class.

12.4.12 Implementing access control

The BOD command framework continues to use the WebSphere Commerce Policy Manager as its default access control engine, but now deals with BOD commands instead of Controller commands and nouns instead of EJBs.

The access control configuration was simplified. For BOD commands, except Get, command-level authorization is no longer performed; only resource-level access control checks that work on nouns are performed.

On the Get command execution, there is an additional check on the access profile that is used. The access profile indicates the view of the data, and certain views can be limited to certain types of users, which is sufficient to check whether a user can run the command against a particular resource.

To enable protection on nouns, a Protectable Proxy class must be in place that acts on behalf of the noun. On the service module generation, the class CustomAppPropertiesTypeProtectableProxy was generated for you, which is located in the CustomAppProperties-Server project.

In the CustomAppProperties service configuration file (wc-component.xml), the relation to the noun is established, which is represented by the CustomAppPropertiesType interface. The settings are sufficient for our scenario, so no update needs to occur.

Chapter 12. Custom Application Configuration Management tool 363

Page 382: My Tutorial

To learn more about the access control of the BOD framework, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdaccesscontrol.htm

Code generation has a pre-built access control import file to be executed with the acpload utility. In a preceding step, you copied this file from the <workspace_dir>/CustomAppProperties-Server/TODO-MoveItToWCServerXMLFolder/xml/policies/xml file, which is in the CustomAppProperties-Server project, into the <WCDE_installdir>/xml/policies/xml directory.

Complete the configuration, and execute the load process:

1. Using Windows Explorer, navigate to the <WCDE_installdir>/xml/policies/xml directory.

2. In a text editor, open the CustomAppProperties-access-control.xml file, and review the content of the generated file:

– Access profile access control

<Action> elements define access profile references. It takes the notation of serviceModuleName.accessProfileName.

According to Actions, Action Groups are defined by <ActionGroup> elements to group the Actions.

Access Control Policies are defined by <Policy> element, which specifies, what Actions (defined by Action Groups) can be executed by which User Groups, which ascertains if a given user can execute a Get command to a requested access profile.

The <PolicyGroup> element and its <PolicyGroupPolicy> sub-elements defines the eligibility of the Access Control Policies to the organizational structure.

Because we removed unnecessary access profiles and created new access profiles, you must update the <Action> elements.

– Access control for actions on the noun

<Action> elements define supported actions on the CustomAppProperties noun. It takes the notation of nounInterface.action.

According to Actions, Action Groups are defined by <ActionGroup> elements to group the Actions.

<Resource> elements define Resources to protect. As mentioned earlier, a Protectable Proxy class acts on behalf of the noun.

364 WebSphere Commerce Line-of-Business Tooling Customization

Page 383: My Tutorial

A <Policy> element now combines an Action Group, a Resource, and an User Group, which ascertains if a given user can execute a BOD command that represents an action request on the requested noun.

Policy Group definitions are analogous.

The generated access control configuration on actions and nouns meets our requirements. However, by default the configuration relates to the non-existing User Group CustomAppPropertiesManagers, so you either must create this User Group or change the configuration to an already existing User Group. In this scenario, you use an existing User Group.

3. Update the CustomAppProperties-access-control.xml file:

a. Replace all access profile-related resources for access profiles Redbooks_Summary and Redbooks_Details with resources that are needed for access profiles Redbooks_Category and Redbooks_Search.

i. Replace the following syntax:

<Action Name="GetCustomAppProperties.Redbooks_Details" CommandName="GetCustomAppProperties.Redbooks_Details"

/><Action

Name="GetCustomAppProperties.Redbooks_Summary" CommandName="GetCustomAppProperties.Redbooks_All"

/>by

<Action Name="GetCustomAppProperties.Redbooks_Category" CommandName="GetCustomAppProperties.Redbooks_Category"

/><Action

Name="GetCustomAppProperties.Redbooks_Search" CommandName="GetCustomAppProperties.Redbooks_Search"

/>

ii. Replace all <ActionGroupAction> sub-elements of the <ActionGroup Name="CustomAppProperties-CustomAppProperties-AllUsers-AccessProfileActionGroup...> by

<ActionGroupAction Name="GetCustomAppProperties.Redbooks_All"/>

<ActionGroupAction Name="GetCustomAppProperties.Redbooks_Category"/>

Chapter 12. Custom Application Configuration Management tool 365

Page 384: My Tutorial

<ActionGroupAction Name="GetCustomAppProperties.Redbooks_Search"/>

iii. Remove the <ActionGroup Name="CustomAppProperties-CustomAppProperties-CustomAppPropertiesManagers-AccessProfileActionGroup...>". We do not need to add an additional Action Group of access profiles because we want to grant read access of the CustomAppProperties noun to everyone.

iv. Remove the <Policy Name="CustomAppProperties-CustomAppProperties-CustomAppPropertiesManagers-AccessProfilePolicy"...>.

v. Remove the <PolicyGroupPolicy> element with attribute Name="CustomAppProperties-CustomAppProperties-CustomAppPropertiesManagers-AccessProfilePolicy".

b. Limit the group of users that have the right to create, update, and delete CustomAppProperties. Only Site Administrators should have this authority. Therefore, you must update the access control further:

i. Move the Action references of the add and delete actions to the <ActionGroup Name="CustomAppProperties-CustomAppProperties-AllUsers-ActionGroup"...>

ii. Remove the empty <ActionGroup Name="CustomAppProperties-CustomAppProperties-CustomAppPropertiesManagers-ActionGroup"...>.

iii. Remove the <Policy Name="CustomAppProperties-CustomAppProperties-CustomAppPropertiesManagers-CreatorPolicy"...>.

iv. Remove the <PolicyGroupPolicy Name="CustomAppProperties-CustomAppProperties-CustomAppPropertiesManagers-CreatorPolicy"...>.

v. In the <Policy Name="CustomAppProperties-CustomAppProperties-AllUsers-CreatorPolicy"...>, change the UserGroup attribute to

UserGroup="SiteAdministrators"

and the Name attribute to

Name="CustomAppProperties-CustomAppProperties-SiteAdministrators-CreatorPolicy"

c. In the <PolicyGroupPolicy Name="CustomAppProperties-CustomAppProperties-AllUsers-CreatorPolicy"...> change Name attribute to

366 WebSphere Commerce Line-of-Business Tooling Customization

Page 385: My Tutorial

Name="CustomAppProperties-CustomAppProperties-SiteAdministrators-CreatorPolicy"

d. Make sure that your CustomAppProperties-access-control.xml file has the same content of Example 12-55.

Example 12-55 CustomAppProperties access control

<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?><!DOCTYPE Policies SYSTEM "../dtd/accesscontrolpolicies.dtd"><Policies>

<!-- defining supported access profiles --><!-- ================================================ --><Action

Name="GetCustomAppProperties.Redbooks_All" CommandName="GetCustomAppProperties.Redbooks_All"

/><Action

Name="GetCustomAppProperties.Redbooks_Category" CommandName="GetCustomAppProperties.Redbooks_Category"

/><Action

Name="GetCustomAppProperties.Redbooks_Search" CommandName="GetCustomAppProperties.Redbooks_Search"

/>

<!-- defining supported actions --><!-- ================================================ --><!-- read action (Get request) --><Action

Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.read"

CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.read"

/><!-- change action (Change request) --><Action

Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.change"

CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.change"

/>

Chapter 12. Custom Application Configuration Management tool 367

Page 386: My Tutorial

<!-- process actions (Process request) --><Action

Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.add"

CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.add"

/><Action

Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.delete"

CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.delete"

/>

<!-- defining resouce category --><!-- ================================================ -->

<!-- category for CustomAppProperties --><ResourceCategory

Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesTypeResourceCategory" ResourceBeanClass="com.redbooks.commerce.customappproperties.facade.server.authorization.CustomAppPropertiesTypeProtectableProxy" /> <!-- defining action groups -->

<!-- ================================================ --><!-- access profiles for all users -->

<ActionGroup Name="CustomAppProperties-CustomAppProperties-AllUsers-AccessProfileActionGroup" OwnerID="RootOrganization">

<ActionGroupAction Name="GetCustomAppProperties.Redbooks_All"/><ActionGroupAction Name="GetCustomAppProperties.Redbooks_Category"/><ActionGroupAction Name="GetCustomAppProperties.Redbooks_Search"/>

</ActionGroup><!-- all user action group which contains read and change actions --><ActionGroup Name="CustomAppProperties-CustomAppProperties-AllUsers-ActionGroup"

OwnerID="RootOrganization"><ActionGroupAction

Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.read"/>

368 WebSphere Commerce Line-of-Business Tooling Customization

Page 387: My Tutorial

<ActionGroupAction Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.change"/>

<ActionGroupAction Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.add"/>

<ActionGroupAction Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType.delete"/>

</ActionGroup>

<!-- defining resource groups --><!-- ================================================ -->

<!-- the customappproperties protectable proxy --> <ResourceGroup Name="CustomAppProperties-CustomAppProperties-ResourceGroup" OwnerID="RootOrganization"> <ResourceGroupResource Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesTypeResourceCategory"/> </ResourceGroup>

<!-- defining policy --><!-- ================================================ --><!-- the all users access profile access control policy --><Policy

Name="CustomAppProperties-CustomAppProperties-AllUsers-AccessProfilePolicy"OwnerID="RootOrganization"UserGroup="AllUsers"

ActionGroupName="CustomAppProperties-CustomAppProperties-AllUsers-AccessProfileActionGroup"

ResourceGroupName="AccessProfileResourceGroup"PolicyType="groupableStandard"

/><!-- all user creator access control policy --><Policy

Name="CustomAppProperties-CustomAppProperties-SiteAdministrators-CreatorPolicy"OwnerID="RootOrganization"UserGroup="SiteAdministrators"ActionGroupName="CustomAppProperties-CustomAppProperties-AllUsers-ActionGroup"ResourceGroupName="CustomAppProperties-CustomAppProperties-ResourceGroup"RelationName="creator"PolicyType="groupableStandard"

/>

Chapter 12. Custom Application Configuration Management tool 369

Page 388: My Tutorial

<!-- defining policy groups --><!-- ================================================ --><PolicyGroup Name="ManagementAndAdministrationPolicyGroup"

OwnerID="RootOrganization"><!-- all user access profile --><PolicyGroupPolicy

Name="CustomAppProperties-CustomAppProperties-AllUsers-AccessProfilePolicy" PolicyOwnerID="RootOrganization" />

<!-- all user creator policy --><PolicyGroupPolicy

Name="CustomAppProperties-CustomAppProperties-SiteAdministrators-CreatorPolicy" PolicyOwnerID="RootOrganization" />

</PolicyGroup></Policies>

e. Save the file.

4. Load the CustomAppProperties-access-control.xml file:

a. Open a command prompt. In Windows XP, click Start → Run.

b. Enter cmd.exe.

c. On the command prompt, type cd <WCDE_installdir>\bin to navigate to the <WCDE_installdir>/bin directory.

d. Use acpload.bat to import CustomAppProperties-access-control.xml into your WebSphere Commerce database. If you are using the Cloudscape database, ensure that no application has a connection to the WebSphere Commerce database, such as the WebSphere Commerce Test Server.

e. Enter acpload CustomAppProperties-access-control.xml.

f. Review the acpload utility log in the <WCDE_installdir>\logs\acpload.log file.

If you need to troubleshoot access control, review the article Debugging access control in WebSphere Commerce on IBM developerWorks® at:

http://www.ibm.com/developerworks/websphere/library/techarticles/0805_callaghan/0805_callaghan.html?ca=dnb-wce061908

The article does not cover access control in the BOD command framework especially, but it gives you advice on tracking problems with access control.

370 WebSphere Commerce Line-of-Business Tooling Customization

Page 389: My Tutorial

12.4.13 Implementing unit tests using the CustomAppProperties client library

Tests that are related to development assets are important to ensure quality and continuity on application refactoring. Unit tests are tests that validate that the units of source code are working correctly.

WebSphere Commerce services uses the widely used JUnit package to build and run unit tests. It is a simple Java testing framework with Eclipse integration. For more information about JUnit, refer to:

http://www.junit.org

The CustomAppProperties-UnitTests project contains the CustomAppPropertiesFacadeClientTest class, which consists of several pre-built test methods to test Get, Process, and Change commands. Following the general JUnit structure, these are JUnit methods:

� setUp()

Gets called before executing a test method.

� tearDown()

Gets called after executing a test method.

� test<Name_of_Test>()

JUnit framework executes all of these public test methods in the order that they appear. setUp() is called first, and tearDown() is called after the test method’s execution.

The generated methods are a good starting point to build your own tests, so take a moment to review the methods. However, because of the numerous updates we made to the CustomAppProperties service module in preceding steps, we will not update the existing methods; instead, we will implement our own unit tests from scratch. Figure 12-34 provides an overview of the implementation.

Figure 12-34 Implement unit tests using the CustomAppProperties client library

Before you use the test methods, first review the unit test project configuration.

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

CustomAppProperties-UnitTests CustomAppProperties-Client

JUnit test cases Client Library

Chapter 12. Custom Application Configuration Management tool 371

Page 390: My Tutorial

3. In the Project Explorer view, open the CustomAppProperties-UnitTests project.

4. Navigate to the src/config/com.ibm.commerce.foundation package, which holds the generic client library configuration.

5. Open wc-config-mapping-registry.xml

The unit test project uses the client library, and this file is part of the client library configuration.

The <_config:filemapping> element defines the name of the configuration file, which is wc-component-client.xml.

Review the information about deploying client libraries in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvdeployclientlibrary.htm

6. Navigate to the src/config/com.redbooks.commerce.customappproperties package, which holds the client library configuration that is specific to the CustomAppProperties service module.

7. Open wc-component-client.xml, which primarily defines the type and the target of the service invocation using the <_config:invocationbinding> element.

The unit tests use remote invocation that employs SOAP Web services over an HTTP transport channel.

The <_config:property name="url"...> element defines the Web service endpoint.

Note, that there are example files that contain configuration to access the service module by local and remote service invocation.

Detailed information about testing a WebSphere Commerce service is provided in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvtestcs.htm

Note: The URL points to http://localhost:81/... by default. If you run the unit test class, it will fail because WebSphere Commerce Test Server listens to port 80. Either, you have to change the value to http://localhost:80/..., or you must start the TCP/IP monitor listening on port 81 before.

372 WebSphere Commerce Line-of-Business Tooling Customization

Page 391: My Tutorial

Implementing utility methodsA number of utility methods encapsulate code that you can reuse for several test cases. The objective is to keep the test cases clean from code that deals with the service invocation, and to focus on building business-relevant test code.

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, open the CustomAppProperties-UnitTests project.

4. Create helper classes to support unit tests.

a. Right-click the src folder, and select New → Package.

b. In the Name field, type com.redbooks.commerce.util, and click Finish.

c. Right-click the com.redbooks.commerce.util package, and select New → Class.

d. In the Name field, type CustomAppPropertiesData, and click Finish.

e. Open CustomAppPropertiesData.java, and copy the content from Example 12-56 into the file.

This class encapsulates the test data that is used for a single test case and is provided for convenience only.

Example 12-56 CustomAppPropertiesData.java

package com.redbooks.commerce.customappproperties.facade.client;

import java.util.HashMap;import java.util.Map;

import com.redbooks.commerce.util.XpathExpressionHelper;

/** * Simple JavaBean to hold CustomAppProperties data */public class CustomAppPropertiesData {

/** * Refers to /CustomAppProperties/CustomAppPropertiesIdentifier/UniqueID * A value of -1 means 'not set' */private long uniqueID = -1;

/**

Chapter 12. Custom Application Configuration Management tool 373

Page 392: My Tutorial

* Refers to /CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier/Name

*/private String name;

/** * Refers to

/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier/Storeent_id */private int storeent_id;

/** * Refers to /CustomAppProperties/Value */private String value;

/** * Refers to /CustomAppProperties/Description */private String description;

/** * Refers to /CustomAppProperties/Category */private String category;

/** * Refers to /CustomAppProperties/ValueType */private String valueType;

/** * Refers to /CustomAppProperties[(search())] */private String searchExpression;

public String getSearchExpression() {return searchExpression;

}

public void setSearchExpression(String searchExpression) {this.searchExpression = searchExpression;

}

public String getCategory() {

374 WebSphere Commerce Line-of-Business Tooling Customization

Page 393: My Tutorial

return category;}

public void setCategory(String category) {this.category = category;

}

public String getDescription() {return description;

}

public void setDescription(String description) {this.description = description;

}

public String getName() {return name;

}

public void setName(String name) {this.name = name;

}

public int getStoreent_id() {return storeent_id;

}

public void setStoreent_id(int storeent_id) {this.storeent_id = storeent_id;

}

public long getUniqueID() {return uniqueID;

}

public void setUniqueID(long uniqueID) {this.uniqueID = uniqueID;

}

public String getValue() {return value;

}

public void setValue(String value) {this.value = value;

Chapter 12. Custom Application Configuration Management tool 375

Page 394: My Tutorial

}

public String getValueType() {return valueType;

}

public void setValueType(String valueType) {this.valueType = valueType;

}

/** * Returns the Bean as Map using field as key * String values will be enquoted. * @return Map The Bean */public Map getAsMap() {

Map theBean = new HashMap();if (name != null)

theBean.put("Name", XpathExpressionHelper.enquote(name));if (value != null)

theBean.put("Value", XpathExpressionHelper.enquote(value));if (category != null)

theBean.put("Category", XpathExpressionHelper.enquote(category));if (valueType != null)

theBean.put("ValueType", XpathExpressionHelper.enquote(valueType));if (description != null)

theBean.put("Description", XpathExpressionHelper.enquote(description));if (uniqueID != -1)

theBean.put("UniqueID", String.valueOf(uniqueID));theBean.put("Storeent_id", String.valueOf(storeent_id));if (searchExpression != null)

theBean.put(XpathExpressionHelper.PARAM_NAME_SEARCH, searchExpression);return theBean;

}}

f. Save the file (Ctrl+s).

g. Repeat steps b to e to create another class named “XpathExpressionHelper“.

h. Open XpathExpressionHelper.java, and copy the content from Example 12-57 on page 377 into the file.

376 WebSphere Commerce Line-of-Business Tooling Customization

Page 395: My Tutorial

The main task of the XpathExpressionHelper is to add parameter values to the XPath expression. It replaces:

• param= with param=value• search() with search(searchExpression)

Example 12-57 XpathExpressionHelper.java

package com.redbooks.commerce.util;

import java.text.MessageFormat;import java.util.Iterator;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;

import com.ibm.commerce.foundation.client.util.oagis.SelectionCriteriaHelper;

/** * Simple utility to set parameter values in a XPath expression */public class XpathExpressionHelper {

public static final String PARAM_BASE_PATTERN = "\\s*=";public static final String EQUAL_CHAR = "=";public static final String QUOTE_CHAR = "'";public static final String CURLY_BRACKET_OPEN = "{";public static final String CURLY_BRACKET_CLOSE = "}";public static final String SEARCH_PATTERN = "search\\(\\)";public static final String PARAM_NAME_SEARCH = "_SearchExpression_";public static final String SEARCH_REPLACEMENT_PATTERN = "search({0})";

/** * Adds values to parameters of a Xpath expression. Works on all occurences. * @param xpath The unresolved Xpath expression template * @param params A Map containing of parameter names (String) and parameter values

(String) * @return String The resolved Xpath Expression */public static String resolveXpathExpression(String xpath, Map params) {

Pattern pat;String replacementContent;String resolvedXpath = xpath;Iterator iter = params.keySet().iterator();while (iter.hasNext()) {

// Get the parameter name

Chapter 12. Custom Application Configuration Management tool 377

Page 396: My Tutorial

String paramName = (String) iter.next();// Compile the RegEx pattern to find parameters, depending on the parameterif (PARAM_NAME_SEARCH.equals(paramName)) {

pat = Pattern.compile(SEARCH_PATTERN);// Define the replacement, e.g.// 'search()' --> 'search(someField=1012)'Object[] searchExpression = { (String) params.get(paramName) };replacementContent = (new MessageFormat(SEARCH_REPLACEMENT_PATTERN))

.format(searchExpression);} else {

pat = Pattern.compile(paramName + PARAM_BASE_PATTERN);// Define the replacement, e.g.// 'ID=' --> 'ID=10001'replacementContent = paramName + EQUAL_CHAR + (String)

params.get(paramName);}// Apply RegEx pattern to all occurrencesMatcher m = pat.matcher(resolvedXpath);resolvedXpath = m.replaceAll(replacementContent);

}return resolvedXpath;

}

/** * Same as <code>resolveXpathExpression (String xpath, Map params)</code> * but builds complete Xpath including access profile * @param xpath The unresolved Xpath expression template * @param params A Map containing of parameter names (String) and parameter values

(String) * @param accessProfile The name of the access profile * @return String The resolved Xpath Expression */public static String resolveXpathExpression(String xpath, Map params, String

accessProfile) {StringBuffer xpathExpr = new StringBuffer();xpathExpr.append(CURLY_BRACKET_OPEN);xpathExpr.append(SelectionCriteriaHelper.STR_ACCESS_PROFILE_PARAMETER);xpathExpr.append(EQUAL_CHAR);xpathExpr.append(accessProfile);xpathExpr.append(CURLY_BRACKET_CLOSE);xpathExpr.append(resolveXpathExpression(xpath, params));return xpathExpr.toString();

}

/**

378 WebSphere Commerce Line-of-Business Tooling Customization

Page 397: My Tutorial

* Returns the paramter enquoted * @param arg The parameter to enquote * @return String The enquoted parameter */public static String enquote(String arg) {

return QUOTE_CHAR + arg + QUOTE_CHAR;}

}

i. Save the file (Ctrl+s).

Implementing test casesImplement five test cases to test create, read, update, and delete the CustomAppProperties nouns:

1. Navigate to src/com.redbooks.commerce.customappproperties.facade.client.

2. Open CustomAppPropertiesFacadeClientTest.java.

3. Provide a basic test case outline by replacing the content in the file with the content from Example 12-58.

Beside the default JUnit methods there is:

– The buildCustomAppPropertiesNoun() method to build a CustomAppProperties noun from test data

– The constructFacadeClient() method to encapsulate the construction of a new CustomAppPropertiesFacadeClient with a default BusinessContext

– An authorization resource that uses the WebSphere Commerce user name and password.

Example 12-58 Basic test case outline

package com.redbooks.commerce.customappproperties.facade.client;

/** * This class represents a set of test cases for testing the * CustomAppProperties facade client. */public class CustomAppPropertiesFacadeClientTest extends junit.framework.TestCase {

/** * The user id to associate with unit tests requiring * SiteAdministrator privileges */// TODO: modify the test username

Chapter 12. Custom Application Configuration Management tool 379

Page 398: My Tutorial

private static final String SITE_ADMIN_USER_ID = "wcsadmin";

/** * The password of the user id for these unit tests. */// TODO: modify the test passwordprivate static final String SITE_ADMIN_PASSWORD = "your_passwd";

/** * The reference to an existing store. */// TODO: modify the store referenceprivate static final int STOREENT_ID = 10101;

/** * The client to access the CustomAppProperties service */private CustomAppPropertiesFacadeClient iClient = null;

/** * Create an instance of the CustomAppProperties Facade Client test case. * @param method The test method to execute. */public CustomAppPropertiesFacadeClientTest(String method) {

super(method);}

/** * Set up any additional information required in order to run any test method. * As part of the setup, the client library will be instantiated for the test

case. * @exception A problem with the setup process. * @see TestCase#setUp() */protected void setUp() throws Exception {

super.setUp();}

/** * Remove any data or setting related to running any test method. * @exception A problem with the tear down process. * @see TestCase#tearDown() */protected void tearDown() throws Exception {

super.tearDown();

380 WebSphere Commerce Line-of-Business Tooling Customization

Page 399: My Tutorial

}

/** * Builds the CustomAppProperties noun from test data * @param testData The test data * @return CustomAppPropertiesType The created CustomAppProperties noun */private CustomAppPropertiesType buildCustomAppPropertiesNoun(

CustomAppPropertiesData testData) {// Create the nounCustomAppPropertiesType capNoun = CustomAppPropertiesFactory.eINSTANCE

.createCustomAppPropertiesType();

// Create CustomAppProperties identifier from test dataCustomAppPropertiesIdentifierType capID = CustomAppPropertiesFactory.eINSTANCE

.createCustomAppPropertiesIdentifierType();capNoun.setCustomAppPropertiesIdentifier(capID);

// Use either UniqueID if available or external identifier otherwiseif (testData.getUniqueID() != -1) {

// set UniqueID to nouncapID.setUniqueID(testData.getUniqueID());

} else {// set external identifier to nounCustomAppPropertiesExternalIdentifierType capExID =

CustomAppPropertiesFactory.eINSTANCE.createCustomAppPropertiesExternalIdentifierType();

capExID.setName(testData.getName());capExID.setStoreentId(testData.getStoreent_id());capID.setExternalIdentifier(capExID);

}

// Insert CustomAppProperties data from test datacapNoun.setCategory(testData.getCategory());capNoun.setDescription(testData.getDescription());capNoun.setValue(testData.getValue());capNoun.setValueType(ValueTypeEnum.get(testData.getValue()));return capNoun;

}

/** * Constructs a facade client using an empty BusinessContext and * and the WebSphere Commerce SampleCallbackHandler */private CustomAppPropertiesFacadeClient constructFacadeClient(String userId,

Chapter 12. Custom Application Configuration Management tool 381

Page 400: My Tutorial

String password) {// construct the callback handlerjavax.security.auth.callback.CallbackHandler callbackHandler = new

com.ibm.commerce.foundation.client.samples.security.auth.callback.SampleCallbackHandlerImpl(

userId, password);

// construct business contextcom.ibm.commerce.foundation.common.datatypes.BusinessContextType

businessContext = com.ibm.commerce.foundation.common.datatypes.CommerceFoundationFactory.eINSTANCE

.createBusinessContextType();

// construct the facade clientreturn new CustomAppPropertiesFacadeClient(businessContext, callbackHandler);

}}

a. Provide valid data for constants SITE_ADMIN_USER_ID, SITE_ADMIN_PASSWORD, and STOREENT_ID.

b. Save the file (Ctrl+s).

4. Add test cases for creating and deleting CustomAppProperties nouns:

a. In CustomAppPropertiesFacadeClientTest.java, add the methods in Example 12-59 that are located between the tearDown() and buildCustomAppPropertiesNoun() methods.

Review the processCustomAppProperties() method to see how to:

• Create a client • Construct the Process BOD command request • Create an action (create or delete) using an XPath expression• Build the CustomAppProperties noun• Send the request

Example 12-59 Test methods for creating and deleting CustomAppProperties nouns

/** * This method tests create CustomAppProperties by sending * the ProcessCustomAppProperties BOD with action add. */public void test_01_ProcessCustomAppPropertiesCreate() {

System.out.println("=== START test_01_ProcessCustomAppPropertiesCreate ===");

// define test inputs

382 WebSphere Commerce Line-of-Business Tooling Customization

Page 401: My Tutorial

CustomAppPropertiesData testData = new CustomAppPropertiesData();testData.setName("aCustomAppProperty");testData.setStoreent_id(STOREENT_ID);testData.setDescription("The description of aCustomAppProperty");testData.setCategory("aCategory");testData.setValue("The value of aCustomAppProperty");testData.setValueType("SimpleText");

// Create the BOD request for creating CustomAppPropertiesAcknowledgeCustomAppPropertiesType acknowledgeCAP =

createCustomAppProperties(testData);

// verify name in responseString resultName = ((CustomAppPropertiesType) acknowledgeCAP.getDataArea()

.getCustomAppProperties().get(0)).getCustomAppPropertiesIdentifier()

.getExternalIdentifier().getName();assertEquals("Test case failed because actual result '" + resultName

+ "' is not equals to the expceted result " + testData.getName(), resultName,

testData.getName());

// verify responseList errorList =

acknowledgeCAP.getDataArea().getAcknowledge().getResponseCriteria();if (errorList != null && errorList.size() != 0)

fail("Test Case failed because the response has error");System.out

.println("+++ Test Case test_01_ProcessCustomAppPropertiesCreate passed. +++");

}

/** * This method tests delete CustomAppProperties by sending * the ProcessCustomAppProperties BOD with action delete. * The noun is identified by external ID. */public void test_06_ProcessCustomAppPropertiesDelete_ExID() {

System.out.println("=== START test_06_ProcessCustomAppPropertiesDelete_ExID ===");

// define test inputsCustomAppPropertiesData testData = new CustomAppPropertiesData();testData.setName("aCustomAppProperty");testData.setStoreent_id(STOREENT_ID);

Chapter 12. Custom Application Configuration Management tool 383

Page 402: My Tutorial

// Create the BOD request for deleting CustomAppPropertiesAcknowledgeCustomAppPropertiesType acknowledgeCAP =

deleteCustomAppProperties(testData);

// verify responseList errorList =

acknowledgeCAP.getDataArea().getAcknowledge().getResponseCriteria();if (errorList != null && errorList.size() != 0)

fail("Test Case failed because the response has error");System.out

.println("+++ Test Case test_06_ProcessCustomAppPropertiesDelete_ExID passed. +++");

}

/** * Create a new CustomAppProperties noun * and returns an acknowledge BOD * @param testData the data to execute the test * @return AcknowledgeCustomAppPropertiesType the acknowledge BOD after creating a

CustomAppProperties noun */private AcknowledgeCustomAppPropertiesType createCustomAppProperties(

CustomAppPropertiesData testData) {return processCustomAppProperties(

testData,

CustomAppPropertiesFacadeConstants.PROCESS_VERB_ACTION_CREATE_CUSTOMAPPPROPERTIES);}

/** * Deletes a CustomAppProperties noun * and returns an acknowledge BOD * @param testData the data to execute the test * @return AcknowledgeCustomAppPropertiesType the acknowledge BOD after creating a

CustomAppProperties noun */private AcknowledgeCustomAppPropertiesType deleteCustomAppProperties(

CustomAppPropertiesData testData) {return processCustomAppProperties(

testData,

CustomAppPropertiesFacadeConstants.PROCESS_VERB_ACTION_DELETE_CUSTOMAPPPROPERTIES);}

/**

384 WebSphere Commerce Line-of-Business Tooling Customization

Page 403: My Tutorial

* Processes a CustomAppProperties noun * And returns an acknowledge BOD * @param testData the data to execute the test * @param argProcessVerb the action to process * @return AcknowledgeCustomAppPropertiesType the acknowledge BOD after creating a

CustomAppProperties noun */private AcknowledgeCustomAppPropertiesType processCustomAppProperties(

CustomAppPropertiesData testData, String argProcessVerb) {// Create service facade client// For Process BOD, you need to provide Site Admin credentialsCustomAppPropertiesFacadeClient iClient =

constructFacadeClient(SITE_ADMIN_USER_ID,SITE_ADMIN_PASSWORD);

// Create Process BODProcessCustomAppPropertiesType processCAP =

CustomAppPropertiesFactory.eINSTANCE.createProcessCustomAppPropertiesType();

processCAP.setDataArea(CustomAppPropertiesFactory.eINSTANCE.createProcessCustomAppPropertiesDataAreaType());

// Create the nounCustomAppPropertiesType capNoun = buildCustomAppPropertiesNoun(testData);

// Create the action using a pre-defined XPath expressionList actions = new ArrayList();actions.add(AbstractBusinessObjectDocumentFacadeClient.createActionExpression(

argProcessVerb, SelectionCriteriaHelper.STR_XPATH_LANG,CustomAppPropertiesFacadeConstants.XPATH_EMPTY_CUSTOMAPPPROPERTIES));

ProcessType processVerb = AbstractBusinessObjectDocumentFacadeClient.createProcessVerb(actions);

processCAP.getDataArea().setProcess(processVerb);

// Add noun into the BODprocessCAP.getDataArea().getCustomAppProperties().add(capNoun);

// logging the request BODSystem.out.println(" The request BOD is sent: ");System.out.println(SDOHelper.toString((DataObject) processCAP));

// Send the BOD requestAcknowledgeCustomAppPropertiesType acknowledgeCAP = iClient

.processCustomAppProperties(processCAP);

Chapter 12. Custom Application Configuration Management tool 385

Page 404: My Tutorial

// logging the response BODSystem.out.println(" The response BOD is returned: ");System.out.println(SDOHelper.toString((DataObject) acknowledgeCAP));

return acknowledgeCAP;}

5. Add test cases for updating the CustomAppProperties nouns:

a. In CustomAppPropertiesFacadeClientTest.java, add:

• The method test_04_ChangeCustomAppProperties(), which is provided in Example 12-60 between the test_01_ProcessCustomAppPropertiesCreate() and test_05_ProcessCustomAppPropertiesDelete_ExID() methods.

• The updateCustomAppProperties() method, which is also provided in Example 12-60 after the processCustomAppProperties() method.

Review the updateCustomAppProperties() method to see how to:

• Create a client• Construct the Change BOD command request • Create an action using an XPath expression• Build the CustomAppProperties noun• Send the request

Example 12-60 Test methods for updating the CustomAppProperties nouns

/** * This method tests update CustomAppProperties by sending * the ChangeCustomAppProperties BOD. * First, the UniqueID will be retrieved. Then the description will be updated. */public void test_05_ChangeCustomAppProperties() {

System.out.println("=== START test_05_ChangeCustomAppProperties ===");

// define input to retrieve UniqueIDCustomAppPropertiesData retrieveData = new CustomAppPropertiesData();retrieveData.setName("aCustomAppProperty");retrieveData.setStoreent_id(STOREENT_ID);

// Create the BOD request for fetching CustomAppPropertiesShowCustomAppPropertiesType showCAP = getCustomAppProperties(retrieveData,

CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ALL_INFORMATION,CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID);

// Read UniqueID from response

386 WebSphere Commerce Line-of-Business Tooling Customization

Page 405: My Tutorial

long uniqueId = ((CustomAppPropertiesType) showCAP.getDataArea().getCustomAppProperties().get(0)).getCustomAppPropertiesIdentifier().getUniqueID();

// define test inputsCustomAppPropertiesData testData = new CustomAppPropertiesData();testData.setUniqueID(uniqueId);testData.setDescription("The UPDATED description of aCustomAppProperty");

// Create the BOD request for creating CustomAppPropertiesRespondCustomAppPropertiesType respondCAP =

updateCustomAppProperties(testData);

// verify description has changed in responseString resultDesc = ((CustomAppPropertiesType) respondCAP.getDataArea()

.getCustomAppProperties().get(0)).getDescription();assertEquals("Test case failed because actual result '" + resultDesc

+ "' is not equals to the expceted result " + testData.getDescription(),resultDesc, testData.getDescription());

// verify responseList errorList = respondCAP.getDataArea().getRespond().getResponseCriteria();if (errorList != null && errorList.size() != 0)

fail("Test Case failed because the response has error");System.out

.println("+++ Test Case test_05_ChangeCustomAppProperties passed. +++");}

/** * Updates a CustomAppProperties noun * and returns an respond BOD. * Uses Change BOD command. * @param testData the data to execute the test * @return AcknowledgeCustomAppPropertiesType the acknowledge BOD after creating a

CustomAppProperties noun */private RespondCustomAppPropertiesType updateCustomAppProperties(

CustomAppPropertiesData testData) {// Create service facade client// For Change BOD, you need to provide Site Admin credentialsCustomAppPropertiesFacadeClient iClient =

constructFacadeClient(SITE_ADMIN_USER_ID,SITE_ADMIN_PASSWORD);

// Create Change BOD

Chapter 12. Custom Application Configuration Management tool 387

Page 406: My Tutorial

ChangeCustomAppPropertiesType changeCAP = CustomAppPropertiesFactory.eINSTANCE.createChangeCustomAppPropertiesType();

changeCAP.setDataArea(CustomAppPropertiesFactory.eINSTANCE.createChangeCustomAppPropertiesDataAreaType());

// Create the nounCustomAppPropertiesType capNoun = buildCustomAppPropertiesNoun(testData);

// Create the action using a pre-defined XPath expressionList actions = new ArrayList();actions.add(AbstractBusinessObjectDocumentFacadeClient.createActionExpression(

AbstractBusinessObjectDocumentFacadeClient.CHANGE_VERB_ACTION_CHANGE,SelectionCriteriaHelper.STR_XPATH_LANG,CustomAppPropertiesFacadeConstants.XPATH_EMPTY_CUSTOMAPPPROPERTIES));

com.ibm.commerce.oagis9.datatypes.ChangeType changeVerb = AbstractBusinessObjectDocumentFacadeClient

.createChangeVerb(actions);changeCAP.getDataArea().setChange(changeVerb);

// Add noun into the BODchangeCAP.getDataArea().getCustomAppProperties().add(capNoun);

// logging the request BODSystem.out.println(" The request BOD is sent: ");System.out.println(SDOHelper.toString((DataObject) changeCAP));

// Send the BOD requestRespondCustomAppPropertiesType respondCAP = iClient

.changeCustomAppProperties(changeCAP);

// logging the response BODSystem.out.println(" The response BOD is returned: ");System.out.println(SDOHelper.toString((DataObject) respondCAP));

return respondCAP;}

6. Add test cases for reading CustomAppProperties nouns:

a. In CustomAppPropertiesFacadeClientTest.java, add:

• The methods test_02_GetCustomAppPropertiesByExtId(), test_03_GetCustomAppPropertiesByCatgByStore(), and test_04_GetCustomAppPropertiesBySearchByStore(), as provided in Example 12-61 on page 389 between the following methods:

388 WebSphere Commerce Line-of-Business Tooling Customization

Page 407: My Tutorial

test_01_ProcessCustomAppPropertiesCreate() and test_05_ChangeCustomAppProperties().

• Add the getCustomAppProperties() method, which is in Example 12-61 before the buildCustomAppPropertiesNoun() method.

Review the getCustomAppProperties() method to see how to:

• Create a client • Construct the Get BOD command request using an XPath expression• Build the CustomAppProperties noun• Send the request

You do not need to define an action because the action of a Get command is always Fetch.

Example 12-61 Test methods for reading CustomAppProperties nouns

/** * This method tests fetching CustomAppProperties by sending * the GetCustomAppProperties BOD command. */public void test_02_GetCustomAppPropertiesByExtId() {

System.out.println("=== START test_02_GetCustomAppPropertiesByExtId ===");

// define test inputsCustomAppPropertiesData testData = new CustomAppPropertiesData();testData.setName("aCustomAppProperty");testData.setStoreent_id(STOREENT_ID);

// Create the BOD request for fetching CustomAppPropertiesShowCustomAppPropertiesType showCAP = getCustomAppProperties(testData,

CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ALL_INFORMATION,CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID);

// verify responseList errorList = showCAP.getDataArea().getShow().getResponseCriteria();if (errorList != null && errorList.size() != 0)

fail("Test Case failed because the response has error");System.out

.println("+++ Test Case test_02_GetCustomAppPropertiesByExtId passed. +++");

}

/** * This method tests fetching CustomAppProperties by sending * the GetCustomAppProperties BOD command. */

Chapter 12. Custom Application Configuration Management tool 389

Page 408: My Tutorial

public void test_03_GetCustomAppPropertiesByCatgByStore() {System.out

.println("=== START test_03_GetCustomAppPropertiesByCatgByStore ===");

// define test inputsCustomAppPropertiesData testData = new CustomAppPropertiesData();testData.setCategory("aCategory");testData.setStoreent_id(STOREENT_ID);

// Create the BOD request for fetching CustomAppPropertiesShowCustomAppPropertiesType showCAP = getCustomAppProperties(

testData,CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ALL_INFORMATION,

CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_BY_CATEGORY_BY_STOREENT_ID);

// verify responseList errorList = showCAP.getDataArea().getShow().getResponseCriteria();if (errorList != null && errorList.size() != 0)

fail("Test Case failed because the response has error");System.out

.println("+++ Test Case test_03_GetCustomAppPropertiesByCatgByStore passed. +++");

}

/** * This method tests fetching CustomAppProperties by sending * the GetCustomAppProperties BOD command. */public void test_04_GetCustomAppPropertiesBySearchByStore() {

System.out.println("=== START test_04_GetCustomAppPropertiesBySearchByStore ===");

// define test inputsCustomAppPropertiesData testData = new CustomAppPropertiesData();testData.setStoreent_id(STOREENT_ID);testData.setSearchExpression("contains(NAME,'tomappprop') and

CATEGORY='aCategory'");

// Create the BOD request for fetching CustomAppPropertiesShowCustomAppPropertiesType showCAP = getCustomAppProperties(

testData,CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_SEARCH,

390 WebSphere Commerce Line-of-Business Tooling Customization

Page 409: My Tutorial

CustomAppPropertiesFacadeConstants.XPATH_PATTERN_CUSTOMAPPPROPERTIES_SEARCH_BY_STOREENT_ID);

// verify responseList errorList = showCAP.getDataArea().getShow().getResponseCriteria();if (errorList != null && errorList.size() != 0)

fail("Test Case failed because the response has error");System.out

.println("+++ Test Case test_04_GetCustomAppPropertiesBySearchByStore passed. +++");

}

/** * * @param testData the data to execute the test * @param accessProfile the access profile * @param xpath the XPath expression * @return ShowCustomAppPropertiesType The result of the data fetch */private ShowCustomAppPropertiesType getCustomAppProperties(

CustomAppPropertiesData testData, String accessProfile, String xpath) {// Create service facade client// For Get BOD, you need no special credentialsCustomAppPropertiesFacadeClient iClient = constructFacadeClient("", "");

// build fully resolved XPath expressionString xpathResolved = XpathExpressionHelper.resolveXpathExpression(xpath,

testData.getAsMap(), accessProfile);

// construct the verbGetCustomAppPropertiesType getCAP = CustomAppPropertiesFactory.eINSTANCE

.createGetCustomAppPropertiesType();getCAP.setDataArea(CustomAppPropertiesFactory.eINSTANCE

.createGetCustomAppPropertiesDataAreaType());getCAP.getDataArea().setGet(

AbstractBusinessObjectDocumentFacadeClient.createGetVerb(SelectionCriteriaHelper.STR_XPATH_LANG, xpathResolved));

// logging the request BODSystem.out.println(" The request BOD is sent: ");System.out.println(SDOHelper.toString((DataObject) getCAP));

// send the "get" request and get the "show" response

Chapter 12. Custom Application Configuration Management tool 391

Page 410: My Tutorial

ShowCustomAppPropertiesType showCustomAppProperties = iClient.getCustomAppProperties(getCAP);

// logging the response BODSystem.out.println(" The response BOD is returned: ");System.out.println(SDOHelper.toString((DataObject) showCustomAppProperties));

return showCustomAppProperties;}

b. Save the file (Ctrl+s).

7. Organize the imports for the CustomAppProperties-UnitTests project:

a. Close all open Java files from the CustomAppProperties-Server project.

a. Open the Java perspective in WebSphere Commerce Developer.

b. Right-click the CustomAppProperties-UnitTests\src folder, and select Source.

c. Select Organize Imports.

8. Ensure that there are no remaining compilation errors.

12.4.14 Deploying to the WebSphere Commerce server

Before you can use the CustomAppProperties service, you must deploy it to the server. To deploy the CustomAppProperties service to the server:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, expand WC, and double-click Deployment Descriptor.

4. Select the Module tab, and click Add, select the CustomAppProperties-Server, and click Finish.

5. Under Modules, click Add, select the CustomAppPropertiesHTTPInterface, and click Finish.

6. Refresh the context root for CustomAppPropertiesHTTPInterface by selecting the module in the Modules display, and clicking Refresh. The context root should now change to /webapp/wcs/component/customappproperties.

7. Under Project Utility Jars, click Add, select CustomAppProperties-Client, click Finish.

8. Repeat these steps for CustomAppProperties-DataObjects.

392 WebSphere Commerce Line-of-Business Tooling Customization

Page 411: My Tutorial

9. Start the WebSphere Commerce Test Server by going to the Server view, right-clicking the WebSphere Commerce Test Server, and selecting Start.

10.If the WebSphere Commerce project is not already published to the WebSphere Commerce Test Server, publish the WebSphere Commerce project:

a. From the Server view, right-click the WebSphere Commerce Test Server, and select Add and Remove Projects.

b. Select the WC project.

c. Click Add. Click Finish.

11.If the WC project is already published, right-click the WebSphere Commerce Test Server, and select Publish.

You will perform the unit tests within 12.6.1, “Testing the CustomAppProperties service using unit tests” on page 411.

12.5 Customizing Management Center Web application

The customization steps employs some of the assets that the generation of the CustomAppProperties service module created; therefore, you must complete the steps in 12.4, “Customizing the WebSphere Commerce services” on page 280 before you customize the Management Center Web application.

The Management Center Web application is a Struts Web application that facilitates communication between the Management Center and WebSphere Commerce services.

The Management Center sends URL requests and receives XML responses, while the WebSphere Commerce server uses BOD messages to retrieve nouns and to invoke business logic. The Management Center Web application acts as a mediator between the Management Center and WebSphere Commerce services by converting requests and responses into the appropriate type of data.

For more information about the Management Center Web application, refer to 2.2.3, “The Mediation layer” or visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctfmancenter.htm

Chapter 12. Custom Application Configuration Management tool 393

Page 412: My Tutorial

12.5.1 Configuring the client-service-mapping

The Management Center Web applications use an XML file to configure:

� The nouns and noun parts that are used in a specific Management Center tool

� Mapping of URL parameters to noun fields

� Locale-specific placement of error messages

To create a client-object configuration for the Custom Application Configuration Management tool:

1. Using Windows Explorer, copy the folder <workspace_dir>/CustomAppProperties-Client/TODO-MoveItToWEBProjectFolder/config to the <workspace_dir>/LOBTools\WebContent\WEB-INF directory.

2. Open WebSphere Commerce Developer.

3. Open the J2EE perspective.

4. In the Project Explorer view, expand the LOBTools project.

5. Navigate to the following folder: WebContent\WEB-INF\config\com.redbooks.commerce.customappproperties

6. Open the wc-customappproperties-clientobjects.xml file, and review the pre-built file:

– The <_config:NounDefinitions> element has a <_config:Noun/> sub-element that defines the noun. It is set to CustomAppProperties and does not need to be changed.

Because we are not using noun parts in the CustomAppProperties service, no <_config:NounElement> sub-element under <_config:Noun/> is necessary.

– The <_config:URLDefinitions> element contains a <_config:URLParameterGroup> sub-element that refers to the <_config:Noun/> definition through its noun attribute.

Every <_config:URLParameter> sub-element that is under the <_config:URLParameterGroup> sub-element defines the mapping of a URL parameter to a noun element using an XPath notation.

Because the pre-built file does not reflect our updated noun, you will update the configuration in the next step.

– The <_config:ErrorDefinitions> element defines resource bundles for locale-specific error messages that are used for server-side validation.

394 WebSphere Commerce Line-of-Business Tooling Customization

Page 413: My Tutorial

Inside the <_config:ErrorGroup> sub-element, each <_config:ReasonCodeParameterAssociation> sub-element defines a message key for a specific error reason code.

In this scenario we do not extend the error messages.

7. Update the wc-customappproperties-clientobjects.xml file:

a. Remove all existing <_config:URLParameter> sub-elements.

b. For every noun element in the CustomAppProperties noun, add an appropriate <_config:URLParameter> sub-element within the <_config:URLParameterGroup> element:

i. Add an attribute “key” with value “true” to the noun element of the UniqueID to flag the primary key.

ii. Add an attribute “return” with value “true” to the noun elements of the UniqueID, Storeent_id, and Name to include their values in the response message to the Management Center client application.

c. Ensure that your file now has the same content that is in Example 12-62.

Example 12-62 wc-customappproperties-clientobjects.xml file

<?xml version="1.0" encoding="UTF-8"?><_config:URLtoOAGIS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.ibm.com/xmlns/prod/commerce/foundation/config ../xsd/url-to-oagis.xsd "

xmlns:_config="http://www.ibm.com/xmlns/prod/commerce/foundation/config"><_config:NounDefinitions>

<_config:Noun name="CustomAppProperties" /></_config:NounDefinitions><_config:URLDefinitions>

<_config:URLParameterGroup name="CustomAppProperties"noun="CustomAppProperties"><_config:URLParameter name="configId"

nounElement="/CustomAppPropertiesIdentifier/UniqueID" key="true" return="true" />

<_config:URLParameter name="key"nounElement="/CustomAppPropertiesIdentifier/ExternalIdentifier/Name"return="true" />

<_config:URLParameter name="storeId"

nounElement="/CustomAppPropertiesIdentifier/ExternalIdentifier/Storeent_id"return="true" />

<_config:URLParameter name="value" nounElement="/Value" /><_config:URLParameter name="type" nounElement="/ValueType"

type="ValueTypeEnum" /><_config:URLParameter name="version" nounElement="/Version" />

Chapter 12. Custom Application Configuration Management tool 395

Page 414: My Tutorial

<_config:URLParameter name="category" nounElement="/Category" /><_config:URLParameter name="description" nounElement="/Description" />

</_config:URLParameterGroup></_config:URLDefinitions><_config:ErrorDefinitions

primaryResourceBundle="com.redbooks.commerce.customappproperties.client.lobtools.properties.CustomAppPropertiesLOBErrorMessages"

alternateResourceBundle="extensions.com.redbooks.commerce.customappproperties.client.lobtools.properties.CustomAppPropertiesLOBErrorMessages">

<_config:ErrorGroup name="CustomAppProperties"><_config:ReasonCodeParameterAssociation

reasonCode="_APP_CUSTOMAPPPROPERTIES_CUSTOMAPPPROPERTIES_NAME_ALREADY_EXISTS"parameterName="name" />

<_config:ReasonCodeParameterAssociationreasonCode="_APP_CUSTOMAPPPROPERTIES_CUSTOMAPPPROPERTIES_NAME_EMPTY"parameterName="name" />

</_config:ErrorGroup></_config:ErrorDefinitions>

</_config:URLtoOAGIS>

d. Save the file (Ctrl+S).

12.5.2 Configuring the client-service-mapping for Get commands

The Management Center Web applications use the XML file get-data-config.xml to define:

� The Java interfaces to the logical SDOs

� The Java interfaces to the client facades to interact with the WebSphere Commerce services

� A list of XPath expression templates that the Management Center client application uses.

To configure the client-service-mapping:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, expand the LOBTools project.

4. Navigate to the following folder: WebContent\WEB-INF\config\com.redbooks.commerce.customappproperties

396 WebSphere Commerce Line-of-Business Tooling Customization

Page 415: My Tutorial

5. Open the get-data-config.xml file, and review the pre-built file:

– The <data-type> element defines a Java interface to the logical SDO. This setting is correct; therefore, you do not change it.

– The <client-facade> element defines a Java interface to the client facade code. This setting is correct; therefore, you do not change it.

– The <expression-builder> element defines an XPath expression template, along with an access profile and the data type of the returning nouns, which is the CustomAppProperties noun that is defined in the <data-type> element before.

The settings do not reflect the actual needs, so you will provide your own expression templates in the next step.

6. Update the get-data-config.xml file:

a. Remove the existing <expression-builder> element.

b. Add <expression-builder> elements for these expression templates:

• {_wcf.ap=$accessProfile$}/CustomAppProperties[(Category='$category$') and CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=$storeent_id$)]]] with access profile “Redbooks_All” and name “findCustomAppPropertiesByCategoryAndStoreent_id”

• {_wcf.ap=$accessProfile$}/CustomAppProperties[CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=$storeent_id$)]] and search(contains(NAME,'$name$') or contains(VALUE,'$value$') or contains(DESCRIPTION,'$description$'))] with access profile “Redbooks_Search” and name “findCustomAppPropertiesByStoreent_idAndSearchTerm”

• {_wcf.ap=$accessProfile$}/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[(Storeent_id=$storeent_id$)] with access profile “Redbooks_Category” and name “findCustomAppPropertiesCategoriesByStoreent”

Note: You must not leave any white space characters between <expression-builder> tags and the expression templates. The open tag, expression template, and closing tag must be on one line:

<expression-builder>expression_template</expression-builder>

Blanks, tabs, new line characters, and so on lead to a non-working configuration.

Chapter 12. Custom Application Configuration Management tool 397

Page 416: My Tutorial

The expression templates must match any of the query template file definitions of the wc-query-CustomAppProperties-get.tpl file. Refer back to “Defining the wc-query-CustomAppProperties-get.tpl query template” on page 347.

The access profiles are specified as <param> sub-elements. They are referenced in the expression template using the notation of $param$. The other parameters are set by URL requests. The parameter names must match the definition from the wc-customappproperties-clientobjects.xml file.

The parameter names that are used in the search() expression, such as NAME or VALUE, must match the definition that is stored in the wc-business-object-mediator.xml file. Refer back to “Updating the CustomAppProperties service configuration” on page 355 for more information.

c. Ensure that your file now has the same content that is in Example 12-63.

Example 12-63 get-data-config.xml file

<?xml version="1.0" encoding="UTF-8"?><_config:get-data-config

xmlns:_config="http://www.ibm.com/xmlns/prod/commerce/foundation/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.ibm.com/xmlns/prod/commerce/foundation/config

../../xsd/get-data-config.xsd "><data-type>

<name>CustomAppProperties</name>

<type>com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType</type>

</data-type><client-facade>

<data-type-name>CustomAppProperties</data-type-name>

<class>com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFacadeClient</class>

<method>getCustomAppProperties</method></client-facade><expression-builder>

<name>findCustomAppPropertiesByCategoryAndStoreent_id</name><data-type-name>CustomAppProperties</data-type-name>

<expression-template>{_wcf.ap=$accessProfile$}/CustomAppProperties[(Category='$category$') and

398 WebSphere Commerce Line-of-Business Tooling Customization

Page 417: My Tutorial

CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=$storeent_id$)]]]</expression-template>

<param><name>accessProfile</name><value>Redbooks_All</value>

</param></expression-builder><expression-builder>

<name>findCustomAppPropertiesByStoreent_idAndSearchTerm</name><data-type-name>CustomAppProperties</data-type-name>

<expression-template>{_wcf.ap=$accessProfile$}/CustomAppProperties[CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=$storeent_id$)]] and search(contains(NAME,'$name$') or contains(VALUE,'$value$') or contains(DESCRIPTION,'$description$'))]</expression-template>

<param><name>accessProfile</name><value>Redbooks_Search</value>

</param></expression-builder><expression-builder>

<name>findCustomAppPropertiesCategoriesByStoreent</name><data-type-name>CustomAppProperties</data-type-name>

<expression-template>{_wcf.ap=$accessProfile$}/CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier[(Storeent_id=$storeent_id$)]</expression-template>

<param><name>accessProfile</name><value>Redbooks_Category</value>

</param></expression-builder>

</_config:get-data-config>

d. Save the file (Ctrl+S).

12.5.3 Configuring views and commands

According to the WebSphere Commerce Struts framework, you must use a Struts configuration file to define the views and commands.

To learn how to define and configure WebSphere Commerce views and commands, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/tasks/tsdstrutsconfig.htm

Chapter 12. Custom Application Configuration Management tool 399

Page 418: My Tutorial

For extensions to the Management Center Web application, you must update the struts-extension.xml file:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, expand the LOBTools project.

4. Navigate to the WebContent\WEB-INF\ folder.

5. Open the struts-extension.xml file, which also opens the Struts Configuration File editor.

6. In the Struts Configuration File editor, on the editor’s bottom line, select the Source tab to work with the XML document source.

If this scenario is your only customization to the Management Center Web application, this file only contains empty base elements, such as

– <data-sources>– <form-beans>– <global-exceptions>– <global-forwards>– <action-mappings>

7. Update the struts-extension.xml file:

a. Within the <action-mappings> element, add <action> elements to map the Management Center client URLs to action classes and response JSPs.

Use these actions to invoke Get commands:

• /GetConfigCategories: A service call to get a list of configuration setting categories of the current store

• /GetConfigCategoryChildren: A service call to get a list of configuration settings of the queried category and the current store

• /FindConfigProperties: A service call to get a list of configuration settings of the current store, according to the search term

Use these actions to invoke Process commands:

• CreateCustomAppProperties: A service call to create a new configuration setting and to store it in the database

• DeleteCustomAppProperties: A service call to delete an existing configuration setting and to remove it from the database

Use this action to invoke Change commands:

• UpdateCustomAppProperties: A service call to update an existing configuration setting and to update it in the database

400 WebSphere Commerce Line-of-Business Tooling Customization

Page 419: My Tutorial

b. Ensure that the <action-mappings> element contains at least the content that is in Example 12-64.

Example 12-64 Struts configuration file, <action-mappings> element

<action-mappings><action path="/GetConfigCategories"

forward="/jsp/redbooks/config/GetConfigCategories.jsp" /><action path="/GetConfigCategoryChildren"

forward="/jsp/redbooks/config/GetConfigCategoryChildren.jsp" /><action path="/FindConfigProperties"

forward="/jsp/redbooks/config/FindConfigProperties.jsp" /><action path="/CreateCustomAppProperties" parameter="CustomAppProperties"

type="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentAction"

className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentActionMapping">

<set-property property="contextParameters" value="storeId" /><set-property property="verb" value="Process" /><set-property property="documentRootFactory"

value="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesFactory" />

<set-property property="clientLibrary" value="com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFacadeClient" />

<set-property property="clientLibraryMethod" value="processCustomAppProperties" />

<set-property property="actionCode" value="Create" /><forward name="success"

path="/jsp/redbooks/config/RespondProcessCustomAppProperties.jsp" /></action><action path="/UpdateCustomAppProperties" parameter="CustomAppProperties"

type="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentAction"

className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentActionMapping">

<set-property property="contextParameters" value="storeId" /><set-property property="verb" value="Change" /><set-property property="documentRootFactory"

value="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesFactory" />

Chapter 12. Custom Application Configuration Management tool 401

Page 420: My Tutorial

<set-property property="clientLibrary" value="com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFacadeClient" />

<set-property property="clientLibraryMethod" value="changeCustomAppProperties" />

<set-property property="actionCode" value="Change" /><forward name="success"

path="/jsp/redbooks/config/RespondChangeCustomAppProperties.jsp" /></action><action path="/DeleteCustomAppProperties" parameter="CustomAppProperties"

type="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentAction"

className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentActionMapping">

<set-property property="contextParameters" value="storeId" /><set-property property="verb" value="Process" /><set-property property="documentRootFactory"

value="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesFactory" />

<set-property property="clientLibrary" value="com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFacadeClient" />

<set-property property="clientLibraryMethod" value="processCustomAppProperties" />

<set-property property="actionCode" value="Delete" /><forward name="success"

path="/jsp/redbooks/config/RespondProcessCustomAppProperties.jsp" /></action>

</action-mappings>

c. Review Example 12-64 on page 401. The action mappings for Process and Change commands need a number of additional property settings:

• contextParameters

A comma separated list of the URL parameters that represent information that is placed in the business context area of the request.

Unless the colon override is specified, the name of the context parameter is the URL parameter, for example, if masterCatalogId:catatlogId is specified, the URL parameter value of masterCatalogId is used, but the context parameter name is catalog. If storeId is specified, the URL parameter and context name is storeId.

This setting is optional. In our scenario, we only use storeId without parameter name mapping.

402 WebSphere Commerce Line-of-Business Tooling Customization

Page 421: My Tutorial

• documentRootFactory

The factory that is used to create the BOD object.

In our scenario, we use the generated class com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesFactory from the CustomAppProperties-DataObjects project.

• verb

The verb of the BOD documentRootFactory.

In our scenario, the supported verbs are Process and Change.

• clientLibrary

The class name of the client library to invoke.

In our scenario, we use the generated class com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFacadeClient from the CustomAppProperties-Client project.

• clientLibraryMethod

The method to invoke on the client library to initiate the service request.

In our scenario, we use the generated methods changeCustomAppProperties() and processCustomAppProperties().

• actionCode

The actionCode of the request. If this is not specified, the URL request must specify the actionCode as a URL parameter.

In our scenario, we use the pre-defined action codes Create, Change, and Delete.

• defaultParameters

A list of parameters in query string format.

This setting is optional. In our scenario, we do not use default parameters.

d. Create a <plug-in> element to announce the client-service-mapping file for the Custom Application Configuration Management tool. In our scenario, we use the file wc-customappproperties-clientobjects.xml in the directory /WEB-INF/config/com.redbooks.commerce.customappproperties.

e. Ensure that the <plug-in> element contains the same content that is in Example 12-65 on page 404.

Chapter 12. Custom Application Configuration Management tool 403

Page 422: My Tutorial

Example 12-65 Struts configuration file, <plug-in> element

<plug-in

className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjectDocumentPlugInImpl">

<set-property property="config"

value="/WEB-INF/config/com.redbooks.commerce.customappproperties/wc-customappproperties-clientobjects.xml" /></plug-in>

12.5.4 Implementing object mapping JSPs for Get commands

When WebSphere Commerce server responds to a Management Center client application Get request, the Management Center Web application transforms nouns into the XML representation that the expects. A JSP file is called on the appropriate Struts action to transform nouns into XML format.

WebSphere Commerce uses a common JSP structure to build the XML response:

� One controller JSP

This JSP creates, sends, and receives the BODs from the WebSphere Commerce server and includes serialization JSP fragments to build the XML response.

� One or more serialization JSP fragments

These JSP fragments create the XML output that is sent back to the Management Center client application and considers the XML format that the Management Center client application expects.

To learn more about Retrieving Management Center objects by transforming Nouns into XML, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/refs/rtfsimpleobject.htm

Add controller JSPs and serialization JSP fragments for the actions /GetConfigCategories, /GetConfigCategoryChildren, and /FindConfigProperties:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, expand the LOBTools project.

4. Navigate to the WebContent\jsp\ folder.

404 WebSphere Commerce Line-of-Business Tooling Customization

Page 423: My Tutorial

5. Create folders for the Custom Application Configuration Management tool JSPs:

a. Right-click the jsp folder, and select New → Folder.b. In the Folder name field, type redbooks. Click Finish.c. Right-click the redbooks folder, and select New → Folder.d. In the Folder name field, type config. Click Finish.e. Right-click the config folder, and select New → Folder.f. In the Folder name field, type serialize. Click Finish.

6. Create JSP files:

a. Right-click the config folder, and select New → JSP file.

b. In the File Name field, type GetConfigCategories.jsp. Click Finish.

c. Repeat steps a and b to create the JSP files GetConfigCategoryChildren.jsp and FindConfigProperties.jsp.

d. Right-click the serialize folder, select New → Other.

e. From the New wizard, select Simple → File. Click Next.

f. In the File name field, type SerializeCustomAppProperty.jspf. Click Finish.

g. Repeat steps d and f to create the serialization JSP fragments: SerializeCustomAppPropCategory.jspf and SerializeCustomAppPropertyForSearch.jspf.

7. Implement the /GetConfigCategories action:

a. Open the GetConfigCategories.jsp file.

b. Replace the file’s content completely with the content in Example 12-66.

The expressionBuilder attribute of the <wcf:getData> tag refers to the <expression-builder> element in the CustomAppProperties component get-data-config.xml file, using the “storeent_id” parameter from the request parameter “storeId”.

Example 12-66 GetConfigCategories.jsp file

<?xml version="1.0" encoding="UTF-8"?><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><%@ taglib uri="http://commerce.ibm.com/foundation" prefix="wcf"%><%

// Use the get-data tag to invoke the expression which will find // CustomAppProperties by storeId.

%><objects><wcf:getData

Chapter 12. Custom Application Configuration Management tool 405

Page 424: My Tutorial

type="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType[]"

var="customAppPropCategories" expressionBuilder="findCustomAppPropertiesCategoriesByStoreent"

varShowVerb="showVerb" ><wcf:param name="storeent_id" value="${param.storeId}" />

</wcf:getData><c:set var="prevCategory" value="" /><c:if test="${!(empty customAppPropCategories)}">

<c:forEach var="customAppPropCategory" items="${customAppPropCategories}"><%

// For each returned customAppProperties, convert it into the XML// representation Management Center expects. This is done// by calling a common serialization JSP fragment that is// used by all URLs that is returning the Management Center// version of the CustomAppProperties noun.

%><%

// Because we only want to read the list of distinct categories,// we skip every record that has the same category as the previous ones.// The list of customAppProperties is sorted by XAPPPROPS.CATEGORY for // that reason.

%> <c:if test="${customAppPropCategory.category != prevCategory}">

<jsp:directive.include file="serialize/SerializeCustomAppPropCategory.jspf" />

<c:set var="prevCategory" value="${customAppPropCategory.category}"/> </c:if>

</c:forEach></c:if></objects>

c. Open the SerializeCustomAppPropCategory.jspf file.

d. Replace the file’s content completely with the content in Example 12-67.

Example 12-67 SerializeCustomAppPropCategory.jspf file

<object objectType="ConfigCategory">

<configCategoryName><![CDATA[${customAppPropCategory.category}]]></configCategoryName></object>

406 WebSphere Commerce Line-of-Business Tooling Customization

Page 425: My Tutorial

8. Implement the /GetConfigCategoryChildren action:

a. Open the GetConfigCategoryChildren.jsp file, and replace the file’s content completely with the content in Example 12-68.

Example 12-68 GetConfigCategoryChildren.jsp file

<?xml version="1.0" encoding="UTF-8"?><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><%@ taglib uri="http://commerce.ibm.com/foundation" prefix="wcf"%><%

// Use the get-data tag to invoke the expression which will find // CustomAppProperties by storeId and category.

%><objects><wcf:getData

type="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType[]"

var="customAppProperties" expressionBuilder="findCustomAppPropertiesByCategoryAndStoreent_id"

varShowVerb="showVerb" ><wcf:param name="storeent_id" value="${param.storeId}" /><wcf:param name="category" value="${param.configCategoryName}" />

</wcf:getData><c:if test="${!(empty customAppProperties)}">

<c:forEach var="customAppProperty" items="${customAppProperties}"><%

// For each returned customAppProperties, convert it into the XML// representation Management Center expects. This is done// by calling a common serialization JSP fragment that is// used by all URLs that is returning the Management Center// version of the CustomAppProperties noun.

%><jsp:directive.include file="serialize/SerializeCustomAppProperty.jspf" />

</c:forEach></c:if></objects>

b. Open the SerializeCustomAppProperty.jspf file, and replace the file’s content completely with the content in Example 12-69.

Example 12-69 SerializeCustomAppProperty.jspf file

<object objectType="ChildConfigProperty">

Chapter 12. Custom Application Configuration Management tool 407

Page 426: My Tutorial

<childConfigPropertyId><![CDATA[${customAppProperty.customAppPropertiesIdentifier.uniqueID}]]></childConfigPropertyId>

<object objectType="ConfigProperty">

<configPropertyId><![CDATA[${customAppProperty.customAppPropertiesIdentifier.uniqueID}]]></configPropertyId>

<category><![CDATA[${customAppProperty.category}]]></category>

<key><![CDATA[${customAppProperty.customAppPropertiesIdentifier.externalIdentifier.name}]]></key>

<value><![CDATA[${customAppProperty.value}]]></value><type><![CDATA[${customAppProperty.valueType}]]></type><description><![CDATA[${customAppProperty.description}]]></description>

</object></object>

9. Implement the /FindConfigProperties action:

a. Open the FindConfigProperties.jsp file, and replace the file’s content completely with the content from Example 12-70.

Example 12-70 FindConfigProperties.jsp file

<?xml version="1.0" encoding="UTF-8"?><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><%@ taglib uri="http://commerce.ibm.com/foundation" prefix="wcf"%><%

// Use the get-data tag to invoke the expression which will find // CustomAppProperties by storeId and search term.

%><objects><wcf:getData

type="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesType[]"

var="customAppProperties" expressionBuilder="findCustomAppPropertiesByStoreent_idAndSearchTerm"

varShowVerb="showVerb" ><wcf:param name="storeent_id" value="${param.storeId}" /><wcf:param name="name" value="${param.searchText}" /><wcf:param name="value" value="${param.searchText}" /><wcf:param name="description" value="${param.searchText}" />

</wcf:getData><c:if test="${!(empty customAppProperties)}">

<c:forEach var="customAppProperty" items="${customAppProperties}">

408 WebSphere Commerce Line-of-Business Tooling Customization

Page 427: My Tutorial

<%// For each returned customAppProperties, convert it into the XML// representation Management Center expects. This is done// by calling a serialization JSP fragment.

%><jsp:directive.include

file="serialize/SerializeCustomAppPropertyForSearch.jspf" /></c:forEach>

</c:if></objects>

b. Open the SerializeCustomAppPropertyForSearch.jspf file, and replace the file’s content completely with the content from Example 12-71.

Example 12-71 SerializeCustomAppPropertyForSearch.jspf file

<object objectType="ConfigProperty">

<configPropertyId><![CDATA[${customAppProperty.customAppPropertiesIdentifier.uniqueID}]]></configPropertyId>

<category><![CDATA[${customAppProperty.category}]]></category>

<key><![CDATA[${customAppProperty.customAppPropertiesIdentifier.externalIdentifier.name}]]></key>

<value><![CDATA[${customAppProperty.value}]]></value><type><![CDATA[${customAppProperty.valueType}]]></type><description><![CDATA[${customAppProperty.description}]]></description>

</object>

c. Save all files (Ctrl+Shift+S).

12.5.5 Implementing object mapping JSPs for Process and Change commands

WebSphere Commerce server responds to a Management Center client application Process request by transforming the nouns into the XML representation that is expected by the Management Center. A JSP file is called on the appropriate Struts action to transform nouns into XML format.

WebSphere Commerce uses a common JSP structure to build the XML response. This Response JSP receives the BODs from the WebSphere Commerce server and serializes the noun to the needed XML response.

In our scenario, the Management Center client application only expects the UniqueID of the successful processed noun, so the JSPs are very simple.

Chapter 12. Custom Application Configuration Management tool 409

Page 428: My Tutorial

To learn more about Processing Management Center services, visit the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/refs/rtfprocessservices.htm

Add response JSPs for the actions: /CreateCustomAppProperties, /UpdateCustomAppProperties, and /DeleteCustomAppProperties:

1. Open WebSphere Commerce Developer.

2. Open the J2EE perspective.

3. In the Project Explorer view, expand the LOBTools project.

4. Navigate to the WebContent\jsp\redbooks\config folder.

5. Create the JSP files:

a. Right-click the config folder, and select New → JSP file.

b. In the File Name field, type RespondProcessCustomAppProperties.jsp, and click Finish.

c. Repeat steps a and b to create the JSP file, RespondChangeCustomAppProperties.jsp.

6. The /CreateCustomAppProperties and /DeleteCustomAppProperties actions use the same response JSP:

a. Open the RespondProcessCustomAppProperties.jsp file, and replace the file’s content completely with the content from Example 12-72.

Example 12-72 RespondProcessCustomAppProperties.jsp file

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><?xml version="1.0" encoding="UTF-8"?><object>

<configPropertyId><c:out value="${nouns[0].customAppPropertiesIdentifier.uniqueID}"></c:out>

</configPropertyId></object>

7. The /UpdateCustomAppProperties action uses a different response JSP, but with identical content:

a. Open the RespondProcessCustomAppProperties.jsp file, and replace the file’s content completely with the content from Example 12-72.

b. Save all files (Ctrl+Shift+S).

410 WebSphere Commerce Line-of-Business Tooling Customization

Page 429: My Tutorial

12.5.6 Deploying the customization to the WebSphere Commerce Test Server

After you apply all of the changes, deploy the Management Center Web application:

1. Start the WebSphere Commerce Test Server by going to the Server view, right-clicking the WebSphere Commerce Test Server, and selecting Start.

2. If the WC project is not already published to the WebSphere Commerce Test Server, publish the WebSphere Commerce project:

a. From the Server view, right-click the WebSphere Commerce Test Server, and select Add and Remove Projects.

b. Select the WC project.

c. Click Add. Click Finish.

3. If the WC project is already published, right-click the WebSphere Commerce Test Server, and select Publish.

12.6 Testing the customization

In the previous sections of this chapter, we discussed customizing the Management Center’s user interface and Web application and WebSphere Commerce services. In this section, we discuss testing of the CustomAppProperties services of the WebSphere Commerce service and the Management Center customizations.

12.6.1 Testing the CustomAppProperties service using unit tests

You will run JUnit-based test cases that you created in 12.4.13, “Implementing unit tests using the CustomAppProperties client library” on page 371 to ensure that the CustomAppProperties service works properly.

To test the CustomAppProperties service:

1. Set up a TCP/IP monitor in WebSphere Commerce Developer. You use this TCP/IP monitor to observe the request and response documents that go to and from the WebSphere Commerce service that you created.

To create a TCP/IP Monitor to forward requests to WebSphere Commerce:

a. Select Window → Preferences.

b. From the Preferences panel, select Internet → TCP/IP Monitor, and lick Add.

Chapter 12. Custom Application Configuration Management tool 411

Page 430: My Tutorial

c. Type the following information:

• Local monitoring port: 81

• Hostname: The host name of the WebSphere Commerce Server where the CustomAppProperties service is running.

On WebSphere Commerce Developer, this is typically localhost

• Port:80 for WebSphere Commerce Developer, 8007 for production

d. Click OK.

e. Select the created TCP/IP monitor, and click Start.

f. Click OK.

2. Run the JUnit test:

a. Right-click the CustomAppPropertiesFacadeClientTest.java class, and select Run.

b. Select JUnit Test. You should see the request and response XML documents transmitted between the client and server on the TCP/IP monitor.

If the validation is successful, you will see a green bar on the JUnit view.

From the TCP/IP Monitor, you can review the request and response BOD messages that are sent between the client and server as part of the test. Figure 12-35 on page 413 contains example output.

412 WebSphere Commerce Line-of-Business Tooling Customization

Page 431: My Tutorial

Figure 12-35 TCP/IP monitor sample output of a test run

12.6.2 Testing the Management Center customizations

To test the Management Center customization, perform the following tasks:

1. Build all projects that you created or updated for the Custom Application Configuration Management tool.

2. Start the WebSphere Commerce Server.

3. Launch the Management Center.

Note: The following steps assume that your workspace has the WebSphere Commerce services, Management Center UI, and Management Center Web application customizations completed for this chapter.

Chapter 12. Custom Application Configuration Management tool 413

Page 432: My Tutorial

4. From the Management Center menu, shown in Figure 12-36, select Application Configuration.

Figure 12-36 Launch Application Configuration tool

5. If no default store is selected, choose the ConsumerDirect store, shown in Figure 12-37, or any store that you want to work with.

Figure 12-37 Store selection

6. In the Explorer view, you see the organizational object, Configuration Categories, shown in Figure 12-38. Because there are no configurations in the database at this point, this folder is empty.

Figure 12-38 Custom Application Configuration Management tool initial Explorer view

7. On the Management Center toolbar, click the Create button to launch the property view, as shown in Figure 12-39 on page 415.

414 WebSphere Commerce Line-of-Business Tooling Customization

Page 433: My Tutorial

Figure 12-39 Toolbar button - Create

8. In the Properties view, enter configuration property information, and click Save, and then click Close. Figure 12-40 shows a sample configuration property.

Figure 12-40 Create new custom application property

Chapter 12. Custom Application Configuration Management tool 415

Page 434: My Tutorial

9. Because we created a new category, refresh the Explorer view using the context menu for Configuration Categories folder. Right-click the Configuration Categories folder, and select Reload, as shown in Figure 12-41.

Figure 12-41 Reload Explorer view

10.The new configuration category is displayed under the Configuration Categories folder. Select the new category, and the navigation list that is in the main work area gets populated, as shown in Figure 12-42.

Figure 12-42 Navigation list display for new category

11.To create a new configuration property of the same category, open the context menu for the category, and select New Configuration Property, as shown in Figure 12-43 on page 417.

416 WebSphere Commerce Line-of-Business Tooling Customization

Page 435: My Tutorial

Figure 12-43 Context menu for the Configuration category

The displayed Properties view should have the Category value pre-populated, as shown in Figure 12-44.

Figure 12-44 Create the custom application property for an existing category

12.To edit an existing Configuration Property, double-click the property in the list view. You can also use the toolbar buttons or context menu as well.

13.To delete an existing Configuration Property, select the configuration property in the list view, and use the toolbar button or context menu, as shown in Figure 12-45 on page 418.

Chapter 12. Custom Application Configuration Management tool 417

Page 436: My Tutorial

Figure 12-45 Context menu for configuration property

14.To test the Search function, in the search bar, enter a search text, and click the Find icon, which displays the search results in the main work area, as shown in Figure 12-46.

Figure 12-46 Search Configuration Property

418 WebSphere Commerce Line-of-Business Tooling Customization

Page 437: My Tutorial

Appendix A. Additional material

In this section, we refer you to additional material that you can download from the Internet.

Locating the Web material

The Web material that is associated with this book is available in softcopy on the Internet from the IBM Redbooks Web server. Point your Web browser to:

ftp://www.redbooks.ibm.com/redbooks/SG247619

Alternatively, you can go to the IBM Redbooks Web site at:

ibm.com/redbooks

Select Additional materials, and open the directory that corresponds with the IBM Redbooks form number, SG247619.

A

© Copyright IBM Corp. 2008. All rights reserved. 419

Page 438: My Tutorial

Using the Web material

The additional Web material that accompanies this book includes the following file:

Redbook.LOBTools.zip, which contains all of the updates for the LOBTools project.

How to use the Web material

Create a subdirectory (folder) on your workstation, and unzip the contents of the Web material zip file into this folder.

Importing the Redbook.LOBTools.zip file

This zip file contains all extension code for all of the chapters. All files are either prefixed with redbook or reside in their own subfolders (named redbooks something). You can import this zip file into your default WebSphere Developer workspace without having to overwrite anything:

1. Right-click the LOBTools project, and click Import.

2. Select Zip file, and click Next.

3. Browse to the location where you downloaded and extracted the redbook main zip file, and select Redbook.LOBTools.zip. Click Open.

4. Ensure that the target into the folder is LOBTools and that the option Overwrite existing resources without warning is not selected.

5. Click Finish.

After the import is complete, you must incorporate the changes from the extended source files to your original files that you already have in your workspace. This is where the “redbook.” files are intended to help you, and after the previous import they will already be located in the appropriate target folders. See figure Figure A-1 on page 422.

420 WebSphere Commerce Line-of-Business Tooling Customization

Page 439: My Tutorial

There are many ways to bring the changes in, and using CVS is one good way, if you have that system available to you. However, if you do not need to compare and merge the contents, we have a simple method. Create an original backup of each target file first, and then make the redbook version the effective copy:

1. Navigate down to the folder that has an extended file, such as /LOBTools/WebContent/WEB-INF.

2. There is an extended version of the struts-extension.xml file in this folder. Make a backup by renaming the original file with an orig. prefix. Click F2, and enter a new name, such as orig.struts-extension.zml.

3. Copy the redbook version over to be the current version. Select the redbook file (such as redbook.struts-extension.xml), and simultaneously press the Ctrl and C keys, and then simultaneously press the Ctrl and V keys.

4. A popup window for the new name is displayed. Enter the actual name to be used (such as struts-extension.xml) by stripping out the first part of the filename. Click OK.

You effectively took a backup of your original files, and copied the redbook version over to be the current one.

5. Rebuild the LOBTools project.

This method works with version 3.0.1 of the WebSphere Commerce Feature Pack. If you are using a later version, you must bring in the changes manually, or ideally set up a CVS system with which the synchronization can be done in a well-managed and guided manner.

The zip contains two versions of the struts-extension.xml file. The first fully inclusive version requires that you imported the Configuration Manager projects to your workspace. If you have not done that, use the second version.

Appendix A. Additional material 421

Page 440: My Tutorial

Figure A-1 List of the extended files in the Redbook.LOBTools.zip file

422 WebSphere Commerce Line-of-Business Tooling Customization

Page 441: My Tutorial

Related publications

The publications that we list in this section are considered particularly suitable for a more detailed discussion of the topics that we cover in this book.

IBM Redbooks

For information about ordering these publications, see “How to get Redbooks” on page 432. Note that some of the documents that we reference here might be available in softcopy only:

� Planning and Managing the Deployment of WebSphere Commerce, SG24-7588

� Deploying and Customizing IBM Sales Center for WebSphere Commerce V6, SG24-7249-00

Online resources

These Web sites are also relevant as further information sources:

� The WebSphere Commerce Information Center is available at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp

� IBM WebSphere Commerce - Feature Packshome page at:

http://www-306.ibm.com/software/genservers/commerceproductline/Description2

� WebSphere Commerce Accelerator section in the WebSphere Commerce Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.user.doc/concepts/ctfmc.htm

� Getting started with the IBM Sales Center section in the WebSphere Commerce Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.telesales.tsr.doc/misc/welcome.htm

© Copyright IBM Corp. 2008. All rights reserved. 423

Page 442: My Tutorial

� WebSphere Commerce Information Center: Rearranging the layout of the Management Center main page:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfmainpagelayout.htm

� WebSphere Commerce Information Center: Rearranging the layout of the Management Center status area:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfstatusarealayout.htm

� WebSphere Commerce Information Center: Rearranging the layout of the Management Center banner:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfbannerlayout.htm

� WebSphere Commerce Information Center: Changing the logo image:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangelogo.htm

� WebSphere Commerce Information Center: Rearranging the layout of the Management Center menu:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfappmenulayout.htm

� WebSphere Commerce V6 Information Center: Changing the tool icon for the Management Center menu:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangeappmenuicon.htm

� WebSphere Commerce V6 Information Center: Changing access control for a Management Center tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfcreatelobrole.htm

424 WebSphere Commerce Line-of-Business Tooling Customization

Page 443: My Tutorial

� WebSphere Commerce V6 Information Center: Changing default values for settings in the Preferences dialog:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangedefaultpref.htm

� WebSphere Commerce V6 Information Center: Adding new fields in the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadpcat.htm

� WebSphere Commerce V6 Information Center: Changing the display name for a Management Center object:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangedisplayname.htm

� WebSphere Commerce V6 Information Center: Adding new search conditions in the advanced search of the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadsca.htm

� WebSphere Commerce V6 Information Center: Changing a column name in a list view:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfchangecolumnlist.htm

� WebSphere Commerce V6 Information Center: Adding new fields in the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadpcat.htm

� OpenLaszlo API defined:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.management-center_customization.doc/refs/rtfmain.htm

� Creating a new Management Center widget at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfcreatenewwidgets.htm

Related publications 425

Page 444: My Tutorial

� Using or extending Management Center widget at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfuseexistingwidgets.htm

� WebSphere Commerce v6 Information Center: Adding new search conditions in the advanced search of the Catalogs tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tutorial/ttfadsca3.htm

� WebSphere Commerce v6 Information Center: Mapping of validation error reason codes:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfmaperror.htm

� WebSphere Commerce BOD command framework:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdsoaprogmodel.htm

� Creating a new WebSphere Commerce BOD service module:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tutorial/tsdsoatutorial.htm

� Developing the Business Logic layer using the BOD command framework:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdcustomizesoasvc.htm

� Installation of WebSphere Commerce feature packs, refer to Installing WebSphere Commerce Enhancements at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.admin.doc/tasks/tigfepmaster1.htm

� Enabling the Management Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/tasks/ttfenablecmc.htm

� Management Center modeling guidelines:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctfguidelines.htm

� Management Center file directory structure:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctfdirectorystructure.htm

426 WebSphere Commerce Line-of-Business Tooling Customization

Page 445: My Tutorial

� Management Center file and class naming conventions:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/concepts/ctffilenaming.htm

� OpenLaszlo documentation:

http://www.openlaszlo.org

� OpenLaszlo profiler which measures the time spent in each function:

http://wiki.openlaszlo.org/CallProfiler

� Management Center search tables at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/refs/rpmmctables.htm

� Improving performance of case-insensitive searches in the Management Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/refs/rtforacleperform.htm

� Review the section Customized WebSphere Commerce Enterprise Application (EAR) assets at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/concepts/cdpcustom_ear.htm

� WebSphere Commerce deployment checklist at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.samples.doc/refs/sddeploymentchecklist.htm

� WebSphere Commerce Information Center for packaging Management Center files for deployment:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/tdecreatewar.htm

� WebSphere Commerce Information Center in the “Rolling back your J2EE asset changes” section:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/refs/rdptbear_rollback.htm

� Deploying a WAR module:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.doc/tasks/tdpdeploying_war_assets_entire.htm

� Logging and Tracing details:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center.doc/tasks/ttflogtrace.htm

Related publications 427

Page 446: My Tutorial

� CVSNT version 2.5.03:

http://www.cvsnt.org

� Merchandising associations and the semantic specifiers, see the Info Center documentation:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.user.doc/concepts/cpnmamass.htm

� Details of working with the library class files, see this Information Center page:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfaddlibrary.htm

� Product Primary Object definition:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/catalog/objectDefinitions/ProductPrimaryObjectDefinition.lzx/catProductPrimaryObjectDefinition.html

� Entry point for mapping new actions to the Management Service UI - class:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/foundation/restricted/CustomService.lzx/wcfCustomService.html

� Catalog Entry browse grid definition in the Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.openlazlo.doc/lzx/commerce/catalog/listViewDefinitions/CatalogEntryGrid.lzx/catCatalogEntryBrowseGrid.html

� Transforming the URL request to a BOD service, see the Information Center page:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/refs/rtfprocessservices.htm

� CNET API:

http://api.cnet.com/

� Register for a developer key with CNET.com. Use the following Web site to register with CNET:

http://membership.cnet.com/1383-4_1-172.html?path=http%3A%2F%2Fapi.cnet.com%2Fdashboard.html

428 WebSphere Commerce Line-of-Business Tooling Customization

Page 447: My Tutorial

� Detailed information about loading catalog data using WebSphere Commerce Accelerator:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.user.doc/tasks/tcacsvld.htm

� ChangePerson:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.component-services.doc/refs/rmschangeperson.htm

� Defining custom attributes for member URLs in WebSphere Commerce Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.developer.doc/tasks/tmsdfatt.htm

� Demonstration of the CheckTextBody in action: http://ws.cdyne.com/SpellChecker/check.asmx?op=CheckTextBody

� Changing access control for a Management Center tool:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.management-center_customization.doc/tasks/ttfcustomizeshell.htm

� Creating a new WebSphere Commerce BOD service module tutorial:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tutorial/tsdsoatutorial.htm

� Installed WebSphere Commerce Feature Pack 3.0.1:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.admin.doc/tasks/tigfepmaster.htm

� Enabled WebSphere Commerce services for Feature Pack 3.0.1:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvenableservices.htm

� Setting up your development environment for creating WebSphere Commerce services:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvsetupdevenv.htm

� Installing the Design Pattern Toolkit and the Component Projects design pattern:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvdptk.htm

Related publications 429

Page 448: My Tutorial

� Creating a WebSphere Commerce service module of the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvcreatecomponent.htm

� Business Object Document Type (BOD) Version in WebSphere Commerce:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdbodversion.htm

� Extending a noun, refer to the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvextendnoun.htm

� Tutorial: Adding new properties to a WebSphere Commerce service using the Data Service layer:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tutorial/twvfounduserdata.htm

� Business object mediators is explained in more detail in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdexposenewdata.htm

� Business Logic layer, using the BOD command framework, see WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdcustomizesoasvc.htm

� Database schema object naming considerations, see WebSphere Commerce Developer at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.database.doc/refs/rdbnamingconventions.htm

� Query templates in WebSphere Commerce Information Center:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdqtf.htm

� Detailed information about the wc-business-object-mediator.xml file in the WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdexposenewdata.htm

� Detailed information about the wc-component.xml file in WebSphere Commerce Information Center at:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdextendconfig.htm

430 WebSphere Commerce Line-of-Business Tooling Customization

Page 449: My Tutorial

� Data Service layer query processing:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdqueryexec.htm

� Extending the configuration of a service module to add name-value parameters:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdextendconfig.htm

� Business Logic layer design patterns:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csddesignpatterns.htm

� Modifying a Get service to use business logic to insert more data for a specific access profile:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/tasks/tsdworkmoredata.htm

� Business Object Document Get processing pattern:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdsoaget.htm

� Registering the new command:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tutorial/twvstep3.htm

� Access control in the BOD command framework:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.developer.soa.doc/concepts/csdaccesscontrol.htm

� Debugging access control in WebSphere Commerce:

http://www.ibm.com/developerworks/websphere/library/techarticles/0805_callaghan/0805_callaghan.html?ca=dnb-wce061908

� JUnit:

http://www.junit.org

� Deploying the client library:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvdeployclientlibrary.htm

Related publications 431

Page 450: My Tutorial

� Testing a WebSphere Commerce service:

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvtestcs.htm

� IBM Redbooks publication, Planning and Managing the Deployment of WebSphere Commerce, SG24-7588, available:

http://www.redbooks.ibm.com/abstracts/sg247588.html?Open

How to get Redbooks

You can search for, view, or download Redbooks, Redpapers, Technotes, draft publications and Additional materials, and order hardcopy Redbooks, at this Web site:

ibm.com/redbooks

Help from IBM

IBM Support and downloads

ibm.com/support

IBM Global Services

ibm.com/services

432 WebSphere Commerce Line-of-Business Tooling Customization

Page 451: My Tutorial

Index

AAbstractCustomAppPropertiesFacadeClient 363access control assets 312acpload utility 364actionCode 403Active Work folder 7activity builder 6Adobe Flash program 12advanced user interface components 7advancedSearchContentClass 124AJAX 4API 4application definition file 284application framework of the Management Center 4applyData method 221

BbaseName attribute 148build cycle 56, 61Business Logic layer 17, 23, 43, 46, 312Business Object Document (BOD) 13, 23Business Object Document Processing Command 23Business Object Editor widget 43Business Object Mediators 24button widget property editor 211buttons 4buyable icons 108

Ccampaign activities 6campaigns 6cancel button 190catalog entries 5catalog management 5catalog tool 143catCatalogEntryExtraProperties class 112catManagePricingInformation 160catManageProduct 160catMerchandisingAssociation class 97catMerchandisingAssociationsAdvancedSearch-Content 127

© Copyright IBM Corp. 2008. All rights reserved.

catProductProperties 160CDYNE service 184, 237cfgConfigTopObjectDefinition.lzx

Custom Application Configuration Management tool 251

change mediators 311, 318ChangeCustomAppPropertiesBasePartCmdImpl 360ChangeCustomAppPropertiesBasePartMediator 318ChangeCustomAppPropertiesMediator 318class wcfMainWorkbench 30client engine 18client side data model 18client side mashup 143–144, 179clientLibrary 403clientLibraryMethod 403Cloudscape 101CMCPriceComparisonEnabled 176CNET API 150CNET service URL 150code generator 299CommerceFoundation model 300common customization scenarios 29complex type 286ComponentProjects design pattern 245consistent user interface paradigm 7ConsumerDirect store 115contentdatapath attribute 152contextParameters 402correctionsView 195, 199createEditor method 202Custom Application Configuration Management tool 249

ChildConfigProperty 250ConfigCategory 250ConfigurationTop 250

Custom Application Configuration Management tool (CACMT) 239custom grid 150custom grid widget 147CustomAppProperties 245CustomAppProperties noun 287, 298customAppProperties.appdef file 284

433

Page 452: My Tutorial

CustomAppPropertiesBODVersion element 288CustomAppProperties-Client 283, 285CustomAppPropertiesClientApplicationMes-sageKeys 362CustomAppPropertiesData 373CustomAppProperties-DataObjects 283, 285CustomAppProperties-DataObjects project 287CustomAppPropertiesExternalIdentifierType type 288CustomAppPropertiesFacadeClient 363CustomAppPropertiesFacadeClientTest 371CustomAppPropertiesFacadeConstants class 348CustomAppPropertiesIdentifierType type 288CustomAppPropertiesManagers 365CustomAppPropertiesMetadata class 313CustomAppProperties-Server 283, 285CustomAppPropertiesServicesHTTPInterface 285CustomAppPropertiesServicesJMSInterface 283, 285CustomAppPropertiesType type 288CustomAppPropertiesTypeProtectableProxy 363CustomAppProperties-UnitTests 283, 285customer relationship management 9

Ddata mediator type 313Data Service Facade 24Data Service Layer (DSL) 23data store 23database schema object naming 315datapath 152datapath attribute 152datapointer 150, 154datapointer registers method 154dataset class 151defaultParameters 403deployment 56Design Pattern Toolkit (DPTK) 59, 283destroy 158developer ID 145DHTML 12dictionary feature 235discount calculation rule 6discounts 6displayName 124documentRootFactory 403doSpellCheck method 211, 213DPTK plug-in 283

EEclipse 63Eclipse Process Framework (EPF) 50Eclipse-enabled template engine 283EJB 16EJB classes and interfaces 312e-mail transport channel 6enablementValue 271exported scripting variable 131expression builder 131expressionBuilder

getData tag 131extCatalogProductPriceGrabber 156extCatalogProductPriceGrabberComponent 156extCatalogProductPricePane 161extCatalogProductPricePropertyGroup 160extCatalogResourceBundle 148extConfigCategoryFilter 265extConfigCategoryPrimaryObjectDefinition 253extConfigCategoryPropertyInputText 268extConfigCategoryPropertyReference 252extConfigOrganizationalObjectDefinition 251extConfigPropertyGrid 261extConfigPropertyList 255extConfigPropertyPrimaryObjectDefinition 256extConfigPropertySearchGrid 260extConfigPropertyValidator 257extConfigResourceBundle 275extConfigTopObjectDefinition 251extConfigurationProperties 256extension points 4ExternalIdentifier element 288extFindConfigurations 256extManagePriceTab 160extPriceComparisonPreference 172extPriceGrabberGrid 152extPriceGrabberGridcolumn 152extPriceGrabberGridcolumn class 152extPropertySpellCheck class 188extraPropertiesId 110extSpellCheckButton 188, 199, 211extSpellCheckButton class 200extSpellCheckButtonWidget 188extSpellChecker.lzx 234extSpellChecker.lzx class 191

FFetchCustomAppPropertiesCmdImpl 359

434 WebSphere Commerce Line-of-Business Tooling Customization

Page 453: My Tutorial

FindConfigProperties 256fit-gap analysis 181full client-server-cycle 4

GGantt chart 41genmodel 298getData tag 131get-data-config.xml 44global solution design 52grid 152

Hhandler class 151highlightedText 195highlightWord 221HTML elements 4HTTP Post method 58

IIBM Management Center for WebSphere Commerce 3, 9, 12, 49IBM Sales Center for WebSphere Commerce 9IBM WebSphere Commerce 3Identity Token 21Init service definition 249InsertMoreData command 359in-store customer service tasks 9

JJACL 72Java programming language 50JavaScript 12JavaScript programming language 50JSON 145JSP 22JSP programming 50JUnit 58JUnit-based tests 59Jython type scripting 72

LlabelsView 195language specific exception messages 312line of business tools 4listClass 124listTitile 124

local browser cache 7logical data model 24, 287, 298logical SDOs 287long description field 180LzDataset 150LzDelegate 157LzUnit 58

Mmacro design 56macro design phase 52MainWorkbench.lzx 30manage campaigns 6manage e-mail activities 6manage e-mail templates 6manage Web activities 6Management Center 3–4Management Center shell 30–31Management Center tools 30Management Center user interface 30Management Center Web application 30marketing management 5master catalog 5maxItems

getData tag 131maxOccurs attribute 294mediation flow 21Mediation layer 17–18, 22, 43merchandising associations 6merchant logo 147merchant name 147message key definitions 312messageView 195meta data configuration 313metadata initialization class. 313micro design 56, 59minOccurs attribute 294model property 186Model-View-Controller architecture 19moveToNextWord method 233

Nname value pair commands 16name-value-pair URLs 13new property editor 202nonbuyable icons 108

Index 435

Page 454: My Tutorial

OOAGIS message structure 13OAGIS services 23Object definitions 249offerMessage 153okCancelView 195onclick handler 201, 212ondata event 154ontext event 153onvalue events 157Open Unified Process (OpenUP) 50OpenLaszlo 12, 17, 58, 179OpenLaszlo application 19OpenLaszlo classes

basegrid 152basegridcolumn 152basescrollbar 152

OpenLaszlo client application 58OpenLaszlo dataset class 151OpenLaszlo programming model 50order capture 9orders 6

Ppage reload 4partKey 145persistence technology 24Physical Data Container 24physical data model 24plain text editor 180predefined promotions types 6preferenceKey 262Presentation layer 17, 23, 43, 179price 147product management 5Product Property Panel 199product property panel 180production deployment 61products 6profiler 59project delivery methods 51project lifecycle pattern 51promotion redemption 6promotion reward 6Promotions and Marketing tools 41promotions management 5promotions tool 6property 156

property component 156Property Editor 187Property Editor class 199property editors 185property panels 185Protectable Proxy class 363protectable proxy class 312proxy server 18

RRational ClearCase 80Read and Change mediators 24read mediator 315read mediators 311ReadCustomAppPropertiesMediator 315ReadCustomAppPropertiesNounPartMediator 315recordSetReferenceId

getData tag 131recordSetStartNumber

getData tag 131Redbooks Web site 432

Contact us xvredemption limits 6release candidate 61replaceWord 221Representational State Transfer (REST) style 18, 20resource bundle class 148REST interface 183rich text property editor 180richinputtext class 221rightButonsView 195root node 154

Ssales catalogs 5searchOptions map 123searchType 124selection fields 4selectNext method 234server side technology 13Service Data Objects (SDOs) 243, 246Service Oriented Integration (SOI) 16service requests 20serviceKey 148, 150service-oriented architecture (SOA) 13, 15serviceURL 148Servlet Filter 21

436 WebSphere Commerce Line-of-Business Tooling Customization

Page 455: My Tutorial

session beans 312setModelObject 157setProperty method 201setResultSize 154setSearchOptions method 123shipping 6skip button 190Software Configuration Management (SCM) 57SOI model 16sourceCatalogEntryCode 127spell check 179Spell Check Editor 187status area 150storefront customization 65storefront implementation 65StoreIdentifierType type 291Struts application 21Struts based Web Application (module) 20successMessage 153

Ttext input fields 4textbox 127textView 195The Open Applications Group 13trace code 200type

getData tag 131

UUI Conceptual Model 54UI Design Guidelines 54UI Protoype 54UniqueID element 288unknown word count 228UpdateCatalogEntryExtraProperties 114updatePropertyObject 158updatePropertyObject method 157updateText method 212user interaction 4user interface code 7UserDataType definition 288

VValueType field 294ValueTypeEnum 292var

getData tag 131variadic 74varShowVerb

getData tag 131versionID attribute 289

Wwc-component.xml file 355wc-componentname-clientobjects.xml 44wcf

getData 44wcfAdvancedSearchContent 123wcfBaseComboBox 127wcfChildListEditor 39, 41wcfCreateService 60, 257wcfDeleteService 109, 257wcfEnablementAndCondition 273wcfEnablementCondition 110wcfGanttGrid 41wcfGanttGrid class 41wcfGetChildrenService element 252wcfGridPropertyImage class 111wcfGridText 262wcfInputText 127wcfLogger 77wcfNavigationListDefinition 255wcfObjectPathFilter 39wcfObjectProperties 40wcfObjectPropertyFilter 39wcfOjbectGrid 39wcfPrimaryObjectDefinitions 120wcfPropertiesComponent 156wcfPropertyCombobox 270wcfPropertyEditor 188, 202wcfPropertyInputMultiLineText 270wcfPropertyInputText 270wcfPropertyPane 266wcfPropertyValue 259wcfReferenceList 41wcfResourceBundleKey class 148wcfRichTextEditor 186wcfSearchDefinition 41wcfSearchDefnition 123wcfSearchService 123wcfService 41wcfServiceParams 125wcfUpdateService 257wcfValueDefinition class 112

Index 437

Page 456: My Tutorial

wcsObjectGrid class 111Web 1.0 application 4Web 2.0 evolution 4Web activity management 6Web Services Description Language (WSDL) 246WebSphere Commerce Accelerator 7–8WebSphere Commerce Component Projects pat-tern 283WebSphere Commerce Developer 50WebSphere Commerce OAGIS services 43WebSphere Commerce Services 50, 59WebSphere Commerce services 30WebSphere Commerce Tools framework 4–5wordForCorrection_SC 208wsadmin tool 72WSDL 246

XXappprops 315XML 12, 50, 145XML response format 145XML Schema Definition (XSD) 246XML schema type 286XML Schema Validation 286XPath expression templates 396XpathExpressionHelper 376Xpaths 61xprop_buyable property 110XSD 246, 299XSD source code 294

Zzoomable GANTT charts 7

438 WebSphere Commerce Line-of-Business Tooling Customization

Page 457: My Tutorial

(0.5” spine)0.475”<

->0.875”

250 <->

459 pages

WebSphere Com

merce Line-of-Business Tooling Custom

ization

Page 458: My Tutorial
Page 459: My Tutorial
Page 460: My Tutorial

®

SG24-7619-00 ISBN 0738431702

INTERNATIONAL TECHNICALSUPPORTORGANIZATION

BUILDING TECHNICALINFORMATION BASED ONPRACTICAL EXPERIENCE

IBM Redbooks are developed by the IBM International Technical Support Organization. Experts from IBM, Customers and Partners from around the world create timely technical information based on realistic scenarios. Specific recommendations are provided to help you implement IT solutions more effectively in your environment.

For more information:ibm.com/redbooks

®

WebSphere Commerce Line-of-Business Tooling CustomizationCustomizing Management Center for WebSphere Commerce

Optimizing the day-to-day activities of the business users

Demonstrating customization scenarios

The Management Center for WebSphere® Commerce is the next generation business user tool for managing online business tasks. It was introduced with WebSphere Commerce Version 6, Feature Pack 3, for example, catalog tasks, marketing tasks, and promotion tasks.

In this IBM® Redbooks® publication, we give you a broad understanding of the features and capabilities of the Management Center for WebSphere Commerce. In addition, you will learn how the Management Center fits into the service-oriented architecture (SOA) framework of IBM WebSphere Commerce.

In this book, we help you to install, tailor, and configure Management Center to optimize the day-to-day activities of the business users who manage merchandising and marketing tasks for stores using the consumer direct and Business-to-Business (B2B) business models. We also discuss the assets that make up the Management Center, what assets you can customize, and we share some of the common customization scenarios. We also demonstrate how to plan and perform customizations to the Management Center and how to understand the use of development tools for creating Management Center customizations. We provide examples of the customization scenarios that we developed and tested in the International Technical Support Organization labs and WebSphere Commerce labs and made available for your use.

The target audience for this book is Commerce Architects, Commerce Developers, Project Managers, and Deployment Managers.

Back cover