Sie sind auf Seite 1von 460

Front cover

WebSphere Commerce Line-of-Business Tooling Customization


Customizing Management Center for WebSphere Commerce Optimizing the day-to-day activities of the business users Demonstrating customization scenarios

Rufus Credle Jeff Coster Steffen Eckardt Girish Gopinathan Vani Mittal Juha Nevalainen Ramya Rajendiran

ibm.com/redbooks

International Technical Support Organization WebSphere Commerce Line-of-Business Tooling Customization November 2008

SG24-7619-00

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

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
Copyright International Business Machines Corporation 2008. All rights reserved. Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.

Contents
Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi The team that wrote this book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii Become a published author . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiv Comments welcome. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv Part 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 1. IBM Management Center for WebSphere Commerce . . . . . . . . 3 1.1 Why Management Center was introduced . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Management Center capabilities. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2.1 Functional capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2.2 Usability capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.4.1 Client-side technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.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 . . . . . . . . . . . . . 16 2.2 Presentation layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.2.1 Overview of the Presentation layer . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.2.2 The OpenLaszlo application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.2.3 The Mediation layer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.3 Business Logic layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.3.1 Components of the Business Logic layer . . . . . . . . . . . . . . . . . . . . . 23 2.3.2 Business Object Mediators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Part 2. IBM Management Center for WebSphere Commerce customization . . . . . . . . . . . 27 Chapter 3. Customization overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3.1 Development assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.1.1 Management Center user interface. . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.1.2 Management Center Web application . . . . . . . . . . . . . . . . . . . . . . . . 43

Copyright IBM Corp. 2008. All rights reserved.

iii

3.1.3 WebSphere Commerce services . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Chapter 4. Planning and designing customizations . . . . . . . . . . . . . . . . . 49 4.1 Who should read this chapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4.2 Knowledge prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4.3 Overview of this chapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 4.4 Customization methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 4.5 Solution Outline phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.5.1 Gathering requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.5.2 Defining the application model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 4.6 Macro Design phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.6.1 Refining the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 4.6.2 Setting up the environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.6.3 Defining the processes and guidelines . . . . . . . . . . . . . . . . . . . . . . . 57 4.6.4 Defining the test specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 4.7 Micro Design phase. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 4.8 Build Cycle phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.8.1 Coding and unit testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.8.2 Performing system testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.8.3 Developing support materials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.9 Deployment phase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.9.1 Setting up the production environment . . . . . . . . . . . . . . . . . . . . . . . 63 4.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 . . . . . . . . . . . . 67 5.1 Development tools. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 5.1.1 WebSphere Commerce Developer . . . . . . . . . . . . . . . . . . . . . . . . . . 68 5.1.2 Management Center assets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 5.2 Deploying the extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 5.2.1 Exporting the extension code from the development environment . . 71 5.2.2 Backing up the application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 5.2.3 Deploying the WAR module to the target WebSphere Commerce server 72 5.2.4 Testing the changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 5.3 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 5.3.1 Tracing your own components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 5.4 Debugging server communication with the TCP/IP Monitor . . . . . . . . . . . 78 5.4.1 Creating the TCP/IP monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 5.5 Hints and tips. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 5.5.1 Turning automatic build off . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 5.5.2 Using a version control system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

iv

WebSphere Commerce Line-of-Business Tooling Customization

5.5.3 Increasing the Management Center inactivity time-out . . . . . . . . . . . 82 5.5.4 Customizing your Workbench perspective . . . . . . . . . . . . . . . . . . . . 83 5.5.5 Using the XML editor for OpenLaszlo files . . . . . . . . . . . . . . . . . . . . 83 5.5.6 Disabling the tools that you are using . . . . . . . . . . . . . . . . . . . . . . . . 83 5.6 Problem determination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 5.6.1 What to do if your changes are not appearing? . . . . . . . . . . . . . . . . 84 5.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 . . . . . . . . . . . . . . . . . . . . . . . . 91 6.2 Checking if the semantic specifier element was provided . . . . . . . . . . . . . 91 6.3 Defining an extended resource bundle and properties file . . . . . . . . . . . . 92 6.3.1 Registering the new properties in the resource bundle . . . . . . . . . . . 94 6.4 Adding the extensions to the tool extension library . . . . . . . . . . . . . . . . . . 95 6.5 Adding the Semantic property to the Merchandising Association class . . 96 6.6 Implementing a Validator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.7 Including the semantic specifier in the JSP. . . . . . . . . . . . . . . . . . . . . . . 100 6.8 Populating database tables with custom semantics . . . . . . . . . . . . . . . . 101 6.9 Testing the extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Chapter 7. Adding a new service action . . . . . . . . . . . . . . . . . . . . . . . . . . 107 7.1 Defining the properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 7.2 Customizing the product list view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 7.3 Updating the catalog entry grid view . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 7.4 Providing the buyable property value definitions. . . . . . . . . . . . . . . . . . . 112 7.5 Defining the Struts action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 7.5.1 Providing the response JSP files . . . . . . . . . . . . . . . . . . . . . . . . . . 114 7.6 Testing the extension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Chapter 8. Advanced search for merchandising associations . . . . . . . . 119 8.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 8.2 Building the customization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 8.2.1 Customizing the Management Center user interface . . . . . . . . . . . 123 8.2.2 Customizing the Management Center Web application . . . . . . . . . 129 8.2.3 Customizing WebSphere Commerce services . . . . . . . . . . . . . . . . 134 8.3 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Chapter 9. Price comparison mashup. . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 9.1 Understanding the requirement. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 9.2 Price comparison service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 9.3 Building the customization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

Contents

9.3.1 Resource bundle definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 9.3.2 Price comparison class definition . . . . . . . . . . . . . . . . . . . . . . . . . . 150 9.3.3 Property component definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 9.3.4 Updating the product properties view . . . . . . . . . . . . . . . . . . . . . . . 159 9.3.5 Updating the library file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 9.4 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Chapter 10. Customizing user preferences . . . . . . . . . . . . . . . . . . . . . . . 165 10.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 10.2 Building the customization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 10.2.1 Customizing the client side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 10.2.2 Customizing the server side . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 10.2.3 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Chapter 11. Spell Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 11.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 11.2 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 11.2.1 Meeting requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 11.2.2 CDYNE service detail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 11.2.3 Component design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 11.2.4 Visual Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 11.3 Deploying the complete or staged examples . . . . . . . . . . . . . . . . . . . . 190 11.4 Staged development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 11.4.1 Explaining the visual prototype stage (example 1) . . . . . . . . . . . . 194 11.4.2 Viewing the visual prototype stage (example 1) . . . . . . . . . . . . . . 204 11.4.3 Explaining the static XML prototype stage (example 2) . . . . . . . . 206 11.4.4 Viewing the static XML prototype stage (example 2) . . . . . . . . . . 209 11.4.5 Explaining the static XML prototype stage (example 3) . . . . . . . . 209 11.4.6 Viewing the static XML prototype stage (example 3) . . . . . . . . . . 210 11.4.7 Explaining the property provided prototype stage (example 4) . . . 211 11.4.8 Testing the property provided prototype stage (example 4) . . . . . 213 11.4.9 Explaining the CDYNE service prototype stage (example 5) . . . . 216 11.4.10 Viewing the CDYNE service prototype stage (example 5) . . . . . 218 11.4.11 Explaining the highlighted text prototype stage (example 6). . . . 219 11.4.12 Viewing the highlighted text prototype stage (example 6). . . . . . 222 11.4.13 Explaining the final stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 11.4.14 Testing the final stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 11.5 Possible enhancements and changes. . . . . . . . . . . . . . . . . . . . . . . . . . 235 11.5.1 Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 11.5.2 Replace /skip single occurrence . . . . . . . . . . . . . . . . . . . . . . . . . . 236 11.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

12.1 Understanding the requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 12.2 Overview of the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 12.2.1 Architectural overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 12.3 Customizing the Management Center user interface . . . . . . . . . . . . . . 248 12.3.1 Main tool definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 12.3.2 Object definitions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 12.3.3 Search definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 12.3.4 List definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 12.3.5 Filter definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 12.3.6 Property view definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 12.3.7 Resource bundle definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 12.3.8 Image files for Custom Application Configuration Management tool . 276 12.3.9 Library file definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 12.3.10 Adding the Custom Application Configuration Management tool to Management Center . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 12.4 Customizing the WebSphere Commerce services . . . . . . . . . . . . . . . . 280 12.4.1 Preparing your development environment . . . . . . . . . . . . . . . . . . 282 12.4.2 Generating the CustomAppProperties service module projects . . 283 12.4.3 Defining the CustomAppProperties noun . . . . . . . . . . . . . . . . . . . 286 12.4.4 Generating the SDOs for the CustomAppProperties noun . . . . . . 298 12.4.5 Generating the Persistence layer for the CustomAppProperties service module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 12.4.6 Understanding the assets of the CustomAppProperties-Server project 309 12.4.7 Updating the Data Service configuration. . . . . . . . . . . . . . . . . . . . 313 12.4.8 Implementing the Business Object Mediators to mediate logical and physical SDOs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313 12.4.9 Configuring the Data Service layer for the CustomAppProperties service module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 12.4.10 Implementing the Business Logic layer. . . . . . . . . . . . . . . . . . . . 356 12.4.11 Implementing the client library . . . . . . . . . . . . . . . . . . . . . . . . . . 362 12.4.12 Implementing access control. . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 12.4.13 Implementing unit tests using the CustomAppProperties client library 371 12.4.14 Deploying to the WebSphere Commerce server. . . . . . . . . . . . . 392 12.5 Customizing Management Center Web application . . . . . . . . . . . . . . . 393 12.5.1 Configuring the client-service-mapping . . . . . . . . . . . . . . . . . . . . . 394 12.5.2 Configuring the client-service-mapping for Get commands . . . . . 396 12.5.3 Configuring views and commands . . . . . . . . . . . . . . . . . . . . . . . . 399 12.5.4 Implementing object mapping JSPs for Get commands . . . . . . . . 404 12.5.5 Implementing object mapping JSPs for Process and Change commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

Contents

vii

12.5.6 Deploying the customization to the WebSphere Commerce Test Server 411 12.6 Testing the customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411 12.6.1 Testing the CustomAppProperties service using unit tests . . . . . . 411 12.6.2 Testing the Management Center customizations . . . . . . . . . . . . . 413 Appendix A. Additional material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 Locating the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419 Using the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 How to use the Web material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Importing the Redbook.LOBTools.zip file. . . . . . . . . . . . . . . . . . . . . . . . . . . . 420 Related publications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 IBM Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 Online resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 How to get Redbooks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432 Help from IBM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433

viii

WebSphere Commerce Line-of-Business Tooling Customization

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

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.

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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. Juhas 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 Ticknor International Technical Support Organization, Raleigh Center Scott Guminy, WebSphere Commerce Architect, IBM Software Group, Application and Integration Middleware Software IBM Canada

Preface

xiii

Daniel Cooper, Software Development - WebSphere Commerce IBM Canada Jacob Vandergoot, IBM Software Group, Application and Integration Middleware Software IBM Canada Rob Leroux, WebSphere Commerce Software Developer IBM 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

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: redbooks@us.ibm.com Mail your comments to: IBM Corporation, International Technical Support Organization Dept. HYTD Mail Station P099 2455 South Road Poughkeepsie, NY 12601-5400

Preface

xv

xvi

WebSphere Commerce Line-of-Business Tooling Customization

Part 1

Part

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

Copyright IBM Corp. 2008. All rights reserved.

WebSphere Commerce Line-of-Business Tooling Customization

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

Copyright IBM Corp. 2008. All rights reserved.

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 tools 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 tools functions to fulfill any customer requirement.

WebSphere Commerce Line-of-Business Tooling Customization

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 Centers 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 features


The 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

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 features


Use 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 features


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

WebSphere Commerce Line-of-Business Tooling Customization

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

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.

WebSphere Commerce Line-of-Business Tooling Customization

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

Table 1-1 Comparison of the WebSphere Commerce Accelerator, IBM Management Center for WebSphere Commerce, and IBM Sales Center Category WebSphere Commerce Accelerator Line-of-business users performing the following roles: Operational roles Business relationship roles Product management and merchandising roles Marketing roles Customer service roles Headquarter and departments 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 IBM Management Center for WebSphere Commerce Line-of-business users performing the following roles: Product management and merchandising roles Marketing roles IBM Sales Center

Audience

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

Typical environment Main application

Headquarter and departments Supports content management, which includes managing: Products and catalogs Content Marketing and promotions

Call center and point-of-sale locations Supports operations, which includes managing: Users Orders

10

WebSphere Commerce Line-of-Business Tooling Customization

Category

WebSphere Commerce Accelerator Traditional browser-based Web application. Uses DHTML, JavaScript code, and CSS.

IBM Management Center for WebSphere Commerce Flash-based rich interface application that runs in a browser. Uses the OpenLaszlo programming model that contains XML declarations and JavaScript code. 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. 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.

IBM Sales Center

Client technology

Eclipse-based rich client platform that is installed on a local machine. Uses the Eclipse programming model that contains XML and Java code. 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. 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.

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.

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.

Chapter 1. IBM Management Center for WebSphere Commerce

11

Category

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

IBM Management Center for WebSphere Commerce 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.

IBM Sales Center

Performing customizations

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. Available in WebSphere Commerce V6.0

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

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

12

WebSphere Commerce Line-of-Business Tooling Customization

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

14

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

15

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.
Presentation layer Management Center

Business logic layer WebSphere Commerce Services

Name Value Pair Commands

Business Object Document Processing Commands

Persistence layer EJB 1.1 Data Service Layer

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.

16

WebSphere Commerce Line-Of-Business Tooling Customization

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

Presentation layer Web browser OpenLaszlo application http Request XML Response

Mediation layer

BOD Request Business Logic layer

BOD Response

WebSphere Commerce services

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

18

WebSphere Commerce Line-Of-Business Tooling Customization

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

Web browser OpenLaszlo Application Data Model User Interaction Controller

View

HTTP Request Mediation Layer

XML Response

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

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

19

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/ctfmance nter.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

Presentation layer Web browser OpenLaszlo Application HTTP Request Servlet Filter Struts Application Client Library XML Response

Mediation layer

JSPs

BOD Request Business Logic layer

BOD Response

WebSphere Commerce Services

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

The four components that comprise the Mediation layer


The 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 layers create, update, and delete request on page 22.

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

21

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 request


Figure 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/ctfmance nter.htm
Management Center

Mediation layer Identity Token filter 2

Line-of-Business Struts Application

Line-of-Business Response JSPs

WebSphere Commerce Services


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

The Mediation layers create, update, and delete request


Figure 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/rtfprocessse rvices.htm

22

WebSphere Commerce Line-Of-Business Tooling Customization

Management Center 1 6

Mediation layer Identity Token filter 2

Line-of-Business Struts Application

Line-of-Business Response JSPs

WebSphere Commerce Services


Figure 2-6 Flow of the Mediation layers 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

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

23

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

Presentation layer Management Center Business logic layer WebSphere Commerce Services

Name Value Pair Commands

Business Object Document Processing Commands Logical SDOs Data Service Facade Data Service Layer

Persistence layer EJB 1.1

Business Object Mediator


Commerce Database

Physical SDOs Physical Data Container

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

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

25

26

WebSphere Commerce Line-Of-Business Tooling Customization

Part 2

Part

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

Copyright IBM Corp. 2008. All rights reserved.

27

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

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.

Copyright IBM Corp. 2008. All rights reserved.

29

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


The 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 area


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

30

WebSphere Commerce Line-of-Business Tooling Customization

Table 3-1 Main application area customization scenarios Scenario Change the layout of the main page Required changes Change the order of wcfBannerArea, wcfMainArea, and wcfStatusArea classes as desired. Reference WebSphere Commerce Information Center: Rearranging the layout of the Management Center main page: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfmainpagelayout.htm

Status area
The 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 Scenario Change the layout of the status area Required changes Change the order of the wcfProgressIndicator and wcfMessageLink classes. Reference WebSphere Commerce Information Center: Rearranging the layout of the Management Center status area: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfstatusarealayout.htm

Banner area
The 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.

Chapter 3. Customization overview

31

Table 3-3 Banner area customization scenarios Scenario Change the layout of the banner area Required changes Change the order of welcomeText, divider1, wcfLogoutLink, divider2, and headerLogo within bannerRightView. Reference WebSphere Commerce Information Center: Rearranging the layout of the Management Center banner: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfbannerlayout.htm None

Change the welcome text in the user identification area

Modify the welcomeText element in ToolBannerArea.lzx to use a different resource bundle property. By default the IBM logo is displayed. You can change it to reflect your custom logo.

Change the branding logo

WebSphere Commerce Information Center: Changing the logo image: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfchangelogo.htm

Application menu
The 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 Accelerators 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.

32

WebSphere Commerce Line-of-Business Tooling Customization

Table 3-4 Application menu customization scenarios Scenario Change the layout of the application menu Required changes Change the order of the various wcfApplicationMenuItem classes. Reference WebSphere Commerce Information Center: Rearranging the layout of the Management Center menu: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/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/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/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/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfcreatelobrole.htm

Preferences dialog
You 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.

Chapter 3. Customization overview

33

Table 3-5 User preferences API classes Class wcfUserPreferenceDialog Source file UserPreferenceDialog.lzx Description This is the user preference dialog that opens when you select Preferences from the application menu. This class contains all of the widgets that are in the user preference dialog. 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. This class defines all of the configurable properties that are used in Management Center. 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.

wcfUserPreferencePanel wcfPreferenceManager

UserPreferencePanel.lzx PreferenceManager.lzx

wcfConfigProperties

ConfigProperties.lzx

wcfUserPreferenceObject

UserPreferenceObjects.lzx

Table 3-6 lists the services that the Preferences feature uses.
Table 3-6 Services used by Preferences Service GetPerson Interface com.ibm.commerce.memb er.facade.client.MemberFa cadeClient.findCurrentPer son() com.ibm.commerce.memb er.facade.client.MemberFa cadeClient.updatePerson( Map parameters) Description This service is called to retrieve the user preferences from the database.

ChangePerson

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

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

34

WebSphere Commerce Line-of-Business Tooling Customization

Table 3-7 User preferences customization scenarios Scenario Change the layout of the preferences dialog Change the default values for preferences Required changes Change the order of the preference objects in wcfUserPreferencePanel (UserPreferencePanel.lzx. The default values are defined in wcfConfigProperties (ConfigProperties.lzx). Reference None

WebSphere Commerce v6 Information Center: Changing default values for settings in the Preferences dialog: http://publib.boulder.i bm.com/infocenter/wchel p/v6r0m0/topic/com.ibm. commerce.management-cen ter_customization.doc/t asks/ttfchangedefaultpr ef.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.

Management Center tools


Each 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. Note: To customize the Promotions tool, you must have at least Feature Pack 4 installed.

Chapter 3. Customization overview

35

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 definitions


The 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 Define a new tool Required changes Define a new class that extends from wcfBusinessObjectEditor. Define the required objects and artifacts for the new tool. Update the business object editor definition to include the new object definition. Update the business object editor definition to include the new service definition. Update the business object editor definition to include the new filter definition. Update the business object editor definition to include the new search definition. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example.

Define a new object

Refer to Object definitions on page 37 for more information. Refer to Service definitions on page 41 for more information. Refer to Filter definitions on page 38 for more information. Refer to Search definitions on page 38 for more information.

Define a new initialization service Define a new filter

Define a new search definition

36

WebSphere Commerce Line-of-Business Tooling Customization

Object definitions
An 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 Define a new object Required changes Define a new class that extends from wcfObjectDefinition. Update an object definition to include new user data or an attribute property. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example. WebSphere Commerce v6 Information Center: Adding new fields in the Catalogs tool: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tut orial/ttfadpcat.htm Define a custom service or change an existing service Update an object definition to include a new wcfCustomService definition. Change the display name attribute of an object definition. Refer to Chapter 7, Adding a new service action on page 107 for an example.

Add a new property or change an existing property

Change an attribute of an object

WebSphere Commerce v6 Information Center: Changing the display name for a Management Center object: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfchangedisplayname.htm

Define a new filter

Update the object definition to include the new filter definition. Define a new client-side validator

Refer to Filter definitions on page 38 for more information. Refer to Chapter 6, Enabling the merchandising associations Semantic Attribute on page 89 for an example.

Define a new validator

Chapter 3. Customization overview

37

Search definitions
A 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 Scenario Define a new search type Required changes Define a new class that extends from wcfSearchDefinition to search for a custom business object. 1. Change the display name 2. Change the view that displays the search results Define a new advanced search class for a tool (for example, a custom tool) that does not support advanced search. Add new search conditions to an existing advanced search class. Reference 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. None

Customize an existing search type

Define an advanced search

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

Customize advanced search

WebSphere Commerce v6 Information Center: Adding new search conditions in the advanced search of the Catalogs tool: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tut orial/ttfadsca.htm

Filter definitions
You 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.

38

WebSphere Commerce Line-of-Business Tooling Customization

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 Scenario Define a new filter Required changes Define a new filter class that extends from one of the classes defined above. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example.

List view definitions


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

Chapter 3. Customization overview

39

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


Table 3-12 Customization scenarios for a list view Scenario Define the list view for a primary object Define the list view for a child object Define the list view for search results Customize an existing list view Description Define a new class that extends from wcfObjectGrid. Define a new class that extends from wcfChildListEditor. Define a new class that extends from wcfObjectGrid. Add a column to the list Delete a column from the list Reorder the default columns Change the default visibility of the columns Change the attributes of a column as desired, for example, text, editable, visible, and so on. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example. Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example. Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example. 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

WebSphere Commerce v6 Information Center: Changing a column name in a list view: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/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.

Properties view definitions


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

40

WebSphere Commerce Line-of-Business Tooling Customization

Table 3-13 lists some customization scenarios for the properties view.
Table 3-13 Customization scenarios for properties view Scenario Define a new properties view Description Define a new class that extends from wcfObjectProperties for a custom business object. Update the properties view to include a new property. Create a new tab to include the new property. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example. WebSphere Commerce v6 Information Center: Adding new fields in the Catalogs tool: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tut orial/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.

Add a new property to the properties view

Calendar view definitions


A 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 definitions
The 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.

Chapter 3. Customization overview

41

Table 3-14 Customization scenarios for service definitions Scenario Define a new create, update, delete, or refresh service for a custom object Required changes 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. 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. 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. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example.

Define a new initialization service for a custom tool

None

Define a new search 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. Refer to Chapter 7, Adding a new service action on page 107 for an example.

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

Define a new get children service for a custom object

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

Define a new get references service for a custom primary object

42

WebSphere Commerce Line-of-Business Tooling Customization

Widgets
Widgets 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.co mmerce.management-center_customization.doc/tasks/ttfcreatenewwidgets.ht m 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.co mmerce.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

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 Define a new retrieval service for a Management Center object Required changes 1. Create a new Get controller JSP. 2. Create a new serialization JSP. 3. Add a new forward action to struts-extension.xml. Reference Refer to Chapter 12, Custom Application Configuration Management tool on page 239 for an example.

44

WebSphere Commerce Line-of-Business Tooling Customization

Scenario Define a new process service for a Management Center object

Required changes 1. Define the mapping between the Noun elements and the Management Center object in a new XML file (wc-componentname-c lientobjects.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 BusinessObjectDocum entPlugin. 3. Create a new BusinessObjectDocum ent Struts action. The process to override an existing retrieval service is similar to creating a new one.

Reference 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

WebSphere Commerce v6 Information Center: Adding new search conditions in the advanced search of the Catalogs tool: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tut orial/ttfadsca3.htm

Override a process service for an existing Management Center object Override an existing error message

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

None

WebSphere Commerce v6 Information Center: Mapping of validation error reason codes: http://publib.boulder.ibm.com/infocente r/wchelp/v6r0m0/topic/com.ibm.commerce. management-center_customization.doc/tas ks/ttfmaperror.htm

Chapter 3. Customization overview

45

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


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

46

WebSphere Commerce Line-of-Business Tooling Customization

Scenario: Retrieval services for Management Center objects


The 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 objects


The 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

48

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

49

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

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.

Solution Startup

Release

Solution Outline

Macro Design

Micro Design

Build Cycle

Deployment

Solution Close

Figure 4-1 Basic project life cycle

Chapter 4. Planning and designing customizations

51

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

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

Chapter 4. Planning and designing customizations

53

Functional and non-functional requirements


To 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 requirements


To 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 designs 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 services
Invocating 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

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 services


If 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

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

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.co mmerce.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.co mmerce.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/ctfdirectorys tructure.htm

Chapter 4. Planning and designing customizations

57

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. 2. 3. 4. 5. 6. 7. Select testing techniques and tools. Define conditions to test. Develop test cases. Combine test cases to test sets. Write test scripts, if necessary. Create test data. 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 testing
For 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

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 testing
The 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. 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 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.co mmerce.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.co mmerce.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

Chapter 4. Planning and designing customizations

59

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 interface


For 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 application


For 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

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 services


Each 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

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

4.8.3 Developing support materials


Make sure that you develop various support materials, such as: Users 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

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

Customization Area

Database Schema

EJB Persistence Layer

SDO Persistence Layer (DSL)

Controller/ Task Commands

BOD Commands

Customer UI

Tools UI

Management Center UI

Sales Center UI

Storefront

Accelerator

Sales Center Management Center WebSphere Commerce Services

Inbound Services/ Outbound Services

Loading Utilities

WebSphere Commerce Customization Sub-project

Possible interdependency within a customization area

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.

Chapter 4. Planning and designing customizations

65

66

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

67

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

5.1.2 Management Center assets


Table 5-1 describes the Management Center assets and directory structure. Note: In the following table, the <component> tag indicates a Management Center component, for example, catalog, marketing, promotion.
Table 5-1 Management Center assets and directory structure Directorya Files in this directory

WebContent/WEB-INF/src/lzx/commerce/<component> <component>ManagementToolDefinition.lzx Tool 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.lzx Add 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.lzx Filter definitions for component. <component>Library.lzx Library file with inclusions for all OpenLaszlo files that the component uses. <component>ResourceBundle.lzx Defines the resource bundle class and property keys that the component uses. <component>Resources.lzx Defines image resources that the component uses.

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

Chapter 5. Development tools and extension deployment

69

Directorya

Files in this directory 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.

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.

70

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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

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

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

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.co mmerce.management-center.doc/tasks/ttflogtrace.htm

Figure 5-5 Logging and Tracing settings

76

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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

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

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

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

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

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

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

86

WebSphere Commerce Line-of-Business Tooling Customization

Part 3

Part

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.

Copyright IBM Corp. 2008. All rights reserved.

87

88

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

89

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

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. 2. 3. 4. 5. 6. Check if the data element is already available in the client model. Extend the Catalog tool with the semantic column. Add support for input validation. Populate the MASSOC table with additional semantic entries. Include the semantic specifier to the JSP response. 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.co mmerce.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

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.properties as the package name, and click Finish. The new package is created.

92

WebSphere Commerce Line-of-Business Tooling Customization

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. 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=Semantic merchandisingAssociationSemantic_REQUIRES=REQUIRES merchandisingAssociationSemantic_COMES_WITH=COMES_WITH merchandisingAssociationSemantic_TEMP=TEMP merchandisingAssociationSemantic_NONE=NONE merchandisingAssociationSemantic_BRAKE_PAD=BRAKE_PAD merchandisingAssociationSemantic_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.

Chapter 6. Enabling the merchandising associations Semantic Attribute

93

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

<wcfResourceBundleKey name="merchandisingAssociationSemantic_TEMP" /> <wcfResourceBundleKey name="merchandisingAssociationSemantic_NONE" /> <wcfResourceBundleKey name="merchandisingAssociationSemantic_BRAKE_PAD" /> <wcfResourceBundleKey name="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. 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. 3. Update the file to point to the new resource bundle file: <library> <!-- File to add customer libraries --> <!-- Catalog resource bundle extension -->

Chapter 6. Enabling the merchandising associations Semantic Attribute

95

<include href="../../redbooks/catalog/ extCatalogManagementResourceBundle.lzx" /> <!-- Merchandising Semantic Validator --> <include href="../../redbooks/catalog/objectDefinitions/ MerchandisingSemanticValidator.lzx" /> </library>

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.

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.co mmerce.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"> ...

96

WebSphere Commerce Line-of-Business Tooling Customization

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"/> <wcfPropertyValue displayName="${extCatalogResources. merchandisingAssociationSemantic_COMES_WITH.string}" value="COMES_WITH"/> <wcfPropertyValue displayName="${extCatalogResources. merchandisingAssociationSemantic_TEMP.string}" value="TEMP"/> <wcfPropertyValue displayName="${extCatalogResources. merchandisingAssociationSemantic_NONE.string}" value="NONE"/> <wcfPropertyValue displayName="${extCatalogResources. merchandisingAssociationSemantic_BRAKE_PAD.string}" value="BRAKE_PAD"/>

Chapter 6. Enabling the merchandising associations Semantic Attribute

97

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): <extMerchandisingSemanticValidator errorMessage="${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

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

else if (semantic == tire && name != accessory) return false; else return 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

<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

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

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

Chapter 6. Enabling the merchandising associations Semantic Attribute

103

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

For further study, see the MASSOC and MASSOCTYPE table definitions here: http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.co mmerce.database.doc/database/massoc.htm http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.co mmerce.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

106

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

107

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 menus buyable=Buyable notBuyable=Not buyable makeBuyable=Make buyable makeNotBuyable=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

http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm.co mmerce.openlazlo.doc/lzx/commerce/catalog/objectDefinitions/ProductPrim aryObjectDefinition.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

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/CustomSer vice.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/Cat alogEntryGrid.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

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

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

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

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

<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

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

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

118

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

119

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

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

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

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/searchDefinitio ns (the folder will be created if it does not already exist)

Chapter 8. Advanced search for merchandising associations

123

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.merchandisingAssociationsSearchDisplayName.string}" listClass="catCatalogEntrySearchGrid" listTitle="${extCatalogResources.merchandisingAssociationsSearchListTitle.string}" advancedSearchContentClass="catMerchandisingAssociationsAdvancedSearchContent"> <wcfSearchService name="findAllMerchandisingAssociations" 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 displayName listClass listTitle Defines the name of the business object search type. The display name for this search type in the simple and advanced search options. The grid class that displays the result of business objects that are returned from the service. 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

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/searchDefinitio ns 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.strin g}" 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

</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.stri ng); this.addItem(catalogResources.merchandisingAssociationName_XSELL.str ing,catalogResources.merchandisingAssociationName_XSELL.string); this.addItem(catalogResources.merchandisingAssociationName_UPSELL.st ring,catalogResources.merchandisingAssociationName_UPSELL.string); this.addItem(catalogResources.merchandisingAssociationName_REPLACEME NT.string,catalogResources.merchandisingAssociationName_REPLACEMENT. string); this.selectItem(catalogResources.merchandisingAssociationName_ACCESS ORY.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

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/FindMerchandisingAssocia tionsSearchDefinition.lzx"/> <include href="../../redbooks/catalog/searchDefinitions/MerchandisingAssociation sAdvancedSearchContent.lzx"/>

Chapter 8. Advanced search for merchandising associations

127

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. 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. 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 Entries merchandisingAssociationsSearchDisplayName=Merchanding Associations catalogEntrySourceCodeSearchPrompt=Catalog Entry Source Code associationNameSearchPrompt=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.

128

WebSphere Commerce Line-of-Business Tooling Customization

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.Catalo gLOB"> <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

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

130

WebSphere Commerce Line-of-Business Tooling Customization

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/SerializeCatalogEn tries.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.Catalog EntryType in its data area. 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. An expression builder constructs an XPath expression to retrieve data. Specifies the name of the exported scripting variable. This variable holds the Show verb object that is retrieved from the services.

var

expressionBuilder varShowVerb

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

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. 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. 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</ty pe> </data-type>

132

WebSphere Commerce Line-of-Business Tooling Customization

<client-facade> <data-type-name>CatalogEntry</data-type-name> <class>com.ibm.commerce.catalog.facade.client.CatalogFacadeClient</c lass> <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.CatalogS earchExpressionBuilder</class> <method>formatExpression</method> <param> <name>template</name> <value>/CatalogEntry[Association[(Name='$associationName$')] and search(CatalogEntryIdentifier/ExternalIdentifier/PartNumber='$source CatentryCode$')]</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

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_ID COLS:CATENTRY:MARKFORDELETE=CATENTRY:MARKFORDELETE <!-- CATALOG table --> COLS:CATALOG=CATALOG:* COLS:CATALOG_ID=CATALOG:CATALOG_ID

134

WebSphere Commerce Line-of-Business Tooling Customization

<!-- 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_TO COLS: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_STATEMENT name=/CatalogEntry[Association[(Name=)] and search()] base_table=CATENTRY sql= SELECT MASSOCCECE.$COLS:CATENTRY_ID_FROM$ FROM CATENTRY 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

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_STATEMENT name=IBM_CatalogEntryDescriptionWithPriceAssocSQL base_table=CATENTRY additional_entity_objects=true sql= SELECT CATENTRY.$COLS:CATENTRY$, CATENTDESC.$COLS:CATENTDESC$, LISTPRICE.$COLS:LISTPRICE$ FROM CATENTRY LEFT OUTER JOIN CATENTDESC ON (CATENTDESC.CATENTRY_ID = CATENTRY.CATENTRY_ID AND CATENTDESC.LANGUAGE_ID IN ($CONTROL:LANGUAGES$)) LEFT OUTER JOIN LISTPRICE ON (CATENTRY.CATENTRY_ID = LISTPRICE.CATENTRY_ID) WHERE CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$) END_ASSOCIATION_SQL_STATEMENT BEGIN_ASSOCIATION_SQL_STATEMENT name=IBM_CatalogEntryToCatalogGroupRelationship base_table=CATENTRY additional_entity_objects=true sql= SELECT CATENTRY.$COLS:CATENTRY$, CATGPENREL.$COLS:CATGPENREL$, CATGROUP.$COLS:CATGROUP$

136

WebSphere Commerce Line-of-Business Tooling Customization

FROM CATENTRY, CATGPENREL JOIN CATGROUP 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 = 0 END_ASSOCIATION_SQL_STATEMENT BEGIN_ASSOCIATION_SQL_STATEMENT name=IBM_ParentCatalogEntryForRootRelationships base_table=CATENTRY additional_entity_objects=true sql= 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$ FROM CATENTRY,CATENTREL JOIN CATENTRY CATENTRY_PARENT ON CATENTRY_PARENT.CATENTRY_ID = CATENTREL.CATENTRY_ID_PARENT LEFT OUTER JOIN CATENTDESC ON CATENTDESC.CATENTRY_ID = CATENTREL.CATENTRY_ID_PARENT AND CATENTDESC.LANGUAGE_ID IN ($CONTROL:LANGUAGES$) WHERE CATENTRY.CATENTRY_ID IN ($ENTITY_PKS$) AND CATENTREL.CATENTRY_ID_CHILD = CATENTRY.CATENTRY_ID AND CATENTRY.MARKFORDELETE = 0 AND CATENTRY_PARENT.MARKFORDELETE = 0 END_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

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_MerchandisingAssociatonsSearch BEGIN_ENTITY base_table=CATENTRY className=com.ibm.commerce.foundation.internal.server.services.dataa ccess.graphbuilderservice.DefaultGraphComposer associated_sql_statement=IBM_CatalogEntryDescriptionWithPriceAssocSQ L associated_sql_statement=IBM_CatalogEntryToCatalogGroupRelationship associated_sql_statement=IBM_ParentCatalogEntryForRootRelationships END_ENTITY END_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

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

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

Chapter 8. Advanced search for merchandising associations

141

142

WebSphere Commerce Line-of-Business Tooling Customization

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.

Copyright IBM Corp. 2008. All rights reserved.

143

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

9.2 Price comparison service


Many Web sites provide price comparison services, for example: http://www.PriceGrabber.com http://www.Shopzilla.com http://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. Note: For more detailed information about the CNET API, refer to the following URL: http://api.cnet.com/ 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> . . .

Chapter 9. Price comparison mashup

145

<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

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

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.

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

148

WebSphere Commerce Line-of-Business Tooling Customization

</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 labels priceTab=Price priceListTitle=Price List merchantColumnTitle=Merchant priceColumnTitle=Price #--Price Comparison component messages noPriceFound=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%3Dtr ue&iod=hlPrice%2Coffers%2CgoodBad&orderBy=price&sortDesc=true&start=0&r esults=10

Chapter 9. Price comparison mashup

149

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

HTTP Dataset declaration


The 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

Custom grid declaration


We 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:/CNETRespon se/" 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

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 area
The 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

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 declaration
We 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

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.st ring, "{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

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

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

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

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 pane


The 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

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 tab


The 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 tab


The 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

extCatalogProductPricePane (See section Creating a new property pane on page 159). 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.
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>

Chapter 9. Price comparison mashup

161

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

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

Chapter 9. Price comparison mashup

163

Figure 9-4 Price tab - Includes new price comparison grid

164

WebSphere Commerce Line-of-Business Tooling Customization

10

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.

Copyright IBM Corp. 2008. All rights reserved.

165

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

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

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.

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.

Chapter 10. Customizing user preferences

167

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

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 files


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

Chapter 10. Customizing user preferences

169

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.extShe llLOB"> <wcfResourceBundleKey name="userPreferencePriceComparisonPrompt" /> </class> <extShellResourceBundle id="extShellResources"/> </library> j. Save and close the file.

170

WebSphere Commerce Line-of-Business Tooling Customization

3. Include extShellResourceBundle.lzx in the extension library so that it is recognized by Management Center and available for use: 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. 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 preference


In 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

Chapter 10. Customizing user preferences

171

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

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.getPrefere nce(this.preferenceName)); ]]> </method> <wcfBaseCheckbox name=priceComparisonEnabled text="${extShellResources.userPreferencePriceComparisonPrompt.str ing}" /> </class> </library> f. Save the file. wcfUserPreferenceObject defines the following methods, which you can override to provide your own implementation: oninit applyValue getValue This handler is called an initialization of the user preference. This method applies the preference value to the global preference setting. 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. 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.

loadValue

Chapter 10. Customizing user preferences

173

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

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


In 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

} ]]> </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 preference if (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

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.Busi nessObjectDocumentClientLibraryAction" 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. 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?top ic=/com.ibm.commerce.component-services.doc/refs/rmschangeperson.htm 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.

Chapter 10. Customizing user preferences

177

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?top ic=/com.ibm.commerce.developer.doc/tasks/tmsdfatt.htm

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.

178

WebSphere Commerce Line-of-Business Tooling Customization

11

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.

Copyright IBM Corp. 2008. All rights reserved.

179

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

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

Note: A customer often has a specific list of required languages.

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.

182

WebSphere Commerce Line-of-Business Tooling Customization

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

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. 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. 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=WebS phere%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

184

WebSphere Commerce Line-of-Business Tooling Customization

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

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.

Product Properties Panel <class = wcfPropertyGroup>

creates
Property Editor <class = wcfRichTextPropertyEditor >

edit facility

binds
Model (Product) {long description property} Widget <class = wcfRichTextEditor>

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.

186

WebSphere Commerce Line-of-Business Tooling Customization

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 Editors basic pattern is the same as the out-of-the box Property Editor of Figure 11-3 on page 186.

Product Properties Panel <class = wcfPropertyGroup>

<class = wcfDialog>

creates

displays

opens

returns corrected text

Property Editor <class = extPropertySpellCheck>

binds
Model (Product) {long description property} Widget <class =extSpellCheckButton>

Figure 11-4 Spell Check Editor Relationship

Chapter 11. Spell Checker

187

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

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.
With suggested corrections 1 title Spell Check There are 2 unknown words 3 highlight A [spellin] misteak or two Unknown word 5 labels spellin Skip 6 skip / replace buttons 2 information 4 unknown word

Replace with

spelling

Replace

Suggestions

spell in spelling spleen spline

7 corrected word 8 suggestions list

9 OK / Cancel Buttons

OK

Cancel

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,

Chapter 11. Spell Checker

189

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

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 follows: 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

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

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

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

Chapter 11. Spell Checker

193

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

There are 2 unknown words

2a 2b

A [spellin] misteak or two

Unknown word

2c spellin
spelling spell in spelling spleen spline

Skip

2d

Replace with Suggestions

Replace

OK

Cancel

Figure 11-6 Spell Checker panel-view hierarchy

194

WebSphere Commerce Line-of-Business Tooling Customization

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

Chapter 11. Spell Checker

195

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

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 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>eCommerce</edittext> <!-- the suggestions list, populated with suggestions for the unknown word as returned by the spell check service -->

Chapter 11. Spell Checker

197

<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

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

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. 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.lz x/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.
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;

200

WebSphere Commerce Line-of-Business Tooling Customization

} </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

</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 long description edit fields. These buttons will invoke a spell check 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

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

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

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

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

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

Chapter 11. Spell Checker

207

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 selection list --> <view name="textView" y="${parent.highlightedText.y +parent.highlightedText.height}"> suggestions

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

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

Example 11-8 spellCheckDS

<!-- xml that would be returned from the spell check service if 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"> <DocumentSummary xmlns: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

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 corrected value. This method is called when the user clicks OK/APPLY to apply 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

</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 textToCheck parameter --> <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 the spell 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 text when the user clicks the OK button after making corrections.

212

WebSphere Commerce Line-of-Business Tooling Customization

Note: this example version is incomplete, it just logs the text to 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

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

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

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 service http://ws.cdyne.com/SpellChecker/check.asmx/CheckTextBody? LicenseKey=anything&BodyText=string note: 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

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

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

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

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 changed if 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 previous var cleanedSentences = wcfStringUtil.replace(this.text, this.appendHighlightHTML, ""); var cleanedSentences = wcfStringUtil.replace(cleanedSentences, this.prependHighlightHTML, ""); // finally, highlight occurences of the word var 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

</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 text this.text = wcfStringUtil.replace(this.text, wordToChange, newWord); </method> <!-- override of the normal datapath apply data method, this is to use the word returned from 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

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. 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(spellCheckWind ow.textToCheck); spellCheckWindow.correctionsView.highlightedText.highlightWord(this.dat a); </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.

222

WebSphere Commerce Line-of-Business Tooling Customization

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

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.
call service checking time out cancel error result[no unknown words]

initial result[unknown words] noCorrectionsNeeded

cancel

timedOut cancel closed

skip/ replace

error cancel

correctionsToDo

select/ edit ok/cancel ok/cancel

skip/ replace

allProcessed skip/ replace

wordEdited

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 of the Spell Check Process. Changes to the currentState attribute will trigger associated listeners and constraints. --> <node id="spellCheckerController_SC"> <attribute name="state" type="string" value="initial" /> <attribute name="transition" type="string" />

224

WebSphere Commerce Line-of-Business Tooling Customization

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

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

226

WebSphere Commerce Line-of-Business Tooling Customization

<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

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 check service --> <text id="unknownWordCount_SC" visible="false" datapath= "spellCheckDS:/DocumentSummary/MisspelledWordCount/text()" ondata="spellCheckWindow.handleUnknownWordCount(this.data);" /> <!-- The spell check results prompt message with [count] place holder 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

do, otherwise set for corrections to do --> <method name="handleUnknownWordCount" args="count" > // first, replace the count placeholder with the count // in the prompt message this.spellCheckResultsMsg = wcfStringUtil.replace(this.spellCheckResultsTemplate , "[count]", count); // next, set the state, this event will update the message // view with the prompt message if (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

Table 11-1 outlines the button state control.


Table 11-1 Button state control Button Cancel Skip Enabled Always Always Disabled Never Never (we hide corrections view when there are no unknown words) state <> wordEdited

Replace

state = wordEdited (for example, a word is selected or edited, but no other action is taken yet) wordReplaced = true (for example, the replace button is used to replace a word)

OK

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. 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();"

230

WebSphere Commerce Line-of-Business Tooling Customization

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

"spellCheckWindow.handleSelectedSuggestion(this.getText());" > <textlistitem datapath="Suggestions/text()" /> </list> ... <!-- handle the case where a user has edited the word for correction i.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 displayed corrected word with it. Also, enable the replace button, as a suggestion 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

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

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

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.

234

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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

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

12

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.

Copyright IBM Corp. 2008. All rights reserved.

239

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

On a federated environment with multiple nodes, the changes of the stores 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

List View Explorer View

Utilities View

Properties View

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.

242

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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

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

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.

IBM Management Center for WebSphere Commerce


LOBTools

WebSphere Commerce Server


HTTP POST XML
LOBTools CustomAppProperties-DataObjects

OpenLaszlo Application

Managament Center Web Application


EJB Call

Logical SDOs

CustomAppProperties service test application


CustomAppProperties-DataObjects

BOD Commands

Business Object Mediators


CustomAppProperties-Server

Physical Object Persistence Service

Logical SDOs
SOAP Request EJB Call

JUnit Test Cases


CustomAppProperties-UnitTests

Client Library
CustomAppProperties-Client

Web Service Router


SOAP Response
CustomAppPropertiesServicesHTTPInterface

JDBC

Database Server
Legend

Remote usage (Call) Local usage (Use)

WebSphere Commerce Database

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.

Chapter 12. Custom Application Configuration Management tool

247

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

248

WebSphere Commerce Line-of-Business Tooling Customization

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

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

Top object definition


The 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

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


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

252

WebSphere Commerce Line-of-Business Tooling Customization

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 definitions


Two primary objects are modeled for the Custom Application Configuration Management tool, ConfigCategory and ConfigProperty.

Primary object definition for ConfigCategory


ConfigCategory 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 objects 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

name for an object is the value of its configCategoryName property, which is the value that is displayed in the Explorers tree view. 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.
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 />

254

WebSphere Commerce Line-of-Business Tooling Customization

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

Primary object definition for ConfigProperty


The 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 objects 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 objects 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

displayNameProperty="key" idProperty="configPropertyId" newDisplayName="${extConfigResource.config_PropertyNewDisplayName.strin g} " 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

<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

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

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

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 definition


Navigation 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

<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

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

Search list definition


The 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

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

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 objects 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. 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.
Example 12-17 Property view class definition

<class name="extConfigurationProperties" extends="wcfObjectProperties"> <wcfPropertyPane name="pane">

266

WebSphere Commerce Line-of-Business Tooling Customization

<!-- 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: Category


The 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

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

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

Chapter 12. Custom Application Configuration Management tool

269

Object property: type


The 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: key


The 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: description


The 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: value


The 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

Table 12-1 value property editors Property type SimpleText Integer Float Date DateTime Any other type Editor wcfPropertyInputText wcfPropertyNumericText wcfPropertyNumericText wcfPropertyDatePicker wcfPropertyDateTimePicker wcfPropertyInputText

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

Chapter 12. Custom Application Configuration Management tool

271

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

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

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

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

Chapter 12. Custom Application Configuration Management tool

275

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

<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 item
To 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

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


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

278

WebSphere Commerce Line-of-Business Tooling Customization

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 menu


The 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

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/ttfcustomizeshel l.htm
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.co mmerce.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.

280

WebSphere Commerce Line-of-Business Tooling Customization

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

Chapter 12. Custom Application Configuration Management tool

281

appdef

DPTK

RAD Projects: CustomAppProperties-Client CustomAppProperties-UnitTests CustomAppProperties-Server

CustomAppProperties-DataObjects CustomAppPropertiesServicesJMSInterface CustomAppPropertiesServicesHTTPInterface

CustomAppProperties-UnitTests JUnit test cases

CustomAppProperties-Client Client Library

Access control policy XML Command registration Service module configuration Business object mediator configuration Value mapping

CustomAppProperties-Server acpload massload Business logic Get commands Change commands Business Object Mediators Read mediators Physical object persistence service Physical SDO Java classes Data Service Layer Wizard Change mediators Process commands Sync commands

Object-relational metadata

Query templates

Database

CustomAppProperties-DataObjects Logical SDOs Generate model code

Legend text Generates Configures Uses or Calls

Noun XSD/WSDL

Ecore, genmodel

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.

282

WebSphere Commerce Line-of-Business Tooling Customization

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

appdef

DPTK

RAD Projects: CustomAppProperties-Client CustomAppProperties-UnitTests CustomAppProperties-Server

CustomAppProperties-DataObjects CustomAppPropertiesServicesJMSInterface CustomAppPropertiesServicesHTTPInterface

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-component name="CustomAppProperties" company="Redbooks" packagenameprefix="com.redbooks.commerce" namespace="http://www.redbooks.ibm.com/xmlns/prod/commerce/9" nlsprefix="redbooks" type="BOD"> <noun

284

WebSphere Commerce Line-of-Business Tooling Customization

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

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-MoveItToWCServerX MLFolder/xml from the CustomAppProperties-Server project into the <WCDE_installdir>/xml directory. 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-MoveItToWCServerX MLFolder/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. 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.
CustomAppProperties-DataObjects Logical SDOs Generate model code Noun XSD/WSDL Ecore, genmodel

Figure 12-18 Defining the CustomAppProperties noun

286

WebSphere Commerce Line-of-Business Tooling Customization

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

2. Right-click the CustomAppProperties-DataObjects project, and select Refresh.

Examining the generated default noun


Before building the noun, let us examine the default noun that was generated for you. Open the CustomAppProperties-DataObjects/xsd/OAGIS/9.0/Overlays/Redbooks/Comme rce/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

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

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 structure


Now you can define the target structure of the CustomAppProperties noun that represents the configuration settings.

290

WebSphere Commerce Line-of-Business Tooling Customization

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/St oreent_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. 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\Com merce\Resources\Components\IdentifierTypes.xsd and use the StoreIdentifierType type. b. /CustomAppProperties/Value

Chapter 12. Custom Application Configuration Management tool

291

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

Figure 12-23 ValueTypeEnum simple type, General tab of Properties view

Chapter 12. Custom Application Configuration Management tool

293

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 nouns identifier. /CustomAppProperties/CustomAppPropertiesIdentifier/ExternalIdentifier This field represents the nouns 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

/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 a CustomAppProperties. </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 a CustomAppProperties. </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

<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 noun was last changed. The value is set as the versionID attribute in the corresponding BODs. </documentation> </annotation> </element>

296

WebSphere Commerce Line-of-Business Tooling Customization

<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

</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 provides the client with information, how to interpret the data stored in the field 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

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

Chapter 12. Custom Application Configuration Management tool

299

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

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

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 conversion if (newValue instanceof ValueTypeEnum) {

302

WebSphere Commerce Line-of-Business Tooling Customization

setValueType((ValueTypeEnum) newValue); } else { setValueType(ValueTypeEnum.get((String) newValue)); } return; Note: If you need to regenerate the logical SDOs, you might need to re-apply the changes that we described here.

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

Physical object persistence service Physical SDO Java classes Data Service Layer Wizard Database

Figure 12-28 Generating the Persistence layer for the CustomAppProperties service module

Chapter 12. Custom Application Configuration Management tool

303

Creating the XAPPPROPS table


Because 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

REFERENCES "STOREENT"("STOREENT_ID") ON DELETE CASCADE ON 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 STOREENT_ID Column type INTEGER NOT NULL Description The internal reference number that identifies the store entity. These columns and the NAME are a unique index. The internal reference number of the configuration setting. For concurrency control. Currently unused. The external identifier that identifies the configuration setting. These columns and the STOREENT_ID are a unique index. The value of the configuration setting. An administrative description of the configuration setting.

XAPPPROPS_ID OPTCOUNTER NAME

BIGINT NOT NULL SMALLINT CHARACTER(254) NOT NULL

VALUE DESCRIPTION

VARCHAR(2000) VARCHAR(2000)

Chapter 12. Custom Application Configuration Management tool

305

Column name VALUETYPE

Column type CHARACTER(254) NOT NULL

Description 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. A category description that is used to group configuration settings. Customizable. Customizable. Customizable. Customizable. Customizable. Customizable.

CATEGORY

CHARACTER(254)

VERSION FIELD1 FIELD2 FIELD3 FIELD4 FIELD5

INTEGER BIGINT FLOAT VARCHAR(2000) VARCHAR(2000) VARCHAR(2000)

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. Note: We did not test the SQL statements on Oracle. 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.

306

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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.datatyp es com.redbooks.commerce.customappproperties.facade.server.entity.datatyp es.impl com.redbooks.commerce.customappproperties.facade.server.entity.datatyp es.util

Chapter 12. Custom Application Configuration Management tool

309

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. 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. 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.customapppropertie s/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.customappproperti es 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

310

WebSphere Commerce Line-of-Business Tooling Customization

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.customapppropertie s/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.dataa ccess.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

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. 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.customapppropertie s/wc-component.xml file using the <_config:protectable-proxy> sub-element of the <_config:authorization-configuration> element. In this scenario, you implement access control.

312

WebSphere Commerce Line-of-Business Tooling Customization

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.datat ypes.impl.CustomAppPropertiesEntityPackageImpl.eINSTANCE.getCustomAp pPropertiesRoot(); 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.data types.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

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

Service module configuration Business object mediator configuration Value mapping Business Object Mediators Read mediators Change mediators

Figure 12-31 Implementing Business Object Mediators and updating the service module configuration

314

WebSphere Commerce Line-of-Business Tooling Customization

Implementing the read mediators


Code 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 tables 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

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 name buildCustomAppPropertiesIdentifier(aCustomAppPropertiesLogicalDO, aCustomAppPropertiesPhysicalDO); // set all attributes aCustomAppPropertiesLogicalDO.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 DataObject buildUserData(aCustomAppPropertiesLogicalDO, aCustomAppPropertiesPhysicalDO); 6. Implement the buildCustomAppPropertiesIdentifier() method. Replace the methods 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 object CustomAppPropertiesIdentifierType aCustomAppPropertiesIdentifier = getCustomAppPropertiesFactory() .createCustomAppPropertiesIdentifierType(); aCustomAppPropertiesLogicalDO .setCustomAppPropertiesIdentifier(aCustomAppPropertiesIdentifier);

316

WebSphere Commerce Line-of-Business Tooling Customization

Xappprops aCustomAppPropertiesPhysicalDO = (Xappprops) aPhysicalEntityType; // set the uid in ID object aCustomAppPropertiesIdentifier.setUniqueID(aCustomAppPropertiesPhysicalDO .getXappprops_id()); // set the name in ID object CustomAppPropertiesExternalIdentifierType 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 methods 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

} } 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 mediators


The code generation pre-built the following read mediators for you: ChangeCustomAppPropertiesMediator ChangeCustomAppPropertiesBasePartMediator

Understanding the ChangeCustomAppPropertiesMediator class


The 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

Table 12-3 ChangeCustomAppPropertiesMediator methods to be implemented Method validateCreate() Description 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. Implementation 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

Method create()

Description 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 updateNameValuePairTy pe() 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.

Implementation 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-mediat or.xml file.

Changes are not necessary.

320

WebSphere Commerce Line-of-Business Tooling Customization

Method validateDelete()

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

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

Chapter 12. Custom Application Configuration Management tool

321

Method findPhysicalEntity()

Description 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().

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

322

WebSphere Commerce Line-of-Business Tooling Customization

Method initializePhysicalDataConta iner()

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

Implementation 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 ChangeCustomAppPrope rtiesBasePartMediator class this method is not implemented.

No action.

Chapter 12. Custom Application Configuration Management tool

323

Method change()

Description Because the Change verb is implemented by the ChangeCustomAppPrope rtiesBasePartMediator class this method is not implemented.

Implementation No action.

Understanding the ChangeCustomAppPropertiesBasePartMediator class


A change mediators 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.

324

WebSphere Commerce Line-of-Business Tooling Customization

Table 12-4 ChangeCustomAppPropertiesBasePartMediator methods to implement Method validateChange() Description 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 the list of exceptions to be returned to the caller. update() Updates the physical data container with the modified logical noun. Sets all fields from logical noun to physical object. Calls the updateNameValuePairTy pe() 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. Implementation 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.

Chapter 12. Custom Application Configuration Management tool

325

Method updateNameValuePairTy pe()

Description 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-media tor.xml file. This method returns the physical SDO from the physical data container that was created in the ChangeCustomAppProp ertiesMediator by calling the getParentPhysicalDataC ontainer() method. Function works similar to findPhysicalEntity() method in the ChangeCustomAppProp ertiesMediator. Is used by the validateChange() and update() methods.

Implementation Does not need to be changed.

findPhysicalEntity()

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.

initializePhysicalDataCon tainer()

Initializes the physical data container for this mediator. It currently performs no actions because the physical data container from the ChangeCustomAppProp ertiesMediator is used in this mediator. Performs no actions because the ChangeCustomAppProp ertiesMediator does the resolve.

Does not need to be changed.

resolveByExternalIdentifi er()

Does not need to be changed.

326

WebSphere Commerce Line-of-Business Tooling Customization

Method validateCreate()

Description Performs no checking because the ChangeCustomAppProp ertiesMediator does the validation. Performs no actions because the ChangeCustomAppProp ertiesMediator creates the nouns. Performs no checking because the ChangeCustomAppProp ertiesMediator does the validation. Performs no actions because the ChangeCustomAppProp ertiesMediator deletes the nouns.

Implementation Does not need to be changed.

create()

Does not need to be changed.

validateDelete()

Does not need to be changed.

delete()

Does not need to be changed.

Updating the CustomAppPropertiesFacadeConstants class


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

Chapter 12. Custom Application Configuration Management tool

327

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

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

// ============================================================================= // 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

/** * 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

*/ 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"; } Note: Declare all constants as public static final and be of type String.

Updating the ChangeCustomAppPropertiesMediator class


Update 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) {

332

WebSphere Commerce Line-of-Business Tooling Customization

String customapppropertiesName = aCustomAppProperties .getCustomAppPropertiesIdentifier().getExternalIdentifier().getName(); if (customapppropertiesName == null || customapppropertiesName.length() == 0) { // name cannot be empty ApplicationError 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 already if (resolveByExternalIdentifier(aNoun)) { ApplicationError validateError = new ApplicationError( ApplicationError.TYPE_GENERIC_ERROR, CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_ALREADY_EXIST S, 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

ApplicationError validateError = new ApplicationError( ApplicationError.TYPE_GENERIC_ERROR, CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_EMPTY, null, LOGGER.getResourceBundleName()); validationErrors.add(validateError); } // Check description String strDescription = aCustomAppProperties.getDescription(); // check description's length if (CustomAppPropertiesMetadata.invalidStringLength(strDescription, CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_DESCRIPTION_LENGTH_LIMIT)) { ApplicationError validateError = new ApplicationError( ApplicationError.TYPE_GENERIC_ERROR, CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_DESCRIPTION_TOO_LO NG, 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 entity CustomAppPropertiesType 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 dataobject Long 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

// set the name and storeent_id if (logicalCustomAppProperties.getCustomAppPropertiesIdentifier() != null && logicalCustomAppProperties.getCustomAppPropertiesIdentifier() .getExternalIdentifier() != null) { physicalCustomAppProperties.setName(logicalCustomAppProperties .getCustomAppPropertiesIdentifier().getExternalIdentifier().getName()); physicalCustomAppProperties.setStoreent_id(logicalCustomAppProperties .getCustomAppPropertiesIdentifier().getExternalIdentifier() .getStoreentId()); } // set String String String String all other attributes description = logicalCustomAppProperties.getDescription(); value = logicalCustomAppProperties.getValue(); valueType = logicalCustomAppProperties.getValueType().getName(); 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 field updateNameValuePairType(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

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 delete CustomAppPropertiesType logicalCustomAppProperties = (CustomAppPropertiesType) aNoun; long customapppropertiesId = logicalCustomAppProperties .getCustomAppPropertiesIdentifier().getUniqueID(); // Get the physical data object with specific id Xappprops 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

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 DataObject if (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 DataObject if (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

// Get a list of extenal IDs from the nouns List 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 // containers SelectionCriteria 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 PhysicalDataContainer physicalEntities = 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

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 exists if (customapppropertiesNoun.getCustomAppPropertiesIdentifier() != null) { uniqueId = customapppropertiesNoun.getCustomAppPropertiesIdentifier() .getUniqueID(); } if (LoggingHelper.isTraceEnabled(LOGGER)) { LOGGER.logp(Level.FINE, CLASSNAME, METHODNAME, "need to resolve noun"); } // get the external id if (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 extID SelectionCriteria 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

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 extID if (physicalEntites.getPhysicalObjects().size() > 0) { resolveStatus = true; Xappprops customapppropertiesEntity = (Xappprops) physicalEntites .getPhysicalObjects().get(0); // set the id back to the Logical Business Object customapppropertiesNoun.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

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 class


Update 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 uid Xappprops physicalCustomAppProperties = (Xappprops) findPhysicalEntity(aNoun, aNounPart); if (physicalCustomAppProperties != null) { CustomAppPropertiesType logicalCustomAppProperties = (CustomAppPropertiesType) aNoun; // Check whether the name is valid if (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

.getStoreentId(); if (name == null || name.length() == 0) { // name cannot be empty ApplicationError 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 exist if (physicalDOList != null && physicalDOList.size() != 0) { ApplicationError validateError = new ApplicationError(

342

WebSphere Commerce Line-of-Business Tooling Customization

ApplicationError.TYPE_GENERIC_ERROR, CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_NAME_ALREADY_EXIST S, new Object[] { name }, LOGGER.getResourceBundleName()); validationErrors.add(validateError); } else if (CustomAppPropertiesMetadata.invalidStringLength(name, CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_NAME_LENGTH_LIMIT)) { // checked name length ApplicationError 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 description if (CustomAppPropertiesMetadata.invalidStringLength(logicalCustomAppProperties .getDescription(), CustomAppPropertiesMetadata.CUSTOMAPPPROPERTIES_DESCRIPTION_LENGTH_LIMIT)) { ApplicationError validateError = new ApplicationError( ApplicationError.TYPE_GENERIC_ERROR, CustomAppPropertiesApplicationMessageKeys._APP_CUSTOMAPPPROPERTIES_DESCRIPTION_TOO_LO NG, 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

// set the name and storeent_id if ((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 String String String String all other attributes description = logicalCustomAppProperties.getDescription(); value = logicalCustomAppProperties.getValue(); valueType = logicalCustomAppProperties.getValueType().getName(); 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 field updateNameValuePairType(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 DataObject if (pdc != null) { CustomAppPropertiesType aLogicalCustomAppProperties = (CustomAppPropertiesType) aNoun;

344

WebSphere Commerce Line-of-Business Tooling Customization

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 DataObject if (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

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

Service module configuration Business object mediator configuration Value mapping Business Object Mediators Read mediators Physical object persistence service Physical SDO Java classes Change mediators

Object-relational metadata

Query templates

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.

346

WebSphere Commerce Line-of-Business Tooling Customization

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

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[ExternalIdentif ier[(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. 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. 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

348

WebSphere Commerce Line-of-Business Tooling Customization

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_All base_table=XAPPPROPS sql= 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

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=XAPPPROPS sql= 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=XAPPPROPS sql=

350

WebSphere Commerce Line-of-Business Tooling Customization

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=XAPPPROPS sql= 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_AllFields base_table=XAPPPROPS additional_entity_objects=true sql= SELECT --> --> --> -->

Chapter 12. Custom Application Configuration Management tool

351

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_Search BEGIN_ENTITY base_table=XAPPPROPS associated_sql_statement=Redbooks_XAPPPROPS_AllFields END_ENTITY END_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.customapppropertie s 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

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_Update base_table=XAPPPROPS sql= SELECT XAPPPROPS.$COLS:XAPPPROPS$ FROM XAPPPROPS WHERE

Chapter 12. Custom Application Configuration Management tool

353

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=XAPPPROPS sql= 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 mapping


You 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.customapppropertie s 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

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.CustomAppProp ertiesType" physicalType="com.redbooks.commerce.customappproperties.facade.server.entity.datatype s.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.co mmerce.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.customapppropertie s 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

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

356

WebSphere Commerce Line-of-Business Tooling Customization

Access control policy XML Command registration

CustomAppProperties-Server acpload massload Business logic Get commands Change commands Process commands Sync commands

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

Chapter 12. Custom Application Configuration Management tool

357

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.co mmerce.developer.soa.doc/concepts/csddesignpatterns.htm

BOD commands used in this scenario


We 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

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

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 commands


Register 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

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.customapppropertie s 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.serv er.commands.ChangeCustomAppPropertiesPartPostActionCmd+/CustomAppPro perties[]" 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

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\CustomAppPro perties-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

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

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.co mmerce.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-MoveItToWCServerXML Folder/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

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-Access ProfileActionGroup...> by <ActionGroupAction Name="GetCustomAppProperties.Redbooks_All"/> <ActionGroupAction Name="GetCustomAppProperties.Redbooks_Category"/>

Chapter 12. Custom Application Configuration Management tool

365

<ActionGroupAction Name="GetCustomAppProperties.Redbooks_Search"/> iii. Remove the <ActionGroup Name="CustomAppProperties-CustomAppProperties-CustomAppProp ertiesManagers-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-CustomAppProp ertiesManagers-AccessProfilePolicy"...>. v. Remove the <PolicyGroupPolicy> element with attribute Name="CustomAppProperties-CustomAppProperties-CustomAppProp ertiesManagers-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-Action Group"...> ii. Remove the empty <ActionGroup Name="CustomAppProperties-CustomAppProperties-CustomAppProp ertiesManagers-ActionGroup"...>. iii. Remove the <Policy Name="CustomAppProperties-CustomAppProperties-CustomAppProp ertiesManagers-CreatorPolicy"...>. iv. Remove the <PolicyGroupPolicy Name="CustomAppProperties-CustomAppProperties-CustomAppProp ertiesManagers-CreatorPolicy"...>. v. In the <Policy Name="CustomAppProperties-CustomAppProperties-AllUsers-Creator Policy"...>, change the UserGroup attribute to UserGroup="SiteAdministrators" and the Name attribute to Name="CustomAppProperties-CustomAppProperties-SiteAdministrato rs-CreatorPolicy" c. In the <PolicyGroupPolicy Name="CustomAppProperties-CustomAppProperties-AllUsers-CreatorPol icy"...> change Name attribute to

366

WebSphere Commerce Line-of-Business Tooling Customization

Name="CustomAppProperties-CustomAppProperties-SiteAdministratorsCreatorPolicy" 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.CustomAppPropertiesT ype.read" CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProp ertiesType.read" /> <!-- change action (Change request) --> <Action Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype.change" CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProp ertiesType.change" />

Chapter 12. Custom Application Configuration Management tool

367

<!-- process actions (Process request) --> <Action Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype.add" CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProp ertiesType.add" /> <Action Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype.delete" CommandName="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProp ertiesType.delete" /> <!-- defining resouce category --> <!-- ================================================ --> <!-- category for CustomAppProperties --> <ResourceCategory Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ypeResourceCategory" ResourceBeanClass="com.redbooks.commerce.customappproperties.facade.server.authorizat ion.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.CustomAppPropertiesT ype.read"/>

368

WebSphere Commerce Line-of-Business Tooling Customization

<ActionGroupAction Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype.change"/> <ActionGroupAction Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype.add"/> <ActionGroupAction Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype.delete"/> </ActionGroup> <!-- defining resource groups --> <!-- ================================================ --> <!-- the customappproperties protectable proxy --> <ResourceGroup Name="CustomAppProperties-CustomAppProperties-ResourceGroup" OwnerID="RootOrganization"> <ResourceGroupResource Name="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ypeResourceCategory"/> </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-AccessProfileAction Group" 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

<!-- 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_c allaghan/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

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 methods 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.
CustomAppProperties-UnitTests JUnit test cases CustomAppProperties-Client Client Library

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.

Chapter 12. Custom Application Configuration Management tool

371

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: 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. 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.co mmerce.component-services.doc/tasks/twvtestcs.htm

372

WebSphere Commerce Line-of-Business Tooling Customization

Implementing utility methods


A 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

* 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

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

} 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

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 import import import import java.text.MessageFormat; java.util.Iterator; java.util.Map; java.util.regex.Matcher; 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 public public public public public public public static static static static static static static static final final final final final final final final String String String String String String String String PARAM_BASE_PATTERN = "\\s*="; EQUAL_CHAR = "="; QUOTE_CHAR = "'"; CURLY_BRACKET_OPEN = "{"; CURLY_BRACKET_CLOSE = "}"; SEARCH_PATTERN = "search\\(\\)"; PARAM_NAME_SEARCH = "_SearchExpression_"; 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

String paramName = (String) iter.next(); // Compile the RegEx pattern to find parameters, depending on the parameter if (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 occurrences Matcher 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

* 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 cases


Implement 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

private static final String SITE_ADMIN_USER_ID = "wcsadmin"; /** * The password of the user id for these unit tests. */ // TODO: modify the test password private static final String SITE_ADMIN_PASSWORD = "your_passwd"; /** * The reference to an existing store. */ // TODO: modify the store reference private 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

} /** * 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 noun CustomAppPropertiesType capNoun = CustomAppPropertiesFactory.eINSTANCE .createCustomAppPropertiesType(); // Create CustomAppProperties identifier from test data CustomAppPropertiesIdentifierType capID = CustomAppPropertiesFactory.eINSTANCE .createCustomAppPropertiesIdentifierType(); capNoun.setCustomAppPropertiesIdentifier(capID); // Use either UniqueID if available or external identifier otherwise if (testData.getUniqueID() != -1) { // set UniqueID to noun capID.setUniqueID(testData.getUniqueID()); } else { // set external identifier to noun CustomAppPropertiesExternalIdentifierType capExID = CustomAppPropertiesFactory.eINSTANCE .createCustomAppPropertiesExternalIdentifierType(); capExID.setName(testData.getName()); capExID.setStoreentId(testData.getStoreent_id()); capID.setExternalIdentifier(capExID); } // Insert CustomAppProperties data from test data capNoun.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

String password) { // construct the callback handler javax.security.auth.callback.CallbackHandler callbackHandler = new com.ibm.commerce.foundation.client.samples.security.auth.callback.SampleCallbackHandl erImpl( userId, password); // construct business context com.ibm.commerce.foundation.common.datatypes.BusinessContextType businessContext = com.ibm.commerce.foundation.common.datatypes.CommerceFoundationFactory.eINSTANCE .createBusinessContextType(); // construct the facade client return 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

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 CustomAppProperties AcknowledgeCustomAppPropertiesType acknowledgeCAP = createCustomAppProperties(testData); // verify name in response String 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 response List 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 inputs CustomAppPropertiesData testData = new CustomAppPropertiesData(); testData.setName("aCustomAppProperty"); testData.setStoreent_id(STOREENT_ID);

Chapter 12. Custom Application Configuration Management tool

383

// Create the BOD request for deleting CustomAppProperties AcknowledgeCustomAppPropertiesType acknowledgeCAP = deleteCustomAppProperties(testData); // verify response List 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

* 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 credentials CustomAppPropertiesFacadeClient iClient = constructFacadeClient(SITE_ADMIN_USER_ID, SITE_ADMIN_PASSWORD); // Create Process BOD ProcessCustomAppPropertiesType processCAP = CustomAppPropertiesFactory.eINSTANCE .createProcessCustomAppPropertiesType(); processCAP.setDataArea(CustomAppPropertiesFactory.eINSTANCE .createProcessCustomAppPropertiesDataAreaType()); // Create the noun CustomAppPropertiesType capNoun = buildCustomAppPropertiesNoun(testData); // Create the action using a pre-defined XPath expression List 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 BOD processCAP.getDataArea().getCustomAppProperties().add(capNoun); // logging the request BOD System.out.println(" The request BOD is sent: "); System.out.println(SDOHelper.toString((DataObject) processCAP)); // Send the BOD request AcknowledgeCustomAppPropertiesType acknowledgeCAP = iClient .processCustomAppProperties(processCAP);

Chapter 12. Custom Application Configuration Management tool

385

// logging the response BOD System.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. Create a client Construct the Change BOD command request Create an action using an XPath expression Build the CustomAppProperties noun Send the request

Review the updateCustomAppProperties() method to see how to:

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 UniqueID CustomAppPropertiesData retrieveData = new CustomAppPropertiesData(); retrieveData.setName("aCustomAppProperty"); retrieveData.setStoreent_id(STOREENT_ID); // Create the BOD request for fetching CustomAppProperties ShowCustomAppPropertiesType 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

long uniqueId = ((CustomAppPropertiesType) showCAP.getDataArea() .getCustomAppProperties().get(0)).getCustomAppPropertiesIdentifier() .getUniqueID(); // define test inputs CustomAppPropertiesData testData = new CustomAppPropertiesData(); testData.setUniqueID(uniqueId); testData.setDescription("The UPDATED description of aCustomAppProperty"); // Create the BOD request for creating CustomAppProperties RespondCustomAppPropertiesType respondCAP = updateCustomAppProperties(testData); // verify description has changed in response String 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 response List 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 credentials CustomAppPropertiesFacadeClient iClient = constructFacadeClient(SITE_ADMIN_USER_ID, SITE_ADMIN_PASSWORD); // Create Change BOD

Chapter 12. Custom Application Configuration Management tool

387

ChangeCustomAppPropertiesType changeCAP = CustomAppPropertiesFactory.eINSTANCE .createChangeCustomAppPropertiesType(); changeCAP.setDataArea(CustomAppPropertiesFactory.eINSTANCE .createChangeCustomAppPropertiesDataAreaType()); // Create the noun CustomAppPropertiesType capNoun = buildCustomAppPropertiesNoun(testData); // Create the action using a pre-defined XPath expression List 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 BOD changeCAP.getDataArea().getCustomAppProperties().add(capNoun); // logging the request BOD System.out.println(" The request BOD is sent: "); System.out.println(SDOHelper.toString((DataObject) changeCAP)); // Send the BOD request RespondCustomAppPropertiesType respondCAP = iClient .changeCustomAppProperties(changeCAP); // logging the response BOD System.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

test_01_ProcessCustomAppPropertiesCreate() and test_05_ChangeCustomAppProperties(). Add the getCustomAppProperties() method, which is in Example 12-61 before the buildCustomAppPropertiesNoun() method. Create a client Construct the Get BOD command request using an XPath expression Build the CustomAppProperties noun Send the request

Review the getCustomAppProperties() method to see how to:

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 inputs CustomAppPropertiesData testData = new CustomAppPropertiesData(); testData.setName("aCustomAppProperty"); testData.setStoreent_id(STOREENT_ID); // Create the BOD request for fetching CustomAppProperties ShowCustomAppPropertiesType showCAP = getCustomAppProperties(testData, CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ALL_INFORMATION, CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_EXTERNAL_ID); // verify response List 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

public void test_03_GetCustomAppPropertiesByCatgByStore() { System.out .println("=== START test_03_GetCustomAppPropertiesByCatgByStore ==="); // define test inputs CustomAppPropertiesData testData = new CustomAppPropertiesData(); testData.setCategory("aCategory"); testData.setStoreent_id(STOREENT_ID); // Create the BOD request for fetching CustomAppProperties ShowCustomAppPropertiesType showCAP = getCustomAppProperties( testData, CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_ALL_INFORMATION, CustomAppPropertiesFacadeConstants.XPATH_CUSTOMAPPPROPERTIES_BY_CATEGORY_BY_STOREENT_ ID); // verify response List 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 inputs CustomAppPropertiesData testData = new CustomAppPropertiesData(); testData.setStoreent_id(STOREENT_ID); testData.setSearchExpression("contains(NAME,'tomappprop') and CATEGORY='aCategory'"); // Create the BOD request for fetching CustomAppProperties ShowCustomAppPropertiesType showCAP = getCustomAppProperties( testData, CustomAppPropertiesFacadeConstants.ACCESS_PROFILE_SEARCH,

390

WebSphere Commerce Line-of-Business Tooling Customization

CustomAppPropertiesFacadeConstants.XPATH_PATTERN_CUSTOMAPPPROPERTIES_SEARCH_BY_STOREE NT_ID); // verify response List 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 credentials CustomAppPropertiesFacadeClient iClient = constructFacadeClient("", ""); // build fully resolved XPath expression String xpathResolved = XpathExpressionHelper.resolveXpathExpression(xpath, testData .getAsMap(), accessProfile); // construct the verb GetCustomAppPropertiesType getCAP = CustomAppPropertiesFactory.eINSTANCE .createGetCustomAppPropertiesType(); getCAP.setDataArea(CustomAppPropertiesFactory.eINSTANCE .createGetCustomAppPropertiesDataAreaType()); getCAP.getDataArea().setGet( AbstractBusinessObjectDocumentFacadeClient.createGetVerb( SelectionCriteriaHelper.STR_XPATH_LANG, xpathResolved)); // logging the request BOD System.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

ShowCustomAppPropertiesType showCustomAppProperties = iClient .getCustomAppProperties(getCAP); // logging the response BOD System.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

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.co mmerce.management-center_customization.doc/concepts/ctfmancenter.htm

Chapter 12. Custom Application Configuration Management tool

393

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-MoveItToWEBProjectF older/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

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

<_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.prop erties.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:ReasonCodeParameterAssociation reasonCode="_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

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='$catego ry$') and CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id= $storeent_id$)]]] with access profile Redbooks_All and name findCustomAppPropertiesByCategoryAndStoreent_id {_wcf.ap=$accessProfile$}/CustomAppProperties[CustomAppPropertie sIdentifier[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/CustomAppPropertie sIdentifier/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

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.CustomAppPropertiesT ype</type> </data-type> <client-facade> <data-type-name>CustomAppProperties</data-type-name> <class>com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFac adeClient</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='$catego ry$') and

398

WebSphere Commerce Line-of-Business Tooling Customization

CustomAppPropertiesIdentifier[ExternalIdentifier[(Storeent_id=$storeent_id$)]]]</expr ession-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[CustomAppPropertie sIdentifier[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/CustomAppPropertie sIdentifier/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.co mmerce.developer.doc/tasks/tsdstrutsconfig.htm

Chapter 12. Custom Application Configuration Management tool

399

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 editors 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 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 UpdateCustomAppProperties: A service call to update an existing configuration setting and to update it in the database

Use these actions to invoke Process commands:

Use this action to invoke Change commands:

400

WebSphere Commerce Line-of-Business Tooling Customization

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.BusinessObjectDocu mentAction" className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjec tDocumentActionMapping"> <set-property property="contextParameters" value="storeId" /> <set-property property="verb" value="Process" /> <set-property property="documentRootFactory" value="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProperties Factory" /> <set-property property="clientLibrary" value="com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFac adeClient" /> <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.BusinessObjectDocu mentAction" className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjec tDocumentActionMapping"> <set-property property="contextParameters" value="storeId" /> <set-property property="verb" value="Change" /> <set-property property="documentRootFactory" value="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProperties Factory" />

Chapter 12. Custom Application Configuration Management tool

401

<set-property property="clientLibrary" value="com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFac adeClient" /> <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.BusinessObjectDocu mentAction" className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjec tDocumentActionMapping"> <set-property property="contextParameters" value="storeId" /> <set-property property="verb" value="Process" /> <set-property property="documentRootFactory" value="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppProperties Factory" /> <set-property property="clientLibrary" value="com.redbooks.commerce.customappproperties.facade.client.CustomAppPropertiesFac adeClient" /> <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

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.Cust omAppPropertiesFactory 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.CustomA ppPropertiesFacadeClient 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

Example 12-65 Struts configuration file, <plug-in> element

<plug-in className="com.ibm.commerce.foundation.client.facade.bod.servlet.struts.BusinessObjec tDocumentPlugInImpl"> <set-property property="config" value="/WEB-INF/config/com.redbooks.commerce.customappproperties/wc-customappproperti es-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.co mmerce.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

5. Create folders for the Custom Application Configuration Management tool JSPs: a. b. c. d. e. f. Right-click the jsp folder, and select New Folder. In the Folder name field, type redbooks. Click Finish. Right-click the redbooks folder, and select New Folder. In the Folder name field, type config. Click Finish. Right-click the config folder, and select New Folder. 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 files 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

type="com.redbooks.commerce.customappproperties.facade.datatypes.CustomAppPropertiesT ype[]" 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 files 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

8. Implement the /GetConfigCategoryChildren action: a. Open the GetConfigCategoryChildren.jsp file, and replace the files 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.CustomAppPropertiesT ype[]" 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 files 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

<childConfigPropertyId><![CDATA[${customAppProperty.customAppPropertiesIdentifier.uni queID}]]></childConfigPropertyId> <object objectType="ConfigProperty"> <configPropertyId><![CDATA[${customAppProperty.customAppPropertiesIdentifier.uniqueID }]]></configPropertyId> <category><![CDATA[${customAppProperty.category}]]></category> <key><![CDATA[${customAppProperty.customAppPropertiesIdentifier.externalIdentifier.na me}]]></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 files 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.CustomAppPropertiesT ype[]" 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

<% // 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 files 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.na me}]]></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

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.co mmerce.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 files 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 files content completely with the content from Example 12-72. b. Save all files (Ctrl+Shift+S).

410

WebSphere Commerce Line-of-Business Tooling Customization

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

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

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

Chapter 12. Custom Application Configuration Management tool

413

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

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

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

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

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

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.

Copyright IBM Corp. 2008. All rights reserved.

419

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

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

Figure A-1 List of the extended files in the Redbook.LOBTools.zip file

422

WebSphere Commerce Line-of-Business Tooling Customization

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/Descr iption2 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

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/ttfmainpagelayou t.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/ttfstatusarealay out.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.ht m 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/ttfchangeappmenu icon.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

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/ttfchangedefault pref.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/ttfchangedisplay name.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/ttfchangecolumnl ist.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?top ic=/com.ibm.commerce.management-center_customization.doc/refs/rtfmai n.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/ttfcreatenewwidg ets.htm

Related publications

425

Using or extending Management Center widget at: http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm .commerce.management-center_customization.doc/tasks/ttfuseexistingwi dgets.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/ctfdirectorys tructure.htm

426

WebSphere Commerce Line-of-Business Tooling Customization

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

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.ht m Product Primary Object definition: http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/topic/com.ibm .commerce.openlazlo.doc/lzx/commerce/catalog/objectDefinitions/Produ ctPrimaryObjectDefinition.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/CustomSer vice.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/Cat alogEntryGrid.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/rtfprocessservice s.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.c net.com%2Fdashboard.html

428

WebSphere Commerce Line-of-Business Tooling Customization

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?top ic=/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?top ic=/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/ttfcustomizeshel l.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

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

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/080 5_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

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

Index
A
AbstractCustomAppPropertiesFacadeClient 363 access control assets 312 acpload utility 364 actionCode 403 Active Work folder 7 activity builder 6 Adobe Flash program 12 advanced user interface components 7 advancedSearchContentClass 124 AJAX 4 API 4 application definition file 284 application framework of the Management Center 4 applyData method 221 catProductProperties 160 CDYNE service 184, 237 cfgConfigTopObjectDefinition.lzx Custom Application Configuration Management tool 251 change mediators 311, 318 ChangeCustomAppPropertiesBasePartCmdImpl 360 ChangeCustomAppPropertiesBasePartMediator 318 ChangeCustomAppPropertiesMediator 318 class wcfMainWorkbench 30 client engine 18 client side data model 18 client side mashup 143144, 179 clientLibrary 403 clientLibraryMethod 403 Cloudscape 101 CMCPriceComparisonEnabled 176 CNET API 150 CNET service URL 150 code generator 299 CommerceFoundation model 300 common customization scenarios 29 complex type 286 ComponentProjects design pattern 245 consistent user interface paradigm 7 ConsumerDirect store 115 contentdatapath attribute 152 contextParameters 402 correctionsView 195, 199 createEditor method 202 Custom Application Configuration Management tool 249 ChildConfigProperty 250 ConfigCategory 250 ConfigurationTop 250 Custom Application Configuration Management tool (CACMT) 239 custom grid 150 custom grid widget 147 CustomAppProperties 245 CustomAppProperties noun 287, 298 customAppProperties.appdef file 284

B
baseName attribute 148 build cycle 56, 61 Business Logic layer 17, 23, 43, 46, 312 Business Object Document (BOD) 13, 23 Business Object Document Processing Command 23 Business Object Editor widget 43 Business Object Mediators 24 button widget property editor 211 buttons 4 buyable icons 108

C
campaign activities 6 campaigns 6 cancel button 190 catalog entries 5 catalog management 5 catalog tool 143 catCatalogEntryExtraProperties class 112 catManagePricingInformation 160 catManageProduct 160 catMerchandisingAssociation class 97 catMerchandisingAssociationsAdvancedSearchContent 127

Copyright IBM Corp. 2008. All rights reserved.

433

CustomAppPropertiesBODVersion element 288 CustomAppProperties-Client 283, 285 CustomAppPropertiesClientApplicationMessageKeys 362 CustomAppPropertiesData 373 CustomAppProperties-DataObjects 283, 285 CustomAppProperties-DataObjects project 287 CustomAppPropertiesExternalIdentifierType type 288 CustomAppPropertiesFacadeClient 363 CustomAppPropertiesFacadeClientTest 371 CustomAppPropertiesFacadeConstants class 348 CustomAppPropertiesIdentifierType type 288 CustomAppPropertiesManagers 365 CustomAppPropertiesMetadata class 313 CustomAppProperties-Server 283, 285 CustomAppPropertiesServicesHTTPInterface 285 CustomAppPropertiesServicesJMSInterface 283, 285 CustomAppPropertiesType type 288 CustomAppPropertiesTypeProtectableProxy 363 CustomAppProperties-UnitTests 283, 285 customer relationship management 9

E
Eclipse 63 Eclipse Process Framework (EPF) 50 Eclipse-enabled template engine 283 EJB 16 EJB classes and interfaces 312 e-mail transport channel 6 enablementValue 271 exported scripting variable 131 expression builder 131 expressionBuilder getData tag 131 extCatalogProductPriceGrabber 156 extCatalogProductPriceGrabberComponent 156 extCatalogProductPricePane 161 extCatalogProductPricePropertyGroup 160 extCatalogResourceBundle 148 extConfigCategoryFilter 265 extConfigCategoryPrimaryObjectDefinition 253 extConfigCategoryPropertyInputText 268 extConfigCategoryPropertyReference 252 extConfigOrganizationalObjectDefinition 251 extConfigPropertyGrid 261 extConfigPropertyList 255 extConfigPropertyPrimaryObjectDefinition 256 extConfigPropertySearchGrid 260 extConfigPropertyValidator 257 extConfigResourceBundle 275 extConfigTopObjectDefinition 251 extConfigurationProperties 256 extension points 4 ExternalIdentifier element 288 extFindConfigurations 256 extManagePriceTab 160 extPriceComparisonPreference 172 extPriceGrabberGrid 152 extPriceGrabberGridcolumn 152 extPriceGrabberGridcolumn class 152 extPropertySpellCheck class 188 extraPropertiesId 110 extSpellCheckButton 188, 199, 211 extSpellCheckButton class 200 extSpellCheckButtonWidget 188 extSpellChecker.lzx 234 extSpellChecker.lzx class 191

D
data mediator type 313 Data Service Facade 24 Data Service Layer (DSL) 23 data store 23 database schema object naming 315 datapath 152 datapath attribute 152 datapointer 150, 154 datapointer registers method 154 dataset class 151 defaultParameters 403 deployment 56 Design Pattern Toolkit (DPTK) 59, 283 destroy 158 developer ID 145 DHTML 12 dictionary feature 235 discount calculation rule 6 discounts 6 displayName 124 documentRootFactory 403 doSpellCheck method 211, 213 DPTK plug-in 283

F
FetchCustomAppPropertiesCmdImpl 359

434

WebSphere Commerce Line-of-Business Tooling Customization

FindConfigProperties 256 fit-gap analysis 181 full client-server-cycle 4

G
Gantt chart 41 genmodel 298 getData tag 131 get-data-config.xml 44 global solution design 52 grid 152

local browser cache 7 logical data model 24, 287, 298 logical SDOs 287 long description field 180 LzDataset 150 LzDelegate 157 LzUnit 58

M
macro design 56 macro design phase 52 MainWorkbench.lzx 30 manage campaigns 6 manage e-mail activities 6 manage e-mail templates 6 manage Web activities 6 Management Center 34 Management Center shell 3031 Management Center tools 30 Management Center user interface 30 Management Center Web application 30 marketing management 5 master catalog 5 maxItems getData tag 131 maxOccurs attribute 294 mediation flow 21 Mediation layer 1718, 22, 43 merchandising associations 6 merchant logo 147 merchant name 147 message key definitions 312 messageView 195 meta data configuration 313 metadata initialization class. 313 micro design 56, 59 minOccurs attribute 294 model property 186 Model-View-Controller architecture 19 moveToNextWord method 233

H
handler class 151 highlightedText 195 highlightWord 221 HTML elements 4 HTTP Post method 58

I
IBM Management Center for WebSphere Commerce 3, 9, 12, 49 IBM Sales Center for WebSphere Commerce 9 IBM WebSphere Commerce 3 Identity Token 21 Init service definition 249 InsertMoreData command 359 in-store customer service tasks 9

J
JACL 72 Java programming language 50 JavaScript 12 JavaScript programming language 50 JSON 145 JSP 22 JSP programming 50 JUnit 58 JUnit-based tests 59 Jython type scripting 72

N L
labelsView 195 language specific exception messages 312 line of business tools 4 listClass 124 listTitile 124 name value pair commands 16 name-value-pair URLs 13 new property editor 202 nonbuyable icons 108

Index

435

O
OAGIS message structure 13 OAGIS services 23 Object definitions 249 offerMessage 153 okCancelView 195 onclick handler 201, 212 ondata event 154 ontext event 153 onvalue events 157 Open Unified Process (OpenUP) 50 OpenLaszlo 12, 17, 58, 179 OpenLaszlo application 19 OpenLaszlo classes basegrid 152 basegridcolumn 152 basescrollbar 152 OpenLaszlo client application 58 OpenLaszlo dataset class 151 OpenLaszlo programming model 50 order capture 9 orders 6

property component 156 Property Editor 187 Property Editor class 199 property editors 185 property panels 185 Protectable Proxy class 363 protectable proxy class 312 proxy server 18

R
Rational ClearCase 80 Read and Change mediators 24 read mediator 315 read mediators 311 ReadCustomAppPropertiesMediator 315 ReadCustomAppPropertiesNounPartMediator 315 recordSetReferenceId getData tag 131 recordSetStartNumber getData tag 131 Redbooks Web site 432 Contact us xv redemption limits 6 release candidate 61 replaceWord 221 Representational State Transfer (REST) style 18, 20 resource bundle class 148 REST interface 183 rich text property editor 180 richinputtext class 221 rightButonsView 195 root node 154

P
page reload 4 partKey 145 persistence technology 24 Physical Data Container 24 physical data model 24 plain text editor 180 predefined promotions types 6 preferenceKey 262 Presentation layer 17, 23, 43, 179 price 147 product management 5 Product Property Panel 199 product property panel 180 production deployment 61 products 6 profiler 59 project delivery methods 51 project lifecycle pattern 51 promotion redemption 6 promotion reward 6 Promotions and Marketing tools 41 promotions management 5 promotions tool 6 property 156

S
sales catalogs 5 searchOptions map 123 searchType 124 selection fields 4 selectNext method 234 server side technology 13 Service Data Objects (SDOs) 243, 246 Service Oriented Integration (SOI) 16 service requests 20 serviceKey 148, 150 service-oriented architecture (SOA) 13, 15 serviceURL 148 Servlet Filter 21

436

WebSphere Commerce Line-of-Business Tooling Customization

session beans 312 setModelObject 157 setProperty method 201 setResultSize 154 setSearchOptions method 123 shipping 6 skip button 190 Software Configuration Management (SCM) 57 SOI model 16 sourceCatalogEntryCode 127 spell check 179 Spell Check Editor 187 status area 150 storefront customization 65 storefront implementation 65 StoreIdentifierType type 291 Struts application 21 Struts based Web Application (module) 20 successMessage 153

getData tag 131 variadic 74 varShowVerb getData tag 131 versionID attribute 289

W
wc-component.xml file 355 wc-componentname-clientobjects.xml 44 wcf getData 44 wcfAdvancedSearchContent 123 wcfBaseComboBox 127 wcfChildListEditor 39, 41 wcfCreateService 60, 257 wcfDeleteService 109, 257 wcfEnablementAndCondition 273 wcfEnablementCondition 110 wcfGanttGrid 41 wcfGanttGrid class 41 wcfGetChildrenService element 252 wcfGridPropertyImage class 111 wcfGridText 262 wcfInputText 127 wcfLogger 77 wcfNavigationListDefinition 255 wcfObjectPathFilter 39 wcfObjectProperties 40 wcfObjectPropertyFilter 39 wcfOjbectGrid 39 wcfPrimaryObjectDefinitions 120 wcfPropertiesComponent 156 wcfPropertyCombobox 270 wcfPropertyEditor 188, 202 wcfPropertyInputMultiLineText 270 wcfPropertyInputText 270 wcfPropertyPane 266 wcfPropertyValue 259 wcfReferenceList 41 wcfResourceBundleKey class 148 wcfRichTextEditor 186 wcfSearchDefinition 41 wcfSearchDefnition 123 wcfSearchService 123 wcfService 41 wcfServiceParams 125 wcfUpdateService 257 wcfValueDefinition class 112

T
text input fields 4 textbox 127 textView 195 The Open Applications Group 13 trace code 200 type getData tag 131

U
UI Conceptual Model 54 UI Design Guidelines 54 UI Protoype 54 UniqueID element 288 unknown word count 228 UpdateCatalogEntryExtraProperties 114 updatePropertyObject 158 updatePropertyObject method 157 updateText method 212 user interaction 4 user interface code 7 UserDataType definition 288

V
ValueType field 294 ValueTypeEnum 292 var

Index

437

wcsObjectGrid class 111 Web 1.0 application 4 Web 2.0 evolution 4 Web activity management 6 Web Services Description Language (WSDL) 246 WebSphere Commerce Accelerator 78 WebSphere Commerce Component Projects pattern 283 WebSphere Commerce Developer 50 WebSphere Commerce OAGIS services 43 WebSphere Commerce Services 50, 59 WebSphere Commerce services 30 WebSphere Commerce Tools framework 45 wordForCorrection_SC 208 wsadmin tool 72 WSDL 246

X
Xappprops 315 XML 12, 50, 145 XML response format 145 XML Schema Definition (XSD) 246 XML schema type 286 XML Schema Validation 286 XPath expression templates 396 XpathExpressionHelper 376 Xpaths 61 xprop_buyable property 110 XSD 246, 299 XSD source code 294

Z
zoomable GANTT charts 7

438

WebSphere Commerce Line-of-Business Tooling Customization

WebSphere Commerce Line-of-Business Tooling Customization

(0.5 spine) 0.475<->0.875 250 <-> 459 pages

Back cover

WebSphere Commerce Line-of-Business Tooling Customization


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

INTERNATIONAL TECHNICAL SUPPORT ORGANIZATION

BUILDING TECHNICAL INFORMATION BASED ON PRACTICAL 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

SG24-7619-00

ISBN 0738431702

Das könnte Ihnen auch gefallen