You are on page 1of 1451

Windchill Customization Guide

Windchill 10.0 December 2011 MR010 Document Version MR010.08

Copyright 2011 Parametric Technology Corporation and/or and/or Its Subsidiary Companies. All Rights Reserved. User and training guides and related documentation from Parametric Technology Corporation and its subsidiary companies (collectively "PTC") are subject to the copyright laws of the United States and other countries and are provided under a license agreement that restricts copying, disclosure, and use of such documentation. PTC hereby grants to the licensed software user the right to make copies in printed form of this documentation if provided on software media, but only for internal/personal use and in accordance with the license agreement under which the applicable software is licensed. Any copy made shall include the PTC copyright notice and any other proprietary notice provided by PTC. Training materials may not be copied without the express written consent of PTC. This documentation may not be disclosed, transferred, modified, or reduced to any form, including electronic media, or transmitted or made publicly available by any means without the prior written consent of PTC and no authorization is granted to make copies for such purposes. Information described herein is furnished for general information only, is subject to change without notice, and should not be construed as a warranty or commitment by PTC. PTC assumes no responsibility or liability for any errors or inaccuracies that may appear in this document. The software described in this document is provided under written license agreement, contains valuable trade secrets and proprietary information, and is protected by the copyright laws of the United States and other countries. It may not be copied or distributed in any form or medium, disclosed to third parties, or used in any manner not provided for in the software licenses agreement except with written prior approval from PTC. UNAUTHORIZED USE OF SOFTWARE OR ITS DOCUMENTATION CAN RESULT IN CIVIL DAMAGES AND CRIMINAL PROSECUTION. PTC regards software piracy as the crime it is, and we view offenders accordingly. We do not tolerate the piracy of PTC software products, and we pursue (both civilly and criminally) those who do so using all legal means available, including public and private surveillance resources. As part of these efforts, PTC uses data monitoring and scouring technologies to obtain and transmit data on users of illegal copies of our software. This data collection is not performed on users of legally licensed software from PTC and its authorized distributors. If you are using an illegal copy of our software and do not consent to the collection and transmission of such data (including to the United States), cease using the illegal version, and contact PTC to obtain a legally licensed copy. Important Copyright, Trademark, Patent, and Licensing Information: See the About Box, or copyright notice, of your PTC software. UNITED STATES GOVERNMENT RESTRICTED RIGHTS LEGEND This document and the software described herein are Commercial Computer Documentation and Software, pursuant to FAR 12.212(a)-(b) (OCT95) or DFARS 227.7202-1(a) and 227.7202-3(a) (JUN95), and are provided to the US Government under a limited commercial license only. For procurements predating the above clauses, use, duplication, or disclosure by the Government is subject to the restrictions set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software Clause at DFARS 252.2277013 (OCT88) or Commercial Computer Software-Restricted Rights at FAR 52.227-19(c)(1)-(2) (JUN87), as applicable. 01012011 Parametric Technology Corporation, 140 Kendrick Street, Needham, MA 02494 USA

Contents

About This Guide ..................................................................................................8 Change Record .................................................................................................. 11 Customization Overview ............................................................................................17 Configuration Options..........................................................................................18 Customizations...................................................................................................21 Windchill Customization Points ............................................................................24 The Windchill Development Environment ....................................................................27 Directory Structure ..............................................................................................28 Environment Variables ........................................................................................34 Property Files .....................................................................................................35 Properties and Property Files ...............................................................................39 Getting Started With Windchill Customization...............................................................43 Example Overview ..............................................................................................44 Windchill Development Environment ....................................................................45 Customization Setup ...........................................................................................46 Creating the Class ..............................................................................................47 Creating a UI ......................................................................................................56 Customizations Next Steps............................................................................ 100 Modeling Business Objects ...................................................................................... 101 Windchill Modeling Heuristics............................................................................. 102 Windchill Foundation Abstractions...................................................................... 105 Managing Customizations ........................................................................................ 112 Setting Up a Directory Structure for Managing Customized Files and Text Tailoring........................................................................................................ 113 Best Practices for Customizing Files Supplied by PTC ......................................... 121 Best Practices for Adding New Packages and Files ............................................. 141 Windchill Utilities ..................................................................................................... 145 Using the xconfmanager Utility........................................................................... 146 Formatting Property Value Guidelines................................................................. 158 Windchill Command .......................................................................................... 159 Windchill Shell .................................................................................................. 162 Encrypted Passwords .............................................................................................. 163 Encrypted Passwords ....................................................................................... 164 Customization Tutorial ............................................................................................. 181 Tutorial Overview .............................................................................................. 182 Create Administrator and User ........................................................................... 184 Create a Library and Document.......................................................................... 194

Allocate Database Columns for Standard Attributes ............................................. 200 Create a New Attribute Definition and Add it to the Document Type ....................... 202 As the End User, Create a Document with the new Attribute ................................. 208 Create a Document Soft Type ............................................................................ 211 Create an Instance of the New Document Soft Type ............................................ 214 Model a New Document Subclass ...................................................................... 215 Create an Instance of the New Document Subclass ............................................. 221 Verify the Customizations .................................................................................. 223 Summary ......................................................................................................... 224 User Interface Technology Overview ......................................................................... 225 Windchill Client Architecture Overview................................................................ 226 Windchill Client Architecture Common Objects Overview ..................................... 239 Javascript Functions Overview........................................................................... 242 Adding Custom Code to all Windchill Client Architecture Pages ............................ 248 MVC Components ................................................................................................... 251 MVC Components Overview.............................................................................. 252 MVC Tables...................................................................................................... 280 Generic UI Customizations....................................................................................... 281 Customizing Role-Based UI Functions - Attribute Visibility .................................... 282 Customizing Role-Based UI Functions Action Visibility..................................... 292 Preference Framework ...................................................................................... 293 Constructing URLs............................................................................................ 299 Offline Package Customization .......................................................................... 300 System Banner Alert Message ........................................................................... 304 Adding a Status Glyph....................................................................................... 306 Customizing HTML Clients Using the Windchill JSP Framework.................................. 309 Customizing Generic Aspects of JSP Pages ....................................................... 310 Bread Crumbs Component ................................................................................ 321 Client Tabs ....................................................................................................... 332 Checkin/Checkout ............................................................................................ 345 Component Access Control ............................................................................... 350 Attachments ..................................................................................................... 355 Attribute Panels ................................................................................................ 365 Customizing Access Control For Packages ......................................................... 413 Customization Tools Overview ........................................................................... 417 Adding Validation Logic for Actions and Properties............................................... 452 Split Pane / Two Pane ....................................................................................... 470 Defining Layouts in a Type Load File .................................................................. 481 Adding Actions and Hooking Them Up in the UI ......................................................... 485 Windchill Client Architecture Action Framework Overview .................................... 486 Tab Models....................................................................................................... 518 Customizing Role-based Visibility....................................................................... 528 User Interface Stickiness ................................................................................... 539 Defining Menus ................................................................................................ 540 Gathering the Data for the UI .................................................................................... 555
Windchill Customization Guide

Acquiring Data via Info*Engine........................................................................... 556 NmObject Utilities ............................................................................................. 562 File Download................................................................................................... 568 Presenting Information in the UI ................................................................................ 573 Soft Attributes and SCAs ................................................................................... 574 Constructing and Rendering a Table Using the JSP Framework ............................ 579 Windchill Client Architecture Tree ....................................................................... 614 Attribute Customization ..................................................................................... 630 Adding Custom Modeled Attributes to all Table Views .......................................... 701 Attribute Tables................................................................................................. 702 Generating the Name Attribute Server ................................................................ 707 Icon Delegates ................................................................................................. 712 UI Validation ..................................................................................................... 718 Customizing the Find Number Field .................................................................... 766 Inline Messaging............................................................................................... 771 Constructing Wizards............................................................................................... 775 Windchill Client Architecture Wizard ................................................................... 776 Wizard Processing ............................................................................................ 802 Building Wizards to Create a Single Object ......................................................... 823 Building Wizards to Edit a Single Object.............................................................. 846 Customizing Reusable Wizard Steps .................................................................. 860 Information Pages ................................................................................................... 891 Customizing Information Page Components........................................................ 892 Incorporating Pickers in JSP Clients.......................................................................... 923 Configuring Pickers........................................................................................... 924 Configuring a Context Picker.............................................................................. 933 Configuring an Item Picker................................................................................. 943 Configuring an Organization Picker .................................................................... 952 Configuring a Type Picker.................................................................................. 960 Configuring a User Picker .................................................................................. 975 Configuring a Participant Picker ......................................................................... 982 Configurable Links................................................................................................... 997 Configurable Link Tables ................................................................................... 998 Customizing Online Help........................................................................................ 1009 Customizing Windchill Help Center Content ...................................................... 1011 Linking to Help Topics ..................................................................................... 1013 Uninstalling the Windchill LearningConnector.................................................... 1016 Customizations in the Type Manager....................................................................... 1019 Adding Columns to Types ................................................................................ 1020 Customizing Business Logic................................................................................... 1033 Customizing a Bill of Materials ......................................................................... 1034 Context Builder Customization Example ........................................................... 1039 Customizing Change Management ......................................................................... 1045 Association Constraints ................................................................................... 1046

Contents

Customizing Multiple Inventory Dispositions ...................................................... 1050 Mass Change Operations ................................................................................ 1060 Mass Change Supported Types ....................................................................... 1067 Sponsored Problem Report and Variances........................................................ 1071 Change Management Cardinality ..................................................................... 1074 Customizing Workflow Administration...................................................................... 1079 Customizing Workflow HTML Templates ........................................................... 1081 Customizing Change Management Workflow Process Templates ....................... 1085 Customizing Promotion Request Workflow Processes ....................................... 1091 Enhanced Promotion Process.......................................................................... 1094 Customizing Workflow Events on an Object ...................................................... 1105 Customizing Workflow Task Pages ................................................................... 1107 Refine and Review Workflow Transitions ...........................................................1115 Adding Custom Workflow Attribute to Workflow Processes ................................. 1122 Customizing Windchill Visualization Services........................................................... 1125 Custom Publishing .......................................................................................... 1126 Interference Detection ..................................................................................... 1144 Report Generation ................................................................................................. 1153 Overview........................................................................................................ 1155 Basic Report Example..................................................................................... 1155 Import and Export of Report Templates ............................................................. 1156 Java Methods ................................................................................................. 1159 Customization Details ..................................................................................... 1160 Cognos Presentation Customization................................................................. 1179 Reporting Info*Engine Task Data Source Customization .................................... 1185 Report Loading ............................................................................................... 1191 ReportTemplate Data Source Customization ..................................................... 1200 Reporting Input Page Customization................................................................. 1204 Report Localization Customization ................................................................... 1209 Report Selection List Customization ................................................................. 1215 Packages ............................................................................................................. 1217 Package Type-Based Properties ...................................................................... 1218 Desktop Integration ............................................................................................... 1227 DTI Customization Framework ......................................................................... 1228 PLM Services Support in Windchill.......................................................................... 1245 Product Lifecycle Management Services, Version 2.0 ........................................ 1246 PLM Mapping Information................................................................................ 1247 PLM Message Format ..................................................................................... 1279 Deploying Arbortext Customizations........................................................................ 1281 Annonymous Arbortext Access ........................................................................ 1282 System Generation................................................................................................ 1291 Modeling Business Objects.............................................................................. 1292 Enumerated Types ................................................................................................ 1315

Windchill Customization Guide

The EnumeratedType Class............................................................................. 1316 Creating an EnumeratedType Subclass ............................................................ 1318 Editing the Resource Info for an Enumerated Type ............................................ 1319 Localizing an Enumerated Type ....................................................................... 1321 Extending an Enumerated Type ....................................................................... 1322 The Enumerated Type Customization Utility ...................................................... 1323 GUI Usage of an Enumerated Type .................................................................. 1325 Customizing LDAP Attributes.................................................................................. 1327 Customizing LDAP Mapped Attributes in a User Information Page ...................... 1328 Viewing LDAP Mapped Attributes in an Audit Report.......................................... 1331 System Configuration Collector Plugin .................................................................... 1337 Creating a System Configuration Collector Plugin .............................................. 1338 Customizing Modeled Elements.............................................................................. 1383 Customizing Column Lengths .......................................................................... 1384 Windchill Design Patterns ...................................................................................... 1387 The Object Reference Design Pattern............................................................... 1388 The Business Service Design Pattern ............................................................... 1390 The Master-iteration Design Pattern ................................................................. 1393 Internationalization and Localization........................................................................ 1395 Background.................................................................................................... 1396 The Windchill Approach................................................................................... 1397 Localizing Text Visible to the User .................................................................... 1399 Resource Info (.rbInfo) Files............................................................................. 1403 The Enterprise Layer ............................................................................................. 1407 Enterprise Abstractions ................................................................................... 1408 Document Abstractions ................................................................................... 1415 Part Abstractions ............................................................................................ 1418 Change Abstractions....................................................................................... 1426 Evolvable Classes ................................................................................................. 1442 Background Information .................................................................................. 1443 General Externalization Guidelines................................................................... 1443 Hand-coded Externalization Guidelines ............................................................ 1445 Migration Guidelines for Classes with Hand-coded Externalization ...................... 1446 Examples of Generated Externalization Code for Evolvable Classes ................... 1447

Contents

About This Guide


The Windchill Customization Guide describes how to customize the out-of-the-box implementation of Windchill. It is intended for developers who are familiar with Windchill Javadoc. This guide can be used with all Windchill solutions. Examples in this guide referencing third-party products are intended for demonstration purposes only. For additional information about third-party products, contact individual product vendors.

Note Some code examples in this guide have been reformatted for presentation purposes and, therefore, may contain line number, hidden editing characters (such as tabs and end-of-line characters) and extraneous spaces. If you cut and paste code from this manual, check for these characters and remove them before attempting to use the example in your application.

Related Documentation
This guide contains a subset of the customization reference topics from the Basic Customization and Advanced Customization sections of the Windchill Help Center. Additional customization information is available in the following guides:

Windchill Explorers Customization Guide Windchill Enterprise Systems Integration Customizer's Guide - Oracle Applications Windchill Enterprise Systems Integration Customizer's Guide - SAP Info*Engine User's Guide Info*Engine Implementation Guide Windchill Adapter Guide Info*Engine Java Adapter Development Kit Programming Reference

Windchill Customization Guide

JavaScript Documentation
For Windchill release F00 and MR010, the JSDoc files are not installed by default. If you attempt to view the JavaScript Documentation from the Customization menu (Navigator Browse Site Tools Customization ( )) the page will not load.

Note There are a number of customization utilities included within the Windchill user interface. They are not enabled by default. To enable these utilities see, Customization Tools Overview on page 417.
JavaScript Documentation is available for download from the following location: http://www.ptc.com/view?im_dbkey=128543 A system administrator will need to extract the contents of this file into the Windchill/codebase directory on the Windchill server. Be sure to preserve the directory structure within the zip file, starting with the directory named CustomizerDoc. When it is extracted correctly, the documentation will be extracted to Windchill/codebase/CustomizerDoc on the Windchill server.

Customization Source Code Examples


Customization source code examples are available for download from the following location: http://www.ptc.com/view?im_dbkey=522

Technical Support
Contact PTC Technical Support through the PTC website, or by phone, email, or fax if you encounter problems using this product or the product documentation. For complete details, see the PTC Customer Service Guide. You can find this guide under Contacting Technical Support on the PTC Technical Support page: http://www.ptc.com/support/index.htm You must have a Service Contract Number (SCN) before you can receive technical support. If you do not have an SCN, contact the PTC Maintenance Department using the instructions found in the PTC Customer Service Guide or on the PTC Technical Support page.

Documentation for PTC Products


You can access PTC documentation using the following resources:
Windchill Help Center The Windchill Help Center is an online knowledge

base that includes a comprehensive index of all Windchill documentation. You can browse the entire Windchill documentation set, or use the search capability to perform a keyword search. To access the help center, you can: Click any help icon in Windchill Select Help Windchill Help Center from the Quick Links menu at the top right of any Windchill page Use the following link to access all PTC help centers: https://www.ptc.com/appserver/cs/help/help.jsp
Reference Documents Website The Reference Documents website is a library

of all PTC guides: http://www.ptc.com/appserver/cs/doc/refdoc.jsp A Service Contract Number (SCN) is required to access the PTC documentation from the Reference Documents website. For more information on SCNs, see the PTC Technical Support page: http://www.ptc.com/support/index.htm

Comments
PTC welcomes your suggestions and comments on its documentation. To submit your feedback, you can: Send an email to documentation@ptc.com. Include the name of the application and its release number with your comments. If your comments are about a specific help topic or book, include the title. Click the PTC help center feedback icon in the upper right of a Windchill Help Center topic and complete the feedback form. The help topic title is automatically included with your feedback.

10

Windchill Customization Guide

Change Record
This table details the updates to the Windchill Customization Guide. Windchill 10.0 F000 and Windchill 10.0 MR010 The following updates were made in the Windchill 10.0 F000 and Windchill 10.0 MR010 releases. ReReDocuDocu- Update Date Description lease ment VerVersion 10.0 10.01 March 18, Initial draft version for Windchill Release F000 2011 10.0. 10.0 10.02 March 28, First update. F000 2011 Added the following chapters: Modeling Business Objects on page 101 Constructing Wizards on page 775 with the following topics: Windchill Client Architecture Wizard on page 776 Wizard Processing on page 802 Information Pages on page 891 Incorporating Pickers in JSP Clients on page 923

10.0 F000

10.03

April 6, 2011

Configurable Links on page 997 Replaced/updated the following chapter: Information Pages on page 891 chapter. The Enterprise Layer on page 1407 Added the following chapter: Updated Constructing Wizards on page 775 with the following topics: Building Wizards to Create a Single Object on page 823 Building Wizards to Edit a Single Object on page 846

11

ReRelease 10.0 F000

DocuDocument VerVersion 10.04

Update Date Description

May 24, 2011

Added the following chapters: Customizing HTML Clients Using the Windchill JSP Framework on page 309 Presenting Information in the UI on page 573 Customizing Online Help on page 1009 Packages on page 1217

Updated the following chapters: Customizing Change Management on page 1045; added Sponsored Problem Report and Variances on page 1071 Added the following chapter: Customizing Modeled Elements on page 1383

10.0 10.05 MR010

June 17, 2011

Updated the following chapters: Customizing Workflow Administration on page 1079; added Adding Custom Workflow Attribute to Workflow Processes on page 1122

10.0 10.06 MR010

August 31, 2011

Updated Customization Tools Overview on page 417 to include information about installing the JavaScript Documentation. Added the following chapters: MVC Components on page 251 Getting Started With Windchill Customization on page 43 Generic UI Customizations on page 281 Adding Actions and Hooking Them Up in the UI on page 485 Gathering the Data for the UI on page

12

Windchill Customization Guide

ReRelease

DocuDocument VerVersion

Update Date Description

555 PLM Services Support in Windchill on page 1245 Updated the following chapters: User Interface Technology Overview on page 225; added Windchill Client Architecture Common Objects Overview on page 239 Javascript Functions Overview on page 242 Customizing HTML Clients Using the Windchill JSP Framework on page 309; added Bread Crumbs Component on page 321 Client Tabs on page 332 Presenting Information in the UI on page 573; added

10.0 10.07 MR010

September 9, 2011

Attribute Customization on page 630 Updated the following chapters: PLM Services Support in Windchill on page 1245; updated the following sections: mapping.xml file on page 1249 Details of the Mapping between Windchill and PLM Services on page 1251

13

ReRelease 10.9 MR010

DocuDocument VerVersion 10.08

Update Date Description

December 2, 2011

Added the following chapters: Desktop Integration on page 1227 Deploying Arbortext Customizations on page 1281 Customizing Business Logic on page 1033 which contains the following sections: Customizing a Bill of Materials on page 1034 Context Builder Customization Example on page 1039 Updated the following chapters: Customizing HTML Clients Using the Windchill JSP Framework on page 309 Added the Exporting and Importing Client Tabs on page 342 section. Updated the Client Tabs on page 332 topic to remove information on functionality that is available starting at release 10.0 MR020. This information was included by mistake in previous versions of the 10.0 MR010 guide. Customizing Online Help on page 1009 Added the Customizing Windchill Help Center Content on page 1011 section PLM Services Support in Windchill on page 1245; removed the following sections: PLM Schema Extensions in Windchill subsection from Product Lifecycle Management Services, Version 2.0
Windchill Customization Guide

14

ReRelease

DocuDocument VerVersion

Update Date Description

on page 1246 Schema Extensions for EPM Documents

Planned Updates The Windchill Customization Guide is updated on a periodic basis between Windchill maintenance releases. Check the Reference Documents site on PTC.com for updates.

15

1
Customization Overview
Configuration Options ................................................................................................18 Customizations .........................................................................................................21 Windchill Customization Points ...................................................................................24

The Windchill solutions are designed to fit the needs of customers in different industries and of different sizes. The Windchill solutions are built to enable product development business processes. Input for these solutions comes from the many PTC customers who are leaders in their domains and from PTC industry experts. In order to reduce the cost of ownership, the Windchill solutions provide extensive out-of-the-box capabilities and configuration options to make them easily adaptable to these disparate customers and their different product development processes and needs. Where the configuration options do not provide sufficient flexibility and no appropriate out-of-the-box capabilities are available to satisfy a particular business need, Windchill provides an extensive set of customization features that customers can leverage to satisfy such business needs.

17

Configuration Options
Properties and Preferences
Windchill provides an extensive set of options that control how the system behaves, how the user interacts with the system, or how the system presents itself to the user. These options are either properties or preferences.

Properties
Properties are created in text files in codebase and control overall system configuration. For example, the wt.home property contains the path to the installation directory. Properties are stored in files with the .properties extension. Changing most properties requires a restart of the Windchill method server. See Property Files on page 35 for some additional information on property files. A complete set of properties and descriptions for the wt.properties, tools.properties, and db.properties files can be found in the Windchill Administrator s Guide and the properties.html file in the codebase directory.

Preferences
Preferences are set through the Windchill user interface and do not require a server restart. They control application behavior1. Preferences can be implemented on different levels of detail. Preferences can be configured to control the whole Windchill installation, or can be used more narrowly to control an organizations or an application container s (e.g. Product, Library), or a specific user s setup. See Preference Framework on page 293 for some additional information on preferences. The table below provides just a few of the available preferences: Description Preference Change Notice without Change Request Allows creating a change notice without a change request. Enable Structure Propagation Enables propagation of effectivity statements down a product structure. Digest Notification Schedule Set up a schedule for Digest Notification. That is, instead of sending individual notification of as events of interest to a user happen, the system will collect and send all notifications in one email
1. For legacy reasons, some Properties also control application behavior.
Windchill Customization Guide

18

Preference

Display Thumbnails

Description according to the administrator-setup schedule. Controls whether the thumbnail action available in tables.

Object Initialization Rules


A business analyst can set up rules that tell the system how to initialize newly created objects. For example, the business analyst can set the system up to number parts according to the companys part numbering policies (e.g. auto-number). The business analyst may also set the system up to require the user to enter a manual number, or alternatively, set the system up so that if the user does not enter a number, the system will assign one. As another example, the business analyst can set the system up to automatically assign objects of certain types to certain workflows; or, alternatively, the business analyst can configure the system with appropriate workflows by object types and it will be up to the end user to select the appropriate workflow to use. For more sophisticated needs, the business analyst can set the system up to route an object appropriately based on the values of meta-data attributes provided by the end user. Object initialization rules provide significant flexibility in adapting a Windchill system to a specific customer s environment and business process needs. For additional information, see the Object Initialization Rules chapter in the Windchill Business Administrator s Guide.

Workflow Templates
Windchill provides a very powerful workflow configuration and execution engine. The workflow engine of Windchill can model virtually any business process which can be modeled via an easy-to-use drag-and-drop tool. The workflow engine has an embedded java virtual machine which allows a business analyst to embed java expressions and process logic where appropriate. For more information on workflow templates see the online help topic Customizing Workflow Administration in the Windchill Help Center.

Customization Overview

19

Soft Typing
Soft Typing is the name of the set of Windchill capabilities that allows a customer to, at runtime, add additional types and attributes to the out-of-thebox Windchill Schema. This is done without having adding additional tables to the database, without restarting the database, and without restarting the system. With the Soft Typing capabilities, customers can add data types and meta data attributes that are meaningful to them and which are necessary for their business processes. For all intents and purposes, these customer-defined types are no different than any other out-of-the-box object in the system: Types can assigned access control rules, can be assigned workflows and lifecycles, can be assigned custom UIs, can have Object Initialization Rules assigned to them, are accessible via APIs, etc.

No user interface modifications are necessary as the Windchill user interfaces automatically accommodate (e.g. adapt to) these additional Types and Attributes. The general guideline to be followed is this: If a need can be satisfied by soft typing, then it should. That is, do not customize (i.e. create modeled extensions) to the out-of-the-box schema. The reason for this rule is to minimize the total cost of ownership of Windchill and minimize upgrade costs and burdens. This, in no way, is a limitation on the customizability of Windchill; but, rather, the intent of the rule is to reduce the cost of ownership.

Organization and Container Templates


Creating an organization or an application container (e.g. Product/Library/Project/ Program) requires that you provide a template to initialize the container with. A template allows you to configure the business rules of the created container. For example, you can specify what approval processes are to be followed, who has access to create and/or view information, what roles are required and who the role players are, what numbering and versioning rules should be followed, etc.

20

Windchill Customization Guide

Customizations
Windchill is an open system that is fully supports customizations at the schema, server, and UI levels. An extensive set of APIs are published, documented, and supported to enable these customizations. But as stated above, in order to reduce the cost of ownership, if changing other mechanisms such as properties or preferences satisfy the business need, then customizations should not be used.

Data Model Customizations


Windchill Information Modeler is one of the Windchill development components that can be used to customize your Windchill environment. Information Modeler contains the Windchill modeling files and source code that you will use to develop your customizations. Custom Java Annotations are used to model business objects. Windchill then uses this model to generate code that is used in server and client development. Information Modeler provides the most powerful capabilities for creating custom business objects and relationships in Windchill systems, but requires greater development skills and is less flexible than using soft types. For example, soft types can be added and changed by an administrator while the system is running, but model changes must be made by a skilled Java developer during strictly managed checkpoints. On the other hand, modeled objects can be created by assembling specific collections of Windchill plug-and-play interfaces to create unique server behavior but soft types can only be created as super types of existing modeled classes with additional attributes. For more information on Java Annotations see Modeling Business Objects on page 1292.

Service Customizations
Windchill supported server-side customizations to enable certain business processes or enforce business constrained. Any kind of customization can be performed. The most common types of customizations falls into one of the following categories: Process form data submitted through the user interface Validate data - (e.g. Do not allow the user to enter a Need Date for a Change Request that is more than 30 days into the future)

Customization Overview

21

Implement service listeners - (e.g. Create a listener that waits for any data to be checked in and populate an MRP system with appropriate data) Get/Put data in an external systems - (e.g. when the user navigates to a parts details, get the cost of the part from the ERP system and display it in the same UI)

User Interface Customizations


The Windchill Client Architecture is a Windchill-aware JSP framework. It provides very high-level building blocks known as common components which make Windchill UI development a very efficient process done with ease. Javadoc and learn-by-example documentation is available to reduce the learning curve and increase developer productivity. For more information on user interface customizations see Generic UI Customizations on page 281.

Info*Engine
Info*Engine provides data access and integration capabilities to access Windchill data, remote Windchill systems and non-Windchill data and services (through adapters). Info*Engine components can be used in many different software and hardware configurations to meet your business requirements for accessing, managing, and presenting data from many different information systems. All basic Info*Engine solutions take advantage of five fundamental concepts: JSP pages, tasks, webjects, groups, and the virtual database. Both JSP pages and tasks are text-based documents that define how Info*Engine either displays or retrieves information. Webjects are the means by which Info*Engine JSP pages and tasks gather, manipulate and display data. Groups are the chunks of information generated and manipulated by JSP pages and tasks. The virtual database (VDB) is the special holding area where groups are stored until they are manipulated or passed along by JSP pages and tasks. For general information on Info*Engine see the Info*Engine User's Guide. For information on Info*Engine customizations see Managing Windchill Info*EngineTasks on page 126.

22

Windchill Customization Guide

Custom Reports
Windchill provides predefined, out-of-the-box reports in the areas of change management, project item status, and parts/products. Your company-specific custom reports can be created using Windchill Query Builder or the Windchillintegrated third-party report authoring tool, Cognos. Use Windchill Query Builder if you would like to create very simple tabular reports and your site is not configured for third-party reporting tool, Windchill Business Reporting. Windchill Business Reporting (WBR) is a new reporting framework that embeds Cognos 8 Business Intelligence (BI) within Windchill to provide out-of-the-box integration between Windchill and Cognos 8 BI. It also includes pre-built reports on change management, project items status, and parts/products. To create tabular reports, visual and graphical reports, dashboard reports, and drilldown reports, use the optional third-party reporting authoring tool. This optional authoring tool also allows you to modify out-of-the-box reports. Using the authoring tool you can create new reports that include charts and graphs (Crosstabs, bar/3D bar, pie, gauge, funnel, scatter and more). The report data sources that are required for creating custom reports in report author tool can be created using Info*Engine report tasks and Query Builder templates. For more information on custom reports see Report Generation on page 1153.

Customization Overview

23

Windchill Customization Points


Windchill is composed of thousands of Java classes. To help you focus your customization efforts, certain Windchill Java classes have been designated as belonging to the Windchill Supported API. To customize Windchill, you should interact only with the classes in the Windchill Supported API. The Javadoc provided with Windchill defines the Supported API.

Windchill Supported API


The Windchill Supported API includes those classes that customizers are meant to work with directly. A class might be in the Supported API because it is meant to be extended by customizers or, more likely, because it has some methods for customizers to call. Programming elements that are part of the Supported API will not be changed without notification and a deprecation period, whenever possible. The deprecation period for a particular supported API begins with release that the Javadoc for that element first declares that it is deprecated. The deprecation period ends when support for that release ends. For Windchill release maintenance information, see the PTC product calendar at this URL: http://www.ptc.com/cs/product_calendar/PTC_Product_Calendar.htm Classes, methods, and other programming elements that are not part of the Supported API should not be used directly by customizers. Those elements are subject to change without notification or a deprecation period. To determine if a class, or one of its methods, is part of the Supported API, consult the Javadoc for that class. For each class, the Javadoc contains a Supported flag, and an Extendable flag. Individual methods within a Supported class may also be flagged as Supported.

24

Windchill Customization Guide

If a class (or method) is flagged as Supported: true , it indicates that the class or method may be referenced by customized code. If a class is flagged as Extendable: true , it indicates that the class may be extended. For example, WTPart is both Supported and Extendable, as shown in the following illustration.

The fact that a class is part of the Supported API indicates that some part of it is meant to be used, or at least understood by customizers. The Javadoc for some classes is distributed for information purposes (and if that is the case, it should be clear from the Javadoc). A class is meant to be extended only if its Javadoc contains the line indicating Extendable: true. (Classes that can be extended are listed in Appendix B, Extendable Classes in the Windchill Supported API.) Methods and other programming elements may also have a Supported API line in their Javadoc. If a class is not part of the Supported API, then neither are any of its methods. If a class is part of the Supported API, that does not indicate that its methods are, too. For a method to be part of the Supported API, its Javadoc must also state Supported API: true.

Customization Overview

25

2
The Windchill Development Environment
Directory Structure.....................................................................................................28 Environment Variables ...............................................................................................34 Property Files............................................................................................................35 Properties and Property Files......................................................................................39

This chapter describes the Windchill development environment.

27

Directory Structure
The image below shows the Windchill directory structure after you install all available components. If Windchill was installed as recommended to follow this structure, go to the home directory where Windchill is installed and navigate through this structure as it is described here.

Windchill Directory Structure ant Installation of supported version of Ant. apacheConf Contains configuration files for Apache Tomcat and Windchill bin Contains various batch scripts, such as ToolsSetup.bat.

28

Windchill Customization Guide

buildlogs Default location for logs created by running Windchill Ant scripts. cgi-bin cgi-bin Contains the Windchill common gateway interface wrappers. codebase Contains the runtime environment files. conf Configuration files for Apache, DCA, Info*Engine and other applications. db Contains the database properties file and SQL scripts. ieconnector Contains the Info*Engine JCA (Java Connector Architecture) which is used for J2EE integrations (EJB or App Server connectivity). It is also used by Info*Engine JCA enabled standalone java SOAP clents. installer Contains files used by, or created by, the installation process, including installation logs. ldif Files related to PTC's InterComm Viewer. lib Contains the wtbeans.jar file, which holds the Java bean components that have been developed for use with Windchill clients. loadFiles Contains files used to load initial data. loadXMLFiles Contains new style xml files used to load initial data. logs Default location for trace logs when logging is turned on. Module Contains Windchill modules' model files, which are used for customization development. opt Install folder for some optionally installed functionality.

The Windchill Development Environment

29

prog_examples Contains Info*Engine program examples src Contains files for customizations, and rbInfo files for text. srclib Contains module jar files. step Contains STEP application related files. taskeditor Contains the Info*Engine task editor startup scripts, help files reside and is the runtime directory for the task editor. tasks Contains Info*Engine tasks. tomcat Apache Tomcat installation. temp Temporary files used by Windchill. Upgrade Contains files to facilitate the upgrade process. utilities Contains various Windchill utilities. vaults Default file vault location. WHC Contains the Windchill Help Center which consists of the online help. WinDU Directory of xml files that declare the existence of tasks that are executable by the Windchill Diagnostic Utility. The codebase directory and src directory are described in more detail in the following subsections.

30

Windchill Customization Guide

The codebase Directory


In general, the codebase directory contains executable class files, property files, and other files that contain information needed by the runtime environment for Java and Web processing. The codebase directory can be expanded to show the following directories.2

The codebase Directory

2.

To allow presentation in manual format, many subdirectories in the wt directory are not included in this figure.

The Windchill Development Environment

31

Most of these directories contain third party product class files. The html directory contains templates that are used to generate HTML dynamically. The wt and com\ptc directories contains the executable code for the packages supplied by Windchill (only a subset of which are shown in this illustration) and files required for localization, such as resource bundles and HTML files. Within these packages are executable class files compiled from corresponding Java files of the same name in the src\wt directory. This set of Java source or .java files is for every business object. Files in the form <object> .ClassInfo.ser are generated and contain metadata needed by the runtime environment. They are all described in more detail in System Generation. Each package also contains resource bundles, that is, files that contain localizable information and are in the form: <packageName>Resource.class <packageName>ModelRB.RB.ser <EnumeratedTypeClassName>RB.RB.ser

The src Directory


In general, the src directory contains the source files needed for application development. The src directory can be expanded to show the following directories.

32

Windchill Customization Guide

The src Directory The wt and com\ptc directories contains the source files for the packages supplied by Windchill (only a subset of which are shown in this illustration). In the wt directory and its package subdirectories, you will see the following kinds of files: Localizable ResourceBundles (.rbInfo and .java) files, which contain customizable display text for EnumeratedTypes and business elements and UI strings.

The Windchill Development Environment

33

Environment Variables
The environment variables required for running Windchill tools and utilities will be defined by starting a Windchill shell. The Windchill shell is described in more detail in Windchill Utilities on page 145.

34

Windchill Customization Guide

Property Files
Windchill uses standard Java property files to determine runtime configuration properties. The codebase directory contains: wt.properties Contains properties used for general Java system configuration and Windchill system configuration. service.properties Contains properties used by the Windchill service delegate mechanism. user.properties Contains user overrides used by resource bundle and sql script generation tools. moduleRegistry.properties Contains list of registered modules. moduleDir.properties Contains home directory for each registered module. The db directory contains: db.properties Contains properties used by the Windchill database connection layer to access the database. The System Generation jars (SystemGeneration.jar, WindchillUtil. jar & CommonCore.jar) contain: tools.properties Contains properties used by resource bundle and sql script generation tools. debug.properties Contains properties used by Windchill code to control debug info capturing. service.properties Contains properties used by the Windchill service delegate mechanism, for the System Generation tools. typedservices.properties

The Windchill Development Environment

35

Contains properties used by the Windchill service delegate mechanism, for the System Generation tools. You must use typedservices.properties when the selector object type could be a soft type. wt.properties This is an abbreviated form of the file that is in codebase. (Care must be taken when using a manually created classpath that includes both codebase and System Generation jars, since properties files will be loaded based on the order of the classpath components.) The following sections discuss only a subset that you as a developer are most likely to be interested in. A complete set of properties and descriptions for the wt. properties, tools.properties, and db.properties files can be found in the Windchill Administrator s Guide and the properties.html file in the codebase directory. To change properties, you can edit the file directly or use the System Configurator GUI from the Windchill application home page. The System Configurator allows you to modify property files; start, stop, and restart the server manager and all method servers; and launch other Windchill applications.

wt.properties wt.properties file


To use Windchill, the following properties must be set in the wt.properties file (this is usually done at installation). Note that you must use double back slashes to specify path names in the wt.properties file. This is necessary because the string is read by a Java program. wt.home, which specifies the top level of the class directory structure where Windchill is installed. The default value is c:\\windchill. wt.server.codebase, which is used by client applications (not applets). It specifies a URL from which client applications can download server resources such as property files. Client applets use their own codebase URL as specified in their APPLET tags. Server applications may use this property when writing dynamically generated HTML to be returned to a client browser. It is used to build URLs for static resources such as images or HTML files that reside under the server s codebase directory. java.rmi.server.hostname, which specifies a host name used to identify the server host. It is used by the Java RMI runtime for clients to look up the IP address of the server. It can be specified as a symbolic name, such as a fullyqualified Internet domain name, or numerically in dot notation (for example, 127.0.0.1). If not specified, the RMI runtime will use the name returned by

36

Windchill Customization Guide

InetAddress.getLocalHost() method, which may return a name that is not known to remote clients. We recommend that this property be set to the fullyqualified Internet domain name of the server host. You may also want to set the following properties: wt.access.enforce This property enforces access control. By default. it is true. However, if you are debugging and want to bypass access control temporarily, you can set it to false. wt.logs.enabled This property enables and disables logging in applications that support it, such as the Windchill Server Manager and Method Server applications. By default, it is false. To write debugging messages to a log file, you must set it to true. wt.method.verboseClient and wt.method.verboseServer These properties cause trace messages to be printed from the client-side and server-side, respectively, of the method server remote interfaces. By default, it is false. Turning on these properties causes trace information to be written to logs for debugging purposes. Similar properties are available for the server manager: wt.manager. verboseClient and wt.manager.verboseServer. In looking through the properties, you will see many service names followed by the word verbose (for example, wt.access.verboseExecution and wt.access. verbosePolicy). In general, these properties allow you to turn on debug tracing.

service.properties service.properties file


The service.properties file contains properties used by the Windchill service delegate mechanism. This mechanism is a general facility for adding delegate classes to an existing service to implement new, customized behavior. In this context, service can mean any sort of Java mechanism that provides functionality to other classes. For example, assume a copy service exists that can make copies of certain classes of objects. The service knows how to make copies only for objects of certain classes: the classes for which copy service delegates have been created. Each delegate implements an interface, defined as part of the copy service, that contains the methods needed by the service. Once the delegate is created and put in the codebase, the copy service is notified of its existence by adding an entry to the service.properties file.

The Windchill Development Environment

37

Generally, each service is accessed using a factory. The factory either returns instances of delegates to perform services on particular classes of objects, or it performs the operations on the objects itself by instantiating the necessary delegates internally. If a Windchill service supports customization by adding delegates, the description of how to do the customization is described elsewhere in the documentation.

tools.properties tools.properties file


wt.generation.sql.dir, which specifies where SQL scripts will be generated. wt.generation.sql.xxxTablesSize, which sets default sizes for tables.

Note Because tools.properties is contained within the SystemGeneration.jar, user overrides to these properties are placed in codebase\user.properties.

user.properties user.properties file


The user.properties file contains user overrides that are used by the System Generation tools.

Note Configuration overrides for System Generation should be configured in user. properties using the xconfmanager utility. See the Windchill System Administrator s Guide for information on the xconfmanager utility.

db.properties db.properties file


The db.properties file contains properties that are used by the Windchill persistence layer to access the database. They can be set in the wt.properties file but are usually kept in a separate file identified by the wt.pom.properties entry. Because a password is contained in this file, you should maintain it in a secure location. The values in the separate file override the values in the wt.properties file. In the db.properties file, you must set the following properties: wt.pom.dbUser, which specifies the Oracle user name you or your Oracle administrator defined for you. This user is the owner of Windchill tables and stored procedures. There is no default; it must be set. wt.pom.dbPassword, which specifies the Oracle password you or your Oracle administrator defined for you. There is no default; it must be set. wt.pom.serviceName, which is the service name you or your Oracle administrator created. There is no default; it must be set.

38

Windchill Customization Guide

Properties and Property Files


In general, properties for Windchill Foundation PDM out-of-the-box clients are grouped as follows: codebase/service. codebase/service.properties properties properties specifying the TemplateProcessor, ActionDelegate, URLActionDelegate, and FormTaskDelegate to use for a given action/object type codebase/htmltemplate. codebase/htmltemplate.properties properties properties specifying the HTML template to use for a given action/object type codebase/htmlcomponent. codebase/htmlcomponent.properties properties properties specifying the HTMLComponent to be used for a given element codebase/wt.properties miscellaneous template processing properties such as colors of various page components (wt.html.color.*), the text encoding used for various locales (wt.template.encoding.*), and the default parameters used for various page tags (wt.templateutil.component.*) The first three of these files contain properties for what are typically known as application context services. These require special loading at runtime and are described in more detail in the following section. The properties in wt.properties are simple name/value pairs that are loaded into a Java Properties class instance at runtime. You should not add to or modify this file directly because it will be hard to maintain your customizations if Windchill is reinstalled or upgraded. Instead, modify this file using either the system configurator client in your Windchill product or the xconfmanager command live utility. These are respectively described in the Administering Runtime Services section of the Windchill System Administrator s Guide and in Using the xconfmanager Utility on page 146. See the section Properties and Property Files for more information on the property files used in Windchill.

Application Context Service/Resource Service/Resource Properties


These are properties, generally used by a factory class, for locating a delegate, service, or resource. They have one of the following formats:
wt.services/svc/default/<Service Type>/< Selector >|null/<Requestor>/<Service Priority Number>=<Service Class Name>/<duplicate or singleton> or wt.services/rsc/default/<Resource Type>/<Selector>|null/<Requestor>/<Service Priority Number>=<Resource Name>

The Windchill Development Environment

39

The first format is used to locate a Java service or delegate class to perform a function or provide a service. The second format is used to locate a resource file for example, a HTML template file or an icon image file
Definitions:

Service Type = the type of service or delegate referenced by this property Resource Type = the type of resource referenced by this property Selector = an identifier used to specify the context in which this service or resource is to be used (for example, an action name) Requestor = the object class for which the service, delegate, or resource is to be used Service Priority Number = a priority rating used to choose between valid delegates (see below) Service Class Name = name of delegate or service class for the given Service Type, Selector, and Requestor Resource Name = name or resource for given Resource Type, Selector, and Requestor Duplicate or singleton = a flag to indicate whether the server should instantiate a shared instance of a delegate class or create a new one for each use. If neither is specified, duplicate will be used. This is an example property for a template processor:
wt.services/svc/default/wt.enterprise.TemplateProcessor/AddAlternates/ wt.part.WTPartMaster/0=wt.part.AlternatesLocalSearchProcessor/duplicate

where
Service Type = "wt.enterprise.TemplateProcessor" Selector = the action name "AddAlternates" Requestor = "wt.part.WTPartMaster"

Note Any service class that incorporates an HTTPState object should be made duplicate. This would include instances of BasicTemplateProcessor, FormTaskDelegate, NavBarActionDelegate, and NavBarURLActionDelegate.
If a factory receives a request for a service or resource class for a given requestor object class but no property entry for that requestor class is found, the factory will attempt to find an entry for the parent class or interface of the requestor class. If no entry for the parent class or interface is found, a search will be made for an entry for the parent of the parent or interface, and so on. It could happen that entries for two or more parent classes or interfaces are found. If the entries have different service priority numbers, the one with the lowest number will be selected. If the entries have the same service priority number, the one selected is arbitrary.

40

Windchill Customization Guide

To be loaded correctly at runtime, files containing application context service properties must be listed for one of the following properties in wt.properties:
wt.services.applicationcontext.WTServiceProviderFromProperties. defaultPropertyFiles wt.services.applicationcontext.WTServiceProviderFromProperties. customPropertyFiles

Property files will be loaded in the order listed, and files listed for defaultPropertyFiles will be loaded before those for customPropertyFiles. If the same property is found in more than one file, the value for the one loaded last will be used. Any custom properties should be placed in the latter list. Except for the need to separate application context service properties from ordinary properties and the effect of load order, the grouping of properties into various properties files is unimportant to the system and based primarily on ease of maintenance. If a TemplateProcessor property is put in the htmltemplate.properties file instead of service.properties the system will still find it. Many of the more heavily customized service property files are not created or edited directly but instead are generated from xml files. XML files used to generate property files have the same name as the associated property file but have the additional extension .xconf. For example, the XML file used to generate service. properties is called service.properties.xconf. See Managing Customizations on page 112 for more information on xconf files. If you need to add application context property entries for your custom HTML clients, we recommend you put them in a new properties file or files used only for your customizations. This file should be added to the list of files for WTServiceProviderFromProperties.customPropertyFiles using the xconfmanager utility. This procedure is described in Managing Customizations on page 112 .

Application Context Service Properties for Soft Types


The application context service properties in service.properties and other files listed for WTServiceProviderFromProperties.defaultPropertyFiles and WTServiceProviderFromProperties.customPropertyFiles cannot reference requestor object types that are soft types. Properties for client features that allow you to specify different services or resources for different soft types must be put in a property file listed for one of the following properties in <Windchill>/codebase/wt.properties: wt.services.applicationcontext.TypeBasedService ProviderFromProperties.defaultPropertyFiles wt.services.applicationtext.TypeBasedService ProviderFromProperties. CustomPropertyFiles

The Windchill Development Environment

41

If you need to add typed service property entries for your custom HTML clients, we recommend you put them in a new properties file or files used only for your customizations. This file should be added to the list of files for TypeBasedServiceProviderFromProperties.CustomPropertyFiles using the xconfmanager utility. This procedure is described in Managing Customizations on page 112.

42

Windchill Customization Guide

3
Getting Started With Windchill Customization
Example Overview.....................................................................................................44 Windchill Development Environment ...........................................................................45 Customization Setup..................................................................................................46 Creating the Class .....................................................................................................47 Creating a UI.............................................................................................................56 Customizations Next Steps .................................................................................. 100

The Windchill product is highly customizable and provides various mechanisms and APIs to customize business logic, user interfaces, and services and infrastructure. The chapters that follow document these mechanisms, making it possible to do everything from minorly tailoring a user interface to creating brand new business objects with supporting user interfaces and server-side logic. This chapter provides a Hello, World! introduction to Windchill customization by introducing a new, persistent class and backing user interface. The example assumes familiarity with Java and the Eclipse IDE. While not obligatory, Eclipse is known to work well and project setup tools are provided.

43

Example Overview
The customization will introduce a new class, Pet. Pet will represent an animal (a pet) and will define the following properties: name the name of the pet kind an enumeration consisting of dog, cat, gerbil, etc. dateOfBirth a date represeting the pets birthday fixed a boolean indicating whether the pet has been spayed or neutered. ContentHolder (a domain interface) to store pictures of the pet Ownable (a domain interface) to support assigning the pet to an owner WTObject (a base class) to provide basic functionailty.

Additionally, the Pet will incorporate the following:

Pets can be stored in the Windchill database and support basic CRUD operations (Create, Read (query), Update, Delete). Additionally, the Windchill user interface will be augmented to support CRUD operations against pets in the browser. Note that the Pet example is not intended to be complete, nor is it an example of a practical customization; it merely demonstrates a simple Windchill customization introducing a new, persisted, and very basic class.

44

Windchill Customization Guide

Windchill Development Environment


The Pet example requires a Windchill installation with Information Modeler installed. The install location is referred to as the load point, and may be a path similar to /opt/ptc/Windchill or C:\ptc\Windchill. The example uses the Eclipse IDE to author and compile source. Pet itself is a Java source file and will reside in the load point/src directory. The Ant script, tools.xml, found in load point/bin provides the following targets which will be used throughout the example: eclipse_project generates an Eclipse project class compiles Java source code bundle builds the resource bundles for enumerations sql_script generates SQL scripts for persistent classes.

Each of these targets provides help (simply append .help to the names above). Basic knowledge of Java, Ant, Eclipse (if you are using it), and persistence is assumed throughout the example.

Getting Started With Windchill Customization

45

Customization Setup
Setup consists of two steps: 1. Start a Windchill shell 2. Install & configure Eclipse. Starting a Windchill Shell The Windchill shell (included in load point/bin/windchill) establishes an environment suitable for customization. It is invoked as follows: 1. cd load point 2. bin/windchill shell The Windchill shell adds Ant and Java to the PATH, configures various Ant environment variables, sets the CLASSPATH to that of the MethodServer, and sets WT_HOME to the load point directory. Installing and Configuring Eclipse Eclipse should be installed and configured. Follow the instructions produced by the following command to get started: ant -f bin/tools.xml eclipse_project.help

46

Windchill Customization Guide

Creating the Class


1. Begin by launching Eclipse (see previous section). The cust_Windchill_src project should be open in Eclipse, which should look similar to the following:

2. Create the Pet class. a. Navigate to File New Class . b. Set Package to com.acme c. Set Name to Pet d. Click Finish .

Getting Started With Windchill Customization

47

The result will be an empty class, as follows:

3. Make the Pet persistent. a. Annotate the class declaration with @GenAsPersistable (note, Control + Space will complete and, as Eclipse supports camel-completion, it is possible to complete this by typing @GAP followed by Control + Space; using Eclipse completion has the advantage that, generally, an inability to complete is an indicator that some larger syntax error exists that needs to be corrected) b. Save Pet (Control-s). Pet will immediately show two compile errors, as follows:

This is expected. c. Resolve them by: i. Making Pet extend _Pet. ii. iii. Adding the required declaration to Pets body

48

Windchill Customization Guide

d. Save Pet again. Pet now extends _Pet, which implements wt.fc. Persistable, resulting in two new errors.

Rather than implement these directly, make WTObject the super class of _Pet by adding superClass=WTObject.class to the annotation above (both superClass and WTObject will complete, and Eclipse will automatically import WTObject as part of the completion). e. Save Pet again. The result, which will compile cleanly, is as follows:

f. Create the no-argument factory method for Pet, which consists of the following:
public static Pet newPet() throws WTException { final Pet instance = new Pet(); instance.initialize(); return instance; }

Windchill persisted objects require the use of factory methods similar to the newPet() factory method over constructors. They are paired with initialize methods accepting the same arguments so child classes can inherit logic present in the parent classs methods. In this case, an explicit initialize method is unnecessary as Pet does not contribute functionality; here, the implementation inherited from WTObject is sufficient. 4. Add ContentHolder and Ownable to Pet. Windchill utilizes Java interfaces to provide domain functionality to persistent business classes. ContentHolder gives the ability to store files (content) and Ownable the ability to take ownership of a business object. a. Add , interfaces={ContentHolder.class, Ownable. class} after the superClass annotation member. Make sure to use Eclipse Control + Space completion auto-import the interfaces
Getting Started With Windchill Customization

49

b. Save Pet 5. Add name, dateOfBirth, and fixed as properties to Pet. a. Declare the properties annotation member by adding a comma after the closing } of interfaces, then adding a newline, and then inserting the following (the annotations closing parethensis is shown): properties= { }) b. All properties will be included between the {}s for properties, each on their own line. First, add name as follows:
@GeneratedProperty(name="name", type=String.class, columnProperties=@ColumnProperties(index=true), constraints=@PropertyConstraints(required=true, upperLimit=60))

This property declares name, of type String. The name is required, must be 60 characters or less in length, and will be indexed in the database. Most of this can be code-completed by the IDE, reducing significantly the amount of effort needed to enter it c. Next, add dateOfBirth immediately following name. It will be necessary to add a comma to the previous line to separate the two declarations:
@GeneratedProperty(name="dateOfBirth", type=Timestamp.class)

Here, dateOfBirth is a java.sql.Timestamp. d. Finally, add fixed (a boolean): @GeneratedProperty (name="fixed", type=boolean.class) 6. Create PetKind, an enumerated type consisting of common pet kinds. a. Navigate to File New Class . b. Set Package to com.acme c. Set Name to PetKind d. Click Finish . Add the GenAsEnumeratedType annotation to the class declaration and make the class extend _PetKind (ignore the warning). The result will look as follows:

7. Create PetKindRB.rbInfo, a resource bundle storing kinds of pets


Windchill Customization Guide

50

a. Select PetKind.java and Type Control-N. b. Select General File and click Next . c. Give PetKindRB.rbInfo as the File name. d. Click Finish. e. Make the contents of PetKindRB.rbInfo as follows (and save it):
ResourceInfo.class=wt.tools.resource.EnumResourceInfo dog.value=Dog dog.order=10 cat.value=Cat cat.order=20 gerbil.value=Gerbil gerbil.order=30

8. Add kind to Pet. a. Place kind between name and dateOfBirth: @GeneratedProperty(name="kind", type=PetKind.class, constraints=@PropertyConstraints(upperLimit=40)) The stored value of an enumerated type is the key value (dog, cat, gerbil) as opposed to the display value (Dog, Cat, Gerbil). An upper limit of 40 was specified as its a more than sufficient value to store the keys. 9. Verify the result. Note that, as a minor clean-up, all the separate annotations imports have been reduced to a single * import:

Getting Started With Windchill Customization

51

10. Compile PetKindRB.rbInfo. a. Find or start a Windchill shell (command assumes shell is in WT_HOME directory). b. run the following command: ant -f bin/tools.xml bundle -Dbundle.input=com.acme.* 11. Ensure Pet, PetKind compile with Ant. a. Reuse Windchill shell from previous command b. ant -f bin/tools.xml class -Dclass.includes=com/acme/ ** -Dclass.force=true 12. Generate SQL scripts. a. Reuse, again, Windchill shell b. ant -f bin/tools.xml sql_script -Dgen.input=com.acme. * 13. Load schema for Pet. a. Locate, under load point/db, Make_pkg_acme_Table.sql. i. Oracle (single byte): db/sql/com/acme/Make_pkg_acme_Table.sql ii. Oracle (multi-byte): db/sql3/com/acme/Make_pkg_acme_Table.sql

52

Windchill Customization Guide

iii. SQLServer: db/sqlServer/com/acme/Make_pkg_acme_Table.sql b. cd to the db/<xxx> directory from above (db/sql, db/sql3, or db/ sqlServer) c. Run the script i. Oracle: sqlplus <database credentials> @com/acme/ Make_pkg_acme_Table.sql ii. SQLServer: d. Repeat for @com/acme/Make_pkg_acme_Index.sql Verifying the customization The customization is incomplete: no user interface (UI) exists to manage Pet objects. Nevertheless, the customization is complete enough to verify that CRUD operations against Pet objects are possible, as the following Jython code demonstrates. To invoke the example: 1. Download (and install) the latest version of Jython from http://www.jython.org 2. Start (or restart) the MethodServer 3. Start a Windchill shell 4. Run jython, which without arguments will start the Jython interpreter. Jython is a Java implementation of the Python programming language and, while Jython uses Pythons syntax, it will be readily familiar to a Java programmer. Jython brings two important advantages of a Java class with a main method: Jython is dynamic: methods can be typed in the interpreter, are immediately invoked by the interpreter, and the result of the invocation is immediately available. This, sometimes refered to as a REPL, offers a level of interaction with code unparalleled by a static class file, even when debugged in a debugger. Furthermore, Jythons dynamic nature precludes typing variables, casting, writing try/catch blocks (unless this is desired), and so on, resulting in significantly shorter code than Javas equivalent. Jython interacts seamlessly with Java: Jython brings Python to Java without sacrificing Java. Jython is pure Java and can instantiate any Java class and call any Java method or access any Java field (within the restrictions of the Java security model). Beyond simply being able to interact with Java, Jython is notable in that the impedance mismatch between it (as a Python implementatiotn) and Java is very small, making interaction with Java simple, predictable, and easy and making conversion to straight-Java trivial.

Getting Started With Windchill Customization

53

Jython is not the only language on top of the Java virtual machine. Notably, theres also Groovy, JRuby, BeanShell, and even JavaScript. All are worth exploring and all have different approaches and philosophies worth discovering, however, Jython excels in simplicity, interactivity, and in the quality of its interpreter. The following code snippets should be executed in the Jython interpreter. While segmented, they should be invoked in the same interpreted session. The segments can also be combined into a single script that is then executed by Jython; if done, note that Jython wont automatically print like it does in the interpreter. 1. Import the Java classes necessary to do CRUD against Pet objects:
from java.sql import Timestamp from java.text import SimpleDateFormat from from from from com.acme import Pet, PetKind wt.fc import PersistenceHelper wt.ownership import OwnershipHelper wt.query import QuerySpec, SearchCondition

2. Create two pets:


dog = Pet.newPet() dog.setName('Fergus') dog.setKind(PetKind.toPetKind('dog')) dog.setDateOfBirth(Timestamp(SimpleDateFormat('yyyy-MM-dd'). parse('1999-02-11').getTime())) dog.setFixed(False) dog = PersistenceHelper.manager.store(dog) cat = Pet.newPet() cat.setName('Stimpy') cat.setKind(PetKind.toPetKind('cat')) cat.setDateOfBirth(Timestamp(SimpleDateFormat('yyyy-MM-dd'). parse('1996-08-24').getTime())) cat.setFixed(False) cat = PersistenceHelper.manager.store(cat)

3. Update the cat (note that # starts a comment and is equivalent to Javas //; the comment string need not be entered and is intended to highlight that the call will print the current principal):
cat.setFixed(True) cat = PersistenceHelper.manager.modify(cat) cat = OwnershipHelper.service.takeOwnership(cat) OwnershipHelper.getOwner(cat) #Should print/return the current principal

4. Query (read) for the Pets named Fergus:


qs = QuerySpec(Pet) qs.appendWhere(SearchCondition(Pet, Pet.NAME, SearchCondition.EQUAL, 'Fergus')) qr = PersistenceHelper.manager.find(qs) qr.size() #Should print/return 1 fergus = qr.nextElement()

54

Windchill Customization Guide

fergus.getName() #Should print/return Fergus

5. Finally, delete the dog:


PersistenceHelper.manager.delete(dog)

Pet customization notes As previously stated, this example serves more as a Hello, World! introduction to Windchill persistence and modeling than an example of a actual Windchill business object. As such, properties of various types (strings, enumerations, timestamps, and primitives) were modeled to demonstrate possibilities, but Pet was clearly insufficient as a class for storing information about pets. Similarly, while Pet implemented Windchill interfaces, it was a particularly lightweight object from a Windchill perspective. Firstly, it is not AccessControlled (from wt.access), so anyone could create, read, update, or delete pets without any permission beyond the minimal requirement of authentication. Secondly, most Windchill business classes are WTContained (from wt.inf.container) because containership is a primary organization principle of Windchill. A final, badly-needed correction to the customization is a helper/service along the lines of those already utilized in the verification (PersistenceManager from PersistenceHelper.manager and OwnershipService from OwnershipHelper.service). The service makes it possible to provide APIs that encapsulate logical operations, such as adoption. These APIs can utilize transactions, addressing the major flaw in the combination of discrete APIs to accomplish adoption on the client: it is possible to modify the pet and fail to takeOwnership, producing a state that would likely be considered corrupt. A service API such as public Pet adopt (Pet pet, WTPrincipalReference owner) throws WTException could utilize a transaction to ensure the entire adoption proceeds smoothly or not at all. Subsequent chapters in this guide will cover these and many more aspects of modeling and server-side customization.

Getting Started With Windchill Customization

55

Creating a UI
So far, Jython has stood in for a real client. Windchill, as a web application, utilizes the browser to provide a user interface. The following user interface components will be created for Pet: A table to display all pets, which will be linked to from the Site Utilities page A pop-up to create new pets (with support for uploading pictures (content)) A similar pop-up to edit existing pets An info page to view pets, with an Attachments tab to download pictures Actions to create, edit, and delete pets

Pet Table
1. Create the PetTable class a. File New Class b. Set Package to com.acme.mvc.builders c. Set Name to PetTable d. Set Superclass to AbstractComponentBuilder (from com.ptc.mvc. components) e. Click Finish 2. AbstractComponentBuilder requires that two methods be implemented (Eclipse will generate method stubs for each). The first, buildComponentData, should return the objects (rows) to display in the table. Replace the methods body with the following code to simply query all pets:
return PersistenceHelper.manager.find(new QuerySpec(Pet.class));

3. The second, buildComponentConfig, returns a table, complete with the columns to display. First, create a convenience method to get individual columns (ColumnConfig and ComponentConfigFactory are imported from com.ptc.mvc.components):
ColumnConfig getColumn(final String id, final ComponentConfigFactory factory) { final ColumnConfig column = factory.newColumnConfig(id, true); column.setSortable(false); return column; }

4. Next, create a new class, acmeManagerResource, to manage the localized display name of the table. The complete listing follows:
package com.acme.jca;

56

Windchill Customization Guide

import wt.util.resource.*; @RBUUID("com.acme.jca.acmeActionResource") public final class acmeManagerResource extends WTListResourceBundle { @RBEntry("Pets") public static final String PET_TABLE_LABEL = "pet_table_label"; }

5. Next, replace buildComponentConfigs generated body with ():


final ComponentConfigFactory factory = getComponentConfigFactory(); final TableConfig table; { table = factory.newTableConfig(); table.setType(Pet.class.getName()); table.setLabel(WTMessage.getLocalizedMessage(RESOURCE, acmeManagerResource.PET_TABLE_LABEL, null)); table.setSelectable(true); table.setShowCount(true); table.setShowCustomViewLink(false); final ColumnConfig name; { name = factory.newColumnConfig(Pet.NAME, true); name.setInfoPageLink(true); name.setSortable(true); } table.addComponent(name); table.addComponent(getColumn(ColumnIdentifiers.INFO_ACTION, factory)); table.addComponent(getColumn(ColumnIdentifiers.NM_ACTIONS, factory)); table.addComponent(getColumn(ColumnIdentifiers.LAST_MODIFIED, factory)); table.addComponent(getColumn(Pet.KIND, factory)); table.addComponent(getColumn(Pet.DATE_OF_BIRTH, factory)); table.addComponent(getColumn(Pet.FIXED, factory)); } return table;

Use Control-L to resolve classes as follows: com.acme.jca. acmeManagerResource, com.ptc.core.components. descriptor.DescriptorConstants.ColumnIdentifiers, com. ptc.mvc.components.TableConfig, and wt.util.WTMessage. Also, assign RESOURCE as a field:
static final String RESOURCE = acmeManagerResource.class.getName();

6. Register PetTable as a bean a. Annotate the PetTable class declaration as follows: @ComponentBuilder("acme.pet.table") b. Alter the projects exclusions: i. Make the projects .classpath ( eclipse/cust_Windchill_src/.classpath) writeable ii. Project Properties iii. Select Java Build Path and the Source tab.

Getting Started With Windchill Customization

57

iv. Select Excluded under cust_Windchil_src/src and select Edit. v. Select config/** and select Edit. vi. Replace config/** with config/logicrepository/** and click OK vii. Click Finish and OK 7. Create a new file named Pet-configs.xml a. File ... Other Other b. Select XML XML File , then Next (if XML/XML File are not available, install Eclipse XML Editors and Tools, which is available under the Web, XML, and Java EE Development category when working with the Helios software site -or- simply create a General -> File) c. Assign parent folder to cust_Windchill_src/src/config/mvc and file name to Pet-configs.xml and click Finish d. Content is as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.ptc.com/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.ptc.com/schema/mvc http://www.ptc.com/schema/mvc/mvc-10.0.xsd"> <!-- Define the builders --> <bean class="com.acme.mvc.builders.PetTable"/> </beans>

8. Validate that the table works by starting/restarting Windchill and appending to the base Windchill URL /app/#ptc1/comp/acme.pet.table. The following table should appear:

58

Windchill Customization Guide

Pet Information Page


Wiring the Pet table into Site Utilities At this point, acme.pet.table is accessible, but requires the user to specify the URL manually. Pet is not WTContained, so a logical place to wire in the table is under Site Utilities . 1. The site utilities or managed by codebase/netmarkets/jsp/object/commonUtilities.jspf, a Windchill-delivered and Windchill-managed file. This file should not be updated in place; rather, it should be handled by the safe area mechanism. a. Create the following two directory structures under load point: wtSafeArea/ptcOrig/codebase/netmarkets/jsp/ objectwtSafeArea/siteMod/codebase/netmarkets/jsp/ object Copy commonUtilities.jspf to both directories just created above. 2. Edit wtSafeArea/siteMod/codebase/netmarkets/jsp/object as follows to add the items in bold: a. After <%@ page import="com.ptc.netmarkets.object. objectResource"%> add: <%@ page import="com.acme. acmeResource"%>
<%@ page import="com.ptc.netmarkets.object.objectResource"%> < % @ page import="com.acme. import="com.acme.acmeResource"% acmeResource"%> >

b. After private static final String ENTERPRISE_RESOURCE = "wt.enterprise.enterpriseResource"; add private static final String ACME_RESOURCE = "com.acme. acmeResource";
<%! private static final String OBJECT_CONFIG_RESOURCE = "com.ptc.netmarkets.object.objectResource"; private static final String ENTERPRISE_RESOURCE = "wt.enterprise.enterpriseResource"; private static final String ACME_RESOURCE = "com.acme.acmeResource";

c. After ResourceBundle enterpriseRb = ResourceBundle. getBundle(ENTERPRISE_RESOURCE, localeBean.getLocale ()); add ResourceBundle acmeRb = ResourceBundle. getBundle(ACME_RESOURCE, localeBean.getLocale());
ResourceBundle objectRb = ResourceBundle.getBundle (OBJECT_CONFIG_RESOURCE, localeBean.getLocale()); ResourceBundle enterpriseRb = ResourceBundle.getBundle (ENTERPRISE_RESOURCE, localeBean.getLocale()); ResourceBundle acmeRb = ResourceBundle.getBundle ResourceBundle.getBundle( ( ACME_RESOURCE, localeBean.getLocale localeBean.getLocale()); ());

Getting Started With Windchill Customization

59

d. After "PERSONAL_CABINETS , add "PET_ADMINISTRATION" ,


String [] knownUtilities={"AUDITING_PURGE", "AUDITING_LICENSE_USAGE", "AUDITING_ORGANIZATION_USAGE", "AUDITING_SECURITY_REPORT_QUERIES", "AUDITING_SECURITY_REPORTS", "CALENDAR_MANAGEMENT", "CLASSIFICATION_ADMINISTRATOR", "SCMI_ADAPTER_ADMINISTRATOR", "SCMI_ADMINISTRATOR", "CONFIGURATION_FILE_GENERATOR", "ESI_TRANSACTION_ADMIN", "REPLICATION_ADMINISTRATOR", "CCS_MANAGER", "IMPORT_EXPORT", "INFO_ENGINE" , "NUMBERING_SCHEMES", "VERSIONING_SCHEMES", "LIFE_CYCLE_ADMIN", "ESI_DISTRIBUTION_TARGET_ADMIN", "OPTEGRA_GATEWAY", "RULES_ADMINISTRATION", "PACKAGES_MAPPING_MANAGER", "PARTICIPANT_ADMINISTRATION", "PERSONAL_CABINETS" , "PET_ADMINISTRATION",

e. After the if (wvs_enabled ) { block add linkDatum.put ("PET_ADMINISTRATION.isUtilityInstalled", "Yes");


if (wvs_enabled ) { linkDatum.put("CAD_AGENT.isUtilityInstalled" linkDatum.put("PRODUCT_VIEW.isUtilityInstalled" linkDatum.put("PUBLISH_MONITOR.isUtilityInstalled" linkDatum.put("PUBLISH_SCHEDULER.isUtilityInstalled" linkDatum.put("PUBLISH_THB_CONTROL.isUtilityInstalled" } , , , , , "Yes" "Yes" "Yes" "Yes" "Yes" ); ); ); ); );

linkDatum.put("PET_ADMINISTRATION.isUtilityInstalled", "Yes");

f. After linkDatum.put("AUDITING_SECURITY_REPORTS. isAuditUtility" , "Yes" ); add // set ACME utility flag. Define only if the utility is considered an ACME utility linkDatum.put("PET_ADMINISTRATION. isACMEUtility", "Yes");
// set audit utility flag. Define only if the utility is considered an auditing utility linkDatum.put("AUDITING_PURGE.isAuditUtility" , "Yes" linkDatum.put("AUDITING_ORGANIZATION_USAGE.isAuditUtility" , "Yes" linkDatum.put("AUDITING_LICENSE_USAGE.isAuditUtility" , "Yes" linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.isAuditUtility", "Yes" linkDatum.put("AUDITING_SECURITY_REPORTS.isAuditUtility" , "Yes" // set ACME utility flag. Define only if the utility is considered an ACME utility ); ); ); ); );

60

Windchill Customization Guide

linkDatum.put linkDatum.put("PET_ADMINISTRATION. ("PET_ADMINISTRATION.isACMEUtility", isACMEUtility", "Yes"); "Yes"

g. After linkDatum.put("PERSONAL_CABINETS.idText" , linkBean.getLinkID(null,"textLink: deletedUsersCabinets") ); add linkDatum.put ("PET_ADMINISTRATION.idText" , linkBean.getLinkID (null,"textLink:petAdmin") );


// The value to use for id. An entry is required for all known utilities linkDatum.put("AUDITING_PURGE.idText" , linkBean.getLinkID(null,"textLink:auditingPurge") ); linkDatum.put("AUDITING_ORGANIZATION_USAGE.idText" , linkBean.getLinkID(null,"textLink:auditingOrgUsage") ); linkDatum.put("AUDITING_LICENSE_USAGE.idText" , linkBean.getLinkID(null,"textLink:auditingLicenseUsage") ); linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.idText" , linkBean.getLinkID(null,"textLink:auditingReportQueries") ); linkDatum.put("AUDITING_SECURITY_REPORTS.idText" , linkBean.getLinkID(null,"textLink:auditingReports") ); linkDatum.put("CAD_AGENT.idText" , linkBean.getLinkID(null,"textLink:cadAgentAdmin") ); linkDatum.put("CALENDAR_MANAGEMENT.idText" , linkBean.getLinkID(null,"textLink:calendarManagement") ); linkDatum.put("CLASSIFICATION_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:classificationAdministrator") ); linkDatum.put("CONFIGURATION_FILE_GENERATOR.idText" , linkBean.getLinkID(null,"textLink:configurationFileGenerator") ); linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.idText" , linkBean.getLinkID(null,"textLink:ESI_DISTRIBUTION_TARGET_ADMIN") ); linkDatum.put("ESI_TRANSACTION_ADMIN.idText" , linkBean.getLinkID(null,"textLink:ESI") ); linkDatum.put("EXTERNAL_STORAGE.idText" , linkBean.getLinkID(null,"textLink:externalStorageAdmin") ); linkDatum.put("IMPORT_EXPORT.idText" , linkBean.getLinkID(null,"textLink:importExportAdmin") ); linkDatum.put("PACKAGES_MAPPING_MANAGER.idText" , linkBean.getLinkID(null,"textLink:packageMappingManager") ); linkDatum.put("INFO_ENGINE.idText" , linkBean.getLinkID(null,"textLink:infoEngineAdmin") ); linkDatum.put("LIFE_CYCLE_ADMIN.idText" , linkBean.getLinkID(null,"textLink:lifeCycleTemplateAdmin") ); linkDatum.put("NUMBERING_SCHEMES.idText" , linkBean.getLinkID(null,"textLink:numberingSchemesAdmin") ); linkDatum.put("POLICY_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:policyAdmin") ); linkDatum.put("PERSONAL_CABINETS.idText" , linkBean.getLinkID(null,"textLink:deletedUsersCabinets") ); linkDatum.put("PET_ADMINISTRATION.idText" , linkBean.getLinkID linkBean.getLinkID(null,"textLink: (null,"textLink:petAdmin") petAdmin") );

h. After linkDatum.put("VIEW_NETWORK.pageLoc" , viewAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request)); add //ACME pageLocs linkDatum.

Getting Started With Windchill Customization

61

put("PET_ADMINISTRATION.pageLoc", NetmarketURL. convertToShellURL("ptc1/comp/acme.pet.table"));


//We need to get the locale specific link for the network admin . NmAction viewAction = NmActionServiceHelper.service.getAction("view","list"); linkDatum.put("VIEW_NETWORK.pageLoc" , viewAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request)); //ACME pageLocs linkDatum.put linkDatum.put("PET_ADMINISTRATION. ("PET_ADMINISTRATION.pageLoc", pageLoc", NetmarketURL.convertToShellURL NetmarketURL.convertToShellURL ("ptc1/comp/ ("ptc1/comp/acme. acme.pet. pet.table")); table"));

i. After linkDatum.put("NUMBERING_SCHEMES.urlPrarms" ,"'NumberingSchemes','resizable=yes, scrollbars=yes,menubar=yes,toolbar=yes, location=yes,status=yes'"); add linkDatum.put ("PET_ADMINISTRATION.urlPrarms" ,"'PetAdmin','resizable=yes,scrollbars=yes, menubar=yes,toolbar=yes,location=yes,status=yes'" );
linkDatum.put("ESI_TRANSACTION_ADMIN.urlPrarms","'ESITransaction',' directories=no,location=no,menubar=no,scrollbars=yes,status=yes, toolbar=no,resizable=yes,height=1000,width=1400'" ); linkDatum.put("EXTERNAL_STORAGE.urlPrarms" ,"'ExternalStorage','resizable=yes,scrollbars=yes,menubar=no, toolbar=no,location=no,status=yes,height=455,width=640'" ); linkDatum.put("IMPORT_EXPORT.urlPrarms" ,"'_blank','resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no, status=yes,height=455,width=640'"); linkDatum.put("PACKAGES_MAPPING_MANAGER.urlPrarms" ,"'_blank','resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no, status=yes,height=500,width=880'"); linkDatum.put("INFO_ENGINE.urlPrarms" ,"'InfoEngine','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes,status=yes'" ); linkDatum.put("LIFE_CYCLE_ADMIN.urlPrarms" ,"'LifeCycleAdmin','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes,status=yes'"); linkDatum.put("NUMBERING_SCHEMES.urlPrarms" ,"'NumberingSchemes','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes,status=yes'"); linkDatum.put("PET_ADMINISTRATION.urlPrarms" ,"'PetAdmin','resizable=yes,scrollbars=yes, ,"'PetAdmin','resizable=yes,scrollbars=yes,menubar=yes, menubar=yes,toolbar=yes, toolbar=yes, location=yes,status=yes'" location=yes,status=yes'" );

j. After linkDatum.put("PERSONAL_CABINETS.linkText" , objectRb.getString(objectResource. PERSONAL_CABINETS)); add linkDatum.put

62

Windchill Customization Guide

("PET_ADMINISTRATION.linkText" ,acmeRb.getString (acmeResource.PET_ADMINISTRATION));


linkDatum.put("EXTERNAL_STORAGE.linkText" ,objectRb.getString(objectResource.EXTERNAL_STORAGE)); linkDatum.put("IMPORT_EXPORT.linkText" ,objectRb.getString(objectResource.IMPORT_EXPORT)); linkDatum.put("PACKAGES_MAPPING_MANAGER.linkText" ,objectRb.getString(objectResource.PACKAGES_MAPPING_MANAGER)); linkDatum.put("INFO_ENGINE.linkText" ,objectRb.getString(objectResource.INFO_ENGINE)); linkDatum.put("LIFE_CYCLE_ADMIN.linkText" ,objectRb.getString(objectResource.LIFE_CYCLE_ADMIN)); linkDatum.put("NUMBERING_SCHEMES.linkText" ,objectRb.getString(objectResource.NUMBERING_SCHEMES)); linkDatum.put("PERSONAL_CABINETS.linkText" ,objectRb.getString(objectResource.PERSONAL_CABINETS)); linkDatum.put linkDatum.put("PET_ADMINISTRATION. ("PET_ADMINISTRATION.linkText" linkText" , acmeRb.getString acmeRb.getString(acmeResource. (acmeResource.PET_ADMINISTRATION)); PET_ADMINISTRATION));

k. After linkDatum.put("PERSONAL_CABINETS.linkDesc" , objectRb.getString(objectResource. PERSONAL_CABINETS_DESCRIPTION)); add linkDatum.put ("PET_ADMINISTRATION.linkDesc" ,acmeRb.getString (acmeResource.PET_ADMINISTRATION_DESCRIPTION));


linkDatum.put("EXTERNAL_STORAGE.linkDesc" ,objectRb.getString(objectResource.EXTERNAL_STORAGE_DESCRIPTION)); linkDatum.put("IMPORT_EXPORT.linkDesc" ,objectRb.getString(objectResource.IMPORT_EXPORT_DESCRIPTION)); linkDatum.put("PACKAGES_MAPPING_MANAGER.linkDesc" ,objectRb.getString(objectResource.PACKAGES_MAPPING_MANAGER_DESCRIPTION)); linkDatum.put("INFO_ENGINE.linkDesc" ,objectRb.getString(objectResource.INFO_ENGINE_DESCRIPTION)); linkDatum.put("LIFE_CYCLE_ADMIN.linkDesc" ,objectRb.getString(objectResource.LIFE_CYCLE_ADMIN_DESCRIPTION)); linkDatum.put("NUMBERING_SCHEMES.linkDesc" ,objectRb.getString(objectResource.NUMBERING_SCHEMES_DESCRIPTION)); linkDatum.put("PERSONAL_CABINETS.linkDesc" ,objectRb.getString(objectResource.PERSONAL_CABINETS_DESCRIPTION)); linkDatum.put linkDatum.put("PET_ADMINISTRATION. ("PET_ADMINISTRATION.linkDesc" linkDesc" ,acmeRb.getString(acmeResource.PET_ADMINISTRATION_DESCRIPTION));

l. Replace
objectRb.getString(objectResource.AUDITING_ADMINISTRATION)}; boolean [] systemHeader={true,false,false}; boolean [] auditHeader={false,false,true};

with
objectRb.getString objectRb.getString(objectResource. (objectResource.AUDITING_ADMINISTRATION), AUDITING_ADMINISTRATION), acmeRb.getString acmeRb.getString(acmeResource. (acmeResource.ACME_ADMINISTRATION)}; ACME_ADMINISTRATION)}; boolean [] systemHeader={true, systemHeader={true,false, false,false, false,false}; false}; boolean [] auditHeader={false, auditHeader={false,false, false,true, true,false}; false}; boolean [] acmeHeader={false, acmeHeader={false,false, false,false, false,true}; true};

Getting Started With Windchill Customization

63

m. After the //Match audit/nonaudit section add //Match acme/ noacme String isACME = knownUtilities[i].concat(". isACMEUtility"); if (linkDatum.containsKey(isACME)! =acmeHeader[currentHeader]) { continue;
//Match audit/nonaudit String isAudit = knownUtilities[i].concat(".isAuditUtility"); if (linkDatum.containsKey(isAudit)!=auditHeader[currentHeader]) { continue; } //Match acme/noacme acme/noacme String isACME = knownUtilities[i]. knownUtilities[i].concat concat(". (".isACMEUtility"); isACMEUtility"); if (linkDatum.containsKey (linkDatum.containsKey(isACME)! (isACME)!=acmeHeader =acmeHeader[currentHeader]) [currentHeader]) { continue;

n. After <% } else if ("RULES_ADMINISTRATION".equals (knownUtilities[i])) { %> href="<%=pageLoc%>" add <% } else if ("PET_ADMINISTRATION".equals(knownUtilities [i])) { %> href="<%=pageLoc%>"
<% } else if ("RULES_ADMINISTRATION".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("PET_ADMINISTRATION".equals(knownUtilities[i])) { %> href="<% href="<% =pageLoc% =pageLoc% >" <% }

3. Edit wtSafeArea/siteMod/codebase/netmarkets/jsp/object as follows:


<%@ page import="java.util.ResourceBundle"%> <%@ page import="com.ptc.netmarkets.object.objectResource"%> <%@ page import="com.acme.acmeResource"%> <%@ page import="wt.fc.Persistable"%> <%@ page import="wt.fc.ReferenceFactory"%> <%@ page import="com.ptc.netmarkets.model.NmOid"%> <%@ page import="wt.util.InstalledProperties"%> <%@ page import="wt.httpgw.URLFactory"%> <%@ page import="wt.method.MethodContext"%> <%@ page import=" wt.httpgw.GatewayServletHelper"%> <%@ page import="java.util.HashMap"%> <%@ page import="wt.query.QuerySpec"%> <%@ page import="wt.fc.*"%> <%@ page import="wt.help.HelpLinkHelper"%> <%@ page import="wt.enterprise.enterpriseResource"%> <%@ page import="com.ptc.netmarkets.util.misc.NmAction" %> <%@ page import="com.ptc.netmarkets.util.misc.NetmarketURL" %> <%@ page import="wt.audit.AuditHelper" %> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@taglib uri="http://www.ptc.com/windchill/taglib/wrappers" prefix="w" %> <%! private static final String OBJECT_CONFIG_RESOURCE = "com.ptc.netmarkets.object.objectResource"; private static final String ENTERPRISE_RESOURCE = "wt.enterprise.enterpriseResource"; private static final String ACME_RESOURCE =

64

Windchill Customization Guide

"com.acme.acmeResource"; private static final String PROINTRA_INSTALL_KEY = "WEF.ProIntralinkGateway"; private static final String TVIEW_INSTALL_KEY = "WVS.ThumbnailViewer"; private static boolean proIGatewayInst=InstalledProperties.isInstalled (PROINTRA_INSTALL_KEY); private static boolean wncpdmInstalled=InstalledProperties.isInstalled (InstalledProperties.WINDCHILL_PDM); private static boolean pdmInstalled=InstalledProperties.isInstalled (InstalledProperties.PDMLINK); private static boolean ArbortextCMInstalled=InstalledProperties.isInstalled (InstalledProperties.ARBORTEXT_CM); private static boolean pjlInstalled=InstalledProperties.isInstalled (InstalledProperties.PROJECTLINK); private static boolean tViewInstall=InstalledProperties.isInstalled (TVIEW_INSTALL_KEY);; private static boolean esiInstall=InstalledProperties.isInstalled (InstalledProperties.ESI); private static boolean classAndReuseInstall=InstalledProperties.isInstalled (InstalledProperties.PARTSLINK); private static boolean pdmProIInstalled=InstalledProperties.isInstalled (InstalledProperties.PDML_PROI); private static boolean archiveSysInstall=InstalledProperties.isInstalled( InstalledProperties.ARCHIVE_SYSTEM); private static boolean scmiInstall=InstalledProperties.isInstalled (InstalledProperties.SCMI); private static boolean sumaInstall=InstalledProperties.isInstalled (InstalledProperties.SUMA); private static boolean exclusiveAuditEnabled=AuditHelper. TMCExclusiveAuditFeaturesEnabled; private static boolean optgwInstalled=InstalledProperties.isInstalled (InstalledProperties.OPTEGRA); private static boolean proIInstalled=InstalledProperties.isInstalled (InstalledProperties.PRO_I); %> <!-Have to duplicate the code, since putting it in a common place, such as main.js does not work for Mozilla1.0 and Netscape 7.0(don't know why yet) it does work for IE though. --> <script language="javascript"> function launchUtilityWindow(linkText,winName,props) { wfWindowOpen(linkText,winName,props); } PTC.navigation.setPageTitle(bundleHandler.get('com.ptc.core.ui. navigationRB.WIN_TITLE_HOME_TAB_UTIL')); </script> <!-<% wt.wvs.VisualizationHelperFactory visHelperFactory = new wt.wvs. VisualizationHelperFactory();

Getting Started With Windchill Customization

65

wt.wvs.VisualizationHelperIfc visHelper = visHelperFactory.getHelper(); boolean wvs_enabled = visHelper.isWVSEnabled(); ResourceBundle objectRb = ResourceBundle.getBundle (OBJECT_CONFIG_RESOURCE, localeBean.getLocale()); ResourceBundle enterpriseRb = ResourceBundle.getBundle (ENTERPRISE_RESOURCE, localeBean.getLocale()); ResourceBundle acmeRb = ResourceBundle.getBundle (ACME_RESOURCE, localeBean.getLocale()); NmOid oid= new NmOid(request.getParameter("oid")); //there is no oid on the URL when the page is redirected by the HTTPGatewayBridgeFilter if( oid.getOid() == null ) { //get the ExchangeContainer ID from the database and create a NmOid from it QuerySpec querySpec = new QuerySpec(); int fromIndex = querySpec.appendClassList( wt.inf.container. ExchangeContainer.class, false ); //ID = thePersistInfo.theObjectIdentifier.id String ID = Persistable.PERSIST_INFO + "." + PersistInfo. OBJECT_IDENTIFIER + "." + ObjectIdentifier.ID; querySpec.appendSelectAttribute( ID, fromIndex, false ); QueryResult results = wt.fc.PersistenceHelper.manager.find ( querySpec ); while( results != null && results.hasMoreElements() ) { //the QueryResult is expected to have Object[] elements //and the first element of each Object[] is a BigDecimal object representing an ID long id = ( (java.math.BigDecimal)( (Object[])results.nextElement() ) [0] ).longValue(); oid = NmOid.newNmOid( new ObjectIdentifier( wt.inf.container. ExchangeContainer.class, id ) ); } } String ReferenceOid= new ReferenceFactory().getReferenceString((Persistable) oid.getContainer()); HashMap ObjectOid=new HashMap(); ObjectOid.put("containerOid",ReferenceOid); // Sorted list of the known utilities. The utilities will be presented in this order // PLEASE BE CAREFUL when adding or changing the display text in this list. This list is supposed to be in alphabetical order in english. // If you add a utility be sure to add it per it's english alphabetical location. If you change the name of one be sure to move it. String [] knownUtilities={"AUDITING_PURGE", "AUDITING_LICENSE_USAGE", "AUDITING_ORGANIZATION_USAGE", "AUDITING_SECURITY_REPORT_QUERIES", "AUDITING_SECURITY_REPORTS", "CALENDAR_MANAGEMENT", "CLASSIFICATION_ADMINISTRATOR", "SCMI_ADAPTER_ADMINISTRATOR", "SCMI_ADMINISTRATOR", "CONFIGURATION_FILE_GENERATOR", "ESI_TRANSACTION_ADMIN",

66

Windchill Customization Guide

"REPLICATION_ADMINISTRATOR", "CCS_MANAGER", "IMPORT_EXPORT", "INFO_ENGINE" , "NUMBERING_SCHEMES", "VERSIONING_SCHEMES", "LIFE_CYCLE_ADMIN", "ESI_DISTRIBUTION_TARGET_ADMIN", "OPTEGRA_GATEWAY", "RULES_ADMINISTRATION", "PACKAGES_MAPPING_MANAGER", "PARTICIPANT_ADMINISTRATION", "PERSONAL_CABINETS" , "PET_ADMINISTRATION", "POLICY_ADMINISTRATOR", "PREFERENCE_MANAGER", "PREFERENCE_MANAGER_X10" , "PROMOTION_PREFERENCE_MANAGER", "PRO_INTRALINK", "PUBLISH_THB_CONTROL", "PURGE_ADMINISTRATOR", "QUEUE_MANAGER", "REPLICATION_RULES_ADMINISTRATOR", "REPLICATION_MANAGE_RULES", "REPLICATION_SCHEDULE_ADMINISTRATOR", "REPORT_MANAGER", "SERVER_STATUS", "TS_PORTAL", "SUPPLIER_ADMINISTRATOR", "TASK_DELEGATE", "TEAM_ADMIN", "TYPE_ATTRIBUTE_MANAGER", "VIEW_NETWORK", "PRODUCT_VIEW", "WORKFLOW_ADMIN", "WORKFLOW_TEMPLATES_ADMIN", "WORKFLOW_ADMIN_DASHBOARD", "CAD_AGENT", "PUBLISH_MONITOR", "PUBLISH_SCHEDULER"}; int nKnownUtilities = knownUtilities.length; HashMap linkDatum= new HashMap(); // set installed flag. Define only if the utility is installed linkDatum.put("AUDITING_PURGE.isUtilityInstalled" , "Yes" ); linkDatum.put("AUDITING_ORGANIZATION_USAGE.isUtilityInstalled" , "Yes" ); linkDatum.put("AUDITING_LICENSE_USAGE.isUtilityInstalled" , "Yes" ); linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.isUtilityInstalled" , "Yes" ); linkDatum.put("AUDITING_SECURITY_REPORTS.isUtilityInstalled" , "Yes" ); if (scmiInstall) {

Getting Started With Windchill Customization

67

linkDatum.put("SCMI_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.isUtilityInstalled" ,"Yes" ); } linkDatum.put("SERVER_STATUS.isUtilityInstalled" , "Yes" ); linkDatum.put("TS_PORTAL.isUtilityInstalled" , "Yes" ); linkDatum.put("CONFIGURATION_FILE_GENERATOR.isUtilityInstalled" , "Yes" ); linkDatum.put("EXTERNAL_STORAGE.isUtilityInstalled" , "Yes" ); linkDatum.put("INFO_ENGINE.isUtilityInstalled" , "Yes" ); linkDatum.put("PERSONAL_CABINETS.isUtilityInstalled" , "Yes" ); linkDatum.put("PARTICIPANT_ADMINISTRATION.isUtilityInstalled" , "Yes" ); linkDatum.put("PREFERENCE_MANAGER.isUtilityInstalled" , "Yes" ); linkDatum.put("PREFERENCE_MANAGER_X10.isUtilityInstalled" , "Yes" ); linkDatum.put("PROMOTION_PREFERENCE_MANAGER.isUtilityInstalled" , "Yes" ); linkDatum.put("QUEUE_MANAGER.isUtilityInstalled" , "Yes" ); linkDatum.put("REPLICATION_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); linkDatum.put("REPLICATION_MANAGE_RULES.isUtilityInstalled" , "Yes" ); linkDatum.put("CCS_MANAGER.isUtilityInstalled", "Yes" ); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); linkDatum.put("RULES_ADMINISTRATION.isUtilityInstalled" , "Yes" ); linkDatum.put("LIFE_CYCLE_ADMIN.isUtilityInstalled" , "Yes" ); linkDatum.put("POLICY_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); linkDatum.put("PURGE_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); if (sumaInstall) { linkDatum.put("SUPPLIER_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); } linkDatum.put("TYPE_ATTRIBUTE_MANAGER.isUtilityInstalled" , "Yes" ); if (pdmProIInstalled || wncpdmInstalled) { linkDatum.put("TEAM_ADMIN.isUtilityInstalled" , "Yes" ); }

68

Windchill Customization Guide

if (pdmInstalled || pjlInstalled) { linkDatum.put("CALENDAR_MANAGEMENT.isUtilityInstalled" , "Yes" ); linkDatum.put("TASK_DELEGATE.isUtilityInstalled" , "Yes" ); linkDatum.put("VIEW_NETWORK.isUtilityInstalled" , "Yes" ); linkDatum.put("WORKFLOW_ADMIN.isUtilityInstalled" , "Yes" ); linkDatum.put("WORKFLOW_TEMPLATES_ADMIN.isUtilityInstalled" , "Yes" ); linkDatum.put("WORKFLOW_ADMIN_DASHBOARD.isUtilityInstalled" , "Yes" ); linkDatum.put("IMPORT_EXPORT.isUtilityInstalled" , "Yes" ); linkDatum.put("PACKAGES_MAPPING_MANAGER.isUtilityInstalled" , "Yes" ); linkDatum.put("REPORT_MANAGER.isUtilityInstalled" , "Yes" ); } if (optgwInstalled) { linkDatum.put("OPTEGRA_GATEWAY.isUtilityInstalled" , "Yes" ); } if (ArbortextCMInstalled) { linkDatum.put("WORKFLOW_ADMIN.isUtilityInstalled" , "Yes" ); linkDatum.put("REPORT_MANAGER.isUtilityInstalled" , "Yes" ); linkDatum.put("CALENDAR_MANAGEMENT.isUtilityInstalled" , "Yes" ); linkDatum.put("TASK_DELEGATE.isUtilityInstalled" , "Yes" ); } if (classAndReuseInstall) { linkDatum.put("CLASSIFICATION_ADMINISTRATOR.isUtilityInstalled" , "Yes" ); } if (esiInstall) { linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.isUtilityInstalled" , "Yes" ); linkDatum.put("ESI_TRANSACTION_ADMIN.isUtilityInstalled" , "Yes" ); } linkDatum.put("NUMBERING_SCHEMES.isUtilityInstalled" , "Yes" ); linkDatum.put("VERSIONING_SCHEMES.isUtilityInstalled" , "Yes" ); if (proIGatewayInst) { linkDatum.put("PRO_INTRALINK.isUtilityInstalled" }

, "Yes" );

Getting Started With Windchill Customization

69

if (wvs_enabled ) { linkDatum.put("CAD_AGENT.isUtilityInstalled" , "Yes" ); linkDatum.put("PRODUCT_VIEW.isUtilityInstalled" , "Yes" ); linkDatum.put("PUBLISH_MONITOR.isUtilityInstalled" , "Yes" ); linkDatum.put("PUBLISH_SCHEDULER.isUtilityInstalled" linkDatum.put("PUBLISH_THB_CONTROL.isUtilityInstalled" } linkDatum.put("PET_ADMINISTRATION.isUtilityInstalled" , "Yes");

, "Yes" ); , "Yes" );

// set system utility flag. Define only if the utility is considered a system utility linkDatum.put("SERVER_STATUS.isSystemUtility" , "Yes" ); linkDatum.put("TS_PORTAL.isSystemUtility" , "Yes" ); linkDatum.put("CAD_AGENT.isSystemUtility" , "Yes" ); linkDatum.put("CALENDAR_MANAGEMENT.isSystemUtility" , "Yes" ); linkDatum.put("EXTERNAL_STORAGE.isSystemUtility" , "Yes" ); linkDatum.put("INFO_ENGINE.isSystemUtility" , "Yes" ); linkDatum.put("PERSONAL_CABINETS.isSystemUtility" , "Yes" ); linkDatum.put("PRO_INTRALINK.isSystemUtility" , "Yes" ); linkDatum.put("REPLICATION_ADMINISTRATOR.isSystemUtility" , "Yes" ); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.isSystemUtility" , "Yes" ); linkDatum.put("REPLICATION_MANAGE_RULES.isSystemUtility" , "Yes" ); linkDatum.put("CCS_MANAGER.isSystemUtility" , "Yes" ); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.isSystemUtility" , "Yes" ); linkDatum.put("QUEUE_MANAGER.isSystemUtility" , "Yes" ); linkDatum.put("TASK_DELEGATE.isSystemUtility" , "Yes" ); linkDatum.put("OPTEGRA_GATEWAY.isSystemUtility" , "Yes" ); linkDatum.put("IMPORT_EXPORT.isSystemUtility" , "Yes" ); linkDatum.put("PURGE_ADMINISTRATOR.isSystemUtility" , "Yes" ); linkDatum.put("SCMI_ADMINISTRATOR.isSystemUtility" , "Yes" ); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.isSystemUtility" , "Yes" );

70

Windchill Customization Guide

// set audit utility flag. Define only if the utility is considered an auditing utility linkDatum.put("AUDITING_PURGE.isAuditUtility" , "Yes" linkDatum.put("AUDITING_ORGANIZATION_USAGE.isAuditUtility" , "Yes" linkDatum.put("AUDITING_LICENSE_USAGE.isAuditUtility" , "Yes" linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.isAuditUtility", "Yes" linkDatum.put("AUDITING_SECURITY_REPORTS.isAuditUtility" , "Yes"

); ); ); ); );

// set ACME utility flag. Define only if the utility is considered an ACME utility linkDatum.put("PET_ADMINISTRATION.isACMEUtility", "Yes"); // The value to use for id. An entry is required for all known utilities linkDatum.put("AUDITING_PURGE.idText" , linkBean.getLinkID(null,"textLink:auditingPurge") ); linkDatum.put("AUDITING_ORGANIZATION_USAGE.idText" , linkBean.getLinkID(null,"textLink:auditingOrgUsage") ); linkDatum.put("AUDITING_LICENSE_USAGE.idText" , linkBean.getLinkID(null,"textLink:auditingLicenseUsage") ); linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.idText" , linkBean.getLinkID(null,"textLink:auditingReportQueries") ); linkDatum.put("AUDITING_SECURITY_REPORTS.idText" , linkBean.getLinkID(null,"textLink:auditingReports") ); linkDatum.put("CAD_AGENT.idText" , linkBean.getLinkID(null,"textLink:cadAgentAdmin") ); linkDatum.put("CALENDAR_MANAGEMENT.idText" , linkBean.getLinkID(null,"textLink:calendarManagement") ); linkDatum.put("CLASSIFICATION_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:classificationAdministrator") ); linkDatum.put("CONFIGURATION_FILE_GENERATOR.idText" , linkBean.getLinkID(null,"textLink:configurationFileGenerator") ); linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.idText" , linkBean.getLinkID(null,"textLink:ESI_DISTRIBUTION_TARGET_ADMIN") ); linkDatum.put("ESI_TRANSACTION_ADMIN.idText" , linkBean.getLinkID(null,"textLink:ESI") ); linkDatum.put("EXTERNAL_STORAGE.idText" , linkBean.getLinkID(null,"textLink:externalStorageAdmin") ); linkDatum.put("IMPORT_EXPORT.idText" , linkBean.getLinkID(null,"textLink:importExportAdmin") ); linkDatum.put("PACKAGES_MAPPING_MANAGER.idText" , linkBean.getLinkID(null,"textLink:packageMappingManager") ); linkDatum.put("INFO_ENGINE.idText" , linkBean.getLinkID(null,"textLink:infoEngineAdmin") ); linkDatum.put("LIFE_CYCLE_ADMIN.idText" , linkBean.getLinkID(null,"textLink:lifeCycleTemplateAdmin") ); linkDatum.put("NUMBERING_SCHEMES.idText" , linkBean.getLinkID(null,"textLink:numberingSchemesAdmin") ); linkDatum.put("POLICY_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:policyAdmin") ); linkDatum.put("PERSONAL_CABINETS.idText" , linkBean.getLinkID(null,"textLink:deletedUsersCabinets") ); linkDatum.put("PET_ADMINISTRATION.idText" , linkBean.getLinkID(null,"textLink:petAdmin") ); linkDatum.put("PREFERENCE_MANAGER.idText" , linkBean.getLinkID(null,"textLink:preferenceManager") ); linkDatum.put("PREFERENCE_MANAGER_X10.idText"

Getting Started With Windchill Customization

71

, linkBean.getLinkID(null,"textLink:preferenceManager") ); linkDatum.put("PROMOTION_PREFERENCE_MANAGER.idText" , linkBean.getLinkID(null,"textLink:preferenceTable") ); linkDatum.put("PARTICIPANT_ADMINISTRATION.idText" , linkBean.getLinkID(null,"textLink:userGroupOrgAdmin") ); linkDatum.put("PRODUCT_VIEW.idText" , linkBean.getLinkID(null,"textLink:productViewAdmin") ); linkDatum.put("PRO_INTRALINK.idText" , linkBean.getLinkID(null,"textLink:proIntralinkAdmin") ); linkDatum.put("PUBLISH_MONITOR.idText" , linkBean.getLinkID(null,"textLink:publishMonitor") ); linkDatum.put("PUBLISH_SCHEDULER.idText" , linkBean.getLinkID(null,"textLink:publishScheduler") ); linkDatum.put("PUBLISH_THB_CONTROL.idText" , linkBean.getLinkID(null,"textLink:pvconfigVizAdmin") ); linkDatum.put("PURGE_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:purgeAdmin") ); linkDatum.put("QUEUE_MANAGER.idText" , linkBean.getLinkID(null,"textLink:queueManager") ); linkDatum.put("REPLICATION_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:replicationAdmin") ); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:replicationScheduleAdmin") ); linkDatum.put("REPLICATION_MANAGE_RULES.idText" , linkBean.getLinkID(null,"textLink:replicationManageRules") ); linkDatum.put("CCS_MANAGER.idText" , linkBean.getLinkID(null,"textLink:ccsManager") ); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:replicationRulesAdmin") ); linkDatum.put("REPORT_MANAGER.idText" , linkBean.getLinkID(null,"textLink:reportManager") ); linkDatum.put("RULES_ADMINISTRATION.idText" , linkBean.getLinkID(null,"textLink:rulesAdministration") ); linkDatum.put("SERVER_STATUS.idText" , linkBean.getLinkID(null,"textLink:serverStatus") ); linkDatum.put("TS_PORTAL.idText" , linkBean.getLinkID(null,"textLink:tsPortal") ); linkDatum.put("TASK_DELEGATE.idText" , linkBean.getLinkID(null,"textLink:taskDelegateAdmin") ); linkDatum.put("OPTEGRA_GATEWAY.idText" , linkBean.getLinkID(null,"textLink:optegraGatewayAdmin") ); linkDatum.put("TEAM_ADMIN.idText" , linkBean.getLinkID(null,"textLink:teamTemplateAdmin") ); linkDatum.put("SCMI_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:scmiAdmin") ); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.idText", linkBean.getLinkID(null,"textLink:scmiAdapterAdmin") ); linkDatum.put("SUPPLIER_ADMINISTRATOR.idText" , linkBean.getLinkID(null,"textLink:viewSuppliers") ); linkDatum.put("TYPE_ATTRIBUTE_MANAGER.idText" , "NoId" ); linkDatum.put("WORKFLOW_ADMIN.idText" , linkBean.getLinkID(null,"textLink:workflowTemplateAdmin") ); linkDatum.put("WORKFLOW_TEMPLATES_ADMIN.idText" , linkBean.getLinkID(null,"textLink:wfTemplatesAdmin") ); linkDatum.put("WORKFLOW_ADMIN_DASHBOARD.idText"

72

Windchill Customization Guide

, linkBean.getLinkID(null,"textLink:workflowDashboard") ); linkDatum.put("VERSIONING_SCHEMES.idText" , linkBean.getLinkID(null,"textLink:versioningSchemes") ); linkDatum.put("VIEW_NETWORK.idText" , linkBean.getLinkID(null,"textLink:viewNetworkAdmin") ); linkDatum.put("CAD_AGENT.pageLoc" , urlFactoryBean.getFactory().getURL("wtcore/jsp/wvs/admincad.jsp",ObjectOid )); // Special case Uses different oid and URL factory NmAction auditPurgeAction = NmActionServiceHelper.service.getAction ("auditing","purgeManager"); linkDatum.put("AUDITING_PURGE.pageLoc" , NetmarketURL.convertToShellURL (auditPurgeAction.getActionUrl (actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request))); NmAction auditOrgUsageAction = NmActionServiceHelper.service.getAction ("auditing","organizationUsage"); auditOrgUsageAction.setContextObject(nmcontext.getContext().getPrimaryOid()); linkDatum.put("AUDITING_ORGANIZATION_USAGE.pageLoc" , NetmarketURL.convertToShellURL (auditOrgUsageAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request))); //if PRO/I use licenseUsage action; otherwise use Usage action NmAction auditLicenseUsageAction = NmActionServiceHelper.service.getAction ("auditing","usage"); if (proIInstalled) { auditLicenseUsageAction = NmActionServiceHelper.service.getAction ("auditing","licenseUsage"); } if(auditLicenseUsageAction != null) linkDatum.put ("AUDITING_LICENSE_USAGE.pageLoc" , auditLicenseUsageAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request)); String reportQueriesAction = ""; if (exclusiveAuditEnabled) { reportQueriesAction = "reportQueriesListSchedule"; } else { reportQueriesAction = "reportQueriesList"; } NmAction auditReportQueriesAction = NmActionServiceHelper.service. getAction("auditing",reportQueriesAction); auditReportQueriesAction.setContextObject(nmcontext.getContext().getPrimaryOid()); linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.pageLoc" , NetmarketURL.convertToShellURL (auditReportQueriesAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request))); NmAction auditReportsAction = NmActionServiceHelper.service.getAction ("auditing","auditCriteria"); linkDatum.put("AUDITING_SECURITY_REPORTS.pageLoc" , auditReportsAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request)); HashMap calendarMgntMap= new HashMap(); calendarMgntMap.put("action","CalendarMgmt");

Getting Started With Windchill Customization

73

calendarMgntMap.put("containerOid",ReferenceOid); linkDatum.put("CALENDAR_MANAGEMENT.pageLoc", urlFactoryBean.getFactory().getURL ("netmarkets/jsp/calender/calenderMgmt.jsp")); linkDatum.put("CLASSIFICATION_ADMINISTRATOR.pageLoc", urlFactoryBean.getFactory().getURL ("wt/clients/csm/classification/Classification.jsp",ObjectOid )); // Special case Uses different oid HashMap cfgMap= new HashMap(); cfgMap.put("alias","com.ptc.core.foundation.generator:simpleFrame.generator"); linkDatum.put("CONFIGURATION_FILE_GENERATOR.pageLoc", urlFactoryBean.getFactory().getURL ("/wtcore/jsp/com/ptc/core/ca/web/gw/gw.jsp" ,cfgMap)); linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.pageLoc", urlFactoryBean.getFactory().getURL ("/netmarkets/jsp/tgt/distributionTargetAdmin.jsp" , ObjectOid)); linkDatum.put("ESI_TRANSACTION_ADMIN.pageLoc", urlFactoryBean.getFactory().getURL ("/netmarkets/jsp/esiTransaction/esiTransactionAdmin.jsp" , ObjectOid)); HashMap purgeMap = new HashMap(); purgeMap.put("containerOid", ReferenceOid); // purgeMap.put("portlet","poppedup"); linkDatum.put("PURGE_ADMINISTRATOR.pageLoc" , urlFactoryBean.getFactory().getURL ("/app/#ptc1/archive/archiveJobAdminWizard" ,purgeMap)); //purgeMap.put("alias", "com.ptc.windchill.enterprise.dataops.purge:purge.main"); //linkDatum.put("PURGE_ADMINISTRATOR.pageLoc" , urlFactoryBean.getFactory().getURL ("/wtcore/jsp/com/ptc/core/ca/web/gw/gw.jsp" ,purgeMap)); HashMap scmMap = new HashMap(); scmMap.put("alias", "com.ptc.swlink.scm:scmiAdmin.home"); scmMap.put("containerOid", ReferenceOid); String containerName = ((wt.inf.container.WTContainer) oid.getContainer()).getName(); scmMap.put("containerName",containerName); linkDatum.put("SCMI_ADMINISTRATOR.pageLoc" , urlFactoryBean.getFactory().getURL ("/wtcore/jsp/com/ptc/core/ca/web/gw/gw.jsp" ,scmMap)); HashMap scmAdapterMap = new HashMap(); scmAdapterMap.put("containerOid", ReferenceOid); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.pageLoc", urlFactoryBean.getFactory().getURL ("/netmarkets/jsp/scmi/scmadapter_administrator.jsp" ,scmAdapterMap));

HashMap sumaMap = new HashMap(); sumaMap.put("containerOid", ReferenceOid); linkDatum.put("SUPPLIER_ADMINISTRATOR.pageLoc" NetmarketURL.buildURL

74

Windchill Customization Guide

( urlFactoryBean, "supplier", "list", null, sumaMap ) ); linkDatum.put("EXTERNAL_STORAGE.pageLoc" , urlFactoryBean.getFactory().getURL ("wt/clients/filevault/storageAdmin.jsp" ,ObjectOid)); linkDatum.put("IMPORT_EXPORT.pageLoc" , urlFactoryBean.getFactory().getURL ("wtcore/jsp/wt/clients/ixb/IXBOptions.jsp" ,ObjectOid)); linkDatum.put("PACKAGES_MAPPING_MANAGER.pageLoc" , urlFactoryBean.getFactory().getURL ("netmarkets/jsp/ixloadui/splitPaneView.jsp" ,ObjectOid)); linkDatum.put("INFO_ENGINE.pageLoc" , urlFactoryBean.getFactory().getURL ("infoengine/jsp/admin/index.jsp" ,ObjectOid)); linkDatum.put("LIFE_CYCLE_ADMIN.pageLoc" , urlFactoryBean.getFactory().getURL ("wt/clients/lifecycle/administrator/LifeCycleAdminTask.jsp" , ObjectOid)); //We need to get the locale specific link for the numbering schemes. String numSchemeLink = HelpLinkHelper.createHelpHREF ("ObjRuleObjectNumbering"); linkDatum.put("NUMBERING_SCHEMES.pageLoc" , numSchemeLink); // Special case Uses different oid and URL factory HashMap personalCabinetMap= new HashMap(); personalCabinetMap.put("action","DeletedUserCabinetList"); personalCabinetMap.put("containerOid",ReferenceOid); linkDatum.put("PERSONAL_CABINETS.pageLoc" , GatewayServletHelper.buildAuthenticatedURL (urlFactoryBean.getFactory(),"wt.enterprise.URLProcessor", "URLTemplateAction",personalCabinetMap).toExternalForm() ); linkDatum.put("POLICY_ADMINISTRATOR.pageLoc" , urlFactoryBean.getFactory().getURL ("wtcore/jsp/domain/admin/PolicyAdmin.jsp" ,ObjectOid)); HashMap participantAdminPrefMap= new HashMap(); participantAdminPrefMap.put("oid",ReferenceOid); linkDatum.put("PARTICIPANT_ADMINISTRATION.pageLoc", NetmarketURL.buildURL(urlFactoryBean, "administration", "participantAdministration", null, participantAdminPrefMap)); HashMap prefMngrMap= new HashMap(); prefMngrMap.put("c.ctx",ReferenceOid); linkDatum.put("PREFERENCE_MANAGER.pageLoc" , urlFactoryBean.getFactory().getURL ("wtcore/jsp/wt/prefs/admin/PrefBrowser.jsp" ,prefMngrMap)); HashMap promotinPrefMap= new HashMap(); promotinPrefMap.put("oid",ReferenceOid); linkDatum.put("PROMOTION_PREFERENCE_MANAGER.pageLoc" , urlFactoryBean.getFactory().getURL ("netmarkets/jsp/promotionRequest/preferenceTable.jsp" ,promotinPrefMap)); NmAction prefAction = NmActionServiceHelper.service.getAction("preference","list");

Getting Started With Windchill Customization

75

prefAction.setContextObject(nmcontext.getContext().getPrimaryOid()); linkDatum.put("PREFERENCE_MANAGER_X10.pageLoc" , NetmarketURL.convertToShellURL (prefAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request))); linkDatum.put("PRODUCT_VIEW.pageLoc" , urlFactoryBean.getFactory().getURL("wtcore/jsp/wvs/pvconfigmain.jsp" , ObjectOid)); linkDatum.put("PRO_INTRALINK.pageLoc" , urlFactoryBean.getFactory().getURL("servlet/IntralinkGWLogon" , ObjectOid)); linkDatum.put("PUBLISH_MONITOR.pageLoc" , urlFactoryBean.getFactory().getURL ("netmarkets/jsp/wvs/queueMonitorMain.jsp" ,ObjectOid)); linkDatum.put("PUBLISH_SCHEDULER.pageLoc" , urlFactoryBean.getFactory().getURL("wtcore/jsp/wvs/schedmain.jsp" , ObjectOid)); linkDatum.put("PUBLISH_THB_CONTROL.pageLoc" , urlFactoryBean.getFactory().getURL("wtcore/jsp/wvs/vetomain.jsp" , ObjectOid)); linkDatum.put("QUEUE_MANAGER.pageLoc" , NetmarketURL.convertToShellURL("ptc1/comp/queue.table")); HashMap replicatonMap= new HashMap(); replicatonMap.put("oid",request.getParameter("oid")); linkDatum.put("REPLICATION_ADMINISTRATOR.pageLoc", urlFactoryBean.getFactory().getURL ("app/#netmarkets/jsp/replication/fileServerAdmin.jsp" ,replicatonMap)); HashMap replMap= new HashMap(); replMap.put("containerOid",ReferenceOid); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.pageLoc", urlFactoryBean.getFactory().getURL ("app/#ptc1/replication/replicationScheduleAdminWizard" ,replMap)); HashMap rulesMap= new HashMap(); rulesMap.put("containerOid",ReferenceOid); linkDatum.put("REPLICATION_MANAGE_RULES.pageLoc", urlFactoryBean.getFactory().getURL ("app/#ptc1/replication/manageRulesWizard" ,rulesMap)); NmAction ccsAction = NmActionServiceHelper.service.getAction ("ccsManager","ccsList"); linkDatum.put("CCS_MANAGER.pageLoc" , ccsAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request)); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.pageLoc", urlFactoryBean.getFactory().getURL ("wt/clients/replication/restrictedCR/replicationAdmin.jsp" ,ObjectOid)); HashMap reportMngrMap = new HashMap(); reportMngrMap.put("containerOid",ReferenceOid); reportMngrMap.put("type", "ReportManager");

76

Windchill Customization Guide

if (pdmInstalled){ reportMngrMap.put("storageHelper", "com.ptc.windchill.pdmlink.report. client.RepositoryStorageHelper"); } linkDatum.put("REPORT_MANAGER.pageLoc", urlFactoryBean.getFactory().getURL ("wtcore/jsp/report/report.jsp" ,reportMngrMap)); linkDatum.put("SERVER_STATUS.pageLoc", urlFactoryBean.getFactory().getURL ("wtcore/jsp/jmx/serverStatus.jsp")); linkDatum.put("TS_PORTAL.pageLoc", urlFactoryBean.getFactory().getURL ("app/#netmarkets/jsp/customersupport/customerSupportPage.jsp")); HashMap ruleAdminMap= new HashMap(); ruleAdminMap.put("oid",ReferenceOid); NmAction oirAction = NmActionServiceHelper.service.getAction("rule","listRules"); oirAction.setContextObject(nmcontext.getContext().getPrimaryOid()); linkDatum.put("RULES_ADMINISTRATION.pageLoc" , NetmarketURL.buildURL ( urlFactoryBean, "rule", "listRules", null, ruleAdminMap )); linkDatum.put("WORKFLOW_TEMPLATES_ADMIN.pageLoc" , NetmarketURL.convertToShellURL (urlFactoryBean.getFactory().getURL("/netmarkets/jsp/workflow/ WfTemplatesAdministrator.jsp" , ruleAdminMap).toString())); linkDatum.put("TASK_DELEGATE.pageLoc" , urlFactoryBean.getFactory().getURL ("infoengine/jsp/admin/delegate/delegateAdministrator.jsp" ,ObjectOid)); linkDatum.put("OPTEGRA_GATEWAY.pageLoc" , urlFactoryBean.getFactory().getURL ("wtx/gateway/client/GatewayAdmin.jsp" ,ObjectOid)); linkDatum.put("TEAM_ADMIN.pageLoc" , urlFactoryBean.getFactory().getURL ("wt/clients/project/ProjectAdminTask.jsp" ,ObjectOid)); //We need to pass a blank JSP into the type manager shell.jsp to prevent the WC home page from appearing linkDatum.put("TYPE_ATTRIBUTE_MANAGER.pageLoc" , urlFactoryBean.getFactory().getURL ("/netmarkets/jsp/administration/shell.jsp",ObjectOid)+"#netmarkets/jsp/ administration/typemgr.jsp"); linkDatum.put("WORKFLOW_ADMIN.pageLoc" , urlFactoryBean.getFactory().getURL ("wt/clients/workflow/definer/WfAdministrator.jsp" ,ObjectOid)); linkDatum.put("WORKFLOW_ADMIN_DASHBOARD.pageLoc" , NetmarketURL.convertToShellURL (urlFactoryBean.getFactory().getURL("/netmarkets/jsp/workflow/WfAdminDashBoard.jsp" ,ruleAdminMap).toString())); //We need to get the locale specific link for the versioning schemes. String verSchemeLink = HelpLinkHelper.createHelpHREF ("ObjRuleObjectVersioning"); linkDatum.put("VERSIONING_SCHEMES.pageLoc" , verSchemeLink); //We need to get the locale specific link for the network admin .

Getting Started With Windchill Customization

77

NmAction viewAction = NmActionServiceHelper.service.getAction("view","list"); linkDatum.put("VIEW_NETWORK.pageLoc" , viewAction.getActionUrl(actionBean, linkBean, objectBean, localeBean, urlFactoryBean,nmcontext, sessionBean,request)); //ACME pageLocs linkDatum.put("PET_ADMINISTRATION.pageLoc", NetmarketURL.convertToShellURL("ptc1/comp/acme.pet.table")); // The value to use for page URL parameters. An entry is required for all known utilities linkDatum.put("CAD_AGENT.urlPrarms" ,"'AdminCad','resizable=yes,scrollbars=yes,menubar=no, toolbar=no,location=no,status=no,height=500,width=700'" ); linkDatum.put("CALENDAR_MANAGEMENT.urlPrarms" ,"'CalendarMgmt','directories=no,location=no, menubar=no,scrollbars=yes,status=yes,toolbar=no,resizable=yes'" ); linkDatum.put("CLASSIFICATION_ADMINISTRATOR.urlPrarms", "'ClassificationAdministrator','directories=no,location=no, menubar=no,scrollbars=yes,status=yes,toolbar=no,resizable=yes'" ); linkDatum.put("CONFIGURATION_FILE_GENERATOR.urlPrarms", "'ConfigurationFileGenerator','resizable=yes,scrollbars=yes, menubar=no,toolbar=no,location=no,status=yes,height=500,width=350'" ); linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.urlPrarms", "'ESIDistributionTargetAdmin','directories=no,location=no, menubar=no,scrollbars=yes,status=yes,toolbar=no,resizable=yes, height=530,width=970'" ); linkDatum.put("ESI_TRANSACTION_ADMIN.urlPrarms", "'ESITransaction','directories=no,location=no,menubar=no ,scrollbars=yes,status=yes,toolbar=no,resizable=yes,height=1000, width=1400'" ); linkDatum.put("EXTERNAL_STORAGE.urlPrarms" ,"'ExternalStorage','resizable=yes,scrollbars=yes,menubar=no,toolbar=no ,location=no,status=yes,height=455,width=640'" ); linkDatum.put("IMPORT_EXPORT.urlPrarms" ,"'_blank','resizable=yes,scrollbars=yes,menubar=no,toolbar=no, location=no, status=yes,height=455,width=640'"); linkDatum.put("PACKAGES_MAPPING_MANAGER.urlPrarms" ,"'_blank', 'resizable=yes, scrollbars=yes,menubar=no,toolbar=no,location=no,status=yes,height=500, width=880'"); linkDatum.put("INFO_ENGINE.urlPrarms" ,"'InfoEngine','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes,status=yes'" ); linkDatum.put("LIFE_CYCLE_ADMIN.urlPrarms" ,"'LifeCycleAdmin','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes ,location=yes,status=yes'"); linkDatum.put("NUMBERING_SCHEMES.urlPrarms" ,"'NumberingSchemes','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes ,location=yes,status=yes'"); linkDatum.put("PET_ADMINISTRATION.urlPrarms" ,"'PetAdmin','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes ,location=yes,

78

Windchill Customization Guide

status=yes'" ); linkDatum.put("POLICY_ADMINISTRATOR.urlPrarms" ,"'PolicyAdmin','resizable=yes,scrollbars=yes,menubar=no,toolbar=no ,location=no, status=yes,height=454,width=600'"); linkDatum.put("PREFERENCE_MANAGER.urlPrarms" ,"'PrefAdmin','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes, status=yes'" ); linkDatum.put("PRO_INTRALINK.urlPrarms" ,"'ProIntralink','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes, status=yes'" ); linkDatum.put("PARTICIPANT_ADMINISTRATION.urlPrarms" ,"'_blank','resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no, status=yes, height=500,width=880'"); linkDatum.put("PERSONAL_CABINETS.urlPrarms" ,"'PersonalCabinets','directories=no,location=no,menubar=no,scrollbars=yes, status=yes, toolbar=no,resizable=yes'"); linkDatum.put("PRODUCT_VIEW.urlPrarms" ,"'PVConfig','directories=no,location=no,menubar=no,scrollbars=yes, status=no,toolbar=no, resizable=yes,width=720,height=660'"); linkDatum.put("PUBLISH_MONITOR.urlPrarms" ,"'pubmain','directories=no,location=no,menubar=no,scrollbars=yes,status=no, toolbar=no, resizable=yes,width=800,height=500'"); linkDatum.put("PUBLISH_SCHEDULER.urlPrarms" ,"'Scheduler','directories=no,location=no,menubar=no,scrollbars=yes,status=no, toolbar=no, resizable=yes,width=720,height=660'"); linkDatum.put("PUBLISH_THB_CONTROL.urlPrarms" ,"'Veto','directories=no,location=no,menubar=no,scrollbars=yes,status=no, toolbar=no, resizable=yes,width=720,height=660'"); linkDatum.put("PURGE_ADMINISTRATOR.urlPrarms" ,"'PurgeAdmin','directories=no,location=no,menubar=no,scrollbars=yes,status=no, toolbar=no, resizable=yes,width=720,height=660'"); linkDatum.put("QUEUE_MANAGER.urlPrarms" ,"'QueueManager','width=605,height=420,directories=no,location=no,menubar=no, scrollbars=yes, status=yes,toolbar=no,resizable=yes'" ); linkDatum.put("REPLICATION_ADMINISTRATOR.urlPrarms" ,"'ReplicationAdmin','resizable=yes,scrollbars=yes,menubar=no,toolbar=no, location=no,status=yes, height=455,width=640'" ); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.urlPrarms" ,"'ReplicationScheduleAdmin','resizable=yes,scrollbars=yes,menubar=no,toolbar=no, location=no, status=yes,height=455,width=750'" ); linkDatum.put("REPLICATION_MANAGE_RULES.urlPrarms" ,"'ReplicationManageRules','resizable=yes,scrollbars=yes,menubar=no,toolbar=no ,location=no,

Getting Started With Windchill Customization

79

status=yes,height=455,width=700'" ); linkDatum.put("CCS_MANAGER.urlPrarms" ,"'CCSManager','resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no, status=yes ,height=455,width=640'" ); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.urlPrarms" ,"'ReplicationAdmin','resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no, status=yes, height=455,width=640'" ); linkDatum.put("REPORT_MANAGER.urlPrarms" ,"'ReportManager','resizable=yes,scrollbars=yes,menubar=no,toolbar=no,location=no, status=yes, height=455,width=640'" ); linkDatum.put("SCMI_ADMINISTRATOR.urlPrarms" ,"'SCMIAdmin','directories=no,location=no,menubar=no,scrollbars=yes,status=no, toolbar=no, resizable=yes,width=720,height=660'"); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.urlPrarms" ,"'SCMIAdapterAdmin','directories=no,location=no,menubar=no,scrollbars=yes,status=no, toolbar=no, resizable=yes,width=720,height=660'"); linkDatum.put("SERVER_STATUS.urlPrarms" ,"'ServerStatus','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes,location=no, status=no, height=830,width=865'" ); linkDatum.put("TS_PORTAL.urlPrarms" ,"'TSPortal','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes,location=yes, status=yes, height=740,width=865'" ); linkDatum.put("TASK_DELEGATE.urlPrarms" ,"'Task_Delegate','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes, status=yes'" ); linkDatum.put("OPTEGRA_GATEWAY.urlPrarms" ,"'Optegra_Gateway','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes, status=yes'" ); linkDatum.put("TEAM_ADMIN.urlPrarms" ,"'TeamAdmin','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes, status=yes'"); linkDatum.put("TYPE_ATTRIBUTE_MANAGER.urlPrarms" ,"'TypeAttributeManager','directories=yes,location=yes,menubar=yes, scrollbars=yes, status=yes,toolbar=yes,resizable=yes'"); linkDatum.put("WORKFLOW_ADMIN.urlPrarms" ,"'WorkflowAdmin','resizable=yes,scrollbars=yes,menubar=yes,toolbar=yes, location=yes, status=yes'"); linkDatum.put("WORKFLOW_TEMPLATES_ADMIN.urlPrarms" ,"'WorkflowTemplatesAdmin','resizable=yes,scrollbars=yes,menubar=yes, toolbar=yes, location=yes,status=yes'"); linkDatum.put("WORKFLOW_ADMIN_DASHBOARD.urlPrarms" ,"'WorkflowAdminDashBoard','resizable=yes,scrollbars=yes,menubar=yes,

80

Windchill Customization Guide

toolbar=yes, location=yes,status=yes'"); linkDatum.put("VERSIONING_SCHEMES.urlPrarms" ,"'VersioningSchemes','resizable=yes,scrollbars=yes,menubar=yes, toolbar=yes ,location=yes,status=yes'"); linkDatum.put("VIEW_NETWORK.urlPrarms" ,"'ViewNetwork','directories=no,location=no,menubar=no,scrollbars=yes, status=yes, toolbar=no,resizable=yes'" ); // The value to use for link text label. An entry is required for all known utilities linkDatum.put("AUDITING_PURGE.linkText" ,auditPurgeAction.getDesc()); linkDatum.put("AUDITING_ORGANIZATION_USAGE.linkText" ,auditOrgUsageAction.getDesc()); if(auditLicenseUsageAction!=null) linkDatum.put("AUDITING_LICENSE_USAGE.linkText" ,auditLicenseUsageAction.getDesc()); linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.linkText" ,auditReportQueriesAction.getDesc()); linkDatum.put("AUDITING_SECURITY_REPORTS.linkText" ,auditReportsAction.getDesc()); linkDatum.put("CAD_AGENT.linkText" ,objectRb.getString(objectResource.CAD_AGENT)); linkDatum.put("CALENDAR_MANAGEMENT.linkText" ,objectRb.getString(objectResource.CALENDAR_MANAGEMENT)); linkDatum.put("CLASSIFICATION_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.CLASSIFICATION_ADMIN)); linkDatum.put("CONFIGURATION_FILE_GENERATOR.linkText" ,enterpriseRb.getString(enterpriseResource.CONFIGURATION_FILE_GENERATOR)); linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.linkText" ,objectRb.getString(objectResource.ESI_DISTRIBUTION_TARGET_ADMIN)); linkDatum.put("ESI_TRANSACTION_ADMIN.linkText" ,objectRb.getString(objectResource.ESI)); linkDatum.put("EXTERNAL_STORAGE.linkText" ,objectRb.getString(objectResource.EXTERNAL_STORAGE)); linkDatum.put("IMPORT_EXPORT.linkText" ,objectRb.getString(objectResource.IMPORT_EXPORT)); linkDatum.put("PACKAGES_MAPPING_MANAGER.linkText" ,objectRb.getString(objectResource.PACKAGES_MAPPING_MANAGER)); linkDatum.put("INFO_ENGINE.linkText" ,objectRb.getString(objectResource.INFO_ENGINE)); linkDatum.put("LIFE_CYCLE_ADMIN.linkText" ,objectRb.getString(objectResource.LIFE_CYCLE_ADMIN)); linkDatum.put("NUMBERING_SCHEMES.linkText" ,objectRb.getString(objectResource.NUMBERING_SCHEMES)); linkDatum.put("PERSONAL_CABINETS.linkText" ,objectRb.getString(objectResource.PERSONAL_CABINETS)); linkDatum.put("PET_ADMINISTRATION.linkText" ,acmeRb.getString(acmeResource.PET_ADMINISTRATION)); linkDatum.put("POLICY_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.POLICY_ADMINISTRATOR)); linkDatum.put("PARTICIPANT_ADMINISTRATION.linkText"

Getting Started With Windchill Customization

81

,objectRb.getString(objectResource.PARTICIPANT_ADMINISTRATION)); linkDatum.put("PRODUCT_VIEW.linkText" ,objectRb.getString(objectResource.PRODUCT_VIEW)); linkDatum.put("PRO_INTRALINK.linkText" ,objectRb.getString(objectResource.PRO_INTRALINK)); linkDatum.put("PREFERENCE_MANAGER.linkText" ,objectRb.getString(objectResource.PREFERENCE_MANAGER)); linkDatum.put("PREFERENCE_MANAGER_X10.linkText" ,objectRb.getString(objectResource.PREFERENCE_MANAGER_X10)); linkDatum.put("PROMOTION_PREFERENCE_MANAGER.linkText" ,objectRb.getString(objectResource.PROMOTION_PREFERENCE_MANAGER)); linkDatum.put("PUBLISH_MONITOR.linkText" ,objectRb.getString(objectResource.PUBLISH_MONITOR)); linkDatum.put("PUBLISH_SCHEDULER.linkText" ,objectRb.getString(objectResource.PUBLISH_SCHEDULER)); linkDatum.put("PUBLISH_THB_CONTROL.linkText" ,objectRb.getString(objectResource.PUBLISH_THB_CONTROL)); if (archiveSysInstall) { linkDatum.put("PURGE_ADMINISTRATOR.linkText" ,enterpriseRb.getString(enterpriseResource.PURGE_ARCHIVE_RESTORE_ADMINISTRATOR)); } else { linkDatum.put("PURGE_ADMINISTRATOR.linkText" ,enterpriseRb.getString(enterpriseResource.PURGE_ADMINISTRATOR)); } linkDatum.put("QUEUE_MANAGER.linkText" ,objectRb.getString(objectResource.QUEUE_MANAGER)); linkDatum.put("REPLICATION_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.REPLICATION_ADMINISTRATOR)); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.REPLICATION_SCHEDULE_ADMINISTRATOR)); linkDatum.put("REPLICATION_MANAGE_RULES.linkText" ,objectRb.getString(objectResource.REPLICATION_MANAGE_RULES)); linkDatum.put("CCS_MANAGER.linkText" ,objectRb.getString(objectResource.CCS_MANAGER)); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.REPLICATION_ADMINISTRATOR)); linkDatum.put("REPORT_MANAGER.linkText" ,objectRb.getString(objectResource.REPORT_MANAGER)); linkDatum.put("RULES_ADMINISTRATION.linkText" ,oirAction.getDesc()); linkDatum.put("SCMI_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.SCMI_ADMIN)); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.SCMI_ADAPTER_ADMIN)); linkDatum.put("SERVER_STATUS.linkText" ,objectRb.getString(objectResource.SERVER_STATUS)); linkDatum.put("TS_PORTAL.linkText" ,objectRb.getString(objectResource.TS_PORTAL)); linkDatum.put("SUPPLIER_ADMINISTRATOR.linkText" ,objectRb.getString(objectResource.SUPPLIER_ADMINISTRATOR)); linkDatum.put("TASK_DELEGATE.linkText" ,objectRb.getString(objectResource.TASK_DELEGATE)); linkDatum.put("OPTEGRA_GATEWAY.linkText" ,objectRb.getString(objectResource.OPTEGRA_GATEWAY)); linkDatum.put("TEAM_ADMIN.linkText"

82

Windchill Customization Guide

,objectRb.getString(objectResource.TEAM_ADMIN)); linkDatum.put("TYPE_ATTRIBUTE_MANAGER.linkText" ,objectRb.getString(objectResource.TYPE_ATTRIBUTE_MANAGER)); linkDatum.put("WORKFLOW_ADMIN.linkText" ,objectRb.getString(objectResource.WORKFLOW_ADMIN)); linkDatum.put("WORKFLOW_TEMPLATES_ADMIN.linkText" ,objectRb.getString(objectResource.WORKFLOW_TEMPLATES_ADMIN)); linkDatum.put("WORKFLOW_ADMIN_DASHBOARD.linkText" ,objectRb.getString(objectResource.WORKFLOW_ADMIN_DASHBOARD)); linkDatum.put("PREFERENCE_MANAGER.linkText" ,objectRb.getString(objectResource.PREFERENCE_MANAGER)); linkDatum.put("PREFERENCE_MANAGER_X10.linkText" ,objectRb.getString(objectResource.PREFERENCE_MANAGER_X10)); linkDatum.put("VERSIONING_SCHEMES.linkText" ,objectRb.getString(objectResource.VERSIONING_SCHEMES)); linkDatum.put("VIEW_NETWORK.linkText" ,objectRb.getString(objectResource.VIEW_NETWORK));

// The value to use for link text Descrition. An entry is required for all known utilities linkDatum.put("AUDITING_PURGE.linkDesc" , auditPurgeAction.getToolTip()); linkDatum.put("AUDITING_ORGANIZATION_USAGE.linkDesc" , auditOrgUsageAction.getToolTip()); if(auditLicenseUsageAction!=null) linkDatum.put("AUDITING_LICENSE_USAGE.linkDesc" , auditLicenseUsageAction.getToolTip()); linkDatum.put("AUDITING_SECURITY_REPORT_QUERIES.linkDesc" , auditReportQueriesAction.getToolTip()); linkDatum.put("AUDITING_SECURITY_REPORTS.linkDesc" , auditReportsAction.getToolTip()); linkDatum.put("CAD_AGENT.linkDesc" ,objectRb.getString(objectResource.CAD_AGENT_DESCRIPTION)); linkDatum.put("CALENDAR_MANAGEMENT.linkDesc" ,objectRb.getString(objectResource.CALENDAR_MANAGEMENT_DESCRIPTION)); linkDatum.put("CLASSIFICATION_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.CLASSIFICATION_ADMIN_DESCRIPTION)); linkDatum.put("CONFIGURATION_FILE_GENERATOR.linkDesc" ,enterpriseRb.getString(enterpriseResource.CONFIGURATION_FILE_GENERATOR_ DESCRIPTION)); linkDatum.put("ESI_DISTRIBUTION_TARGET_ADMIN.linkDesc", objectRb.getString (objectResource.ESI_DISTRIBUTION_TARGET_ADMIN_DESCRIPTION)); linkDatum.put("ESI_TRANSACTION_ADMIN.linkDesc", objectRb.getString (objectResource.ESI_DESCRIPTION)); linkDatum.put("EXTERNAL_STORAGE.linkDesc" ,objectRb.getString(objectResource.EXTERNAL_STORAGE_DESCRIPTION)); linkDatum.put("IMPORT_EXPORT.linkDesc" ,objectRb.getString(objectResource.IMPORT_EXPORT_DESCRIPTION)); linkDatum.put("PACKAGES_MAPPING_MANAGER.linkDesc" ,objectRb.getString(objectResource.PACKAGES_MAPPING_MANAGER_DESCRIPTION)); linkDatum.put("INFO_ENGINE.linkDesc" ,objectRb.getString(objectResource.INFO_ENGINE_DESCRIPTION)); linkDatum.put("LIFE_CYCLE_ADMIN.linkDesc" ,objectRb.getString(objectResource.LIFE_CYCLE_ADMIN_DESCRIPTION));

Getting Started With Windchill Customization

83

linkDatum.put("NUMBERING_SCHEMES.linkDesc" ,objectRb.getString(objectResource.NUMBERING_SCHEMES_DESCRIPTION)); linkDatum.put("PERSONAL_CABINETS.linkDesc" ,objectRb.getString(objectResource.PERSONAL_CABINETS_DESCRIPTION)); linkDatum.put("PET_ADMINISTRATION.linkDesc" ,acmeRb.getString(acmeResource.PET_ADMINISTRATION_DESCRIPTION)); linkDatum.put("POLICY_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.POLICY_ADMINISTRATOR_DESCRIPTION)); linkDatum.put("PARTICIPANT_ADMINISTRATION.linkDesc" ,objectRb.getString(objectResource.PARTICIPANT_ADMINISTRATION_DESCRIPTION)); linkDatum.put("PRODUCT_VIEW.linkDesc" ,objectRb.getString(objectResource.PRODUCT_VIEW_DESCRIPTION)); linkDatum.put("PRO_INTRALINK.linkDesc" ,objectRb.getString(objectResource.PRO_INTRALINK_DESCRIPTION)); linkDatum.put("PREFERENCE_MANAGER.linkDesc" ,objectRb.getString(objectResource.PREFERENCE_MANAGER_DESCRIPTION)); linkDatum.put("PREFERENCE_MANAGER_X10.linkDesc" ,objectRb.getString(objectResource.PREFERENCE_MANAGER_DESCRIPTION_X10)); linkDatum.put("PROMOTION_PREFERENCE_MANAGER.linkDesc" ,objectRb.getString(objectResource.PROMOTION_PREFERENCE_MANAGER_DESCRIPTION)); linkDatum.put("PUBLISH_MONITOR.linkDesc" ,objectRb.getStri ng(objectResource.PUBLISH_MONITOR_DESCRIPTION)); linkDatum.put("PUBLISH_SCHEDULER.linkDesc" ,objectRb.getString(objectResource.PUBLISH_SCHEDULER_DESCRIPTION)); linkDatum.put("PUBLISH_THB_CONTROL.linkDesc" ,objectRb.getString(objectResource.PUBLISH_THB_CONTROL_DESCRIPTION)); if (archiveSysInstall) { linkDatum.put("PURGE_ADMINISTRATOR.linkDesc" ,enterpriseRb.getString(enterpriseResource.PURGE_ARCHIVE_RESTORE _ADMINISTRATOR_DESCRIPTION)); } else { linkDatum.put("PURGE_ADMINISTRATOR.linkDesc" ,enterpriseRb.getString(enterpriseResource.PURGE_ADMINISTRATOR_DESCRIPTION)); } linkDatum.put("QUEUE_MANAGER.linkDesc" ,objectRb.getString(objectResource.QUEUE_MANAGER_DESCRIPTION)); linkDatum.put("REPLICATION_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.REPLICATION_ADMINISTRATOR_DESCRIPTION)); linkDatum.put("REPLICATION_SCHEDULE_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.REPLICATION_SCHEDULE_ADMINISTRATOR_DESCRIPTION)); linkDatum.put("REPLICATION_MANAGE_RULES.linkDesc" ,objectRb.getString(objectResource.REPLICATION_RULES_ADMINISTRATOR_DESCRIPTION)); linkDatum.put("CCS_MANAGER.linkDesc" ,objectRb.getString(objectResource.CCS_MANAGER_DESCRIPTION)); linkDatum.put("REPLICATION_RULES_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.REPLICATION_RULES_ADMINISTRATOR_DESCRIPTION)); linkDatum.put("REPORT_MANAGER.linkDesc" ,objectRb.getString(objectResource.REPORT_MANAGER_DESCRIPTION)); linkDatum.put("RULES_ADMINISTRATION.linkDesc" ,oirAction.getToolTip()); linkDatum.put("SCMI_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.SCMI_ADMIN_DESCRIPTION)); linkDatum.put("SCMI_ADAPTER_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.SCMI_ADAPTER_ADMIN_DESCRIPTION)); linkDatum.put("SERVER_STATUS.linkDesc" ,objectRb.getString(objectResource.SERVER_STATUS_DESCRIPTION));

84

Windchill Customization Guide

linkDatum.put("TS_PORTAL.linkDesc" ,objectRb.getString(objectResource.TS_PORTAL_DESCRIPTION)); linkDatum.put("SUPPLIER_ADMINISTRATOR.linkDesc" ,objectRb.getString(objectResource.SUPPLIER_ADMINISTRATOR_DESCRIPTION)); linkDatum.put("TASK_DELEGATE.linkDesc" ,objectRb.getString(objectResource.TASK_DELEGATE_DESCRIPTION)); linkDatum.put("OPTEGRA_GATEWAY.linkDesc" ,objectRb.getString(objectResource.OPTEGRA_GATEWAY_DESCRIPTION)); linkDatum.put("TEAM_ADMIN.linkDesc" ,objectRb.getString(objectResource.TEAM_ADMIN_DESCRIPTION)); linkDatum.put("TYPE_ATTRIBUTE_MANAGER.linkDesc" ,objectRb.getString(objectResource.TYPE_ATTRIBUTE_MANAGER_DESCRIPTION)); linkDatum.put("WORKFLOW_ADMIN.linkDesc" ,objectRb.getString(objectResource.WORKFLOW_ADMIN_DESCRIPTION)); linkDatum.put("WORKFLOW_TEMPLATES_ADMIN.linkDesc" ,objectRb.getString(objectResource.WORKFLOW_ADMIN_DESCRIPTION)); linkDatum.put("WORKFLOW_ADMIN_DASHBOARD.linkDesc" ,objectRb.getString(objectResource.WORKFLOW_ADMIN_DASHBOARD_DESCRIPTION)); linkDatum.put("PREFERENCE_MANAGER.linkDesc" ,objectRb.getString(objectResource.PREFERENCE_MANAGER_DESCRIPTION)); linkDatum.put("PREFERENCE_MANAGER_X10.linkDesc" ,objectRb.getString(objectResource.PREFERENCE_MANAGER_DESCRIPTION_X10)); linkDatum.put("VERSIONING_SCHEMES.linkDesc" ,objectRb.getString(objectResource.VERSIONING_SCHEMES_DESCRIPTION)); linkDatum.put("VIEW_NETWORK.linkDesc" ,objectRb.getString(objectResource.VIEW_NETWORK_DESCRIPTION)); %> --> <c:set var="helpPath" value="${helpPath}" /> <div class="utilities"> <w:helpButton helpSelectorKey="${helpPath}"/> <TABLE id="utilTable"> <% String [] headers={objectRb.getString(objectResource.SYSTEM_ADMINISTRATION), objectRb.getString(objectResource.BUSINESS_ADMINISTRATION), objectRb.getString(objectResource.AUDITING_ADMINISTRATION), acmeRb.getString(acmeResource.ACME_ADMINISTRATION)}; boolean [] systemHeader={true,false,false,false}; boolean [] auditHeader={false,false,true,false}; boolean [] acmeHeader={false,false,false,true}; boolean headerShown; for (int currentHeader=0; currentHeader < headers.length; currentHeader++) { headerShown=false; for (int i = 0; i < nKnownUtilities; i++) { //Match system/nonsystem String isSystem = knownUtilities[i].concat(".isSystemUtility"); if (linkDatum.containsKey(isSystem)!=systemHeader[currentHeader]) { continue; } //Match audit/nonaudit String isAudit = knownUtilities[i].concat(".isAuditUtility"); if (linkDatum.containsKey(isAudit)!=auditHeader[currentHeader]) { continue;

Getting Started With Windchill Customization

85

} //Match acme/noacme String isACME = knownUtilities[i].concat(".isACMEUtility"); if (linkDatum.containsKey(isACME)!=acmeHeader[currentHeader]) { continue; } // Is caller requesting this utility if (!showUtility.containsKey(knownUtilities[i])) { continue; } // Is utility requested installed if (!linkDatum.containsKey(knownUtilities[i].concat(".isUtilityInstalled"))) { continue; } if (!headerShown) { headerShown=true; %> <TR><TD colspan=2 class="header"> <%=headers[currentHeader]%> </TD> </TR> <% } %> <TR><TD class="title"> <a id="<%=linkDatum.get(knownUtilities[i].concat(".idText"))%>" <% String pageLoc = String.valueOf(linkDatum.get(knownUtilities[i].concat(".pageLoc"))); String urlPrarms = String.valueOf(linkDatum.get(knownUtilities[i].concat (".urlPrarms"))); if ("SUPPLIER_ADMINISTRATOR".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self" <% } else if ("PREFERENCE_MANAGER_X10".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("PROMOTION_PREFERENCE_MANAGER".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("TS_PORTAL".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("CCS_MANAGER".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("PURGE_ADMINISTRATOR".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("REPLICATION_ADMINISTRATOR".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("REPLICATION_SCHEDULE_ADMINISTRATOR".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("REPLICATION_MANAGE_RULES".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("VIEW_NETWORK".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("AUDITING_PURGE".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self" <% } else if ("AUDITING_ORGANIZATION_USAGE".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self" <% } else if ("AUDITING_LICENSE_USAGE".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self" <% } else if ("AUDITING_SECURITY_REPORT_QUERIES".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self"

86

Windchill Customization Guide

<% } else if ("PACKAGES_MAPPING_MANAGER".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("AUDITING_SECURITY_REPORTS".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self" <% } else if ("WORKFLOW_TEMPLATES_ADMIN".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("QUEUE_MANAGER".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" target="_self" <% } else if ("WORKFLOW_ADMIN_DASHBOARD".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("PARTICIPANT_ADMINISTRATION".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("RULES_ADMINISTRATION".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else if ("PET_ADMINISTRATION".equals(knownUtilities[i])) { %> href="<%=pageLoc%>" <% } else { %> href="javascript:launchUtilityWindow('<%=pageLoc%>',<%=urlPrarms%>);" <% } %> > <%=linkDatum.get(knownUtilities[i].concat(".linkText"))%></a> </TD><TD> <%=linkDatum.get(knownUtilities[i].concat(".linkDesc"))%> </TD></TR> <% } %> <% } %> </TABLE> </div>

4. Enable PET_ADMINISTRATION a. Create the following two directory structures under load point: wtSafeArea/ptcOrig/codebase/netmarkets/jsp/ sitewtSafeArea/siteMod/codebase/netmarkets/jsp/ site b. Copy listUtilities.jspf to both directories just created above. c. Edit wtSafeArea/siteMod/codebase/netmarkets/jsp/site/ listUtilities.jsp, appending (after line 67) the following to the enabled:
utilitiesshowUtility.put("PET_ADMINISTRATION" , "Enable");

5. Deploy the site modifications: ant -f bin/swmaint.xml installSiteChanges 6. Create the imported acmeResource as shown
package com.acme; import wt.util.resource.*; @RBUUID("com.acme.acmeResource")

Getting Started With Windchill Customization

87

public class acmeResource extends WTListResourceBundle { @RBEntry("ACME Administration") public static final String ACME_ADMINISTRATION = "acme_administration"; @RBEntry("Pet Administration") public static final String PET_ADMINISTRATION = "pet_administration"; @RBEntry("CRUD opererations for pets") public static final String PET_ADMINISTRATION_DESCRIPTION = "pet_administration_description"; }

7. Start/restart Windchill. 8. Site Utilities should incorporate ACME Administration , as shown

Pet Information Page The table currently shows an i for an info page (for Stimpy), but the information page has not been created yet (clicking the i will result in an error). 1. Create the primary builder for the information page. Complete source follows:
package com.acme.mvc.builders; import wt.util.WTException; import import import import import import com.ptc.jca.mvc.builders.DefaultInfoComponentBuilder; com.ptc.mvc.components.ComponentBuilder; com.ptc.mvc.components.ComponentId; com.ptc.mvc.components.ComponentParams; com.ptc.mvc.components.InfoConfig; com.ptc.mvc.components.TypeBased;

@ComponentBuilder(ComponentId.INFOPAGE_ID) @TypeBased("com.acme.Pet") public class PetInfoBuilder extends DefaultInfoComponentBuilder { @Override protected InfoConfig buildInfoConfig(final ComponentParams params) throws WTException { final InfoConfig info = getComponentConfigFactory().newInfoConfig(); info.setTabSet("petDetails"); return info; }

88

Windchill Customization Guide

2. Define the petDetails tab set by creating its action model (in config/actions/Pet-actionmodels.xml).
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE actionmodels SYSTEM 'actionmodels.dtd'> <actionmodels> <model name="petDetails"> <action name="primaryAttributes" type="object"/> <action name="attachments" type="object"/> </model> </actionmodels>

3. Define the primaryAttributes.


package com.acme.mvc.builders; import wt.util.WTException; import import import import import import import import import import import com.acme.Pet; com.ptc.core.ui.resources.ComponentType; com.ptc.jca.mvc.components.AbstractAttributesComponentBuilder; com.ptc.jca.mvc.components.JcaAttributeConfig; com.ptc.jca.mvc.components.JcaGroupConfig; com.ptc.mvc.components.AttributePanelConfig; com.ptc.mvc.components.ComponentBuilder; com.ptc.mvc.components.ComponentConfigFactory; com.ptc.mvc.components.ComponentId; com.ptc.mvc.components.ComponentParams; com.ptc.mvc.components.TypeBased;

@ComponentBuilder("primaryAttributes") @TypeBased("com.acme.Pet") public class PetInfoAttributesBuilder extends AbstractAttributesComponentBuilder { @Override protected AttributePanelConfig buildAttributesComponentConfig (final ComponentParams params) throws WTException { final ComponentConfigFactory factory = getComponentConfigFactory(); final AttributePanelConfig panel; { panel = factory.newAttributePanelConfig(ComponentId.ATTRIBUTE_PANEL_ID); panel.setComponentType(ComponentType.WIZARD_ATTRIBUTES_TABLE); final JcaGroupConfig group; { group = (JcaGroupConfig) factory.newGroupConfig(); group.setId("attributes"); group.setLabel("Attributes"); group.setIsGridLayout(true); group.addComponent(getAttribute(Pet.NAME, factory)); group.addComponent(getAttribute(Pet.KIND, factory)); group.addComponent(getAttribute(Pet.DATE_OF_BIRTH, factory)); group.addComponent(getAttribute(Pet.FIXED, factory)); }

Getting Started With Windchill Customization

89

panel.addComponent(group); } return panel; } JcaAttributeConfig getAttribute(final String id, final ComponentConfigFactory factory) { final JcaAttributeConfig attribute = (JcaAttributeConfig) factory.newAttributeConfig(); attribute.setId(id); return attribute; } }

4. Register the beans by updating Pet-configs.xml to include:


<bean class="com.acme.mvc.builders.PetInfoBuilder"/> <bean class="com.acme.mvc.builders.PetInfoAttributesBuilder"/>

5. Add Pet-actionmodels.xml to site.xconf. a. Just before the last line, </Configuration> add <ddToProperty name="com.ptc.netmarkets.util.misc. defaultActionmodels" value="config/actions/Petactionmodels.xml"/>. b. Run bin/xconfmanager -pF to propagate the change. 6. Start/restart Windchill and verify (noting the Attachments tab for content).

90

Windchill Customization Guide

Creating a New Pet


Creating a new Pet involves building a dialog for it and making it visible on the table. 1. Create create.jsp, a wizard for creating pets. a. Navigate to File New Other... Select Other JSP File and then click Next .

Note If the option Other... Select Other JSP File is not available, install Web Page Editor. This is available under the Web, XML, and Java EE Development category when working with the Helios software site. As an alternative you can also create a general file (Other... General File )
b. The folder is cust_Windchill_src/src/netmarkets/jsp/ acme/pet, file name is create.jsp. c. Click Finish and replace content with the following:
<%@taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib /components"%> <%@taglib prefix="attachments" uri="http://www.ptc.com/windchill/taglib/attachments"%> <%@include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <jca:initializeItem baseTypeName="com.acme.Pet" operation= "${createBean.create}" attributePopulatorClass="com.ptc.core.components.forms. DefaultAttributePopulator"/> <jca:wizard> <jca:wizardStep action="petDefineItemAttributesWizStep" type="pet"/> <jca:wizardStep action="attachments_step" type="attachments"/> </jca:wizard> <attachments:fileSelectionAndUploadApplet/> <%@include file="/netmarkets/jsp/util/end.jspf"%>

2. Define the petDefineItemAttributesWizStep action. a. Create Pet-actions.xml alongside Pet-actionmodels.xml in config.actions. b. Assign its content as follows:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE listofactions SYSTEM 'actions.dtd'> <listofactions> <objecttype name="pet" class="com.acme.Pet"

Getting Started With Windchill Customization

91

resourceBundle="com.acme.jca.acmeActionResource"> <action name="petDefineItemAttributesWizStep" afterVK="setAttributesWizStep" preloadWizardPage="true" required="true"> <command url="netmarkets/jsp/acme/pet/ defineItemAttributesWizStep.jsp" windowType="wizard_step"/> </action> </objecttype> </listofactions>

c. Register Pet-actions.xml in site.xconf <AddToProperty name="com.ptc.netmarkets.util.misc.defaultActions" value="config/actions/Pet-actions.xml"/> d. Run xconfmanager again to propagate the change 3. Create the defineItemAttributesWizStep.jsp JSP page alongside create.jsp with the following content:
<%@taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%> <%@include file="/netmarkets/jsp/util/begin_comp.jspf"%> <jsp:include page="${mvc:getComponentURL('acme.pet.SetAttributesPanel')}"/> <%@include file="/netmarkets/jsp/util/end_comp.jspf"%>

4. Define the component (acme.pet.SetAttributesPanel) a. Create PetSetAttributesPanelBuilder with content.


package com.acme.mvc.builders; import wt.util.WTException; import import import import import import import import import import import com.acme.Pet; com.ptc.core.ui.resources.ComponentType; com.ptc.jca.mvc.components.AbstractAttributesComponentBuilder; com.ptc.jca.mvc.components.JcaAttributeConfig; com.ptc.jca.mvc.components.JcaGroupConfig; com.ptc.mvc.components.AttributePanelConfig; com.ptc.mvc.components.ComponentBuilder; com.ptc.mvc.components.ComponentConfigFactory; com.ptc.mvc.components.ComponentId; com.ptc.mvc.components.ComponentParams; com.ptc.mvc.components.TypeBased;

@ComponentBuilder("acme.pet.SetAttributesPanel") @TypeBased("com.acme.Pet") public class PetSetAttributesPanelBuilder extends AbstractAttributesComponentBuilder { @Override protected AttributePanelConfig buildAttributesComponentConfig (final ComponentParams params) throws WTException { final ComponentConfigFactory factory = getComponentConfigFactory(); final AttributePanelConfig panel; { panel = factory.newAttributePanelConfig (ComponentId.ATTRIBUTE_PANEL_ID);

92

Windchill Customization Guide

panel.setComponentType (ComponentType.WIZARD_ATTRIBUTES_TABLE); final JcaGroupConfig group; { group = (JcaGroupConfig) factory.newGroupConfig(); group.setId("setAttributes"); group.setLabel("Set Attributes"); group.setIsGridLayout(true); group.addComponent(getAttribute(Pet.NAME, factory)); group.addComponent(getAttribute(Pet.KIND, factory)); group.addComponent(getAttribute(Pet.DATE_OF_BIRTH, factory)); group.addComponent(getAttribute(Pet.FIXED, factory)); } panel.addComponent(group); } return panel; } JcaAttributeConfig getAttribute (final String id, final ComponentConfigFactory factory) { final JcaAttributeConfig attribute = (JcaAttributeConfig) factory.newAttributeConfig(); attribute.setId(id); return attribute; } }

b. Add the following to Pet-configs.xml to register the builder <bean id="acme.pet.SetAttributesPanel" class="com.acme.mvc.builders. PetSetAttributesPanelBuilder"/> 5. Create the resourceBundle referred to by petDefineItemAttributesWizStep, with content as follows (note the reuse of createPackage.gif as the icon for creating pets):
package com.acme.jca; import wt.util.resource.*; @RBUUID("com.acme.jca.acmeActionResource") public final class acmeActionResource extends WTListResourceBundle { @RBEntry("New Pet") public static final String PET_CREATE_TITLE = "pet.create.title"; @RBEntry("New Pet") public static final String PET_CREATE_TOOLTIP = "pet.create.tooltip"; @RBEntry("New Pet") public static final String PET_CREATE_DESCRIPTION = "pet.create.description"; @RBEntry("createPackage.gif") public static final String PET_CREATE_ICON = "pet.create.icon";}

6. Wire the create action into PetTable.

Getting Started With Windchill Customization

93

a. Add the following model to Pet-actionmodels.xml (just above the petDetails model).
<model name="pets list"> <action name="create" type="pet" shortcut="true"/> </model>

b. Add the create action to pet in Pet-actions.xml (just above petDefineItemAttributesWizStep).


<action name="create"> <command class="com.ptc.core.components.forms.CreateObjectFormProcessor" url="netmarkets/jsp/acme/pet/create.jsp" windowType="popup"/> </action>

c. Incorporate the action model (pets list) into PetTable (add before table.setSelectable(true);). Example: table. setActionModel("pets list"); 7. Start/restart Windchill. a. Verify the New Pet icon is available on the table b.

94

Windchill Customization Guide

c. Click New Pet and verify a pop-up consisting of a wizard with two steps.

d. Create a pet. Be sure to upload the content. e. Go to the new pets info page and verify that the content shows and is viewable/downloadable.

Getting Started With Windchill Customization

95

Editing Pet
The process of editing a pet is similar to the process of creating one. 1. Copy createPet.jsp a. Select create.jsp. b. Right-click -> Copy c. Right-click -> Paste, set new name to editPet.jsp. d. Open editPet.jsp and replace createBean.create with createBean.edit. 2. Register editPet and make it available on the information page. a. Add the action to Pet-actions.xml.
<action name="editPet"> <command class="com.ptc.core.components.forms.DefaultEditFormProcessor" url="netmarkets/jsp/acme/pet/editPet.jsp" windowType="popup"/> </action>

b. Add a menu to the info page.


<model name="pet actions" menufor="com.acme.Pet"> <action name="editPet" type="pet"/> </model>

3. Add the following to acmeActionResource.java :


@RBEntry("Edit Pet") public static final String PET_EDIT_PET_TITLE = "pet.editPet.title"; @RBEntry("Edit") public static final String PET_EDIT_PET_TOOLTIP = "pet.editPet.tooltip"; @RBEntry("Edit") public static final String PET_EDIT_PET_DESCRIPTION = "pet.editPet.description"; @RBEntry("edit.gif") public static final String PET_EDIT_PET_ICON = "pet.editPet.icon";4.

4. Implement a wt.verification.Verifier (non-AccesControlled objects are shielded from inadvertent (or malicious) updates and deletes by a Verifier in lieu of access control) a. Create PetVerifier with content as follows:
package com.acme; import wt.fc.Persistable; import wt.fc.collections.WTCollection; import wt.util.WTException;import wt.verification.Verifier; public class PetVerifier implements Verifier { @Override public boolean verify(Persistable a_object) throws WTException { return true; }

96

Windchill Customization Guide

@Override public boolean verify(WTCollection a_objects) throws WTException { return true; }}

b. Register PetVerifier as a verifier for Pet by adding the following to site.xconf and propagating with xconfmanager.
<Service context="default" name="wt.verification.Verifier" targetFile="codebase/service.properties"> <Option cardinality="duplicate" order="1" requestor="com.acme.Pet" serviceClass="com.acme.PetVerifier" selector="DEFAULT"/> </Service>

5. Start/restart Windchill a. Verify that edit is available as an action of an info page.

b. Verify the edit pop-up.

c. Edit the pet.

Getting Started With Windchill Customization

97

Deleting a Pet
1. Under the create action of the pets list model (in Pet-actionmodels.xml ), add
<action name="delete" type="object" shortcut="true"/>

2. Start/restart Windchill. 3. Verify that delete has been added as an action to the pet table

4. Delete a pet.

98

Windchill Customization Guide

Customization Notes
The user interface customization incorporates pets into the Windchill UI. All basic CRUD operations are supported. However, more could be done. For example, while content was not demonstrated in Jython (and is demonstrated in the UI), ownership has been ignored and left out of the UI. How to incorporate concepts like ownership will be covered elsewhere in the guide. Additionally, both PetInfoAttributesBuilder and PetSetAttributesBuilder set the groups label to a hard-coded, unlocalizable string. To correct that, take a look at setLabel in PetTable, which does this correctly. The choice to incorporate the table into Site Utilities was based on Pet being neither AccessControlled nor WTContained, making it more like Windchills administrative objects in practice than like the many Windchill business objects. The manner in which a modeled customization is incorporated into the Windchill UI is largely dictated by the behavior (as determined by the domain interfaces it implements and the parent class it extends).

Getting Started With Windchill Customization

99

Customizations Next Steps


The Pet example illustrates a simple from scratch modeled customization with very little (unique/interesting) logic and no (new) associations. There are, not surprisingly, many different kinds of customizations. Some customizations simply extend and existing business class to add properties (a customization largely superseded by Windchills soft typing capabilities), some exist to add new associations to existing business objects, some exist to add validation and other logic to existing Windchill classes, and so on. The remaining sections will cover all of the various kinds of customizations, as well as providing greater insight into this customization.

100

Windchill Customization Guide

4
Modeling Business Objects
Windchill Modeling Heuristics ................................................................................... 102 Windchill Foundation Abstractions ............................................................................ 105

This chapter explains how to model business objects.

101

Windchill Modeling Heuristics


This section is intended to give you some background on the design of the Windchill class architecture and the approach we have used in modeling. The Windchill class architecture was designed with the following objectives in mind: To promote the development of business objects that reflect the characteristics of a three-tier architecture; that is, presentation for the client layer, business logic for the server layer, and persistence for the database layer. To ensure a model from which optimized code can be generated. The code that is generated should provide for managing the state of objects, transporting objects between the client and the server, and manipulating objects in the database. To provide an environment that enables value-added development. You must be able to extend the model and put new capabilities in existing objects.

One approach to achieving these objectives is to inherit functionality.

Functionality through Inheritance As you add subclasses to a parent class, in this case extending class WTObject with Item and then DomainItem, the attributes and methods of each preceding class are inherited by the subclasses. This approach works in many circumstances. But sometimes you need only a small percentage of the functionality that is being inherited. In that case, either you have much more than you actually need in your object, or you copy just the code you want and add it to your own object, creating redundancy and potential maintenance problems.
Windchill Customization Guide

102

Another approach, which we have implemented in Windchill, is to partition functionality, as in the figure below, into objects that are responsible primarily for maintaining business information (also called knowers) versus objects responsible primarily for performing business operations (also called doers).

Functionality through Partitioning Using this approach, business models have two major kinds of classes: business information classes and business manager classes. Business information classes represent the business information and associations you want to manage and maintain in a database. These classes extend the foundation classes provided in Windchill. They may implement one or more business manager interfaces. These classes go back and forth between the client and the server with data. Business manager classes represent the business rules that are applied to the business information objects. These classes extend the Windchill StandardManager class. Business managers implement an interface class that provides a client-side API to the business manager methods. The code for business manager classes is located in the server. The following is an example of one of the managers Windchill provides, the LockService. (In naming classes, managers are sometimes also called services.)

Modeling Business Objects

103

LockService Example In this example, Lockable is a knower that is implemented by MyItem (which also extends the abstract class Item). Lockable objects, including MyItem, are managed by the StandardLockService (a doer), with APIs exposed by the implememnted remote interface LockService. Besides the attributes and methods it inherited from Item, MyItem also has the functionality defined in the Lockable interface. The left side of the figure shows how to model the interface for a server-side service on a client. The doer is StandardLockService and it runs on the server. It inherits from the Windchill StandardManager, which provides standard, basic operations for a typical manager, such as starting and shutting down. (When you write your own managers, they also can inherit from StandardManager.). The LockService interface describes the lock services that are available on the client, lock and unlock. These services are invoked remotely from the client to the server. StandardLockService on the server actually contains all the code to support the lock and unlock methods. LockServices APIs expect a Lockable object. They can accept MyItem because MyItem implemented the Lockable interface. Likewise, they can accept any other business information class that implements the Lockable interface. To get access to the lock service functionality, a class must implement the Lockable interface.

104

Windchill Customization Guide

Windchill Foundation Abstractions


At an infrastructure layer of Windchills architecture are foundational abstractions to be used by services and applications. These abstractions, shown in the following figure, represent the fundamental types that are commonly used by others as a part of a Windchill system.

Foundation Hierarchy

Windchill Foundation Interfaces


At the root of the hierarchy is the NetFactor interface. If an abstraction asserts itself as being an object of type NetFactor, it is classified as belonging to a Windchill system. One side effect of being a NetFactor type is that static factory (new<Class>) methods, along with supporting initialize methods replace constructors.

Modeling Business Objects

105

Classes that are asserted as being ObjectMappable can be written into and read from the database. All remaining abstractions in the foundation hierarchy are a kind of ObjectMappable abstraction. All subtypes of ObjectMappable are Externalizable, which gives an object the ability to use RMI for travel between the client and server. ObjectMappable adds readExternal and writeExternal APIs (similar to those of Externalizable) to support reading from and writing to the database. Windchill annotation processors generate the appropriate implementations for these APIs. The PersistInfo interface contains information for each object that is stored in the database. PersistInfo does not implement Persistable; it is a structured attribute. It does, however, implement ObjectMappable. This means createStamp, modifyStamp, updateStamp, and updateCount will all be included in readExternal and writeExternal operations. Links, object references, and query keys are generalized as interfaces as shown in the following figure.

Binary Links The QueryKey interface specifies a qualification for a persistable object in the database, represented as a combination of a class(name) and identifier. The WTReference interface aggregates a single QueryKey and provides a corresponding object representing the (inflated) Persistable corresponding to the key. An attempt to inflate a key that results zero or multiple Persistent objects will result in an exception. The Link interface specifies the concept of a container of roles and, in particular, the BinaryLink interface, a kind of Link, is an abstraction of an attributed member of an association between two persistable objects. The actual containment of the objects is done by aggregation of references for each role.

106

Windchill Customization Guide

The Persistable interface gives an object a primary key (that is, the object identifier) as shown in the following figure, and a table in the database. It is this primary key that is the identifier for an ObjectReference, a WTReference implementation referring to a Persistable via its primary key.

Persistable Objects First class objects implement the Persistable interface. As a result, a database table is generated for each class in which their objects will be stored. The structured attributes are stored in the database table of their associated first class object. All persistable objects, plus any structured attributes that must be written into or read from the database, must implement the ObjectMappable interface.

Modeling Business Objects

107

Windchill Foundation Classes


Windchill provides three base classes with some basic functionality for business information objects: WTObject, Item, and ObjectToObjectLink. Many business information objects provided by Windchill, and probably many that you create yourself, extend these foundation classes and, therefore, inherit attributes and methods from these classes. (We recommend that if you extend Windchill-supplied classes, you use those described in the The Enterprise Layer, which were designed to be used for customization.) WTObject Represents the base class for all Windchill business information classes. Item and ObjectToObjectLink are subclasses of WTObject. Item Represents a discrete business item. ObjectToObjectLink Represents a concrete binary association between two Persistable objects; that is, you can define a link between two items, between an item and a link, and between two links. Each link has a roleA side and a roleB side therefore, if you have a link, you can use it to navigate to all other objects associated with it. The ObjectToObjectLink class can be extended and therefore can have additional attributes and methods. As shown in the following figure, the ObjectToObjectLink aggregates ObjectReference for both role A and B. The ObjectReference in turn aggregates the primary key ObjectIdentifier as an overridden key to reference its object for both roles. The ObjectIdentifier extends QueryKey and adds the id as an additional attribute.

Object to Object Link

108

Windchill Customization Guide

WTObject contains a few general-purpose methods that are inherited by every business object and provide a low level of functionality. For example, the checkAttributes method is called when the object is saved to perform elementary validity checking. If you have not supplied information for required attributes, an exception is thrown and the object is not made persistent.

Modeling Business Objects

109

111

5
Managing Customizations
Setting Up a Directory Structure for Managing Customized Files and Text Tailoring .............................................................................................................. 113 Best Practices for Customizing Files Supplied by PTC ................................................ 121 Best Practices for Adding New Packages and Files .................................................... 141

This chapter describes the best practices that should be used when you are customizing files that are supplied by PTC or changing configuration settings that interact with the way PTC delivers software maintenance releases. The chapter contains information that can help you understand how to structure and maintain the files you modify or add to your Windchill environment. It also describes the tools and Windchill Service Pack options that can be used to set up and update customized files for Windchill maintenance releases.

Note These recommendations apply to managing the <Windchill> installation directory (where <Windchill> is the Windchill Services installation directory). Best practices for products installed into other directories are not described here. If the implementation of Windchill at your site involves modifying files supplied by PTC, it is important to understand that the maintenance installation process could overwrite any file that is delivered by PTC (except for the site.xconf file). This includes files that you may have modified during customization activities.

112

Windchill Customization Guide

Setting Up a Directory Structure for Managing Customized Files and Text Tailoring
To customize a Windchill system it is often necessary to modify files released by PTC. Because these files can subsequently be updated by PTC in a maintenance release, you should use a strategy for managing your files so that your customizations are not lost when the maintenance updates are installed. As a general rule, the Windchill Service Pack installer can overwrite any files that are in established PTC directories under the installation directory where the Windchill product is installed, regardless of their modification status. It is your responsibility to manage your customized files to avoid loss of your changes and, when updates are applied, to be able to easily identify PTC changes that affect the files you have modified. PTC recommends that you manage customized files by creating a directory structure known as the safe area. The actual directory name is <Windchill>/wtSafeArea, where <Windchill> is the directory where Windchill Services is installed. By using the wtSafeArea directory, you can store copies of the customized versions of PTC files where they will not be overwritten by the Windchill Service Pack installer, as well as keep versions of the original PTC files. Additionally, the Windchill Service Pack installer uses this safe area to store updated files that correspond to your customized files. You can then compare the original files to those updated by PTC to identify where changes have been made. Doing the comparison can assist you in incorporating PTC updates into your customized files. PTC provides a script to assist with managing and installing customized files into your system runtime locations within the <Windchill> installation directory. Additionally, if you make changes to resource bundle information files (RBINFO files), then you must use the <Windchill>/wtCustom directory structure to store those changes.

Managing Customizations

113

Directory Structure Diagram for Customized Files and Text Tailoring


The following diagram gives an example directory structure that includes the wtCustom directory for text tailoring and the wtSafeArea directory for other customizations. The wtSafeArea directory contains subdirectories for storing sitemodified (i.e., customized) files and corresponding current versions and original versions of the files that PTC has delivered. Following the diagram are the details about how these directories are used.

Safe Area Directory Structure


Under the wtSafeArea directory shown in the previous diagram, notice that a similar directory structure is shown for the siteMod, ptcCurrent, and ptcOrig subdirectories. For example if the installed file <Windchill>/codebase/templates/abcx.html has been modified, then the following set of related files is located under the wtSafeArea directory: wtSafeArea/siteMod/codebase/templates/abcx.html wtSafeArea/ptcCurrent/codebase/templates/abcx.html wtSafeArea/ptcOrig/codebase/templates/abcx.html The following summary describes the purpose of each subdirectory: siteMod contains the site version of each PTC file that you have modified and want to run in production.

114

Windchill Customization Guide

ptcCurrent contains the current PTC version of the file. This is a version newer than the version in the ptcOrig directory and is copied to the directory by the Windchill Service Pack when the installer finds a corresponding file in the siteMod directory. ptcOrig contains the original file from PTC. Put the version of the file in this directory before you modify it for the first time and place the customized version in the siteMod directory. The following items describe the purpose and processing of the files under each of the subdirectories in more detail: siteMod Under this directory structure, store the site version of PTC files that you modify and want to run in production When running the Windchill Service Pack installer, selecting the Complete installation type option directs the installer to copy files from the siteMod directories to the selected installation directory. The files that are copied overwrite existing files in the installation directory. The actual file copying is done by the execution of the installSiteChanges target of the <Windchill>/bin/swmaint.xml Ant script. For more information on this target, see PTC Script for Working with Customized Files on page 117. As described in PTC Script for Working with Customized Files on page 117 there are a few files that you should not put under the siteMod directory. You must place and update files in this directory yourself; the Windchill Service Pack installer does not modify the files in the directory. Although the previous diagram only shows a codebase subdirectory of siteMod, modified versions of files from other directories can also be deployed from the siteMod directory. For example, you can add a tasks directory under the siteMod directory and in that directory, store customized Windchill Info*Engine tasks. ptcCurrent This directory structure holds the most current PTC versions of files you have modified (as identified by the presence of those files under the siteMod directory). Windchill Service Pack installer automatically places files in this directory when the following things are true: The siteMod directory exists.

Managing Customizations

115

There are files in the siteMod directory that are being updated by the service pack installer. The files copied to the ptcCurrent directory are the files in the service pack that have the same name as files found in the siteMod directory. Instead of copying these files to your installation directory, the files are put in the ptcCurrent directory. This means that your customized files are not overwritten by the updated PTC files. After running the service pack installer (using any of the installation types), this directory contains updated PTC versions of the set of files that have been modified at your site. A file appears in the ptcCurrent directory when PTC delivers an updated version in a maintenance release, but only after you initially create your customized version in the siteMod directory. ptcOrig Before making first-time modifications to a file, put a copy of the original PTC file in this directory. The original PTC file is the last version of the file that PTC delivered prior to making modifications. This file could be the file supplied in a major release or in one of the maintenance releases. You must place files in this directory yourself; the Windchill Service Pack installer does not modify the files in the directory. ptcOrig is a suggested directory name; there are no PTC tools that actually look for this name. After setting up this directory structure and installing updated files, you can compare the most recent version of a file from PTC (located in the ptcCurrent directory) with the currently deployed file (located in the siteMod directory) and the original version of the file (located in the ptcOrig directory). From the comparisons, you can determine how the version in the siteMod directory should be updated to incorporate the latest changes from PTC. For additional information, see Using the Safe Area Directory Structure When Installing the Windchill Service Pack on page 120. Text Tailoring Directory Structure Store your updates to PTC-supplied RBINFO files in the wtCustom directory shown in Directory Structure Diagram for Customized Files and Text Tailoring on page 114. The details on which files can be updated and how to do the updates are in Best Practices for Customizing Files Supplied by PTC on page 121.

116

Windchill Customization Guide

PTC Script for Working with Customized Files


PTC provides the swmaint.xml Ant script to help you manage the files in the <Windchill>/wtSafeArea/siteMod directory. The swmaint.xml script is installed in the <Windchill>/bin directory during Windchill Services installation. To obtain a list of all swmaint.xml script target options, enter the following ant command from a Windchill shell:
ant -f bin/swmaint.xml -projecthelp

Following is a list of the most common target options: createSafeArea creates the <Windchill>/wtSafeArea/siteMod, <Windchill>/wtSafeArea/ptcCurrent, and <Windchill>/wtSafeArea/ptcOrig directories. listSiteChanges lists the files in the siteMod directory. installSiteChanges copies the files under the <Windchill>/wtSafeArea/siteMod directories to their corresponding <Windchill> installation directories. The timestamps on files from the siteMod directory are preserved when the copying is done. There are a few files and directories that could be present under wtSafeArea/siteMod but are not copied. For example, the files under the following wtSafeArea/siteMod directory structures are not copied to installation directories: .xconf-backup installer logs codebase/instreg tasks/codebase temp vaults wtCustom wtSafeArea

Note Most of these directories contain files that you should never modify; therefore, the directories should not be in the wtSafeArea/siteMod directory. If you happen to have files in any of these directories, the target reports that the files were not copied.

Managing Customizations

117

The following files in the wtSafeArea/siteMod directory structure are also not copied to installation directories: bin/swmaint.xml codebase/.xconf-target-file-hints declarations.xconf site.xconf For an up-to-date list of files and directory structures excluded when the installSiteChanges target option is processed, see the output from the listSiteModExclusions target option (described next). listSiteModExclusions lists the files and directory tree structure patterns of those files and directories that are excluded when the installSiteChanges target option is processed. listSiteChangesIgnored lists the files under the <Windchill>/wtSafeArea/siteMod directory that are not copied to corresponding <Windchill> installation directories when you run installSiteChanges. This target option is also run when you run the swmaint. xml script with the listSiteModExclusions target option. MakeJar.xml a script to build JAR files and maintain a network of definition files for building jar files. For more information see Managing Client JAR Files on page 127.

Executing the swmaint.xml script is always done from an ant command. For example, from a Windchill shell, execute the following ant command to copy the siteMod files to their executable location:
ant -f bin/swmaint.xml installSiteChanges

118

Windchill Customization Guide

Using the Safe Area Directory Structure When Customizing Files


Note The following descriptions assume that you have set up your safe area directory structure, as described in Directory Structure Diagram for Customized Files and Text Tailoring on page 114.
Use the following procedure to modify a PTC file for the first time: 1. Copy the original version of the PTC file into the proper subdirectory under the ptcOrig directory. For example, copy: <Windchill>/codebase/templates /adcx.html to: <Windchill>/wtSafeArea/ptcOrig/codebase/templates/ abcx.html. 2. Also copy the file to the siteMod directory and then make your modifications to the file that is in the siteMod directory. For example, copy the abcx.html file as follows and then modify the copied file: <Windchill>/wtSafeArea/siteMod/codebase/templates/ abcx.html. 3. When you are ready to use the customized files in your <Windchill> installation directory, copy the customized files into the installation directory. Run the following swmaint.xml script from a Windchill shell to complete this step:
ant -f bin/swmaint.xml installSiteChanges

The script is described in PTC Script for Working with Customized Files on page 117.

Managing Customizations

119

Using the Safe Area Directory Structure When Installing the Windchill Service Pack
Use the following procedure to incorporate updates at a maintenance release: 1. Run the Windchill Service Pack installer using the Updates for Site-Modified Files to Safe Area installation type. Using this option puts the updated PTC versions of customized files in the ptcCurrent directory. (A file is copied into the ptcCurrent directory only if the file exists in the siteMod directory.) 2. Using the three versions of the file found in the siteMod, ptcOrig, and ptcCurrent directories, determine what changes PTC has made in this maintenance release to each of your customized files.

Note If there is no corresponding file in the ptcCurrent directory, then there are no updates for the file in the current maintenance release. You can run the following swmaint.xml script from a Windchill shell to list the site changes contained in files that are under the wtSafeArea/siteMod directory:
ant -f bin/swmaint.xml listSiteChanges

Additionally, other target options described in PTC Script for Working with Customized Files on page 117.
3. Update each filed that is in the siteMod directory appropriately. 4. After all files in the siteMod directory have been updated, run the following swmaint.xml script from a Windchill shell to copy the files into place for testing.
ant -f bin/swmaint.xml installSiteChanges

Running this target also lists all files that are not copied. Normally, there should be no files listed. Inspect any files listed to determine why they were not copied. If they were in the wrong directory, put them in the correct directory and rerun the script.

Note The Windchill Service Pack installer executes this script and target automatically whenever there is a siteMod directory and you select the Complete installation type.

120

Windchill Customization Guide

Best Practices for Customizing Files Supplied by PTC


The following sections call out specific file types and directories where sites typically modify PTC files. The text recommends procedures to follow that work in concert with the maintenance installation process to avoid unexpected file overwrites. If you are modifying files that are not specifically identified in the following sections, consult Setting Up a Directory Structure for Managing Customized Files and Text Tailoring on page 113 to determine if the procedures outlined there can assist with managing your changes. Often, sites make changes to the following types of files: RBINFO files *.properties files HTML templates XML files Windchill Info*Engine tasks INI files Client JAR files

Additionally, your site may modify other files in the codebase directory. Use the information in the following sections to help you manage your customizations.

Changing Displayed Text Found in RBINFO Files


To ensure that site changes to displayed text that resides in RBINFO files is properly handled, note the following points: Site changes to PTC text values should be stored in RBINFO files that are in the <Windchill>/wtCustom directory structure. Never edit the RBINFO files in the <Windchill>/src directory. When the enumCustomize tool is used, it creates the required wtCustom directory structure. Changes to displayed text may have an effect on resources that are incorporated in client JAR files. Make sure to consult Managing Client JAR Files on page 127. The Windchill Service Pack and patch installers automatically re-compile these resources so maintenance updates and your site changes are re-combined.

Managing Customizations

121

The following sections provide additional details on text tailoring and updating client JAR files. For general information about the enumCustomize tool, see Enumerated Types. For recommendations on where and how to create new localized resources (for example, new RBINFO files), see Best Practices for Adding New Packages and Files on page 141.

Details on Tailoring Text


The text that is displayed in most of the user interface, be it HTML or Java-based UIs and regardless of the locale, is produced from text stored in RBINFO files. The files installed to the directory <Windchill>/src contain PTC text, site changes to the displayed text are to be done to corresponding files in the <Windchill>/wtCustom directory. There is a clear structure relationship between RBINFO files in the <Windchill>/wtCustom directory, the <Windchill>/src and the <Windchill>/ codebase directory. For example, the list of valid life cycle states are stored as compiled resources in <Windchill>/codebase/wt/lifecycle/StateRB*, original PTC sources are in <Windchill>/src/wt/lifecycle/StateRB*.rbInfo , and any site modifications must be stored at <Windchill>/wtCustom/wt/lifecycle/ StateRB*.rbInfo. The files under <Windchill>/src should never be edited. This is because these files can be overwritten during a maintenance installation, thus losing site modifications. There are three kinds of text stored in RBINFO files. For all of these, site changes should only be done in files under the <Windchill>/wtCustom directory. Text for enumerations (EnumResourceInfo lists of values) is changed using the enumCustomize tool that is launched from <Windchill>/bin/ enumCustomize. Using the enumCustomize tool creates the required files in the wtCustom directory and stores the values you replace. Text for many string messages, user interface (UI) buttons, and labels are declared in WTListResourceBundle classes, but they are changed by placing site-specific values in the wtCustom/wt/util/resource/resourceCustomize.rbInfo file. For more information on customizing these values, see the documentation in this file: <Windchill>/src/wt/util/resource/ resourceCustomize.rbInfo

122

Windchill Customization Guide

Displayable text for modeled business information such as classes, attributes, relationships, and so on (MetadataResourceInfo) is changed by placing site specific values in RBINFO files in the wtCustom directory. By using a text editor, enter only the values you want to override in the files; values that you are not changing should not be included.

For your text changes to be used by the running product, they must be compiled into the codebase. Running the enumCustomize tool does this automatically, but only for EnumResourceInfo resources. However, all three kinds of resources can be compiled by using the ant script <Windchill>/bin/tools.xml and the bundle_custom target. To use this script, start a Windchill shell and execute the following command:
ant -f bin/tools.xml bundle_custom -Dbundle.input=registry

Both the Windchill Service Pack installer and patch installer automatically execute this command to ensure that any updates delivered by PTC are merged with your site changes in the <Windchill>/wtCustom directory. For text changes that are to be used by any applets, you must additionally execute the MakeJar command as follows:
ant -f <Windchill>/codebase/MakeJar.xml custUpdate

See Managing Client JAR Files on page 127 for more information. For example, if you add a life cycle state to StateRB.rbInfo, you must run the above command to see the new state in an applet such as the Lifecycle Administrator.

Managing codebase Property Files


In most cases, the property files (*.properties) in the codebase directories should only be modified by using PTC tools, and never manually edited. This is a major change from previous Windchill releases, where editing property files was very common. There are two key points regarding property files: Use either the xconfmanager Utility or System Configurator to make property file changes. Additional information on these topics is covered in the next two sections. When you cause a property file to be changed, you may need to update downloadable client JAR files. Make sure to consult Managing Client JAR Files on page 127.

Managing Customizations

123

Manipulating Property Files


Most property files should be manipulated using the xconfmanager Utility or the System Configurator. The reason to use either of these tools is that they store the property values you set in the <Windchill>/site.xconf file. They then propagate those values to the proper *.properties files. (Comment blocks are placed at the top and bottom of *.properties files that the xconfmanager has updated.) If a PTC maintenance update delivers changes to properties that you have changed, the xconfmanager automatically propagates the property changes stored in your site. xconf file on top of the PTC updates. Information on these tools can be found in the Windchill System Administrator s Guide. In many cases, there is a one-to-one correspondence between an *.xconf file and its *.properties file; for example codebase/wt.properties.xconf and codebase/wt. properties. In other cases, there is not a matching XCONF file. Even without an associated XCONF file, a properties file can still be manipulated with the xconfmanager Utility. The following codebase properties should not be manipulated with the xconfmanager Utility: associationRegistry.properties descendentRegistry.properties modelRegistry.properties moduleRegistry.properties moduleDir.properties debug.properties

This is because these properties contain properties not suitable for the xconfmanager Utility. If there are a lot of new properties that you need to add to a file such as wt. properties, rather than using xconfmanager Utility to set each property, consider creating your own declarative XCONF file. In this file, you declare the properties with a targetFile of wt.properties. Then use xconfmanager Utility to install this file into the declarations.xconf file. For an example of creating a service provider property file, see Adding a Custom Service Provider Property File on page 142.

Using XCONF Files


The XCONF files supplied by PTC are not intended for direct editing. All *.xconf files, except <Windchill>/declarations.xconf and <Windchill>/site.xconf should be considered read-only. The declarations.

124

Windchill Customization Guide

xconf and site.xconf files are both manipulated by the xconfmanager Utility. See Using the xconfmanager Utility on page 146 for details on using the xconfmanager Utility.

Managing HTML Templates in the < Windchill >/codebase/templates/ Directory


The HTML template files are located in the <Windchill>/codebase/templates directory. These files must be in this directory at runtime. If you want to modify any of the files in this directory, be sure to put a copy of the corresponding PTC files (before you make any changes) in the <Windchill>/wtSafeArea/ptcOrig/codebase/templates directory. Then modify the files and put a copy of your customized files in the <Windchill>/wtSafeArea/siteMod/codebase/templates directory. For details on using the <Windchill>/wtSafeArea directory, see Setting Up a Directory Structure for Managing Customized Files and Text Tailoring on page 113.

Managing the LogicalAttributes.xml LogicalAttributes.xml File


The LogicalAttributes.xml file is used to assign logical names to the attributes of business objects. These logical names are used to identify the attributes when configuring certain clients. For details on the format and content of the file, see the file itself and the corresponding Javadoc. The file is located in the <Windchill>/codebase directory. To prevent overwriting, use the safe area procedures as described in Setting Up a Directory Structure for Managing Customized Files and Text Tailoring on page 113.

Managing codebase/{wtcore, codebase/{wtcore,netmarkets, netmarkets,pdmlink} pdmlink} Files


If you have a requirement to modify any of the files, such as JSP files, under the <Windchill>/codebase/wtcore, <Windchill>/codebase/netmarkets, or <Windchill>/codebase/pdmlink directories, be aware that during a maintenance installation the PTC updates to the same files could overwrite your changes. To prevent overwriting, you should utilize the safe area procedures as described in Setting Up a Directory Structure for Managing Customized Files and Text Tailoring on page 113.

Managing Customizations

125

Managing Windchill Info*EngineTasks Info*EngineTasks


Windchill Info*Engine tasks are stored in the <Windchill>/tasks directory. If you customize any of the task files, they could be overwritten during a maintenance installation if PTC must update the same task files. To prevent overwriting modified tasks, you should utilize the safe area procedures that are described in Setting Up a Directory Structure for Managing Customized Files and Text Tailoring on page 113. For example, if you needed to modify a task in the tasks/com/ptc/windchill/enterprise directory, first put the original PTC version in the wtSafeArea/ptcOrig/tasks/com/ptc/windchill/enterprise directory and your modified version would go into the wtSafeArea/siteMod/tasks/com/ptc/windchill/enterprise directory.

INI Files for Workgroup Manager


If you modify any INI files for the workgroup managers, then you should copy the originals to the ptcOrig directory and put your modified versions in the siteMod directory. The Workgroup Manager for Pro/ENGINEER 2001 has the following INI files: The Workgroup Manager for CATIA V4 has the following INI files: catiafileadapter.ini newcatiadocument.ini catiaworkspaceconfig.ini registryserver.ini registryclient.ini cadds5workspaceconfig.ini registryclient.ini newdocument.ini proefileadapter.ini newdocument.ini proeworkspaceconfig.ini registryclient.ini

The Workgroup Manager for CADDS has the following INI files:

126

Windchill Customization Guide

Managing Client JAR Files


Clients need to have the same versions of client JAR files as those located on the Windchill server in <Windchill>/codebase. Customizations to displayed text and properties can require that JAR files downloaded to clients are updated.

Note When the client JAR files are updated, clients download them from the Windchill server as the applications detect the previously downloaded JAR files are out-ofdate.
There are two times when you need to ensure that the client JAR files have been updated by rebuilding the files. Rebuild client JAR files: As part of installing a maintenance release. When customizations have been made that affect the client JAR files

Note When updating for a maintenance release, running Windchill Service Pack installer with the Complete installation type rebuilds all client JAR files as needed. If you make new customizations or re-install existing customizations after running this installer, you must manually rebuild the client JAR files.
Most client JARs are maintained through the use of an Ant script, MakeJar.xml, provided with Windchill. To ensure that the JAR files maintained through the MakeJar.xml script are updated correctly, you should add the following to the <Windchill>/codebase/jarContents/Cust.bom: Paths for the compiled resources (*.ser and/or *.class files) of the files you change Paths of customized property files

To verify that all customized property files are listed in Cust.bom, you can compare targetFile entries in site.xconf with the files listed in Cust.bom. Any files listed in targetFile entries that are not in Cust.bom should be added to Cust.bom. For example, if the site.xconf file has an entry for the following:
targetFile="codebase/wt/change2/change2.properties"

Then, ensure that codebase/jarContents/Cust.bom contains the following entry:


wt/change2/change2.properties

To rebuild the client JAR files that are managed by jarContents and jarManifest specifications, execute the following command from a Windchill shell:
ant -f codebase/MakeJar.xml custUpdate

See Rebuilding Client JARs on page 132 for more information.

Managing Customizations

127

Overview of Client JAR Deployment Approach


To effectively manage your client JAR customizations, you need to understand the Windchill approach to client JAR deployment. Logical JARs The concept of a logical JAR was introduced to Windchill in R7.0. Each logical JAR is actually composed of four JARs, in addition to any external dependencies it might have, e.g. to 3rd-party jars. The components of a logical JAR are shown in the figure below.

In this figure, the bolded labels denote role names for each component JAR whereas the italicized name denotes the actual name of the JAR. Thus for a logical JAR named MyApplet, for instance, the components would be MyApplet.jar, MyAppletCust.jar, MyAppletDSU.jar, and MyAppletFCS.jar.

Note The classloading precendence is from left to right in the figure, so that customization JARs override DSU JARs, which in turn override original distribution JARs.
Head JARs only include manifests declaring the component and other JARs upon which they depend, as well as a JAR index in cases where the head JAR is the toplevel JAR for an applet. PTC distributions leave customization JARs empty, as these are for customer additions and overrides (e.g. to resource bundles). DSU JARs are left empty until a maintenance release provides additional files to target client(s) and/or newer versions of files already present in the corresponding FCS JAR. The FCS JAR contains all the original files required by a module at FCS (first customer shipment). The head JAR may list additional JARs upon which it is dependent after its own components.

Note The usage of DSU comes from the fact that, pre-R7.0, maintenance releases to Windchill were delivered in Downloadable Software Updates.

128

Windchill Customization Guide

Modular Client JARs In addition to breaking logical JARs into different components for customization, maintenance releases, and original distribution, an effort has been made to break client JARs into appropriate modular components so that resources required by one applet are not automatically downloaded by all applets. This effort has been balanced with a desire to prevent any resource from being downloaded more than once, that is, included in more than one FCS JAR. DSU and Customization JARs will indeed duplicate resources contained by corresponding FCS JARs to override them without requiring an FCS JAR rebuild. Indeed only in small, targeted cases is a resource downloaded in more than one FCS JAR. In general, these efforts have led to the use of a dependency tree (more precisely, a unidirected graph) of logical JARs as described in the following section. Current Foundation JAR Tree Definition A representative view of the dependency graph of the client JARs is shown below.

Note The figure and the table following it constitute merely a representative view, not necessarily the complete dependency graph.
Each label refers to a logical JAR (composed of head, customization, DSU, and FCS components) unless otherwise noted. Bolded labels are root JARs intended as top-level JARs to directly support applets, whereas the non-bolded labels are intended solely for re-use from other JARs. Each arrow implies a dependency (and essentially inclusion by reference) in the direction of the arrow. It should thus be clear that all JARs currently defined depend on wtApplet and 3rdPartyApplet with the notable exception of wtBootInst. Thus all duplicates are consolidated down the tree except from wtBootInst which is completely independent. The graph shown supports almost all of the Windchill Foundation applets and will certainly grow over time.

Managing Customizations

129

These logical JARs are further described in the following table. Logical JAR 3rdPartyApplet Description A head JAR which collects all the commonly required 3rd-party libraries into a single point of reference. As such it does not include any separate resources and thus has no customization, DSU, or FCS components. Rather it is purely an ordered list of references to 3rd-party libraries. This list is similar to that found in 3rdparty.jar but has had all library references which do not make sense for applets (e.g. JSSE) removed. Common base (non-3rd-party) resources shared amongst most Windchill applets. Like all other shared logical JARs, this JAR serves to collect all resources which would otherwise have been duplicated in JARs above it. Please note that the intermediate JARs wtPolicy, wtQB, and wtWork also serve to consolidate duplicates between themselves and JARs above them. The JAR for the Bootstrap loader installation applet. This is currently the only root applet JAR which is not based on wtApplet. This JAR does duplicate a few resources from wtApplet, but this JAR was kept separate as it had so little overlap with wtApplet and without this dependency could be kept extraordinarily small and lightweight. The JAR for the Policy Administration and domain browser/selector applets. The JAR for the QueryBuilder and Report

wtApplet

wtBootInst

wtPolicy wtQB

130

Windchill Customization Guide

Logical JAR wtWork

wtFVault wtExp

Description Management applets. The JAR for the Workflow, Life Cycle, and Teamrelated Applets (Workflow Administration, Team Administration, Lifecycle Administration, Initiate Process, Process Manager, and Setup Participants). The JAR for the External and Remote File Vault Administrator applets. The JAR for the Windchill Explorer applet. Note that this JAR references / depends-on wtPolicy, wtQB, and wtWork as many of the clients supported by these JARs can be launched from within Windchill Explorer.

wtCal wtESig wtIXB wtSearch

wtTypeAdm wtLogin ptcAnnotator, ptcCore (not shown)

Note This JAR is obsolete as of Windchill release 9.0. The Calendar applet JAR. The electronic signature/identity applet JAR. The JAR to support import/export and bulk-loading applets. The JAR to support Applet.jsp, AppletQuery.jsp, and ChooserTask.html customization samples. This JAR essentially only contains the top-level applet class and exists primarily to keep wtApplet from containing any applet-specific resources and to provide a simple top-level JAR sample. The JAR for the Attribute Administrator, Type Manager, CSM, and Re-Use Manager applets The JAR for the login/reauthentication applet (i.e. that accessed via Login.jsp). The JARs for the Product Structure Explorer (PSE) applet. There are no customizable or inheritable classes in these JARs.

Note that wt.jar and 3rdparty.jar, the JARs used in Windchill applet deployments prior to R7.0 are not used at all by the new applet deployments. Both of these JARs are now the sole province of any applications which use them to maintain and use as they see fit. The new JARs are dramatically smaller than wt.jar.

Using the Client JAR Architecture


The following sections discuss how you should use the client applet JARs.
Managing Customizations

131

Rebuilding Client JARs The client JARs are built via the Java SDK's jar command and an Ant script (MakeJar.xml) that coordinates the builds of the client JARs and other related activities (e.g. consolidation of duplicate entries, removal of known inappropriate resources, and updating JPI cache versions. To rebuild all of the new client JARs, one can simply type:
ant -f MakeJar.xml

from a command prompt in the <Windchill>/codebase.

Caution As a general rule, customizers should not use this command pattern, as it will rebuild the FCS jars and cause unnecessary downloads by clients that have already downloaded the FCS jars by this point. Instead, 'custUpdate' and 'dsuUpdate' targets, as described in the following sections, should be used.
If you are using Java 2 v1.4.x, then any resources listed in a .includes file which are not present in your codebase will result in an error. To remove any such resources from your .includes files, add the following to your MakeJar.xml command line:
-DremoveStaleEntries=true

Although it takes only a couple minutes or so to rebuild all client JARs, in most cases you are only testing an applet or two at a time. In this case you will wish to the faster Ant targets for individual applets. For instance, to rebuild all JARs loaded by a workflow applet, one would use (all on one line):
ant -f MakeJar.xml buildFullClientJars -DlogicalJarNames=wtWork

Omitting the '-DdoDeepBuild=true' argument would limit the rebuild to the wtWork JARs, i.e. it would not rebuild the wtApplet JARs and so forth. To determine what actions a command would perform, without actually performing them, the following argument can be added to the command line for any of the MakeJar.xml targets:
-DtraceOnly=true

The MakeJar.xml script contains targets allowing a wide variety of JAR building and maintenance operations to be performed for one or more JARs or sets thereof. To obtain more information on these targets, execute the following command:
ant -f MakeJar.xml -projecthelp

132

Windchill Customization Guide

Managing Client JAR Contents For optimal performance, all resources (.class files, .properties files, etc.) needed by a Windchill applet should be contained within one of the client JARs it uses. Each resource not found within one of an applet's client JARs that is needed by the applet will require a separate round-trip network request and the resource will not be compressed as it would be if it was part of a client JAR. This leads to especially poor performance on slow or wide-area networks. Providing the correct content in a client JAR file helps ensure optimal performance of the applet. If you have any customized applets, their JARs may not contain all the custom resources they require. If you suspect that the client JAR file used by an applet does not have the correct contents, you can determine which missing resources should be added. After customizing applets or JARs, you can identify what resources are used by an applet but are not contained in the corresponding client JAR files as they should be. If you are using the Apache Web server, PTC provides the HTTP Request Log utility that can be used to identify resources that are missing from a client JAR file and can then be added to the client JAR file. Use the following steps to determine which resources are missing from a set of client JAR files. 1. Open the HTTP Request Log utility. This marks the location of the current end of Apache log file so that all entries added to the file can be examined to see if they identify resources that have been downloaded to the client. 2. In a browser window, open the applet associated with the client JAR files and test the applet functionalities you wish to ensure/troubleshoot the performance of. Any resource downloaded for use in the client is recorded in the Web server access log. The HTTP Request Log utility searches the log file for the resource requests made of types peculiar to applets (for example, .class and .properties files) since you opened the utility in step 1. These resources were not found in the client JARs and thus were being pulled from the Web server. 3. Use the results from the utility to update the appropriate client JAR files. The following section provides details about using the HTTP Request Log utility. Using the HTTP Request Log Utility You can use the HTTP Request Log utility to determine which resources are missing from the client JAR files used by Windchill applets. It searches the Apache log file, either by a specific user or all users, for specified file extensions and displays them in sorted order.

Managing Customizations

133

Note To use the utility, you must be using the Apach Web server.
1. Log in as a user named in the wt.sysadm.administrators property in the wt. properties file. For example, if the property value is: $(wt.admin.defaultAdministratorName),demo You can log in as the demo user or the user stored in the wt.admin. defaultAdministratorName property. 2. In the browser window, access the following page:
<local_host_name>/<Web_app_name>/wtcore/jsp/wt/sysadm/HttpRequestLogUtil Start.jsp.

The HTTP Request Log Utility Start Page opens:

3. In a separate browser window, start to the applets you want to test and complete your testing. 4. Return to the browser window where you started the HTTP Request Log Utility Start Page. Click View single client results to view the results from your testing session. Click View all client s results to view the results from all sessions recorded.

134

Windchill Customization Guide

The results are a sorted list of all of the resources that were accessed during the testing that are not contained in a client JAR file. Use this input to update the appropriate JAR files. For example, if the list is as follows:

5. Copy the resources from the resulting list and paste them into the following file:

Managing Customizations

135

<Windchill>/codebase/jarContents/<topJarName>Cust. includes <topJarName> is the leafname of the top-level JAR used by the applet. For example, the QueryBuilder top-level JAR in the applet tag is wtQB.jar. Therefore, paste the resources into the file named: <Windchill>/codebase/jarContents/wtQBCust.includes 6. From a Windchill shell, run the following script from the codebase directory:
ant -f MakeJar.xml custUpdate

Tip The search results are only as accurate and complete as the testing you do. If the HTTP Request Log Utility Start Page was not accessed before the testing, the entire log file is searched. Otherwise, the search begins from the point in the log that immediately follows your most recent access. The types of resource files that are searched for can be configured. By default, the defined extensions are .class, .ser, and .properties. To change from the default, edit the fileExtensions variable in wtcore/jsp/wt/sysadm/ HttpRequestLogUtilStop.jsp file. Note Depending on the servlet engine configuration you may have to restart the servlet engine for these changes to take effect. To find all resources needed for an applet, remove the client JARs used by the applet and use the previous steps to log all resources that are used. This type of testing creates a lot of network traffic since every resource is downloaded from the server. You would typically only do this type of testing if you believed the client JARs contained significantly more resources than were required for your use cases. This generally should not be done with PTC supplied *FCS.jar and *DSU.jar files.

Note If, using the above methods, you discover that there are resources missing from Windchill client JARs that you have not modified, file a problem report with technical support. Include the following in the report:
136

The list of missing resources. The applet or root JAR against which the testing was being performed. A brief description of the functionalities exercised. The exact build against which the testing was performed. The version of the Java Plug-In used in the testing. The client OS.
Windchill Customization Guide

Adding New Applets Re-using an Existing Root JAR If you have decided to directly re-use an existing root JAR for the applet(s) in question, then all you have to do is list this JAR in the plug-in tag. Using a New Logical Root JAR In the case where a new JAR is to be added, however, the necessary steps are as follows. 1. Create content and manifest description files for your logical JAR's components. You can use a target within MakeJar.xml to do this for you by executing the following in codebase:
ant -f MakeJar.xml makeNewJarDescr -DlogicalJarName= logicalJarName

For example, for a new logical JAR, foo, one would execute:
ant -f MakeJar.xml makeNewJarDescr -DlogicalJarName=foo

This creates an empty FCS .includes files for the specified logical JAR in codebase/jarContents, e.g. for a logical JAR, foo, this file would be fooFCS.includes. This also creates head, Customization, DSU, and FCS .manifest files in codebase/jarManifests for the specified logical JAR, e.g. for a logical JAR, foo, these files would be foo.manifest, fooCust.manifest, fooDSU.manifest, and fooFCS.manifest. All of these files except the head manifest (e.g. foo. manifest) are initially empty. The head manifest defaults to have a ClassPath entry listing the Customization, DSU, and FCS JAR components of the logical JAR followed by wtApplet.jar, e.g. for a logical JAR, foo, the entry would be:
Class-Path: fooCust.jar fooDSU.jar fooFCS.jar wtApplet.jar

This entry should be amended if your logical JAR does not depend on wtApplet.jar or has additional dependencies - in either case these should be listed after the FCS JAR entry. 2. Create a .set file in <Windchill>/codebase/jarManifests that includes the logical name of your new JAR. 3. Build your JAR by executing an appropriate target on the MakeJar.xml script (from the codebase directory), e.g.:
ant -f MakeJar.xml buildFullClientJars -DlogicalJarNames=foo

where foo should be replaced by the name of your logical JAR.

Managing Customizations

137

4. Test your new JAR by using it in your applets' plug-in tags, recording missing resources via the HTTP Request Logging utility as described in Using the HTTP Request Log Utility on page 133. 5. Update your new JAR's contents as described in Using the HTTP Request Log Utility on page 133. 6. Re-test your applet. Updating Client JARs At Maintenance Releases Because of the inclusion of DSU JARs in the logical JARs, clients only have to download resources that were added or changed as part of the maintenance release (plus new root head jars), not the entire set of client JARs. The process of rebuilding the client JARs at a maintenance release has been automated via the following command (note that this command rebuilds Customization JARs when necessitated by new or updated DSU JARs):
ant -f MakeJar.xml dsuUpdate

This command executes the following targets: createCodebaseDsuBOM: Takes entries in codebase/../*_bom.txt BOM files which are in codebase and places them in jarContents/DSU.bom, but written relative to codebase (i.e. it removes "codebase/" from each entry). updateDSUIncludes: Intersects each FCS .includes file with jarContents/DSU. bom and adds the intersection to the corresponding DSU .includes file. updateCustIncludes: Intersects each FCS .includes and DSU .includes file pair with jarContents/Cust.bom and adds the intersection to the corresponding Customization .includes file expandJarLocales: For resource bundles represented by _en localization in DSU and FCS .includes, places other localizations requested in jarContents/ clientJarLocales into Customization .includes removeNonexistantDsuAndCustEntries: Removes any entries from the Customization and DSU .includes files which are not found in codebase. buildDSUClientJars: Rebuilds all DSU and Customization jar components. Also builds all indexed head jars which are parents (directly or indirectly) of these jars. The addition of any new DSU jar entries required for reasons other than being in the intersection of the DSU BOM and FCS jar contents (e.g. previously missed entries, new classes, etc). The inclusion of a codebase/../*_bom.txt file containing the files changed by the DSU.
Windchill Customization Guide

The only steps omitted by dsuUpdate for the Foundation resources and jars are:

138

These should both be provided (e.g. as updated DSU .includes files and a foo_bom.txt file) as part of the maintenance release itself. Updating Client JARs for Customizations The Customization JAR components exist to allow customization additions and overrides to the out-of-the-box JAR sets as these components take load precedence over the corresponding DSU and FCS components. A customer or customizer can add entries to any Customization .includes files they want and rebuild the corresponding JAR via:
ant -f MakeJar.xml buildCustClientJars -DlogicalJarNames=jar1,jar2,

where jar1,jar2, should be replaced by the list of logical JARs whose Customization components should be rebuilt. More often, however, the customer is likely to have a number of files they have overridden and simply wish to have the client JARs updated to account for this. This can be done by listing the overridden/customized files in codebase/ jarContents/Cust.bom and then executing the command:
ant -f MakeJar.xml custUpdate

This command executes the following targets: updateCustIncludes: Intersects each FCS .includes and DSU .includes file pair with jarContents/Cust.bom and adds the intersection to the corresponding Customization .includes file. Note that Cust.bom contains a few of the most volatile entries (e.g. properties files regenerated during code generation) initially out-of-the-box. expandJarLocales: For resource bundles represented by _en localization in DSU and FCS .includes, places other localizations requested in jarContents/ clientJarLocales into Customization .includes buildCustClientJars: Re-builds all Customization JAR components. Also, builds all indexed head JARs which are parents (directly or indirectly) of these JARs.

Additionally more extensive client customizations can be supported by proceeding to build new client JAR sets in much the same way as was described for the previous sections.

Managing Customizations

139

Handling Localized Resources The MakeJar.xml script contains reusable targets which wrap custom Ant tasks which handle localized resource entries in client JARs. standardizeJarLocales: removes all except one locale-specific resource entries for each resource bundle encountered in the FCS and DSU .includes of the logical JARs listed by the input property logicalJarNames. Note that the null/ default locale entry is also not removed. This target is used by various targets including sanitizeAndBuildJarSets to eliminate most of the overhead of undesired localization in client JARs. expandJarLocales: for each resource bundle in the FCS and DSU .includes of the logical JARs listed by the input property logicalJarName, places the corresponding entries specific to the locales desired by the site (as specified in jarContents/clientJarLocales) in the corresponding Customization .includes files. Conversely, entries from bundles represented in a DSU.includes or FCS. includes but from locales not requested by the site are removed from the corresponding Customization.includes. This target is used by dsuUpdate and custUpdate to ensure that the client JARs support the locales requested by the site.

As a whole the MakeJar.xml script ensures reasonable handling of site-specific locale sets. It does not handle user-specific locale sets (i.e., delivery of different JAR sets to each user depending on their locale settings).

140

Windchill Customization Guide

Best Practices for Adding New Packages and Files


To create custom applications, your site may need to create new packages and files. You can store new packages and files under the <Windchill>/src/directory structure; however, the packages and files that are defined should not be stored under the <Windchill>/src/wt or <Windchill>/src/com/ptc directory. Typically, newly developed packages and files are stored under the domain name of your company. For example if your company domain name is mycompany.com, store them under <Windchill>/src/com/mycompany.

Caution When you create a new package, you need to add it to the includeClassStartsWith property in wt.properties. This property lists the package hierarchies that are included when resolving inherited descriptor information. For example, if you add the package com.mycompany, use xconfmanager to add com.mycompany. to the property, with the following command from a windchill shell:
xconfmanager --add com.ptc.core.meta.descriptor.server.impl. includeClassStartsWith=com. com. mycompany. -p

The types of files that you should store under <Windchill>/src/com/mycompany include new Java source files, property files, HTML templates, RBINFO files, and XCONF files. In addition to keeping your new packages and files in a <Windchill>/src/com/ mycompany directory structure, you must include corresponding packages and files in your runtime system. For example, the following list explains where your files should be placed: Java files are typically compiled to a comparable directory under < Windchill>/ codebase. For example, if you create a class under <Windchill>/src/com/ mycompany/part, you could compile it to <Windchill>/codebase/com/ mycompany/part. Resource bundle files must be compiled into a directory under <Windchill>/ codebase at runtime. This can be done using the ResourceBuild command. For example, if you have new RBINFO files in the directory <Windchill>/src/com/ mycompany/part, you could compile them to the <Windchill>/codebase/com/ mycompany/part directory by executing the following command from a windchill shell:
ResourceBuild com.mycompany.part

Property files maintained in a custom directory like <Windchill>/src/com/ mycompany must be copied to a directory in <Windchill>/codebase at runtime.

Managing Customizations

141

Often when you integrate new packages and files into your existing environment, you must change files that were supplied by PTC. Be sure to manage these customized files as directed in earlier sections.

Note When you are updating files for a maintenance release, remember to copy any updated new packages and files that are used in your runtime system from your test system to your production system.

Modeling Recommendations
Sites that use custom modeled classes using Windchill InformationModeler and Java Annotations, may store their new packages and classes under the <Windchill>/src directory structure; however, the packages that are defined should not be stored under the <Windchill>/src/wt or <Windchill>/src/com/ptc directory. Typically, newly developed packages and classes are stored under the domain name of your company, as described previously. Some customizations can also be stored under the <Windchill>/src/ext directory.

Adding a Custom Service Provider Property File


Some site customizations involve creating a new service provider property file. Service provider property files must be declared in one of the following <Windchill>/codebase/wt.properties entries: wt.services.applicationcontext.WTServiceProviderFromProperties . customPropertyFiles wt.services.applicationcontext.WTServiceProviderFromProperties . defaultPropertyFiles wt.services.applicationcontext.TypeBasedServiceProviderFromProperties . defaultPropertyFiles wt.services.applicationcontext.TypeBasedServiceProviderFromProperties . customPropertyFiles Customizing service.properties on page describes the use of these properties. These properties are handled in a special fashion with xconfmanager Utility. Rather than directly specifying a new property value for any of these properties, you should instead establish a new declarative XCONF file that causes your new service provider file to be used. A key benefit to doing this is that it will avoid conflicts with these property values if you later install other PTC products that require their own service provider property values. This is illustrated with the following example.
Windchill Customization Guide

142

Suppose your new service provider file name is named codebase/ext/sitepart/ sitepart.properties. It contains the entries that define your new services. In order to get this property listed as one of the files in the following wt.properties entry:
wt.services.applicationcontext.WTServiceProviderFromProperties.customProp ertyFiles

You should create a new declarative XCONF file, for example, codebase/ext/ sitepart/sitepart.xconf. It would look like the following:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE Configuration SYSTEM "xconf.dtd"> <Configuration targetFile="codebase/wt.properties"> <!-- Ensure that the file ext/sitepart/sitepart.properties is appended to the list of custom property files. --> <Property default="ext/sitepart/sitepart.properties" name="wt.services applicationcontext.WTServiceProviderFromProperties.customPropertyFiles"/> </Configuration>

The Property statement (formatted on two lines for this guide) is one line in the file that declares that the file ext/sitepart/sitepart.properties (a path relative to the codebase directory) should be added as a value for the property:
wt.services.applicationcontext.WTServiceProviderFromProperties.customProp ertyFiles

This property is in the codebase/wt.properties file. Store a copy of new XCONF files in your source directories as described in Best Practices for Customizing Files Supplied by PTC on page 121. To install the codebase/ext/sitepart/sitepart.xconf file and generate the sitepart. properties file, execute the xconfmanager Utility from a windchill shell, as follows:
xconfmanager -i codebase/ext/sitepart/sitepart.xconf -p

After running the above command, the wt.properties file is updated to reference your service provider file, codebase/ext/sitepart/sitepart.properties.

Managing Customizations

143

6
Windchill Utilities
Using the xconfmanager Utility ................................................................................. 146 Formatting Property Value Guidelines ....................................................................... 158 Windchill Command................................................................................................. 159 Windchill Shell......................................................................................................... 162

145

Using the xconfmanager Utility


The xconfmanager is a command line utility that you can run to add, remove, or modify properties in Windchill property files that are used for your defining your system. Windchill uses some property files to manage internal system activities that you should never modify, including the following: associationRegistry.properties descendentRegistry.properties modelRegistry.properties moduleRegistry.properties moduleDir.properties debug.properties

The xconfmanager utility saves your changes in the site.xconf file and provides an option to generate updated property files using the updates in the site.xconf file. The site.xconf file contains the changes made to Windchill property files starting with the installation and continuing with each use of the xconfmanager utility. The site.xconf file is located in the directory where Windchill is installed. Anyone with write access to the XCONF and property files under the Windchill installation directory can successfully run the xconfmanager utility. The following sections describe how to enter the xconfmanager command and how to set property values and list property information using the command. The last section describes the other xconfmanager options that may be useful when running your Windchill solution. The xconfmanager utility is located in the bin directory where your Windchill solution is installed. For example, if Windchill solution is installed in the C:\ptc\Windchill directory, then the utility is in the C:\ptc\Windchill\bin directory. Before executing the xconfmanager command, set up your environment by using the windchill shell. To use the shell, either execute the shortcut (on a Windows system) or enter the following on the command line:
windchill shell

Then from the new window that opens, you can enter the xconfmanager command, as described in the next section.

146

Windchill Customization Guide

xconfmanager Command Syntax


The syntax of xconfmanager command that administrators should use is as follows:
xconfmanager {-fFhuwvV -fFhuwvV} {-r -r <product_root>} {-d -d <property_names>} {-s -s <property_pair>} {-t -t <property_file>} {--add --add <property_pair>} {--remove --remove <property_pair>} {--reset --reset <property_names>} {--setfromfile --setfromfile <property_file>} {--undefine --undefine <property_names>} {-i -i <declarative_xconf>} {--validateassite --validateassite <site_xconf>} {--validateasdecl --validateasdecl <declarative_xconf>} {--validatefilesassite --validatefilesassite <site_list_file>} {--validatefilesasdecl --validatefilesasdecl <declar_list_file>} {-p -p}

The brackets ({}) in the syntax indicate optional parameters and indicate parameters that you specify together. The syntax includes only the short version of each parameter name. Parameter names are case-sensitive; enter the names using the case shown in the syntax and the following table. The following variables are used in the syntax of multiple parameters:

<property_pair> is a command-line escaped name=value pair that is compatible with the specification for java.util.Properties. For an example, see Setting Property Values and Propagating Your Changes on page 152. <property_names> is a comma-separated list of property names. <property_file> is the relative or full path name of the property file. <declarative_xconf> is either a full URL or relative file path to the declarative XCONF file.

In the following table, all parameter names are listed in alphabetical order with corresponding parameter descriptions: Parameter Name
--add

Description Add the specified value at the end of the set of ordered values already defined in the property. Use this parameter only when the property is declared as a multi-valued property. To determine if property is multi-valued, you can display the current set of values using the -d parameter. The output from this parameter lists the multivalue separator when the property is multi-valued. Lists the values that are currently set and the corresponding XCONF file where each value is set for the specified properties. This parameter executes after all parameter setting options and the -p option have executed. Forces the propagator to ignore its cache of XCONF-toproperties file dependencies and ignore the timestamp

-d

or
--describe

-F

Windchill Utilities

147

Parameter Name or
--force

Description comparison it usually does to determine which property files need to be updated. Using this option propagates all site-specific changes to property files. Use this parameter in place of -p if you suspect that there are problems with file timestamps or you want to switch between the -w and -u options. Forces the propagator to ignore its cache of XCONF-toproperties file dependencies. This parameter is ignored if you specify -F. Use this option in place of -p if you suspect that the cache is out of date. Displays the help for the xconfmanager command.

-f

or
--forcescan

-h

or
--help -i

or
--install

-p

or
--propagate

Installs a declarative XCONF file that you have created. New declarative XCONF files are used when creating additional property files. When you are adding code in which new properties can be set, you can choose to create a separate property file where the properties are stored. For details on what to put in the declarative XCONF file, see Using XCONF Files on page 124. Propagates all changes that have been made to XCONF files into the property files that are being used. This option always executes after any options that set properties. This execution order ensures that the newly set properties are included in the propagation. Updated property files are accessed when the Windchill solution is restarted. The root directory from which all relative paths are based for XCONF references specified in the declarations.xconf file and target file paths specified in the -t parameter. The default root directory is the bin directory where the Windchill solution is installed. Removes the specified value that is in the set of ordered values defined in the property. Use this option only when the property is declared as a multi-valued property.

-r

or
--productroot

--remove

148

Windchill Customization Guide

Parameter Name

Description To determine if a property is multi-valued, you can display the current set of values using the -d parameter. The output from this parameter lists the multivalue separator when the property is multi-valued. Resets the site specific value of a property or set of properties to the declared default values. Sets the named property to a specific value in the site. xconf file. To set multiple properties in the same target property file, use multiple occurrences of this parameter or use the following parameter:
--setfromfile

--reset -s

or
--set

To set multiple properties that are in different target property files, enter multiple xconfmanager commands, one for each target file. Use this parameter in conjunction with the -t parameter. Adds the name=value pairs that are in the specified file to the end of the site.xconf file, thus setting each property named to the specified value. There is no checking done to determine if the value set is the default.

--setfromfile

<property_file> is the file that contains a set of name=value pairs (one pair per line) that indicate the properties and values you want set in one target property file. Each pair sets a value for one property.
With this parameter, you can set multiple properties in the same target property file using one xconfmanager command. To set properties that are in different target property files, enter multiple xconfmanager commands, one for each target file. Use this parameter in conjunction with the -t parameter. Identifies the property file in which the property value specified in the -s parameter is set or the property values specified in the following parameter are set:
--setfromfile

-t

or
--targetfile

Use this parameter in conjunction with either the -s or the following parameter:
--setfromfile

Windchill Utilities

149

Parameter Name

Description This parameter is optional when setting common properties where the default property file to update has been declared and is available to the xconfmanager utility. For example, properties stored in wt.properties and db. properties do not require this parameter. For other properties, you may need to specify the file path of the property file in this parameter. For example, updating properties in the federation.properties file requires that you enter this parameter using the codebase/federation.properties file path. Indicates the platform for which the property files are to be generated. Normally, the current platform settings determine the format of the property files. Include this parameter when you want to generate property files for a specific platform that is not the current platform. For UNIX platforms, specify -u or the following:
--unix

-u|w

or
--unix|win

For Windows platforms, specify -w or the following:


--win --undefine

-v -V

--validateasdecl

Resets the specified properties such that their values will be null (instead of an empty string) when read through a java.util.Properties instance. Turns on verbose console output, which shows full exception stack traces. Turns on debug verbose console output. This option shows full exception stack traces and additional information. Validates a specific file as a declarative XCONF file. Returns a non-zero result if file cannot be validated. Validates a list of files as declarative XCONF files. The list is contained in the specified file, where each line in the file is either a full URL or relative file path to a declarative XCONF file. Returns a non-zero result if any of the files cannot be validated.

--validatefilesasdecl

150

Windchill Customization Guide

Parameter Name

Description

--validatefilesassite

<declar_list_file> is either a full URL or relative file path to the file containing the list of declarative XCONF files you want to validate. Validates a list of files as site-specific XCONF files. The list is contained in the specified file, where each line in the file is either a full URL or relative file path to a site-specific XCONF file.
Returns a non-zero result if any of the files cannot be validated.

--validateassite

<site_list_file> is either a full URL or relative file path to the file containing the list of site-specific XCONF files you want to validate. Validates a specific file as a site-specific XCONF file.
Returns a non-zero result if file cannot be validated.

<site_xconf> is either a full URL or relative file path to the site-specific XCONF file you want to validate. Note The xconfmanager executes the following parameters in the order that they are specified in the command:
-s, --reset, --add, --remove, --undefine

This means that if the same property is set in multiple parameters, the last setting is used.
The xconfmanager always executes the -p parameter after executing the previously listed parameters for setting, resetting, adding, removing, and undefining values. This is done so that all parameter settings are included in the propagation. Additionally, the xconfmanager always executes the -d parameter after executing the previously listed parameters. This is done so that the descriptions returned include all of the parameter settings made on the command.

Viewing xconfmanager Help


On the xconfmanager command, use -h or the following parameter:
--help

to list the xconfmanager command syntax and provide a description of each parameter.

Windchill Utilities

151

Setting Property Values and Propagating Your Changes


The xconfmanager utility provides options that allow you to manage the properties in a Windchill property file as follows. You can: Set a property value to specific value by using the -s and -t parameters. Set a property value to the declared default value by using the following parameter:
--reset

Set a property value to null (instead of an empty string) using the following parameter:
--undefine

Add and remove property values from properties that are multi-valued using the following parameters:
--add --remove

Propagate the site changes stored in the site.xconf file to all affected property files using the -p parameter. Since property values are cached, propagated values are not used until you restart Windchill and your servlet engine.

Setting Specific Property Values


On the xconfmanager command, use the -s parameter to set a specific property value and the -t parameter to set the target property file for the property setting. In a given xconfmanager command, you can specify multiple -s parameters. However, all properties specified must reside in the same target property file; there can only be one -t parameter. The property values you set must conform with the specification for java.util. Properties. The following guidelines will help ensure that you set properties correctly: Use forward slashes (/) in file paths so that the platform designation is not an issue. To specify a property whose value contains characters that might be interpreted by your shell, escape them using the appropriate technique for the shell you are using. When setting passwords, specify the password in plain text and the xconfmanager utility encrypts the password as described in the Windchill Administration - Configuring Your Windchill Environment guide.

152

Windchill Customization Guide

For example, on a Windows system you can include spaces in a value by enclosing the argument with doubles quotes. For example, use the following:
-s wt.inf.container.SiteOrganization.name="ACME Corporation"

On a UNIX system, you can use doubles quotes or you can escape the space character with a backslash. For example, use the following:
-s wt.inf.container.SiteOrganization.name="ACME\ Corporation"

On UNIX, dollar signs are usually interpreted by shells as variable prefixes. To set a property value that has a dollar symbol in it, use single quotes around the argument so that it is not interpreted by the shell or use backslash to escape the dollar symbols. For example, use either of the following:
-s 'wt.homepage.jsp=$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp'

or
-s wt.homepage.jsp=\$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp

Other than escaping arguments so that the command line shell does not misinterpret them, the values should not need to be escaped any further to be compatible with XML or property file syntaxes. The xconfmanager escapes property names and values automatically if necessary. The following xconfmanager command used on a Windows system sets the wt. properties property file wt.temp property to the WCtemp directory that is under the Windchill installation directory [as defined by $(wt.home)]:
xconfmanager -s wt.temp=$(wt.home)/WCtemp -t wt.properties -p

Assuming that the command was executed from the Windows C:\ptc\Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\.. java -jar "C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar" -r "C:\ptc\Windchill\bin\.." -s wt.temp=$(wt.home)/WCtemp -t wt.properties -p Propagating xconf data to target files...

The xconfmanager creates a backup of the current site.xconf file, adds the property element for wt.temp to the site.xconf file (replacing any existing property setting that had been in the site.xconf file), and then propagates the change to wt. properties. Since property values are cached, the propagated values are not used until you restart Windchill and your servlet engine.

Windchill Utilities

153

Restoring a Property Value to Its Default Value


Use the reset parameter on the xconfmanager command to restore one or more properties to their default values. To specify multiple properties in the parameter, separate the properties using a comma. The following xconfmanager command resets the wt.temp property:
xconfmanager --reset wt.temp -p

Assuming that the command was executed from the Windows C:\ptc\Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\.. java -jar "C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar" -r "C:\ptc\Windchill\bin\.." --reset wt.temp -p Propagating xconf data to target files...

The xconfmanager creates a backup of the current site.xconf file, removes any existing property settings for the specified properties that had been in the site.xconf file, adds a ResetProperty element for each property that was specified (in this case, only wt.temp), and then propagates the change to property files that have the specified properties (in this case, only wt.properties).

Setting a Property Value to the Null Value


Use the following parameter on the xconfmanager command to set one or more properties to null values:
--undefine

To specify multiple properties in the parameter, separate the properties using a comma. The following xconfmanager command sets the wt.services.service.1160 property to null (which disables the service):
xconfmanager --undefine wt.services.service.1160 -p

Assuming that the command was executed from the Windows C:\ptc\Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\.. java -jar "C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar" -r "C:\ptc\Windchill\bin\.." --undefine wt.services.service.1160 -p Propagating xconf data to target files...

154

Windchill Customization Guide

The xconfmanager creates a backup of the current site.xconf file, removes any existing property settings for the specified properties that had been in the site.xconf file, adds an UndefineProperty element for each property that was specified (in this case, only wt.services.service.1160), and then propagates the change to property files that have the specified properties (in this case, only wt.properties).

Adding and Removing a Property Value to a Multi-valued Multi-valued Property


To add a new classpath entry (d:\MyLibaries\somelibrary.jar) to the Windchill end of the classpath specified in the wt.java.classpath property, execute the following command from the windchill shell:
xconfmanager --add wt.java.classpath=d:\MyLibaries\somelibrary.jar -p

The value d:\MyLibaries\somelibrary.jar is added to the end of the ordered set. You do not have to specify the delimiter $(path.sep) as this will be added to the property value automatically by the xconfmanager. To remove the classpath entry added in the previous example from the wt.java. classpath property, execute the following command from the windchill shell:
xconfmanager --remove wt.java.classpath=d:\MyLibaries\somelibrary.jar -p

The value d:\MyLibaries\somelibrary.jar is removed.

Tip The previous example commands do not include the target file (in the -t parameter). The target file is not needed when the property is known to be in only one existing property file.

Listing Property Information


Use the -d parameter on the xconfmanager command to list information about one or more properties. To specify multiple properties in the parameter, separate the properties using a comma. The resulting output includes the current value of each property and the location of the files where each property is set. The following xconfmanager command lists the information for the wt.home property:
xconfmanager -d wt.home

Assuming that the command was executed from the Windows C:\ptc\Windchill\bin directory, then the resulting output is:
Default product root=C:\ptc\Windchill\bin\.. java -jar "C:\ptc\Windchill\bin\..\codebase\WEB-INF\lib\install.jar" -r "C:\ptc\Windchill\bin\.." -d wt.home

Windchill Utilities

155

WARNING: Propagation of xconfs to properties was not requested. To ensure your properties are up to date, re-run with the -p option. Property information for 'wt.home': Values: - C:\Windchill Locations: - file:/C:/Windchill/site.xconf, line 9 - file:/C:/Windchill/codebase/wt.properties.xconf, line 17

Validating XCONF Files


You can use the following options to validate XCONF files: To validate a site-specific XCONF file, Use:
--validateassite

or to validate a list of site-specific XCONF files, use:


--validatefilesassite

To validate a declarative XCONF file, use:


--validateasdecl

or to validate a list of declarative XCONF files, use:


--validatefilesasdecl

The following section provides examples.

Validating XCONF Files Examples


To validate a single file as a site-specific XCONF file, run the command:
xconfmanager --validateassite=<site_xconf>

If the file is valid, then the xconfmanager will issue no output and exit with a return code of zero. To validate that several files are valid site XCONF files in one invocation, there are two options. You can use the
--validateassite

parameter multiple times. For example:


xconfmanager --validateassite=<site_xconf> --validateassite=<site_xconf>

The other option is to create a text file, add a line for each path to a file to be validated, then run the command:
xconfmanager --validatefilesassite=<site_list_file>

If all the files are considered valid site XCONF files, xconfmanager issues no output and exits with a return code of zero.
Windchill Customization Guide

156

You can validate declarative XCONF files in the same manner using the following parameters:
--validateasdecl

or
--validatefilesasdecl

Other xconfmanager Options


The xconfmanager utility provides additional options that can be useful when setting up a Windchill cluster, performing customizations, or analyzing system problems: To specify the root directory that is not the default root directory, use -r. The default root directory is the bin directory under the Windchill installation directory. The xconfmanager utility uses the root directory when relative paths for XCONF references and target file paths are used. To force propagation of all property values listed in the site.xconf, use -F instead of using -p. The -F option forces the propagation regardless of the analysis that is done to determine which files are already up-to-date. To generate properties in a format different from the current platform setting, use one of the following: For the UNIX platform format, use -u. For the Windows platform format, use -w. To turn on additional console output, use either -v (verbose) or -V (debug verbose).

Windchill Utilities

157

Formatting Property Value Guidelines


The following guidelines will help ensure that you set properties correctly on the command line when using xconfmanager: To specify a property whose value contains characters that might be interpreted by your shell (such as spaces and special characters), escape them using the appropriate technique for the shell you are using. On a Windows system, you can include spaces in a value by enclosing the argument with doubles quotes or you can escape the space character with ^. For example, use either of the following:
-s "wt.inf.container.SiteOrganization.name=ACME Corporation" -s wt.inf.container.SiteOrganization.name=ACME^ Corporation

On a UNIX system, you can use doubles quotes or you can escape the space character with \. For example, use either of the the following:
-s "wt.inf.container.SiteOrganization.name=ACME Corporation" -s wt.inf.container.SiteOrganization.name=ACME\ Corporation

In many UNIX shells, the use of a backward slash (\) escapes the following character as a literal. In most cases, using forward slashes (/) in file paths is a simple way to specify a path without having to know the intricacies of your shells command line escaping rules. On UNIX, dollar signs are usually interpreted by shells as variable prefixes. To set a property value that has a dollar symbol in it, use single quotes around the argument so that the shell does not interpreted it or use backslash to escape the dollar symbols. For example, use either of the following:
-s 'wt.homepage.jsp=$(wt.server.codebase)/wtcore/jsp/wt/portal/ index.jsp'

or
-s wt.homepage.jsp= \$(wt.server.codebase)/wtcore/jsp/wt/portal/index.jsp

Other than escaping arguments so that the command-line shell does not misinterpret them, you should not need to escape other values to be compatible with XML or property file syntaxes. The xconfmanager escapes property names and values automatically if necessary.

158

Windchill Customization Guide

Windchill Command
About the windchill Command
PTC has provided a command, windchill, to invoke Windchill actions. For example, the command can be used to stop and start Windchill, check the status of the Windchill server, and create a new shell and set the environment variables. It can also be used as a Java wrapper. In that regard, it can accept a Class file as an argument, just like Java, and execute it without a predefined environment (Windchill classes in CLASSPATH, Java in PATH, and so on). The windchill command should be used to execute any server-side Windchill Java code. This will ensure that the environment that the command is executed in is properly setup. The environment that actions are executed within, including the windchill shell action, is defined by the wt.env properties in the wt.properties file. For example, the wt.env.CLASSPATH property will set the CLASSPATH environment variable for the action that is being invoked. The windchill command is a Perl script that has also been compiled into a Windows binary executable. For UNIX systems, Perl 5.0 or greater must be installed. The windchill script assumes that Perl is installed in the standard install location of /usr/bin/perl. If Perl is not installed at this location, you can either create a symbolic link (recommended method) to the Perl install location or edit the windchill script to reference the Perl install location. To modify the windchill script, edit the <Windchill>/bin/windchill file. Locate the #! entry (for example, #!/usr/bin/perl -w) and change the Perl directory to the location where Perl is installed. The windchill command is located in the <Windchill>/bin directory. If you receive a command not found message when you execute the windchill command, add the <Windchill>/bin directory to your PATH environment variable. The syntax of the windchill command is:
windchill [args] action

You can display the help for the windchill command by executing windchill with the -h argument or with no argument. The following tables list some of the arguments and actions applicable to the windchill command. To see a complete list of the arguments, use the report generated from the help (argument).

Windchill Utilities

159

windchill Arguments
Arguments (optional)
-h, --help -v, --[no]verbose

Description Displays help and exits. Explains what is being done when a command is executed. Default is:
-- noverbose

-w, --wthome=DIR

Sets the Windchill home directory. Default is the parent directory containing the windchill script.

--java=JAVA_EXE

-cp, --classpath=PATH

--javaargs=JAVAARGS

Note On UNIX systems where you have multiple instances of Windchill installed under the same user account, settings made to WT_HOME and SQLPATH environment variables by using this -w option are overridden by any settings to these same variables in the user's .cshrc, .login, and .profile shell initialization files. The Java executable. Default is the wt.java.cmd variable value specified in the $WT_HOME/codebase/wt. properties file. Java classpath. Default is the wt.java.classpath variable value specified in the $WT_HOME/codebase/wt. properties file. Java command line arguments.

windchill Actions
Action shell start stop status version properties <resource> Description Sets up a Windchill environment in a new instance of the currently running shell. Starts the Windchill server. Stops the Windchill server. Retrieves the status of the Windchill server. Displays the Windchill installation version. Displays the properties as seen by Windchill for the given resource with substitution and other actions executed. It can be limited to a given set of keys. For example: windchill properties wt.properties lists all wt. properties
Windchill Customization Guide

[,...][?key[&key2]...]

160

Action

Description windchill properties wt.properties?wt.server.codebase lists server codebase windchill properties wt.properties?wt.env.* lists all the environment variables use by windchill shell

windchill properties generates the help report with no arguments CLASS [CLASS_ARGS] Run a Windchill class with optional class arguments. For example: windchill wt.load.Developer -UAOps

Windchill Utilities

161

Windchill Shell
About the windchill shell
The windchill shell brings up a new command shell, from the parent shell that is setup for the Windchill environment. This includes setting all environment variables defined in wt.env property in the wt.properties file. To execute the windchill shell, at the command prompt enter the following command:
windchill shell

When you are finished using the windchill shell, you can exit the shell and return to the parent shell. PTC recommends running all server-side Windchill applications, tools, and utilities from the windchill shell. Also, you can use the windchill shell to set up your development environment to use javac or Java directly.

162

Windchill Customization Guide

7
Encrypted Passwords
Encrypted Passwords .............................................................................................. 164

This chapter explains how to encrypt passwords currently stored as plain text in a file.

163

Encrypted Passwords
Background
Historically, Windchill has stored password values in plain-text in files on a file system and relied on appropriate access permissions to restrict access to those files. As of Windchill release 9.1 M050 these passwords can be optionally encrypted such that the plain-text value is no longer displayed when the file is viewed. Windchill provides out of the box property values that can be encrypted. However, you can encrypt additional values for Windchill .xconf file managed properties, as well as, values that are not managed by .xconf files. Once a value is encrypted, code must exist to properly decrypt this value prior to use or failures likely will result when the encrypted value is used by the system. If you have created an .xconf property value that is a password or is otherwise sensitive information, consider encrypting the value. If you have customized code that extends base Windchill classes or reads Windchill .properties files directly, it may require updating to ensure proper handling of encrypted values. For complete details regarding encryption, including the encryption mechanism, accompanying files, SOX compliance, and more, see the online help topic System Password Encryption Options. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions Assume you have code that adds a new .xconf property for Windchill use whose value contains sensitive information. Assume you have code that adds a property which isnt managed by the Windchill xconf framework whose value contains sensitive information. Assume you have code that reads Windchill .properties files directly to access property values.

Intended Outcome Once a property is encrypted the corresponding value for that property will no longer appear in plain text and instead, appear in an encrypted form. For example, one of the out of the box property values that Windchill can optionally encrypt is the wt.pom.dbPassword .xconf property. Prior to encryption, in <wt_home>/site.xconf this value appears as:
<Property name="wt.pom.dbPassword" overridable="true" targetFile="db/ db.properties" value="my_password my_password"/>

164

Windchill Customization Guide

In the underlying <wt_home>/db/db.properties file, this value appears as: wt.pom.dbPassword=my_password my_password After encrypting the wt.pom.dbPassword property, each value appear as:
<Property name="wt.pom.dbPassword" overridable="true" targetFile="db/ db.properties" value="encrypted.wt.pom.dbPassword encrypted.wt.pom.dbPassword"/> wt.pom.dbPassword=encrypted.wt.pom.dbPassword encrypted.wt.pom.dbPassword

The encrypted values appear in the form of: encrypted.<property_name>. Solution Use Windchills encryption mechanism to provide a secure means to store sensitive property value information. To ensure a standard practice, properties which require encryption should ideally be xconf managed, using xconfmanager set commands, if able. This ensures an easier process to encrypt the property. However, there may be design considerations or architecture issues which prevent the property from being xconf managed, such as the file not strictly containing key/value pairs or the xconf framework not being present in the classpath that can influence whether that is feasible. Prerequisite knowledge To apply this best practice, you need to have an understanding of the following: Basic development using Java Optionally Windchill xconf framework

Solution
To ensure a standard practice, properties which require encryption should ideally be xconf managed, using xconfmanager set commands, if able. This ensures an easier process to encrypt the property. However, there may be design considerations or architecture issues which prevent the property from being xconf managed, such as the file not strictly containing key/value pairs or the xconf framework not being present in the classpath that can influence whether that is feasible. Use Windchills encryption mechanism to provide a secure means to store sensitive property value information. Prerequisite Knowledge To apply this documentation, you need to have an understanding of the following:

Encrypted Passwords

165

Basic development using Java Optionally Windchill xconf framework

Solution Elements
Element WTKeyStore Type Java Class Description An interface and API to the secure location for encrypted values. This class can be used to encrypt and decrypt the values. See the Javadoc for the APIs. This class contains the primary API to encrypt a property value and a secondary means to decrypt a value. An interface and API that provides helper methods to obtain the validProperties.list properties and decrypted values. See the Javadoc for the APIs. This class contains the primary API used to determine if a property value is encrypted and decrypt it accordingly. The <wt_home>/bin/ adminTools/sip/ validProperties.list file is a list of Windchill xconf managed properties which can be encrypted. Each property is contained on a separate line as is the fully name of the .xconf managed property.

WTKeyStoreUtil

Java Class

validProperties.list

List File

166

Windchill Customization Guide

Element

Type

Description This file is how Windchills xconf framework determines what properties should be encrypted. New .xconf managed properties can be added on a new line in the file by specifying the new property name. The <wt_home>/bin/ adminTools/sip/ validIEProperties.list file is a list of Windchill xconf managed properties which can be encrypted specific to the use of out-of-process InfoEngine adapters installed on a host separate from Windchill. This file should only contain properties necessary for out-of-process IE adapters on a separate host. The <wt_home>/bin/ adminTools/sip/ EncryptPasswords.xml is an xml file containing ANT tasks that provide administrative utilities for managing encrypted passwords and the securing mechanism. This file can be used as a guide to see how to encrypt non-.xconf managed properties. You can examine the encryptWVSWorkerAgent and encryptWVSCADAgent

validIEProperties.list

List File

EncryptPasswords.xml

XML File

Encrypted Passwords

167

Element

Type

WTKeyStoreUtilWVS

Java Class

Description targets. These targets rely on WTKeyStoreUtil methods to encrypt properties that are not xconf managed but still rely on securing the property values using Windchills encryption mechanism. An interface and API that provides methods to encrypt WVS CAD and Worker configuration passwords. This class contains code that can be used as an example on how to encrypt non-.xconf managed properties.

There are two variations of the problem: 1. You want to encrypt and decrypt .xconf managed property values. 2. You want to encrypt and decrypt non-.xconf manager property values. Each of these uses the encryption and decryption mechanism for various properties. The difference is that if a property is a single valued managed .xconf property the xconf framework can be used to set an encrypted value for that property. If the property is not managed by .xconf files then a secondary means to encrypt the property needs to be coded. In both situations, code needs to specifically decrypt the property prior to its use otherwise the value will likely result in errors and/or failures as the value is encrypted.

Procedure Encrypting Static . xconf Managed SingleValued Properties


New properties that are xconf managed, have a static property name, that is the property name never changes, and contain a single value can be encrypted using the same means that Windchill relies on for the out-of-the-box encryption of these properties.

168

Windchill Customization Guide

Encrypting a Property Value. (This assumes that you have already created your new . xconf managed property): 1. Edit <wt_home>/bin/adminTools/sip/validProperties.list file and add the property name to a new line below the last file entry. This tells the encryption mechanism that this property should be encrypted. 2. From a Windchill shell run xconfmanager to set a value for this property. For example, <wt_home>/bin/xconfmanager s <name>=<value> p. This will encrypt the properyValue. In your site.xconf and companion .properties file where the value lives youll see the encrypted value and not the value entered on the command line. The actual value is stored by Windchills encryption mechanism. You can also encrypt additional .xconf properties that Windchill provides out-ofthe-box if your value for that property is sensitive information. To do so, follow the above procedure, the only difference is that the property is provided by Windchill and not created as part of a customization. Additionally, there is a secondary means to encrypt a password using the EncryptPasswords.xml file. 1. Edit <wt_home>/bin/adminTools/sip/validProperties.list file and add the property name to a new line below the last file entry. This tells the encryption mechanism that this property should be encrypted. 2. From a Windchill shell, run <wt_home>/bin/adminTools/sip/ EncryptPasswords.xml encryptPw DpropertyName=<property> -Dpassword=<password_value>. 3. For additional details see the online topic System Password Encryption Options. This encrypts the property value. However, for the value to be used properly by code that relies on the value, the code must be updated to decrypt the value prior to use. For out-of-the-box properties, Windchill decrypts properties at the appropriate interface locations. Any code that relies on this value must be updated to properly decrypt it.

Procedure Decrypting a Property Value


1. All code that extends Windchill base classes which retrieve property values must be updated if they overwrite methods that return property values. For custom code that obtain and use property values you can decrypt an encrypted value by using the following:

Encrypted Passwords

169

a. com.ptc.windchill.keystore.WTKeyStoreUtil provides an API to obtain the decrypted value of a property value if it is encrypted (see the Javadoc for complete details). The API is:
public static String decryptProperty(String property_name, String property_value, String product_root)

Where property_name is the property name for which you want to decrypt a value for, property_value is the value that may currently be encrypted and product_root is the fully qualified path to <wt_home> (or <adapater_home> for adapter installations). A code example for the usage of this API is as follows:
final String encrypted_value = encrypted.wt.pom.dbPassword; final String property = wt.pom.dbPassword; final String PATH = D:\ptc\Windchill\; String decrypted = com.ptc.windchill.keystore.WTKeyStoreUtil. decryptProperty(property,encrypted_value, PATH);

The string decrypted now contains the decrypted value and can be used properly elsewhere in the code where it is relied on.

Procedure Encrypting Dynamic . xconf Managed SingleValued Properties


New properties that are xconf managed, have a dynamic property name, that is the property name changes, and contain a single value can be encrypted using the same means that Windchill relies on for the out-of-the-box encryption of these properties. A dynamic property name could be one that is built on-the-fly in code and relies on specified derived information such as a hostname for example. Care must be taken when encrypting a dynamic property. Dynamic property encryption is based on the use of regular expressions due to the properties dynamic nature. As a result, the regular expression used to encrypt a property must ensure that it is restrictive enough to only encrypt those properties which are intended for encryption. If a too broad regular expression is used an unwanted consequence is that additional properties could be encrypted with the necessary decryption code not yet existing. Encryptring a Property Value This assumes that you have already created your new .xconf managed property: 1. Edit <wt_home>/bin/adminTools/sip/validProperties.list file and add the property name token to a new line below the last file entry. This tells the encryption mechanism that this property token will be used to encrypt

170

Windchill Customization Guide

properties matching regular expressions. For consistency, the property name token should resemble the regular expression used for matching properties. 2. It is then necessary to add to WTKeyStore.javas implementation by extending private Static List<String> getEncryptionPropertiesRegExList(final String productRoot) method. This methods implementation generates a Collection of regular expression used to match property names. If a property name matches a regular expression the property value is encrypted accordingly. This methods implementation should be overridden through a custom implementation. 3. There is additional work needed to change the <wt_home>/bin/adminTools/sip/ EncryptPasswords.xml file. Certain Ant targets within this file validate property name inputs. The validInput private target would require updating to also validate the regular expression added in step 2. The files current implementation can be examined for guidance on how to accomplish this.

Note Any code that relies on this value must be updated to properly decrypt it.
Decrypting a Property Value: 1. All code that extends Windchill base classes which retrieve property values must be updated if they overwrite methods that return property values. For custom code that obtain and use property values you can decrypt an encrypted value by using the following: com.ptc.windchill.keystore.WTKeyStoreUtil provides an API to obtain the decrypted value of a property value if it is encrypted (see the Javadoc for complete details). The API is public static String decryptProperty(String property_name, String property_value, String product_root). A code example for the usage of this API is as follows:
final String encrypted_value = encrypted.wt.federation. defaultAuthorization.machine123.subnet.net; inal String property = wt.federation.defaultAuthorization. machine123.subnet.net; inal String PATH = D:\ptc\Windchill\; String decrypted = com.ptc.windchill.keystore.WTKeyStoreUtil. decryptProperty(property,encrypted_value, PATH);

Encrypted Passwords

171

The string decrypted now contains the decrypted value and can be used properly elsewhere in the code where it is relied on. Where property_name is the property name for which you want to decrypt a value for, property_value is the value that may currently be encrypted and product_root is the fully qualified path to <wt_home> (or <adapater_home> for adapter installations).

Procedure Encrypting Non-. Non-. xconf Managed Properties


New properties that are non-.xconf managed and contain can be encrypted using Windchills encryption mechanism. However, you must create a means to encrypt the password as well as decrypt it. Encrypting a Property Value 1. You must create a means to encrypt your property value. This can be done through a Java class that can be invoked through a main() method and through modifying <wt_home>/bin/adminTools/sip/EncryptPasswords.xml. a. <wt_home>/bin/adminTools/sip/EncryptPasswords.xml contains ANT targets, encryptWVSWorkerAgent and encryptWVSCADAgent, that encrypt property values that are not xconf managed. These targets can be examined for an example on how to do this. You must create a new target that accepts parameters that invokes a Java class to do the encryption. b. The Java class that is invoked uses the parameters, a property and value, and encrypts them using the Windchill encryption mechanism. This Java class must also contain logic to property encrypt the file where this property is stored as well as placing the correct value in the Java keystore. The WTKeyStoreUtilWVS.java class contains code that is invoked by the encryptWCSWorkerAgent and encryptWCSCADAgent targets which can be examined for an example on the logic used to encrypt a file where the property value is stored. This encrypts the property value. However, for the value to be used properly by code that relies on the value, the code must be updated to decrypt the value prior to use. For out-of-the-box properties, Windchill decrypts properties at the appropriate interface locations.

Note Any code that relies on this value must be updated to properly decrypt it.

172

Windchill Customization Guide

Decrypting a Property Value All code that extends Windchill base classes which retrieve property values must be updated if they overwrite methods that return property values. For custom code that obtain and use property values you can decrypt an encrypted value by using the following: com.ptc.windchill.keystore.WTKeyStoreUtil provides an API to obtain the decrypted value of a property value if it is encrypted (see the Javadoc for complete details). The API is public static String decryptProperty (String property_name, String property_value, String product_root) Where property_name is the property name for which you want to decrypt a value for, property_value is the value that may currently be encrypted and product_root is the fully qualified path to <wt_home> (or <adapater_home> for adapter installations). A code example for the usage of this API is as follows:
final String encrypted_value = encrypted.wt.pom.dbPassword; final String property = wt.pom.dbPassword; final String PATH = D:\ptc\Windchill\; String decrypted = com.ptc.windchill.keystore.WTKeyStoreUtil. decryptProperty(property,encrypted_value, PATH);

The string decrypted now contains the decrypted value and can be used properly elsewhere in the code where it is relied on.

Customization Points
For each solution element whose usage involves the use of parameters, provide a 2nd-level section with a table that describes all of the available parameters. This can be used for API methods, XML elements, JSP tags, etc. Use the following template for the table(s): WTKeyStore.java WTKeyStore.java API: public WTKeyStore (final String product_root) Parameter product_root Default Value None Possible Values String Req? Yes Description A String that is the fully qualified path to the home location, either <wt_home>

Encrypted Passwords

173

Parameter

Default Value

Possible Values

Req?

Description or <adapater_ home>

WTKeyStore.java WTKeyStore.java API: public String get(final get(final String key) Parameter key Default Value None Possible Values String Req? Yes Description A String that is the key used to retrieve a value from the Java keystore

WTKeyStore.java WTKeyStore.java API: public put(final put(final String key, final String value) Parameter key Default Value None Possible Values String Req? Yes Description A String that is the key used to retrieve a value from the Java keystore A String that is the value to place in the Java keystore

value

None

String

Yes

WTKeyStore.java WTKeyStore.java API: public String remove(final remove(final String key) Parameter key Default Value None Possible Values String Req? Yes Description A String that is the key for a value to remove from the Java keystore

174

Windchill Customization Guide

WTKeyStoreUtil.java WTKeyStoreUtil.java API: public static String decryptProperty(final decryptProperty(final String property_value, final String product_root) Parameter Default Value property_value None Possible Values String Req? Yes Description A String that is a value which may need decryption A String that is the fully qualified path to the home location, either <wt_home> or <adapater_ home>

product_root

None

String

Yes

WTKeyStoreUtil.java WTKeyStoreUtil.java API: public static String decryptProperty(final decryptProperty(final String property_name, final String property_value, final String product_root) ) Parameter Default Value property_name None Possible Values String Req? Yes Description A String that is a property name A String that is a value which may need decryption A String that is the fully qualified path to the home location, either <wt_home> or <adapater_ home>

property_value None

String

Yes

product_root

None

String

Yes

Encrypted Passwords

175

WTKeyStoreUtil.java WTKeyStoreUtil.java API: private static String getEncryptionPropertiesRegExList(final getEncryptionPropertiesRegExList(final String product_root) Parameter product_root Default Value None Possible Values String Req? Yes Description A String that is the fully qualified path to the home location, either <wt_home> or <adapater_ home>

EncryptPasswords.xml EncryptPasswords.xml API: run Ant f EncryptPasswords.xml EncryptPasswords.xml projecthelp to see the full list of available commands and usage. Parameter wt.home Default Value env.WT_ HOME env.wt_home ../../../. The value defaults to environment variable WT_HOME, then wt_home, and finally the canonical path ../../../. Possible Values String Req? No Description A String that is the fully qualified path to the home location, either <wt_home> or <adapater_ home>.

Limitations
The properties that are encrypted need to be accessible from the server side as the encryption mechanism relies on a location that is not web accessible from a client for security purposes. There is minimal performance overhead for encrypting and decrypting a property. However, it should be noted that the underlying implementation of the Java keystore relies on a singleton pattern and access to the keystore is synchronized.

176

Windchill Customization Guide

Sample Code
Creating a Java keystore for Windchill to encrypt values:
try { WTKeyStore keyStore = new WTKeyStore(WTProperties.getLocalProperties(). getProperty("wt.home")); }catch(IOException e){ logger.error("Could not load keystore", e); }

Encrypting a value in the keystore:


String value = encrypted.wt.pom.dbPassword; String property = wt.pom.dbPassword; try { WTKeyStore keyStore = new WTKeyStore(WTProperties.getLocalProperties(). getProperty("wt.home")); // encrypt property value keyStore.put(property, value); } catch (IOException ioe) { logger.error("Error creating keystore: ", ioe); } catch (NullPointerException npe) { logger.error("Could not add the encrypted value to the keystore: ", npe); }

Decrypting a property:
String product_root = WTProperties.getLocalProperties(). getProperty(wt.home); String value = encrypted.wt.pom.dbPassword; String property = wt.pom.dbPassword; // decrypt encrypted values value = WTKeyStoreUtil.decryptProperty(property, value, product_root); /* value can now be used as normal as it will contain the decrypted value */

Additionally, a secondary means can be used to decrypt a value:


String value = encrypted.wt.pom.dbPassword; try { WTKeyStore keyStore = new WTKeyStore(WTProperties.getLocalProperties(). getProperty("wt.home")); // decrypt encrypted values String ks_value = keyStore.get(value); if(ks_value != null) {

Encrypted Passwords

177

value = ks_value; } }catch(IOException e){ logger.error("Could not load keystore", e); }

Adding a new regular expression for encrypting dynamic properties:


/* This code currently exists in WTKeystoreUtil.java. except where * where denoted NEW */ private static final String NEW_REGULAR_EXPRESSION = <your regular expression goes here>; // NEW

private static List<String> getEncryptionPropertiesRegExList(final String product_root) { List<String> propertiesList = new ArrayList<String>(); if(isCompletePropertiesListFile(product_root)) { /* * add a hardcoded list of dynamic properties that will * utilize regular expressions to determine what to encrypt * for dynamic property names. */ propertiesList.add(WT_FEDERATION_DEFAULTAUTHORIZATION); propertiesList.add(NEW_REGULAR_EXPRESSION); // NEW logger.debug("Full property list found, returning regex list of size=" + propertiesList.size()); } else { logger.debug("Full property list not found, return empty regex list"); } return propertiesList; }

This will add a new regular expression for matching property name patterns. Again, care must be taken when creating a regular expression. See Procedure Encrypting Dynamic .xconf Managed Single-Valued Properties on page 170.

Examples of Usage in Windchill Code


wt.dataservice.DSPropertiesServer.java This Java class works with DSProperties.java to decrypt property values that appear encrypted. This class uses reflection to ensure that the DSPropertiesServer exists on the server and not the client side. com.ptc.wvs.server.cadagent.Inifile.java This Java class implements a means to decrypt properties that are not .xconf file managed properties. com.ptc.windchill.keystore.WTKeyStoreUtilWVS.java
Windchill Customization Guide

178

This Java class implements a means to encrypt properties that are not .xconf file managed properties. com.ptc.windchill.keystore.WTKeyStoreUtil.java This Java class implements a means to encrypt dynamic properties that are. xconf file managed properties.

Encrypted Passwords

179

8
Customization Tutorial
Tutorial Overview..................................................................................................... 182 Create Administrator and User.................................................................................. 184 Create a Library and Document ................................................................................ 194 Allocate Database Columns for Standard Attributes.................................................... 200 Create a New Attribute Definition and Add it to the Document Type.............................. 202 As the End User, Create a Document with the new Attribute ........................................ 208 Create a Document Soft Type................................................................................... 211 Create an Instance of the New Document Soft Type ................................................... 214 Model a New Document Subclass............................................................................. 215 Create an Instance of the New Document Subclass.................................................... 221 Verify the Customizations ......................................................................................... 223 Summary ................................................................................................................ 224

This tutorial is intended for programmers who are not that familiar with Windchill.

181

Tutorial Overview
This tutorial illustrates a minimal configuration to create an environment in which you can create administrative objects (users) and business objects (attribute definitions, types and subclasses) and test them as an end user (by creating a container and document instances). This will give you some idea how to work in Windchill products, and help you ensure that your customization environment is configured correctly.

Note This tutorial is intended for programmers that are not familiar with Windchill.

Goals
In this tutorial you will: set up and navigate a Windchill test system define soft and modeled types create instances of those types confirm that their development environment is properly configured shows that Windchill UIs adapt to new type and attribute definitions

Performing these tasks will:

Assumptions
PDMLink standalone or Integral PDMLink and Windchill ProjectLink. You are using Oracle for your database storage (SQLServer will be similar). The system is installed, configured and runs. You know how to start and stop the system. You have the ability to compile Java code into the system codebase. You have access to the system database instance and permission to create new schema. You can login as the Windchill System Administrator.

Outline
1. As the System Administrator, create Organization Administrator and End User. 2. As the end user, create a Library and a document instance. 3. Allocate database columns for Standard attributes.

182

Windchill Customization Guide

4. As the Organization Administrator create a soft attribute definition and add it to the standard document type. 5. As the end user, create a document instance which will include the new attribute. 6. As the Organization Administrator create a document type and add a new standard attribute to it. 7. As the end user, create an instance of the new document soft type. 8. Model a new document subclass and deploy it. As the Organization Administrator add an attribute to it and update the layouts. 9. As the end user, create an instance of the new document subclass. 10. Verify what you have done, by searching for instances of your documents.

Customization Tutorial

183

Create Administrator and User


1. Open Windchill in your browser and login as the System Administrator.

2. Open the Navigator . 3. Select the Browse tab. 4. Select the Site context. 5. Select Utilities .

6. Under Business Administration , select Participant Administration .

184

Windchill Customization Guide

7. Select Create new user .

8. Create an Organization Administrator with the following values: Name: orgadmin First: Orville Last: Adams E-mail Address: orgadmin@acme.com Organization Click Search to select for the organization. Choose the default Organization created for your system (this was specified when the system was installed). Password and Password Confirmation: orgadmin

Customization Tutorial

185

9. Select Next . 10. Select the green + icon to add groups to the table. 11. In the Find Participant dialog select Search (leave the search field blank)

186

Windchill Customization Guide

12. Add Administrators , Attribute Administrators and Type Administrators to the Participant List , then select OK .

Note For any other organization you would not need to select Administrators . But because this is the default site organization, the organization administrator must also be a site administrator in order to manage types and attributes.
13. Select Finish .

Customization Tutorial

187

14. Select Create new user . 15. Create an End User using the same steps that you used to create the Organization Administrator user. Be sure to use the same Organization. Important: Do NOT add the End User to any groups.

188

Windchill Customization Guide

16. Verify that you have defined two users:

Customization Tutorial

189

17. Now you must declare the Organization Administrator user as an Organization Administrator. Open the Navigator . 18. Select the Browse tab 19. Select the Organizations context. 20. Select the plus icon next to your Organization . 21. Select Administrators .

22. Click the add users icon (

).

190

Windchill Customization Guide

23. In the Add Organization Administrators dialog select Search , leaving the search fields blank. Select the user you created to be the Organization Administrator, and then select Add >> and OK .

24. Return to your Organization in the Navigator and select Creators .

Customization Tutorial

191

25. Select Library Creators from the Creators pull down menu 26. Select the Add Users to the Library Creators Group icon.

27. In the Add User to the Creators Group dialog, select Search. Select the End User and select Add>>. Then select OK.

28. You should now see your user in the Creators table:

192

Windchill Customization Guide

At this point in the process, as the System Administrator, you have created an Organization Administrator and an End User. The Organization Administrator is also a Soft Attribute and Soft Type administrator. The End User is also a Library Creator.

Customization Tutorial

193

Create a Library and Document


Now as the End User you will create a Library and a document instance in that Library. 1. You must now login to the Windchill system as the end user. With some browsers you can do this in a new browser window. Others browsers may require closing the current browser first. 2. Confirm that you are logged in as the End User (not the Organization Administrator and not the System Administrator) You should see the name of the End User displayed at the top of the display:

3. Navigate to the Library context and select View all

4. As the End User, create a new Library. Select New Library.

194

Windchill Customization Guide

5. Enter the attributes for the Library, and select OK.

6. Now you will see the details for your new library.

Customization Tutorial

195

7. From the Actions menu select New, and from the sub menu New Document:

196

Windchill Customization Guide

8. In the New Document dialog, select Document in the Type drop down menu. Then Browse to select a local document to upload as the Primary Content. Change the Name of the document to Document 1. Select Finish

9. Navigate to your Librarys Folders:

Customization Tutorial

197

10. Here is the new document in its folder. Note that the Number is automatically assigned.

11. Select the View Information icon to see details about the document.

198

Windchill Customization Guide

Customization Tutorial

199

Allocate Database Columns for Standard Attributes


To create new Standard Attributes, you first need to allocate space for them in the database. You add columns per database table, per type of attribute for required data type. You can allocate more than you plan to use immediately for future growth. We will add five number columns to the WTDocument table for use later in the tutorial. 1. From the Windchill shell, run the following command line utility (the expected console output is also shown): AddColumns wt.doc.WTDocument Long=5

2. The Upgrade Schema window will automatically appear, and disappear, after executing:

200

Windchill Customization Guide

3. The five new columns have been created on the WTDocument table for the respective data type. To make use of them, you must restart the Windchill Method Server. Do that now.

Note If the server is SOX configured then you have to first de-configure the SOX and run the Add column command and again configure the server to SOX.

Customization Tutorial

201

Create a New Attribute Definition and Add it to the Document Type


1. As the Organization Administrator you will create a new attribute type and add it to the default Document type. 2. Confirm that you are logged in as the Organization Administrator.

3. To open the Type and Attribute Management , navigate to Organization Utilities . Then under Business Administration Type and Attribute Management .

202

Windchill Customization Guide

4. In Manage Types select Document .

5. From Actions select Edit .

Customization Tutorial

203

6. With the Attributes tab selected, you can now select the Create a new attribute icon and a new dialog will appear:

7. Specify a new Integer attribute with Unique Identifier sizeA. The type will be Standard. Select Next

8. Set the Datatype to Integer Number and select Next:

204

Windchill Customization Guide

9. Change the Display Name to Size A and select Finish:

10. Type and Attribute Management will now show your Attribute:

Customization Tutorial

205

11. Set the Default Value for the Size A attribute to 1, select Save:

206

Windchill Customization Guide

12. Close the Attribute panel within the dialog by selecting the collapse panel button and select OK to finish editing. You have now added the Size A standard attribute to the Document type:

13. In this case, we do not need to change, or add to, any attribute layouts. For Document, the Create layout and More attributes layout contain default groups that will automatically include your attribute in Create layouts and Info Page layouts in Windchill standard UIs. 14. Close the Type and Attribute Management dialog window.

Customization Tutorial

207

As the End User, Create a Document with the new Attribute


1. Follow the instructions above that you used to create a document, create a new document with the following attributes. Remember to do it as the End User you defined. Note: Set Size A to 101 and the Name to Document 101) then select Finish:

2. Navigate to the Details for the new document. Here you should see the Size A attribute with value 101:

208

Windchill Customization Guide

3. If you go back and look at the attributes for the first document you created, it will now display Size A, but with no value. Even though you specified a default value for sizeA. This is because the default value only applies to instances created after the attribute was defined on the type.

Customization Tutorial

209

210

Windchill Customization Guide

Create a Document Soft Type


As the Organization Administrator, you will create a new document soft type. 1. Verify that you are logged in as the Organization Administrator. 2. Select Organization Utilities Type and Attribute Management . 3. In the Type and Attribute Management window, select Document with the right mouse button and select New Sub-Type

Customization Tutorial

211

4. Specify the new document type Internal Name and Display Name, then select OK:

5. Follow the instructions above that you used to create the Size A standard attribute, to create a new Standard Attribute, for your new type, called Size B with a default value of 2.

212

Windchill Customization Guide

When you are done, your new document type will look something like this:

6. Edit your type and change the Icon for your type to netmarkets/images/ repair_failure.gif. The name of the icon is not meaningful, but it is a distinctive image that you will be able to pick out in the UI later. Note that the image automatically to the right of the path you just entered:

7. Select OK to save your changes.

Customization Tutorial

213

Create an Instance of the New Document Soft Type


1. Now, as the End User, create an instance of the new document type called Document 102. Be sure to set the Type of your document to your new type. Use the default value for Size A and set Size B to 102. Then look at the attributes for the document instance: Also note that this document instance has a unique icon (a rectangle with a red cross in it - the repair_failure.gif file that you selected in the previous step).

214

Windchill Customization Guide

Model a New Document Subclass


Now you will use Java Annotations provided by Windchills Information Modeler to create a document subclass with a new integer attribute. 1. From the Windows Start menu open a Windchill Shell and change to the src directory.

2. The new class will be in the package called com.acme. Change directory to com/acme, creating the directories if necessary.

3. Create a new source file called AcmeModeledDoc.java in the acme directory. Here are the contents for the source file:
package com.acme; import wt.doc.WTDocument; import wt.util.WTException; import com.ptc.windchill.annotations.metadata.*; @GenAsPersistable(superClass=WTDocument.class, properties={ @GeneratedProperty(name="sizeC", type=Integer.class, initialValue="3", javaDoc="Integer value to represent the size of C.")}, iconProperties=@IconProperties(standardIcon="netmarkets/images/stop.gif", openIcon="netmarkets/images/stop.gif") ) public class AcmeModeledDoc extends _AcmeModeledDoc { static final long serialVersionUID = 1; public static AcmeModeledDoc newAcmeModeledDoc() throws WTException { AcmeModeledDoc instance = new AcmeModeledDoc(); instance.initialize(); return instance; } }

Customization Tutorial

215

The name of the icon is not meaningful, but it is a distinctive image that you will be able to pick out in the UI later. 4. Now go back to the command prompt and compile your file with this command:tools class -Dclass.includes=com\acme\*

You will find the compiled class file and generated ClassInfo.ser file (that contains meta data about the new class) here: ..\Windchill\codebase\com\acme\ 5. Now you will generate the SQL scripts for your new document class. Enter this command in the Windchill Shell:tools -Dgen.input=com.acme.* sql_script

216

Windchill Customization Guide

This will generate the SQL commands necessary to create the database schema for your new subclass. You will find the generated schema here: ..Windchill\db\sql\com\acme\create_AcmeModeledDoc_ Table.sql 6. You can inspect the sql files to see what was generated. 7. Now you will create the table and associated database artifacts for your new document class. To do this, from within sqlplus, you will execute two scripts: ..\Windchill\db\sql\com\Make_pkg_com_Table.sql

Customization Tutorial

217

..\Windchill\db\sql\com\Make_pkg_com_Index.sql 8. From the Windchill Shell, login to sqlplus.sqlplus <db_user>/ <db_user_pw>@<sid> 9. At the SQL prompt execute the two scripts using full path names similar to this:@<Windchill>\db\sql\com\Make_pkg_com_Table.sql@ <Windchill>\db\sql\com\Make_pkg_com_Index.sql

10. Now execute a describe command to see the columns in the new table for your class. Note that there is a SIZEC column for the attribute you added directly to the class.describe AcmeModeledDoc You may also want count the number of rows in the table to confirm that it is empty:select count(*) from AcmeModeledDoc; 11. Restart the method server. 12. As the Organization Administrator, open the Type and Attribute Management . You will now see your modeled document subclass in the type hierarchy. Note the red flag stop icon that you specified for your subclass in the model

218

Windchill Customization Guide

13. We must now change the display name for the sizeC attribute and add it to a group in each layout. Edit your type, and change the default name of the sizeC attribute to Size C. Select Save

14. Select the Create layout. Drag the Size C attribute to the Attributes column and Save.

Customization Tutorial

219

15. Select the More attributes layout. Drag the Size C attribute to the Attributes column and Save and OK.

220

Windchill Customization Guide

Create an Instance of the New Document Subclass


1. As the End User, navigate to your Library folder and create an instance of your new document type. Type: com.acme.AcmeModeledDoc Name: Document 103 sizeC: 103

2. Browse for a file to add as content, and leave the other attributes with default values.

3. Navigate to the info page for Document 103 and note that the sizeA and sizeC attributes have the correct values.

Customization Tutorial

221

4. You now have four documents: Document 1 is an instance of the default Windchill document type Document 101 is an instance of the default Windchill document type with the new sizeA attribute that you added Document 102 is an instance of the new soft document type you added Document 103 is an instance of the new modeled document type you added

222

Windchill Customization Guide

Verify the Customizations


To verify what you have done, search for instances of your documents. 1. In the top right corner of the Windchill page, enter Document 1* in the Search box. Your results should look like this:

2. Review the Modeled Object info page for the new modeled subclass.

Note The instances of the types you created are shown with the custom icons you specified. This confirms that your new custom types are integrated with standard Windchill functionality.

Customization Tutorial

223

Summary
In this tutorial you have: Created new users including an Organization Administrator and an End User Made the Organization Administrator a Type and Attribute Administrator Made the End User a Library creator Created a library Created soft attributes definitions and soft type definitions, and instances of those types Created a modeled type and an instance of that type Confirmed that your Windchill development environment is configured to support modeling with Java Annotations and the Windchill Information Modeler Verified what you have done, by searching for instances of your documents.

224

Windchill Customization Guide

9
User Interface Technology Overview
Windchill Client Architecture Overview ...................................................................... 226 Windchill Client Architecture Common Objects Overview ............................................ 239 Javascript Functions Overview ................................................................................. 242 Adding Custom Code to all Windchill Client Architecture Pages ................................... 248

This chapter explains and gives some basic overview of the Windchill Client Architecture UI Framework. Before reading this chapter, you should be familiar with Java, JavaServer Pages (JSP), JavaServer Pages Standard Tag Library (JSTL) and Expression Language (EL).

225

Windchill Client Architecture Overview


Note Before reading this chapter, you should be familiar with Java, JavaServer Pages (JSP), JavaScript, JavaServer Pages Standard Tag Library (JSTL) and Expression Language (EL). For more information on JSTL see: http://java.sun.com/products/jsp/jstl/ For more information on EL see: http://java.sun.com/j2ee/1.4/docs/tutorial/doc/ JSPIntro7.html.

The Windchill Client Architecture provides a framework for building pages easily and consistently by providing a standard set of components and services that are configurable and customizable. The set of components includes, but is not limited to, a table, a tree, an information page, a wizard, and a dynamic javascript menu. At a lower level, these container components use other common components, called actions, action models and GUI components, to display data inside of them.

The Windchill Client Architecture is Model-View-Controller based. There are two MVC based paths available for use, a Java Builder based approach and a JSP based approach. A good deal of information about the Model-View-Controller design pattern is available on the web. For more information about MVC and the Model 2 architecture, see http://www. oracle.com/technetwork/articles/javase/servlets-jsp-140445.html.

226

Windchill Customization Guide

Java Builder based This approach is new for this release and is the recommended way of implementing tables, trees, information pages, and panels of attributes. When implementing one of these components, the configuration of the component is specified in a ComponentConfigBuilder (java file) and the data acquisition is specified in a ComponentDataBuilder (java file). For more details about this approach, refer to Java Builders on page 228. JSP and Tags based This approach was used in previous releases and should only be used for implementing wizards (create/edit) and property panels. Although tables and trees can be implemented with this approach it is not recommended. When implementing one of these components, the configuration of the component and the data acquisition is defined in a tag (from Windchill Components tag library) in a JSP. For more details about this approach, refer to JSP and Tags on page 231. Please note that at some point in the future, this approach will be deprecated in Windchill. The future vision is to have all components in the system converted to use the new Java model and controller builders. See MVC Components on page 251 for more information. When creating new customizations use the Java Builders path when possible. Many previous customizations using the Tag and TagLibs path will continue to work.

URL Strategy
In a Windchill client application starting at 10.0 the URL consists of multiple pieces. The URL still begins with the host information and the Windchill web app name. Then the URL has the following components. app/ # app/ is the address of the shell. The shell renders the header, navigator and a blank content area. The # character is the token. The complete 10.0 URL is actually made up of two URLs put together. This token marks the end of the URL for the shell and the beginning of the URL for the content that will be displayed within the content area. After the # token is the URL to the content page. It is loaded via AJAX into the content area. This is a logical content address, not a physical location. The URL after the # token is normally an MVC path to a controller, for example: ptc1/comp/recent.

ptc1/comp/ ptc1/tcomp/ ptc1/

User Interface Technology Overview

227

updates.table comp Used in the URL to specify that the builder to look up is not type based. tcomp Used in the URL to specify that the builder to look up is type-based. The URL after the # token can also take the formptc1/<objecttype>/<action name>, which mirrors the action mappings in actions.xml, for example: ptc1/report/ listUpdates After the question mark is the query-string as in any other URL. It is possible to have two query strings in the URL. When the ? is before the # token the query string parameters will be passed to the shell. When the query string is after the content address after the # token the parameters will be passed to the page in the content area.

Query Strings

Most pages need to be loaded through the shell to work correctly. Calling their URLs directly will load them without the CSS and JavaScript they need to function correctly. Every page in Windchill is now being served through a controller class. Even URLs which look like direct JSPs are being served through the LegacyController. Spring MVC is used under the covers to configure them. SeeMVC Components on page 251 for more information.

Java Builders
This approach presents several advantages over the older JSP and Tags based approach. By separating the model and controller from the JSP, we enable a more flexible and maintainable system. For example, several different JSPs can now take advantage of the same java builder. And, because, builders are now written in java, they can share attributes through inheritance. The basic steps to produce many components (table, tree, attribute panel, etc) are: Describe the component (Component Config Builder) Acquire the necessary data (Component Data Builder) Render the component (JSP)

Controller ComponentController Requests for JCA components are routed to a centralized ComponentController. This controller derives the component ID from the request parameters, and then uses Spring configuration to look up builder implementations. SeeMVC Components on page 251 for more information.
Windchill Customization Guide

228

Model Component Config and Data Builders The model for your UI is made up of the component configuration information and the data. These are created by a class or classes that implement the ComponentConfigBuilder and ComponentDataBuilder interfaces. ComponentConfigBuilder You control the rendering of your UI through a Java Class that implements the ComponentConfigBuilder Interface. This interface contains one method buildComponentConfig. This method should contain all the configuration information needed for the UI you are building. One example of a ComponentConfigBuilder might look like the following:
public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); table.setLabel("My Table"); table.setSelectable(true); table.setType("wt.pdmlink.PDMLinkProduct"); table.setActionModel("my_toolbar_actions"); table.setShowCustomViewLink(true); table.addComponent(factory.newColumnConfig(ICON, true)); table.addComponent(factory.newColumnConfig(NAME, true); table.addComponent(factory.newColumnConfig(INFO_ACTION, false)); return table; }

ComponentDataBuilder The data for your UI is created by a Java Class that implements the ComponentDataBuilder Interface. This interface contains one method buildComponentData. The object returned from this method should represent the Model for the UI and can take multiple forms. Some examples of what this method might return are ComponentData, a Persistable, a QuerySpec, any custom Java Object, etc. One example of a ComponentDataBuilder might look like the following:
public Object buildComponentData(ComponentConfig config, ComponentParams params) throws Exception { String tableId="netmarkets.product.list"; return ProductListCommand.getProducts(tableId); }

Data Sources Table and Tree components are able to make use of a new feature called DataSources. DataSources provide improved perceived table and tree performance through features like the ability to asynchronously load data and the ability to sort and scroll data on the client. To make use of this new

User Interface Technology Overview

229

asynchronous feature, your Component Data Builder should implement ComponentDataBuilderAsync for table components and TreeDataBuilderAsync for Tree components. View JSP In this approach, the JSP is simply a view, rather than a combination of all three, as it is in the JSP and Tags approach. Each component has a default view (JSP) to render out the component, however if you wish to override the default view you can call the setView() on the ComponentConfig that your ComponentConfigBuilder returns. All the view jsps should be located in codebase\WEB-INF\jsp base location. Basic Elements of the JSP When Creating a JSP view for a Java Builder, you will need to be aware of a few important jsp fragment files. The first and most important is the begin_new.jspf. This files exists in c odebase/netmarkets/jsp/util/ . The purpose of this jspf is to: Setup the model data information required by the view. Another jspf that is included is the end.jspf also located in codebase/netmarkets/jsp/util/. The purpose of this file is to: Mark that the page load is complete to allow proper functioning of the javascript within the page. An example of a jsp view might look like:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%> <%@include file="/netmarkets/jsp/util/begin_new.jspf"%> <mvc:table setPageTitle="true"/> <%@ include file="/netmarkets/jsp/util/end_new.jspf"%>

Supported Components Table Tree Information Page Attribute Panel Attribute Table Property Panel

Related Customization Documentation MVC Components on page 251 Attribute Tables on page 702

230

Windchill Customization Guide

Windchill Client Architecture Tree on page 614 Information Pages on page 891

JSP and Tags


Several tags and taglibs are delivered as part of the framework. These taglibs contain a set of handlers for including components and other common functionality into your pages. The basic steps to produce many components (table, tree, property panel, wizard, etc.) are: Describe the component (JSP) Acquire the necessary data (Data Acquisition Tags) Render the component (Component Renderer Tags)

The configuration of these phases is done by calling the tag handlers in the JSP Page. To use the tags, you need to include the components library. The following code snippet includes the library:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

Controller JSP Basic Elements of the JSP You will need to be aware of a few important jsp fragment files. The first and most important is the begin.jspf. This files exists in codebase/ netmarkets/jsp/util/. The purpose of this jspf is to: Include a tag for rendering the shell that surrounds all pages. Take care of housekeeping like: Instantiates the beans (context, clipboard, etc) Executes a command (for actions only) Includes some JS functions Creates ONE form for the page data (called mainform) Provides support for closing pop ups and refreshing the main page Another jspf that is included is the end.jspf also located in codebase/netmarkets/jsp/util/. The purpose of this file is: mark the begin and end of the content area for DHTML content switching catch exceptions and handles them if they occur within the page

User Interface Technology Overview

231

When constructing a wizard, there is a special beginWizard.jspf file, located in netmarkets\jsp\components, that should be used instead of the begin.jspf that will do essentially the same things as the begin.jspf. Component Description Tags Component description tags are the first tag included in the jsp. These generally take the form of describe*Tag. (E.g. DescribeTableTag) Component Description Tags define the columns/properties that the component will display. This happens first in a JSP since the way the data is retrieved may depend on the properties that are requested. During the component description phase the developer uses a describe tag handler that tells the infrastructure about the component they would like to display. One example describe handler is the describeTable, which might look like the following:
<jca:describeTable var="tableDescriptor" id="my.table.id" configurable="true" type="com.myco.MyType" label="${myLabel}"> <jca:setComponentProperty key="actionModel" value="my action model"/> <jca:describeColumn id="name"/> <jca:describeColumn id="nmActions" /> <jca:describeColumn id="status"> <jca:setComponentProperty key="percent" value="true"/> </jca:describeColumn> </jca:describeTable>

Structure of the example The tag contains a set of nested tags which give it some structure. There are two kinds of nested tags: setComponentProperty This tag configures the properties of its parent tag that arent exposed as attributes of the parent tag itself. This gives the infrastructure and the developer some flexibility about the metadata theyd like to be available down the road, without always requiring a tag library definition (tld) update to do so. describeColumn This tag describes a particular column that the developer wants to display. Like the parent describeTable tag, this tag accepts child setComponentProperty tags. There is also a describeProperty tag that has the same semantics when used in property panels. Underneath the covers, the describeTable tag is simply configuring a java bean that implements the ComponentDescriptor interface. The attributes that are available via the tag handler typically correspond to properties of

232

Windchill Customization Guide

the ComponentDescriptor. The ComponentDescriptor object is important to keep in mind as it comes into play later on during the data acquisition phase. The ComponentDescriptor object that the describe tag handlers build is communicated to the rest of the world via the required "var" attribute. The handler creates a scoped variable for the ComponentDescriptor object named whatever the var attribute value is. In the example above, the var attribute was mapped to "tableDescriptor", but it can be mapped to any legal JSP variable identifier. Note that this semantic for the var attribute is reused from the JSTL tag handlers. Since the ComponentDescriptor object is a scoped attribute, it can be referenced later in the page using the JSP EL as well as Java code. Subsequent tags can now refer to the descriptor using the ${varName} syntax, for example. Model Data Acquisition Tags The necessary model data is acquired through data acquisition tags. These generally take the form of get*Tag. (E.g. getModelTag) The Data Acquisition Tag will be the second phase and will come second in your jsp. This is because the Data Acquisition Tag gets the model data based on the description from Component Description Tag. In the data acquisition phase, the developer combines a component description with some additional information on how to actually go and get the data that will back the component. One example of getting a model for a table might look like the following:
<jca:getModel var="tableModel" descriptor="${tableDescriptor}" serviceName="com.myco.MyService" methodName="getMyObjects"> <jca:addServiceArgument value="${myArgument}" type="java.lang.Long"/> </jca:getModel>

Structure of the example descriptor and var The tag gets a component description by using the EL to look up the scoped "tableDescriptor" variable. The tableDescriptor variable would typically be put in the page by a previous describe tag that had a var value of "tableDescriptor". Like the describe tags, the get tags produce a java bean that is added to the page as a scoped variable named with the var attribute value. In the case of the get tags, the resulting bean is an instance of ComponentModel. What is it doing? Developers typically don't interact with the ComponentModel object produced by the get tags. Instead, the developer provides information on some lower-

User Interface Technology Overview

233

level API that the client infrastructure invokes and then transforms into a ComponentModel. The sample code above, for example, will invoke the com. myco.MyService.getMyObjects(myArgument) method, take the results, and turn these into a ComponentModel object. View Component Renderer Tags The view is rendered by the Component Renderer Tag. These generally take the form of render*Tag (E.g. RenderTableTag) This produces HTML and JavaScript based on the model data. Rendering using Component Renderer Tags is usually simple for the developer to set up. The Windchill Client Architecture provides a few render tags that take the ComponentModel produced by a get tag and turns it into HTML and JavaScript. Like the get tags, these tags uses the EL to accept scoped variable data from the page:
<jca:renderTable model="${tableModel}"/>

Structure of the example In this case, the table renderer is taking an input ComponentModel assigned to the scoped variable "tableModel", and rendering it as a table. Supported Components Wizard (Create/Edit) Table Tree Property Panel Attribute Table

Additional Resources Tag Library Documentation The Windchill Tag Library Documentation is delivered with the product and can be accessed through the UI. To locate the documentation, first enable the customization examples and tools, then browse to the customization navigation and select the tools option. Under the API documentation section of the page you will find a link to the Windchill Tag Library Documentation Related Customization Documentation Windchill Client Architecture Wizard on page 776 Wizard Processing on page 802 Building Wizards to Create a Single Object on page 823
234

Windchill Customization Guide

Building Wizards to Edit a Single Object on page 846 Attribute Panels on page 365

Common Java Services


GUI Components GUI Components are objects that define how an attribute is to be rendered. They are controlled though properties set in the Data Utilities. A GUI Component also contains a renderer that is responsible for writing out the HTML and/or JavaScript. For more information on GUI Components see Data Utilities on page 669. Data Utilities Data Utilities are delegates invoked during construction of the model that allow post-processing and/or augmentation of the data returned by data acquisition APIs. For more information on GUI Components see Data Utilities on page 669. Action Service Configuration of actions and action models that are available within the system are defined using xml files. There is an action service that reads these xml files and manages the set of actions and action models. Interaction with the service is done via the components. Developers in general would not call the service directly. For more detailed information about the action framework see Adding Actions and Hooking Them Up in the UI on page 485. Validation Service Validation of actions and properties can be done via logic encapsulated into a validator that gets executed when a component such as a action menu, table, or property panel includes that action or property. When a page including one of these components is requested, the framework will call the validation service to determine which of the actions or properties should be displayed, disabled, or hidden. The service will invoke the appropriate delegates to gather the requested status for that action or property. As a customization point, you can write a delegate that is mapped to a specific property or action, that contains logic to indicate when that element is valid to show, hide, or disable in the user interface. The validation framework is tied into the Role Based UI framework Role based support is included for most actions in the product, and customized actions can also take advantage of this capability. Role based capability is supported for global attributes created via Type and Attribute Management utility, not modeled attributes. That validation service will actually call the role based service as a first

User Interface Technology Overview

235

pass of validation. If the action or property is valid for the user based on role, the service will then invoke the appropriate delegate. See Customizing Role-Based UI Functions - Attribute Visibility on page 282 for more information. For more detailed information about the validation framework see Adding Validation Logic for Actions and Properties on page 452.

Additional Resources
Theme The Windchill theme defines the look and feel (colors, fonts, images etc). These are controlled by css. For more information on adding custom css seeAdding Custom Code to all Windchill Client Architecture Pages on page 248 for more detailed information. Windchill Javascript Functions The Windchill JSDoc Javascript documentation is delivered with the product and can be accessed through the UI. This documentation describes common JavaScript functions which are available for use in your customizations. To locate the documentation, first enable the customization examples and tools, then browse to the customization navigation and select the tools option. For more information see Enabling Customization Examples and Tools on page 237. Under the API documentation section of the page you will find a link to the Windchill JSDoc. Third Party Javascript Libraries Also installed with Windchill are two third party javascript libraries: ExtJS and Prototype. Javadoc The Windchill Javadoc is delivered with the product and can be accessed through the UI. To locate the documentation, first enable the customization examples and tools, then browse to the customization navigation and select the tools option. For more information see Enabling Customization Examples and Tools on page 237. Under the API documentation section of the page you will find a link to the Windchill Javadoc.

236

Windchill Customization Guide

Java Beans There is a set of Java Beans that is part of the framework that carries data like context and session information. The developer does not need to interact with most of the beans. See Windchill Client Architecture Common Objects Overview on page 239 for more information. Enabling Customization Examples and Tools To enable the customization examples and tools icon in the Navigator you must set a site preference. 1. Login as the Site Administrator and navigate to Site Utilities .

2. In the Utilities List Select the Preference Manager. Expand Client Customization.

3. Right click on the Client Customization Preference and select Set Preference and set the preference to Yes. Now you will see the customization icon in the Navigator.

User Interface Technology Overview

237

238

Windchill Customization Guide

Windchill Client Architecture Common Objects Overview


This section provides a basic overview of common Windchill Client Architecture objects used in the UI. These objects will be heavily used in customizations but are not likely to be extended except for NmSimpleOid.

NmCommandBean
NmCommandBean provides Windchill Client Architecture state information to other Windchill Client Architecture layers. It is the what, where, and how of the UI. It wraps the request object and adds value by parsing the parameters into related items. Once initialized by the request, the NmCommandbean can answer Windchill Client Architecture related questions. It will execute actions if they exist on the request but it won't execute actions accidentally if the page is manually refreshed and the form is resubmitted. It essentially carries the request and state information from the Tomcat VM to the Method Server VM. Interesting attributes: Context: the where. compcontext, parentContext, element context, etc are used to determine what page is displayed and where actions are launched. oids : the objects that actions or pages apply to. requestData : all the state info about the page getActionOid() : gets the object that is the target of the action. getPageOid() : gets object that the page is being displayed in this page. getViewingContainer() : gets the container that the page is displayed in.

Contains a number of helper APIs:

See the javadoc for more info api usages.

NmAction
NmAction represents a line from actions.xml which describes a page in Windchill. It is rendered as all the icons and links that one can click to make changes to the Windchill system. Each jsp page should be described by an NmAction in an xml file. The localized attributes of the NmAction can be found in the action.properties or other rbInfo files.

User Interface Technology Overview

239

NmOid
A Netmarkets version of a WTReference that hides some details of the different reference types and provides helper apis to aid in caching. Furthermore, it is the object that understands how to parse any string format from the request that represents an object in the db.

NmSimpleOid
NmSimpleOid represents a non-persisted business object. It is often to represent some item that has not been created yet or some object that wraps a persistable with more information. String parsing of the NmSimpleOid is completely handled by the code for the relevant table and actions and should be in an NmObjectUtility. See NmObject Utilities on page 562 for more information.

NmContext
NmContext represents a UI address of a page. Component is a jsp page Jsp page can include multiple components Component address includes addresses of ancestor components Context (address) of a component B is Address 1 - Address B

Example NmContext string a document residing in a folder on a projects folders page: folder$list$OR:wt.projmgmt.admin.Project2:2343$OR: wt.folder.SubFolder:7195^VR:wt.doc.WTDocument:18913!*

240

Windchill Customization Guide

Note The $, ^, and !* are reserved separator characters.

User Interface Technology Overview

241

Javascript Functions Overview


This section explains some of the common Windchill Client Architecture javascript functions. These functions are located in: Windchill\codebase\netmarkets\javascript\util\main. js

TableUtils package
Name getTableRows (parentNode) Purpose Return array of Nmcontexts for each row in a table given the outer DIV DOM node. Return array of Nmcontexts for each row in a table given a table id Return array of Nmcontexts for each row in a table given the outer DIV DOM node. Given some DOM Element, walk up the DOM tree to figure out which table this is in. Given some DOM Element, walk up the DOM tree to find the table DOM Node. Gets the hidden input field that contains the added rows of a table id. Returns String that can be tokenized. Gets the hidden input field that contains the removed rows of a table id. Returns String that can be tokenized Walk up the Dom tree finding the first <tr> tag Remove a row from a table/tree returns true/false if the dom NODE is a row in the table with the class JCA_tablerow @param node - checkbox dom node Invoked when a checkbox is clicked and it changes the row css so that it appears as highlighted. Get all the form nodes within the given

getTableRowsByID (tableID getTreeRows (parentNode)

findTableID (node)

findParentTableNodeId (node) getAddedRows (tableid)

getRemovedRows (tableid)

getParentTR (node) removeParentRow (oid, node, tableid) isTableCheckBox (node)

deSelectOtherTableRows (table id)

getFormNodes (node)

242

Windchill Customization Guide

Name

disableRow (tr) updateHeader (tableid) getUnformattedTableId (tableid)

getFormattedTableId (id)

Purpose parent node. If parentNode is unspecified, the entire document is searched. Disable all form inputs in the given row Updates row Count in Title bar. turns the outer div node id into a normal table id defined by the jsp tags table__jca.sometable__TABLE -> jca.sometable turns a div table id into the simple table id used as in the jsp tags table__jca.sometable__TABLE -> jca. sometable Updates Count of selected rows in footer. Disables the select all checbox given a table id enables the select all checbox given a table id

updateFooterCount (tableid, count, changeValue) disableSelectAllChBox enableSelectAllChBox

TreeHandler
Name toggle () Purpose The expand/Collapse function, Finds the current state of the row and changes it to the opposite. This may result in refreshing the page for legacy trees otherwise an ajax call is made to get new rows for the expand action. Will collapse a row or expand the folder row by changing its icon. Param alist is a list of tree rows, if null it will be calculated from the page. It is faster to not lookup the list of tr nodes over and over. Param action - 'c' or 'e' for the action type

collapseFolders (oid, action, list)

User Interface Technology Overview

243

asyncResponseHandler Name handleResponse (responseText, responseObject) Purpose Parses actions from an asynchronous response. Generic high level method that will delegate to all the types of responses. Gets rid of unwanted text from the response. Substrings out antying not inbetween the html comment. Can execute javascript blocks conditionally. Start/end are the html comment strings to use to find the response in.

stripText (text, divID, skipScriptEval, start, end)

rowHandler Name addRows (oidList, table_id, tableRows, params)

Purpose Add rows to a table. oidList is an array of oids to add as rows. Tablerows is an array of all current rows to improve performance of the api Params is extra params to add to the ajax request.

removeRowsFromParentTable removeRows ( rows, table_id, visually_remove ) requestHandler Name handleRequest (table_id, params) doRequest (url, options)

Remove rows from the table, rows is an array of oids.

Purpose Refreshes a table given the params Make the ajax request for the table. Used by the above method to change the url with the options set.

Other Functions in main.js Name getElementsByClassNameAndTag Purpose Returns all the children of the
Windchill Customization Guide

244

Name (className, parentElement , tag name)

Purpose parentElement that match the given Tagname and contain the className. Optimized version of getElementsByClassname so that it does not have to look at all the items in the page. refreshDivTag(id, name, url) Refreshes the contents of a div (via Ajax) when an element fires its change event. getElementHtml(params, divID, doASimilar to Prototypes updater, performs synch, url) an Ajax call (appears to ignore divID). addRows( list, tableId, refresh, doAjax- Modifies the hidden form fields of taUpdate, preventDuplicates ) bles used in wizards when users dynamically add rows to said table. Can cause the row to be added dynamically if the doAjaxUpdate is true. PJLrefreshOpener() and refreshOpener- Refreshes the parent window. Only() getClipboardItems() Family of methods for getting contents of the Clipboard as a comma delimited list.

Wizard.js functions Name handleRequest (table_id, params) doRequest (url, options) Purpose Refreshes a table given the params Make the ajax request for the table. Used by the above method to change the url with the options set. Add request params to the options based on the params list passed in. Adds all this form params to the ajax request including the params passed in. Updates the wizard step indicator images for all steps based on the current state. Updates the embedded help based on the current step. Gets the next step id.

parseAnonymousParams (startIndex, params, result) getParamString updateStepImage

updateEmbeddedText getNextStep

User Interface Technology Overview

245

Name setNextStepDirty goBack goNext setActiveStep (stepId, wizardAction)

Purpose Sets the next step in the wizard to be refreshed when displayed. Make the wizard go back one step Make the wizard go to the next step Makes a specific step active. wizardAction is an optional parameter. It indicates if the user is attempting to go back or forward in the wizard. Find the index of a step id Override what the next step id is Set a step to need a refresh should it display again Set a step to NOT need a refresh should it display again Set a step to need to be vistited again as it needs more info Set a step to NOT need to be vistited again as it does not needs more info Make a user visit a step before the wizard can be completed Make a user able to complete the wizard WITHOUT visiting the specified step id Remove a step from the list of steps Add a new step to the list of steps based on what has already happened - dynamic steps Sets the ok button to be displayed or not based on the current state. Sets the next/back button to be displayed or not based on the current state. Force the finish and apply buttons to be disabled Force the finish and apply buttons to be enabled Gets the current active step id Refreshes the current wizard step Refreshes the speicified wizard step This function takes a url and turns it into
Windchill Customization Guide

findStepIndex setNextStep setStepDirty setStepClean setStepIncomplete setStepComplete setStepRequired setStepOptional removeStep insertStep

resetOkButton resetNextBackButton disableOkButton enableOkButton getCurrentStep refreshCurrentStep refreshStep getAbsoluteUrl

246

Name goProgress stopProgress onSubmitMain handleSubmitResult

onClickValidation (evt, key)

Purpose an absolute URL. Turns on the progress indicator Turns off the progress indicator Finish the wizard by executing it on the server Handles the response of the wizard submission, the response is mostly a form result string object that tells the browser what to do. Not quite jSON yet though. To do Ajax validation when an action is clicked. The event object. The key to use in validation code Grabs every input that is styled as 'required' and checks to make sure it has a value. If any required fields do not have values, the field in question is highlighted and an alert message is displayed. This function returns a boolean that is true if the required fields are entered and false if any required field is not filled in. @param skipErrorMsg can be used to suppress the alert message

checkRequired (skipErrorMsg)

User Interface Technology Overview

247

Adding Custom Code to all Windchill Client Architecture Pages


This section explains how to add custom code to all Windchill Client Architecture pages.

Javascript files
To add any custom javascript to all the pages, you should create a new custom jsfrag file. The file needs to be deployed in: codebase\netmarkets\javascript\util\jsfrags The file can be named custom.jsfrag or any other name that is not already in use. To include the file in all pages run the combine command. This will make the js available in main.js: Windchill/bin>ant -f jsfrag_combine.xml

CSS Files
To add any custom css scripts to all the pages, modify the netmarkets. presentation.cssFiles property in site.xconf to have the necessary css files included. You can include multiple css files as a comma or semicolon separated list in the value. Note that order is important, and that the files will be loaded after the Windchill style sheets so they will properly override the default styles.
<Property name=" netmarkets.presentation.cssFiles" overridable="true" targetFile="codebase/presentation.properties" value="mypath/mycss.css;mypath/mycss2.css"/>

Customizing the Theme


It is not recommended to change any of the standard Windchill CSS style sheets. Instead, insert custom stylesheet files using the as described above. To discover which styles are defined, a good place to start is the theme file: codebase/ netmarkets/themes/windchill/xtheme-windchill.css

248

Windchill Customization Guide

Maintenance Messaging
The file codebase/netmarkets/jsp/util/begin_custom.jspf can also be used to add custom messages to the page for system maintenance or mass communication. For example, place the following code in this file:
<div style="color: sienna; position: absolute; top: 15px; z-index: 1000; left: 300px; font-size: 18px;"> <h1>This is a test</h1></div> </div>

You should place any HTML for your message within a div as in this example. You can then use css to position and style the message as desired.

Customization Points
codebase/netmarkets/jsp/util/begin_custom.jspf

User Interface Technology Overview

249

10
MVC Components
MVC Components Overview .................................................................................... 252 MVC Tables ............................................................................................................ 280

251

MVC Components Overview


This explains and introduces the different pieces of the Windchill Client Architecture UI Framework. MVC on page 252 Data Sources on page 264 JCA Components on page 272

MVC
ModelViewController (MVC) is a software architecture, currently considered an architectural pattern used in software engineering. Model represents enterprise data and the business rules that govern access to and updates of this data. View renders the model. Controller translates interactions with the view into actions to be performed by the model. For web-based clients such as browsers uses Java Server Pages (JSP ) to render the view, Servlet as the controller, and Enterprise JavaBeans (EJB ) components as the model.

MVC in Windchill
In Windchill 9.x, for JCA Clients, JSP was serving both as the Controller and View. In Windchill 10.0, we are introducing a clear separation between Controller and View for which we are using Spring MVC Framework. The primary motivation for this move is to enable our components to be both requested by and rendered to any client technologies. The MVC pattern is a well understood industry standard approach that allows us to better leverage 3rd-party technologies and training. Finally, the MVC pattern improves the maintainability and testability of our implementations. Having multiple servlets as controllers is going to be difficult to manage and hence we have adopted the Front Controller pattern approach a main servlet to make the control more manageable. DispatcherServlet acts as the Front controller. Request Handling The servlet and servlet mapping for the Web container is defined in <WT_HOME>\codebase\WEB-INF\web.xml. The below mentioned url patterns are mapped to Spring DispatcherServlet and hence will be termed as MVC requests.
<servlet-mapping> <servlet-name>MVCDispatcher</servlet-name> <url-pattern>/servlet/WizardServlet/*</url-pattern>

252

Windchill Customization Guide

<url-pattern>/servlet/ActionsMenu/*</url-pattern> <url-pattern>/servlet/RecentList/*</url-pattern> <url-pattern>/servlet/Navigation/*</url-pattern> <url-pattern>/servlet/SuggestServlet/*</url-pattern> <url-pattern>/servlet/TypeBasedIncludeServlet/*</url-pattern> <url-pattern>/servlet/UIValidationAJAXServlet/*</url-pattern> <url-pattern>/ptc1/*</url-pattern> <url-pattern>/app/*</url-pattern> <url-pattern>/gwt/*</url-pattern><servlet-mapping> </servlet-mapping> <servlet> <description>MVC Dispatcher Servlet for JCA</description> <servlet-name>MVCDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>

The web container, based on the servlet mapping configured, directs all the MVC Requests to Spring DispatcherServlet. Application Context An application Context represents the set of configuration files that are used to provide configuration information to the application and is in <WT_HOME>\codebase\WEB-INF\MVCDispatcher-servlet.xml. Imports all the Spring configuration xml files that reside at <WT_HOME>\codebase\config\mvc\ folder. Any custom

MVC Components

253

configurations should go in <WT_HOME>\codebase\config\mvc\custom.xml. Defines the handler mapping by loading the mappings specified in the properties files at <WT_HOME>\codebase\config\mvc\. Any custom handler mapping should go in <WT_HOME>\codebase\config\mvc\custom.properties.

When the web container is initialized, Spring loads the application context and hence to get effect of any configuration changes, you need to restart the server. Request Handling by Spring The client requests for a resource in the Web application. As seen in earlier section, the web container directs all MVC request to the Spring DispatcherServlet. The Spring Front controller will intercept the request and will find the appropriate handler based on the handler mapping (configured in Spring configuration files). In other words the handler mapping is used to map a request from the client to the handler. With the help of Handler Adapter, the Spring Front controller will dispatch the request to the handler.

In Windchill we use two handler mappings

254

Windchill Customization Guide

DefaultAnnotationHandlerMapping, which maps handlers based on HTTP paths expressed through the RequestMapping annotation at the type or method level. SimpleUrlHandlerMapping which maps from the URLs to request handler beans. Mappings are specified in the properties files at <WT_HOME>\codebase\config\mvc\

e.g /servlet/WizardServlet* = wizardController Once the handler is found, it will find the suitable handler adapter from the configured adapters. In Windchill we use three types of handler adapters SimpleControllerHandlerAdapter, an adapter to use the plain Controller AnnotationMethodHandlerAdapter which maps handler methods based on HTTP paths, HTTP methods and request parameters expressed through the RequestMapping annotation. GwtHandlerAdapter, an adapter to handle GWT client requests (handler is RemoteServiceServlet)

Handlers They are beans that can handle a request. An OOTB handler has been provided to handle requests to build components - com.ptc.mvc.components. ComponentController. It prepares a ModelAndView (org. springframework.web.servlet.ModelAndView) which can be handled by the DispatcherServlet To build a component, we need its description and the data to be presented. We have introduced the concept of builders, which will provide these artifacts. Component description will be represented via ComponentConfig and a ComponentConfigBuilder provides them. Component data will be represented via ComponentData and a ComponentDataBuilder provide them. ComponentConfig and ComponentData together define the component information to be shown in the UI and will be represented by ComponentDefintion. It is the Model in MVC paradigm, where as the ComponentController is the Controller.

MVC Components

255

How find a builder? A typical MVC resource to build a component will be ptc1/<handler_key>/ <componentId> where handler_key is used to map the request to a handler. componentId represent the component to be build.

ComponentController is injected with a ComponentBuilderResolver, which will find the respective builders for the given componentId. Internal artifacts of ComponentController Few notable internals of a ComponentController ComponentBuilderResolver, finds the ComponentConfigBuilder and ComponentDataBuilder for the componentId specified in the resource defaultMappings defines the default views for different ComponentConfig. ComponentParamsFactory create ComponentParams from request and response that will be made available in the builders.

256

Windchill Customization Guide

The builders provide ComponentConfig and ComponentData, from which the Model, ComponentDefinition is made. ModelAndView is populated with ComponentDefinition and the view information comes either from the ComponentConfig or from the defaultMapping provided. The artifacts that are in green are Windchill Client Architecture (e.g JCA) specific ones. The black ones are the ones provided by the component owners.

MVC Components
The components that extend/implement ComponentConfig interface are MVC components. Some of them are : TableConfig AttributesTableConfig TreeConfig AttributePanelConfig InfoConfig ColumnConfig PropertyConfig PropertyPanelConfig

MVC Components

257

MVC Builders
There are two types of Builders. The one that provides ComponentConfig are called ComponentConfigBuilder and the one that provides the ComponentData are called ComponentDataBuilder. ComponentConfigBuilder :beans that implement com.ptc.mvc.components. ComponentConfigBuilder ComponentDataBuilder :beans that implement any of the following interface com.ptc.mvc.components.ComponentDataBuilder com.ptc.mvc.components.ComponentDataBuilderAsync com.ptc.mvc.components.TreeDataBuilderAsync Specifying the componentid Typically the component ID that a builder maps to is declared using the @ComponentBuilder annotation in your builder class declaration.
@ComponentBuilder(value = {<componetId1>, <componetId2>}) public class MyBuilder extends {}

If you wish to implement your config and data builders in separate classes, then you must supply an additional ComponentBuilderType parameter to the @ComponentBuilder annotation. For config builders, this looks like:
@ComponentBuilder(value=<componetId>", type=ComponentBuilderType.CONFIG_ONLY) public class MyConfigBuilder implements ComponentConfigBuilder . {}

For data builders, this looks like:


@ComponentBuilder(value=<componetId>", type=ComponentBuilderType.DATA_ONLY) public class MyDataBuilder implements ComponentDataBuilder {}

Note that framework will throw an error if two builders will have the same component id. Spring initialization will fail in the MethodServer start up phase. If you need to override an OOTB builder, please use OverrideComponentBuilder annotation.
@ComponentBuilder(value="{compId1, compId2, compId3}") public class OOTBBuilder1 extends { } @OverrideComponentBuilder public class MyCustomBuilder1 extends { }

MyCustomBuilder1 will be mapped to compId1, compId2, compId3

@ComponentBuilder(value="{compIdA, compIdB, compIdC}") public class OOTBBuilder2 extends { } @ComponentBuilder(value="{compIdA, compIdC}")

258

Windchill Customization Guide

@OverrideComponentBuilder public class MyCustomBuilder2 extends { } @ComponentBuilder(value="{compIdB}") @OverrideComponentBuilder public class MyCustomBuilder3 extends { }

MyCustomBuilder2 will be mapped to compIdA, compIdC MyCustomBuilder3 will be mapped to compIdB

TypeBased To build certain components, you may need the Windchill Type of the context object playing a role in finding the appropriate builder. For example you have an info page and you want to populate the content based on the Windchill Type. For these scenarios, we have introduced an annotation TypeBased that can be used in the builder, to attach the builder to a specific Windchill Type. This works with ComponentBuilder.
@ComponentBuilder("compIdA") @TypeBased(value="{WTPart, WTDocument}") public class OOTBBuilder1 extends { } @ComponentBuilder("compIdA") @TypeBased(myPart) public class OOTBBuilder2 extends { }

If the context objects Windchill Type is WTPart and the componentId = compIdA, the best match builder for that component is OOTBBuilder1 If the context objects Windchill Type is a sub-type of WTPart(myPart) and the componentId = compIdA, the best match builder for that component is OOTBBuilder2 If the context objects Windchill Type is a sub-type of WTDocument (myDoc) and the componentId = compIdA, the best match builder for that component is OOTBBuilder1

While resolving to find the suitable builder, the context objects Windchill type hierarchy is respected. The attribute value can take Internal Name of the Windchill Type If the representation has domain name of the exchange container involved, then can use ${internet_domain_name} for its representation. e.g ${internet_domain_name}.DynamicDocument

MVC Components

259

Registering Builders Once the builders are created, you need to let Spring infrastructure know about it. Registration can be done either via explicit configuration or by automated scanning. Automated scanning is the preferred approach for typical use cases. 1. Automated scanning: You can configure to automatically pick up all builders within a certain package hierarchy. To do this, add the <mvc:builderscan/> configuration element to <WT_HOME>\codebase\config\mvc\custom.xml.
<beans xmlns="xmlns:mvc="http://www.ptc.com/schema/mvc" xsi:schemaLocation="http://www.ptc.com/schema/mvc http://www.ptc.com/schema/mvc/mvc-10.0.xsd"> <mvc:builder-scan base-package="com.ptc.windchill.enterprise.preference.mvc.builders"/> </beans>

The builder-scan implementation scans the entire classpath, so you should take care to be specific with the package name you declare if using scanning. (dont scan com.ptc.* for example). In addition, this means that classes that are outside your interest, but that are in the classpath and match the package hierarchy, will also get scanned. From a performance standpoint (MethodServer startup) each scan adds up time. You are requested to take advantage of the OOTB scan provided on com.ptc.mvc.builders base package. This means that all the builders that you author should be under com. ptc.mvc.builders package. If you are not using the OOTB scan, the rule of thumb is to use the scan if there are more than 10 builders available in the package. 2. a. Explicit configuration : To do this, simply add a bean declaration for the builder to the <WT_HOME>\codebase\config\mvc\custom.xml e.g <bean class=" my.builder.class.name "/> You are encouraged not to specify the bean name while declaring the bean and use @ComponentBuilder annotation in the builder for proper registration of it in the Spring bean factory.

260

Windchill Customization Guide

Abstract Builders

Creating Multiple Components


There will be requirement to build multiple components using the same builder and can have two use cases.

MVC Components

261

Use Case 1 The components are made from an already existing components/builders. For example if there is already a component with id="test.ComponentA" and another with id="test.ComponentB" and we want to get both the components in a page.
@ComponentBuilder(value="test.multi.AB", type=ComponentBuilderType.CONFIG_ONLY) public class MultiComponentBuilder extends AbstractComponentConfigBuilder{ @Override public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { MultiComponentConfig configs = new MultiComponentConfig(); configs.addNestedComponent("test.ComponentA"); //you are specifying the componentId configs.addNestedComponent("test.ComponentB"); configs.setView("/test/multi.jsp"); return config ; } }

There is no need for ComponentDataBuilder as this multiComponent by itself doesn't have any data. You need to specify a view jsp for this ComponentConfig as no default view can handle that. When you use addNestedComponent to provide a componentId, make sure that componentIds are to be handled by the same controller instance. In other words, you can have only non-type based or type based components combined together with this approach.

Use Case 2 : Here the components need to be defined and they exist together. E.g. you want property panel coming with a table. There is a need for ComponentDataBuilder. Infrastructure invokes the buildComponentData for each ComponentConfig available in the MultiComponentConfig. Its invoked in the same order it has been put in the MultiComponentConfig. You can access the rawData for the ComponentConfig that has already been processed from the ComponentParams supplying the componentId You need to specify a view jsp for this ComponentConfig as no default view can handle that.

@ComponentBuilder("test.array.PQ") public class ComponentArrayBuilder extends AbstractComponentBuilder { @Override public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { MultiComponentConfig configs = new MultiComponentConfig();

262

Windchill Customization Guide

TableConfig table1 = createTable1(); //create a table with id = component1 ...... TableConfig table2 = createTable2();//create a table with id = component2 ...... configs.addComponent(table1); //add the components configs.addComponent(table2); configs.setView("/test/array.jsp"); return configs ; } @Override public Object buildComponentData(ComponentConfig config, ComponentParams params) throws WTException { if ("component1".equals(config.getId())) { //return data for table with id= component1 } else { //return data for table with id= component2 } } }

MVC Components

263

Data Sources
Its an infrastructure for holding the data and streaming the data to the client. It will enable faster page loads as well as the potential for asynchronous server processing of results. The basic strategy is to return large result sets to clients in chunks, along with an ID that can be used to get more chunks. From the UI perspective it looks like the data is streaming into the client. This approach is different from DB paging, where we persist the big result set in the database. With DataSources, the result lives in memory only for as long as it takes the client to request it in chunks. In addition, there will be support for the server to add chunks to the datasource in a separate thread, so one can request the datasource and spin off a thread to work on getting data for it, without the client waiting.

Some of the benefits of using DataSources are Display data without overly consuming client- and server-side resources. Allow users to interact with the page while data is loading. Improve perceived performance. Provide messaging and feedback while data is loading.

Modes of Data Sources


Synchronous: This is useful if you have all the data that need to be send to client with you already and want to put the data in DataSource so that it can be send to the clients in chunks. The DataSource session takes in a list of objects that you want sent to the client and returns you a DataChunk object, which contains the first chunk of data to be send to the client. If the List of data could fit in one chunk,

264

Windchill Customization Guide

then the session doesn't even create a DataSource, it just returns you the chunk. Otherwise a DataSource is created with the data, which can be polled later for additional chunks. The DataSource will be closed so that no more data can be added. Asynchronous: In this case, you haven't got your data yet. You want to submit a task to get the data in a background thread and have the data returned to the client later. We leverage the capabilities of Executor framework provided by Java.(for more details refer JavaDoc of Executor) To create an asynchronous DataSource, the DataSource session takes a DataSourceTask which will be run by in a background thread sometime in the future. It returns a DataSourceFuture object, so that you have a way to access the DataSource information. Disabled: Not DataSource enabled

DataSources with Data Acquisition


Synchronous data sources with Synchronous data acquisition: Uses synchronous data acquisition (all data comes from the database in one chunk) and streams chunks to the client. No blank chunk is sent, so the component is not rendered until the first data chunk is received. Currently we dont support this for Tree components.

Asynchronous data sources with Synchronous data acquisition: Uses synchronous data acquisition (all data comes from the database in one chunk) and streams chunks to the client. The first chunk sent to the client contains no table data but enables the table to be rendered before a full data chunk is available. This gives the user control of the table and some of its actions sooner. The data chunks then stream in behind the blank chunk as they are processed.

MVC Components

265

Asynchronous data sources with Asynchronous data acquisition: Uses asynchronous data acquisition (data is obtained from the database in chunks) and streams chunks to the client. The first chunk sent to the client contains no table data but enables the table to be rendered before a full data chunk is available. This gives the user control of the table and some of its actions sooner. The data chunks then stream in behind the blank chunk as they are processed. In this case, we have the potential to see chunks of data rendered in the client while data is still being acquired from the database.

There is change in loading behavior in case of Trees. In Windchill 9.x, we had followed the depth first loading approach where by each node was expanded till its leaf node, before starting to expand it sibling. In Windchill 10, with DataSource, we have moved the Breadth first loading approach. Nodes are loaded per level.

266

Windchill Customization Guide

Monitoring Data Sources


DataSourceMonitor MBean can be used to monitor and configure various properties. To find the monitor From windchill shell, run jconsole Select MethodServerMain Select MBeans tab MBean located at com.ptc>WebAppContexts>${WEBAPP_NAME} >Monitors>DataSourceMonitor

MVC Components

267

MBean monitoring Parameter ActiveDataSourceCount TotalDataSourcesCreated TotalDataSourcesDestroyed Description The number of datasources that currently are active in all user sessions The total number of DataSources that have been created for all user sessions The total number of DataSources that have been destroyed for all user sessions

MBean operations Parameter cancelLongRunningDataSources Description Cancel any datasources that have been running for at least the given amount of milliseconds, in all user sessions. This will cancel both active and inactive DataSources
Windchill Customization Guide

268

MBean configuration Parameter AllEmptyPollingTimeout Description The timeout in milliseconds to wait for data chunks when the client polls for chunks and none of the ids it asked for have chunks available Controls the number of chunks a DataSource can hold before it blocks the addition of more items until something polls it or it times out. The actual number of items this resolves to is ChunkBlockingLimit*MaxChunkSize. The amount of time in milliseconds to keep idle threads alive in the DataSource task pool The maximum number of threads allowed in the DataSource task pool The amount of time in milliseconds to keep idle DataSources alive The number of feedback items a DataSource can hold before it blocks the addition of more feedback until something polls it or it times out The amount of time in milliseconds to wait to for the initial chunk of data to be available, when using asynchronous datasources. This enables components to try and display some data in the table on initial rendering if possible The maximum size of data that is returned by a DataSource for each poll. The minimum size of data for a poll. This is used when polling asynchronous datasources, to allow the server to decide whether to wait for more data or not The preferred size in bytes of the total response to a polling request. If the initial chunks do not reach this size limit, then additional chunks are added until they are over the limit. This property is

ChunkBlockingLimit

DataSourceTaskPoolKeepAliveTime

DataSourceTaskPoolSize DataSourceTimeout FeedbackBlockingLimit

InitialChunkPollingTimeout

MaxPollSize PreferredMinPollSize

PreferredSerializationSize

MVC Components

269

Parameter ResultLimit SomeEmptyPollingTimeout

Description not currently used. The total number of items that can be added to a DataSource before it fails. The timeout in milliseconds to wait for data chunks when the client polls for chunks and some of the ids it asked for have chunks available, but not all of them

Persisting the updated MBean Configuration values It is possible to persist the updated configuration values of "DataSourceMonotor" MBean in the XML. Open Jconsole and change any of the configurable value of "DataSourceMonitor" MBean. Click on the "DataSourceMonitor" MBean. From the MBeanInfo, copy the "ObjectName".

270

Windchill Customization Guide

Open the Loader MBean com.ptc > WebAppContexts >${WEBAPP_NAME} Got to its "Operation invocation" tab. Paste the "ObjectName" as a parameter for "addInjectionTargetMBean" method and click on the "addInjectionTargetMBean" button.

Now click the "Save" button. The changed value of the "DataSourceMonitor" MBean will get persisted in the <WTHome>/codebase/WEB-INF/wtWebAppMBeans.xml file. On any subsequent server restart, the last saved value will show up the in "DataSourceMonitor" MBean. Configurable properties can be reverted back to the default values by invoking "removeInjectionTargetMBean" method with the "ObjectName", followed by a save operation.

MVC Components

271

JCA Components
These are few implementation of ComponentConfig : JcaTableConfig JcaAttributesTableConfig JcaTreeConfig JcaAttributePanelConfig JcaColumnConfig JcaInfoConfig JcaPropertyConfig JcaPropertyPanelConfig

JCA Configurations for MVC


All the JCA specific Spring configurations are available in <WT_HOME>\codebase\config\mvc\jca-mvc.xml. The below snippet shows the configuration of url handler mapping. All the url pattern ptc1/comp/* are mapped to a bean with id componentController and the pattern ptc1/tcomp/* are mapped to a bean with id typeBasedComponentController.
<bean id="abstractComponentHandlerMapping" abstract="true" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> ----</bean> <bean id="componentHandlerMapping" parent="abstractComponentHandlerMapping"> <property name="mappings" ref="componentHandlerMappings componentHandlerMappings" /> ----</bean> <bean id="componentHandlerMappings componentHandlerMappings" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="properties"><props> <prop key="/comp/**">componentController componentController</prop> <prop key="/tcomp/**">typeBasedComponentController typeBasedComponentController</prop> </props></property> </bean>

Below snippet shows the definition of the bean with componentController id. jcaComponentBuilderResolver is injected as theComponentBuilderResolver defaultViewMappings property is defined to map the default views

<bean id="componentController componentController" class="com.ptc.mvc.components.ComponentController"> <property name="componentBuilderResolver" ref="jcaComponentBuilderResolver jcaComponentBuilderResolver" /> <property name="defaultViewMappings defaultViewMappings"> <map> <entry key="com.ptc.mvc.components.TreeConfig" value="/components/tree.jsp" />

272

Windchill Customization Guide

<entry key="com.ptc.mvc.components.TableConfig" value="/components/table.jsp" /> <entry key="com.ptc.mvc.components.AttributesTableConfig value="/components/table.jsp" /> <entry key="com.ptc.mvc.components.AttributePanelConfig value="/components/attributePanel.jsp" /> </map> </property> ----------</bean>

Below snippet shows the definition of the bean with typeBasedComponentController id. typeBasedComponentBuilderResolver is injected as the ComponentBuilderResolver. It respects the Windchill Type of the context object also while finding the best matched builder.

<bean id="typeBasedComponentController typeBasedComponentController" class="com.ptc.mvc.components.ComponentController parent="componentController> <property name="componentBuilderResolver" ref="typeBasedComponentBuilderResolver typeBasedComponentBuilderResolver" /> </bean>

The default handler specified will handle all the MVC url patterns that doesnt have a mapping.
<bean id="componentHandlerMapping" parent="abstractComponentHandlerMapping"> <property name="defaultHandler defaultHandler" ref="netmarketsController" /> ----</bean> <bean id="netmarketsController" class="com.ptc.jca.mvc.controllers.LegacyController LegacyController" />

ComponentConfigFactory
Builders which are ComponentConfigFactoryAware will be injected with a ComponentConfigFactory. ComponentConfigFactory provides instances of different implementations of ComponentConfig (eg table, tree etc). In JCA, the injection happens in the bean post processor and is configured in <WT_HOME>\codebase\config\mvc\jca-mvc.xml.
<bean class="com.ptc.mvc.components.support.ComponentBuilderBeanPostProcessor ComponentBuilderBeanPostProcessor"> ..... <property name="componentConfigFactory" ref="jcaComponentConfigFactory" /> <property name="infoComponentConfigFactory"> ...... </property> <property name="typedAttrLayOutFactory"> <bean class="com.ptc.jca.mvc.components.JcaTypedAttrLayOutFactory" /> </property> </bean> <bean name="jcaComponentConfigFactory" class="com.ptc.jca.mvc.components.JcaComponentConfigFactory"

MVC Components

273

factory-method="getInstance" />

JCA DataBuilders

ComponentDataConvertor
<bean id="jcaComponentDataConverter jcaComponentDataConverter" class="com.ptc.jca.mvc.components.JcaComponentDataConverter" /> <bean id="jcaComponentDataBuilder jcaComponentDataBuilder" class="com.ptc.jca.mvc.components.DefaultJcaComponentDataBuilder" scope="prototype"> <property name="componentDataConverter" ref="jcaComponentDataConverter jcaComponentDataConverter" /> </bean> <bean id="jcaComponentBuilderResolver jcaComponentBuilderResolver class="com.ptc.jca.mvc.components.JcaComponentBuilderResolver"> ...... <lookup-method name="createJcaDataBuilder" bean="jcaComponentDataBuilder jcaComponentDataBuilder" /> </bean>

The data that is available from the ComponentDataBuilder need to be processed so that it can be consumed by JCA. Running the data thorough the dataUtilities happen in this stage. JcaComponentDataConverter does that and is injected into the jcaComponentBuilderResolver.

274

Windchill Customization Guide

ComponentBuilder Resolver
If the DataBuilder specified is an instance of ConvertingComponentDataBuilder, JcaComponentBuilderResolver uses that as the ComponentDataBuilder. If the DataBuilder specified is an instance of ComponentDataBuilder, JcaComponentBuilderResolver uses that as the internal builder for the DefaultJcaComponentDataBuilder.

Generate MVC URLs


There are two types of JCA MVC urls. Non TypeBased JCA MVC url : Here the context object doesnt participate in the builder resolution process. TypeBased JCA MVC url : Here the context objects type participate in the builder resolution process.

This is generated using action definition


<action> <component name="myCompId" /> </action> <action> <component name="myCompId" " typeBased="true" /> </action> e.g <action name="CustEx_mvc_table"> <component name="carambola.mvc.table" windowType="page" />

MVC Components

275

</action> <action name="primaryAttributes" resourceBundle="com.ptc.core.ui.navigationRB"> <component name="primaryAttributes" typeBased="true" windowType="page"/> --</action>

<WT_HOME>/codebase/ WEB-INF/tlds/mvc.tld has helper functions that can be used


<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%> --<jsp:include page="${mvc:getComponentURL('part.report.multiLevelBOM')}" /> -----

JCA Components with DataSources


Table Size Limit The maximum number of rows displayed in a table is driven by this preference which has a USER level visibility. It will be applicable to all the JCA tables in the system. Currently the OOTB default value is 2,000 rows and you can vary it based on client hardware and browser type.

For trees, the limit is enforced but can be overridden by the end users. Once the tree reaches the size limit, collapse of any node will remove its children from the client, to free some resource in the client. This will happen till the number of nodes in the client comes below the size limit.

276

Windchill Customization Guide

Action Handling Actions can be broadly divided into three groups. These actions can be performed once your objects are loaded. Group 1 Actions which act only on loaded data Row-level and multi-select actions Select all, Ctrl/Shift select, Clear all View selected objects only Group 2 Actions which act on the entire data set These actions can be performed anytime (If incomplete data set, goes to the server to get all the data) Switching table views Search in table Export list Group 3 Actions which apply to the table itself These actions can be performed anytime Create actions

MVC Components

277

Cancel data loading Save table view Sorting Sorting is a special action and with DataSource, depends on the data in the client. If complete data set Sorting happen in the client If data still loading Sorting happen on the data already in the client Insert remaining polling rows into the client in sorted order If results limit was reached Sorting happen in the client Only the rows that are in the client are sorted (not the complete data set) Version column is an exception, which makes a server trip to do the sorting, but only on the data set available in the client.

Tips
Enabling Spring Logging Please add the following entry in <WT_HOME>\codebase\WEB-INF\log4jMethodServer.properties and restart the server. log4j.logger.org.springframework=DEBUG Accessing Localized Messages ResourceBundleClientMessageSource can be used to get the localized messages.
String resourceBundle = "com.ptc.test.TestResource"; ClientMessageSource messageSource = new ResourceBundleClientMessageSource(resourceBundle); String message = messageSource.getMessage(TestResource.TEST); Entry in the TestResource file @RBEntry("Test Message") public static final String TEST = "test";

If your builder extends OOTB abstract builders, take advantage of its api AbstractComponentConfigBuilder.getMessageSource(String resourceBundle) AbstractComponentDataBuilder.getMessageSource(String resourceBundle)
278

Windchill Customization Guide

AbstractInfoConfigBuilder.getMessageSource(String resourceBundle) Storing View Components All the view jsps should be placed under <WT_HOME>\WEB-INF\jsp and the value you specify while specifying it should be relative to <WT_HOME>\WEB-INF\jsp.
table.setView("/carambola/carambolaMVCExampleTable.jsp");

Requesting the Nm*Bean in JCA Component Builders


NmHelperBean helper = ((JcaComponentParams) params).getHelperBean(); NmCommandBean nmCommandBean = helper.getNmCommandBean(); HttpServletRequest request = nmCommandBean.getRequest();

Thread Safety of Builders By default the builders follow the thread safety paradigm of servlets (Singleton scope), meaning that instance variables in your builders must be thread-safe. Communication between your config and data builder APIs can be done through either the config object itself, or via ComponentParams.
public class TestComponentBuilder extends AbstractComponentBuilder{ @Override public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { Object myObject; //add information that you want to pass to data builder params.setAttribute("myKey", myObject); ----} @Override public Object buildComponentData(ComponentConfig config, ComponentParams params) throws WTException { //get the information that was put in config builder Object myObject = params.getAttribute("myKey"); ----} }

MVC Components

279

MVC Tables
MVC Tables are discussed in Constructing and Rendering a Table Using the JSP Framework on page 579.

280

Windchill Customization Guide

11
Generic UI Customizations
Customizing Role-Based UI Functions - Attribute Visibility........................................... 282 Customizing Role-Based UI Functions Action Visibility ........................................... 292 Preference Framework............................................................................................. 293 Constructing URLs .................................................................................................. 299 Offline Package Customization ................................................................................. 300 System Banner Alert Message.................................................................................. 304 Adding a Status Glyph ............................................................................................. 306

This chapter describes user interface customizations that are independent of any particular Windchill client technology.

281

Customizing Role-Based Role-Based UI Functions Attribute Visibility


Objective
You want to customize the set of UI components (actions or other UI elements) that the administrators of the site, organization or containers can manage using the role-based visibility feature.

Background
The role-based UI functionality enables administrators to optimize the number of actions presented to users, so as not to confuse users by seeing actions they dont need or use for their role. Initially this support was just for container managers (in particular, project managers). It has been extended to a concept called profiles which sets action visibility at the site or organization level. A site administrator, organization administrator or container administrator can specify which users have visibility to the actions defined. For site and organization administrators this can be done through profiles. Profiles can be created at Site>Profiles or Org->Profiles. The actions defined will be presented with their default settings, and the administrator can choose to hide those actions. The administrator can then specify which participants (users, groups, orgs) belong to the profile. All members of the profile will have that visibility. If a member is in multiple profiles, the greatest visibility is provided. At the container level, the administrator can specify the visibility based on user roles. Anyone in those roles will have the visibility specified. Container-level role visibility will override any profile in which the member might be a participant. See the Windchill Business Administrator's Guide for more details about profile and role-based visibility administration.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


The role-based visibility administration capability is turned on, that is, the preference com.ptc.netmarkets.roleAccess.enabled is set to true. The customization can be performed while the capability is turned off, but the results will not appear in the UI until the capability is turned on. The customizer can manage both OOTB UI components and customized UI components with this capability.

282

Windchill Customization Guide

Intended Outcome
When configuring visibility by roles and configuring profiles, the administrator is presented with a list of UI components that can be managed. The administrator is unable to manage the visibility for any UI components that are not included in this list. As a customizer, you have the ability to customize the list of UI components available to administrators. You can: add UI components to the list, remove UI components from the list, specify default visibility settings for UI components, change the order that UI components appear in the list, and change the labels for the UI components on the list.

At the site or organization level your intention is to manage the list presented when creating profiles:

Generic UI Customizations

283

At the container level, you are managing the equivalent list presented when configuring visibility by roles:

284

Windchill Customization Guide

Solution
Modify the roleaccessprefs.xml file (and associated files as needed).

Prerequisite Knowledge
To achieve this objective, you need to have an understanding of the following: The behavior of user roles in Windchill The administration of ad hoc access control policies in Windchill The actions framework in the Windchill client architecture The navigation framework in the Windchill client architecture The management of XML file customizations The management of RBINFO file customizations

Note The Additional Resources section below includes references to many or all of these subjects.
Solution Elements Element *actionModels.xml

Type XML

*actions.xml

XML

Description Files which define the models where actions are used. If an action is not already defined in a model, one will need to be created for the validation code to find the action and properly set visibility. actionmodels.xml is located in <Windchills>/codebase; other *actionmodels.xml files are generally in <Windchill>/codebase /config/actions Files where actions and other UI components are defined. Actions are optionally given a uicomponent value. actions.xml is located in <Windchill>/codebase; other *actions.xml files are generally in <Windchill>/codebase /config/actions. File for assigning default visibility to UI components. Setting items in this file can make them not appear at all for the site or containers. Whether or not the container manager can override the default value can also be changed here.

roleaccessprefs.xml

XML

Generic UI Customizations

285

Element

Type

Description Located in <Windchill>/codebase.

roleAccessResource. XML rbInfo

Defines the labels to provide in the Uis for the actions or UI components. Located in <Windchill>/wtCustom/ com/ ptc/netmarkets/ roleAccess/.

In actions.xml (and all *actions.xml files), an action can be assigned a uicomponent attribute value. The uicomponent attribute provides a name for a UI component that can be referenced from the roleaccessprefs.xml and roleAccessResource.rbInfo files. Multiple actions can use the same uicomponent value; this provides the ability to manage those actions as a single UI component. If an action does not have a uicomponent, then the action name can be used to reference it as a UI component instead. However, in this case it cannot be grouped with other actions into a single UI component. The roleaccessprefs.xml file consists of a <uics> element containing several elements (or sections) that correspond to the primary tabs in the Windchill user interface. For example, the <project> section corresponds to the Project tab. Each section contains zero or more <uic> elements, each representing a UI component whose visibility within that tab can be administered. Each UI component, specified with the name attribute of the <uic> element, can appear in one or more sections. This allows the default visibility settings for that UI component to be assigned independently for different tabs. The roleaccessprefs.xml file applies to the UI component lists for visibility administration based both on profiles (at the site and organization levels) and on roles (at the container levels). However, the <global> section applies only to visibility administration using profiles. If a UI component is not tied to a specific tab (such as is the case with the Search link in the Windchill UI header) or the UI component is a first-level tab itself, it should be listed in the <global> section of roleaccessprefs.xml. Each UI component must have an entry in roleAccessResource.rbInfo that provides a user-friendly label for that UI component. These labels are used for the UI components in the lists that are presented to the administrator when configuring visibility. In this file the resource entry constant identifies the UI component; it
Windchill Customization Guide

286

must match either the uicomponent from the action definition or the action name if the action has no uicomponent. The resource entry value provides the user-friendly label.

Note Your UI component label should be a verb phrase. If your action/UI component name is not already a verb phrase, place View in front, for example View Team Page.
Procedure Making an Action Available to Visibility Administration In this example, you provide the administrator with the ability to manage the visibility of the Create Folder action in the Project, Program, Product, and Library tabs.

Note This example assumes that the Create Folder action is not already available for role-based visibility management; in the actual product, it is available out of the box.
1. Add a new <uic> to the roleaccessprefs.xml under the sections <project>, <program>, <product>, and <library>:
<uic name=PROJECT_CREATE_FOLDERS order=00 enabled=true defaultAll= true defaultManager=true defaultGuest=false managerEnabled=true guestEn abled=false/>

Note See the section on the uic element below for attribute descriptions. Note For actions that are valid for multiple tab types, put the entry under all the sections you want it to affect.
2. In roleAccessResource.rbInfo, add a new resource entry for the action display name:
31.value=Create Folders 31.constant=PROJECT_CREATE_FOLDERS PROJECT_CREATE_FOLDERS

Regenerate your bundles. The name of the uic should be the same as the constant for the entry in the resource bundle. 3. In <Windchill>/codebase/actions.xml, modify the create folder action by: adding the attribute uicomponent=PROJECT_CREATE_FOLDERS
<action name= folder_create checkaccess=true uicomponent= PROJECT_CREATE_ FOLDERS >

Generic UI Customizations

287

Caution Follow best practices in backing up your XML files when customizing them.
4. Restart the servlet engine and the method server. Steps 1 through 3 above can be performed in any order. Note that PROJECT_CREATE_FOLDERS is used for the uic name, the resource entry constant (but without the quotes), and the action uicomponent. It is necessary for all three of these items to share the same value in order to tie the customized behavior together. Upon completion of this procedure, an administrator can now configure the visibility to the Create Folder action under the Project, Program, Product, and Library tabs, based on profiles defined at the site or organization level, and based on roles at the container level. Customization Points

uic Element
Each UIC in roleaccessprefs.xml represents a UIComponent or action to be controlled. Parameter Default Possible Req? Description Values Value name Y n/a string The name of the UI component. This must match the value of the uicomponent (or name) attribute on an action element in actions. xml. This must also match the value of a resource entry constant in the resource bundle. Integer N order n/a The position of this UI component in the wizard. UI components with lower numbers are placed before those with higher numbers. true N enabled true | false Whether or not this uicomponent will be shown in the wizard and utilized by the system. true N defaultAll true | false The default visibility value for All Members. N defaultMan- true true | false The default visibility value for ager Project Managers.
Windchill Customization Guide

288

Parameter

Default Value

Possible Values

Req? Description

defaultGuest true

true | false

Note The permissions are a union of all permissions across all roles; if you set defaultManager to false; you should also defaultAll to false, otherwise managers will still have access through the ALL_MEMBERS role. The default visibility value for people in the Guest role. Note Guests are not technically members of the Project; they are not unioned with the ALL_MEMBERS role. Whether or not this uicomponent can affect the manager role. Do not change this value in out-of-the-box UICs. For customized UICs, you may choose your own setting. Whether or not this uicomponent can affect the guest role. Do not change this value in out-of-the-box UICs. For customized UICs, you may choose your own setting.

managerEna- true bled

true | false

guestEnabled true

true | false

Generic UI Customizations

289

Making a Customized Tab Available to Visibility Administration


Making a customized action available to visibility administration is essentially the same procedure as making an out of the box action available. A tab, however, cannot be managed by container administrators (configuring role-based visibility). Therefore you can only make a customized tab available to site and organization administrators for configuring visibility profiles. This means you can add a <uic> element for the tab only to the <global> section of roleaccessprefs.xml. For example, assume that you have already created a customized tab, and have an associated <MyTab>actions.xml file. You can add the tab to the list for profilebased visibility administration as follows: 1. Add a new uic element to roleaccessprefs.xml under the <global > section with a unique name, for example, CUSTOMIZED_TAB.
<uic name= CUSTOMIZED_TAB order=190 enabled=true defaultAll=true/>

2. Associate the appropriate actions in action.xml with the UIComponent.


<ooleanpe name=customization > <action name=list2 uicomponent= CUSTOMIZED_TAB > <command windowType=page/> </action>

3. Add a new entry to roleAccessResource.rbInfo with a constant that is the same as the uic name. The value is what will be displayed in the profile actions UI.
40.value=View View Customized Tab 40.constant=CUSTOMIZED_TAB constant=CUSTOMIZED_TAB

Regenerate your bundles. 4. Restart the servlet engine and the MethodServer.

Assigning One uicomponent to Multiple Actions


If you want to tie one UI component to multiple actions, you need to specify the uicomponent attribute for each of those actions, using the same value. For example, the procedure described in theProcedure Making an Action Available to Visibility Administration on page 287 creates a UI component called PROJECT_CREATE_FOLDERS associated with the folder_create action. You can assign the list_create_folder action to the same UI component by specifying the uicomponent attribute for that action in actions.xml as follows:
<action name=list_create_folder uicomponent=PROJECT_CREATE_FOLDERS ajax=row>

As a result, the Create Folders entry in the Configure Roles and Create Profile pages will affect the visibility for both folder_create and list_create_folder actions.

290

Windchill Customization Guide

Changing the Labels for a UI Component You can alter the label used for a UI component in the Configure Roles or Create Profile pages, without making any other changes to that UI component. Simply change the associated resource entry value in the roleAccessResource.rbInfo file, and regenerate your bundles. For example:
31.value=Create Create Folders My New Label 31.constant=PROJECT_CREATE_FOLDERS

Sample Code Examples of Usage in OOTB Code Example of multiple actions using the same uicomponent: The Team pages in Product/Project/Library share the same code, but each action is defined separately for each object. Each action has the same uicomponent of PROJECT_TEAM. This allows the same resource (rbInfo) entry to be used, and helps to minimize the size of the action display table in the Create Profile page. PROJECT_TEAM still needs to be defined in roleaccessprefs.xml for each tab type in which it is used, and different defaults can be set for each. Additional Resources

Related Customization Documentation


Managing Customizations on page 112

Other Related Windchill Documentation


Windchill Business Administrator's Guide Role-Based Visibility Administration Windchill Business Administrator's Guide Access Control (ad hoc policies)

Generic UI Customizations

291

Customizing Role-Based Role-Based UI Functions Action Visibility


Role-based action visibility in Windchill is implemented only in JSP pages. See the Customizing Role-based Visibility on page 528 section in Adding Actions and Hooking Them Up in the UI on page 485 for more information.

292

Windchill Customization Guide

Preference Framework
The Preferences Framework is based on the principle that a unique preference consists of the following attributes: Parent Node (or root node if at the top of the hierarchy) Preference Node (usually associated as a group of similar preferences) Preference Key

Together these attributes form a unique key structure of parent/node/key. This unique key structure will be referred to as the fully qualified preference key. To separate individual user and group preferences for the same fully qualified preference key, a context is applied to the preference. The context consists of the following elements: Macro a constant defining the type of context (see below) (optionally) Descriptor text defining the name of the context. These elements are placed together with a : to form the Preference Context. The fully qualified preference key when placed together with a context will form a unique row in the database table, allowing users, and other divisions to have individual preferences.

Preference Macros
The wt.prefs.WTPreferences class defines the following types of Preference Context Macros: USER_CONTEXT - the context for individual users DEFAULT_CONTEXT - the context for the system default (shipping) values CONTAINER_CONTEXT - a context used in the container hierarchy CONTAINER_POLICY_CONTEXT - a container context that is enforced as a policy DIVISION_CONTEXT - the context used for any scopes defined in addition to the default, container, and user scopes DIVISION_POLICY_CONTEXT - a division context that is enforced as a policy

Generic UI Customizations

293

Setting the Hierarchy


The delegates.properties value wt.prefs.delegates.DelegateOrder controls the hierarchy in which delegates are called. For each level in the hierarchy there should be an entry in this property. The customized entries should appear as DIVISION_CONTEXT. For example, in the out-of-the-box hierarchy, there is a division scope called Windchill Enterprise, and the out-of-the-box wt.prefs. delegates.DelegateOrder property value is: $DEFAULT,$CONTAINER,$DIVISION:WindchillEnterprise,$USER In this value, there is no DIVISION_POLICY_CONTEXT defined since DIVISION_POLICY_CONTEXT and DIVISION_CONTEXT are related and are at the same level in the preference hierarchy. Similarly, the CONTAINER_POLICY_CONTEXT need not be included. Entries are designated differently only when storing and retrieving preferences internally. For more details on correctly naming delegates, see the delegates.properties file. If wt.prefs.delegates.DelegateOrder has been removed from the delegates. properties file, Windchill uses the following: $DEFAULT,$CONTAINER,$USERSetting Preferences Edit the file Windchill/loadFiles/preferences.txt. This file is used to put the system values into the database. Note that you dont put quotes around the strings unless you actually want quotes persisted as part of the preference. Syntax:
PrefEntry~keyName~default value~fullyQualifiedNodePath

Example:
PrefEntry~fileOperationType~ASK~/wt/content

Getting Preferences
You can get a preference by first navigating the preferences tree to the proper node, then setting the context for that particular user, then getting the value for that key. Example:
// returns an instance of the top node in the Windchill preference "tree" Preferences root = WTPreferences.root(); // returns the preference node at that path Preferences myPrefs = root.node( "/wt/content" ); ((WTPreferences)myPrefs).setContextMask (PreferenceHelper.createContextMask() ); // get( ), gets the value for that // preference key String prefValue = myPrefs.get( "fileOperationType", "SAVE" );

294

Windchill Customization Guide

Clearing a Preference
There is a big difference between "clear" and "remove". Assuming there are no division-level defaults or policies, if you "clear" a user preference by setting the value to be the empty string "", then the value returned will be ""; but if you "remove" the user-level preference, then the value returned would be system default value. In most cases you will want to remove the user-level preference and not clear it, giving the user the upper hierarchical preference as their default. Example:
Preferences root = WTPreferences.root(); Preferences myPrefs = root.node( "/wt/content" ); ((WTPreferences)myPrefs).setEditContext (PreferenceHelper.createEditMask()); ((WTPreferences)myPrefs).setContextMask (PreferenceHelper.createContextMask()); String prevValue = myPrefs.remove("fileOperationType");

Preference Registry
The preference registry is a way to take a cryptic name like a preference and provide a localized series of data about it. This registry is in the form of rbInfo files. Anyone adding preferences to the system will have the option of adding this localized information to the Preference Registry. Adding a preference to the preference registry To add a Preference to the Preference Registry, you need to edit the file <Windchill>src/wt/prefs/registry/prefRegistry.rbInfo and for the Preference you want to add, add at least:
DISPLAY_NAME DESCRIPTION DEFAULT

The format is as follows:


/node-name/key-name% [ ]tag.value=

Where /node-name is the name of the node (for example /wt/workflow), /key-name is the name of the key under the node (SortOrder) and % [ ]tag is one of the tags mentioned above (% [ ]DISPLAY_NAME).

Generic UI Customizations

295

Creating a Preference The creation of a preference is done through an XML load file. When creating a preference the following pieces of information need to be determined: Unique preference name Visibility: if the preference will appear in the preference manger UI and visible at what contexts: SITE, ORGANIZATION, CONTAINER or USER . Preference category: The category the new preference will appear under in the Preference Management utility. Display name: This is the Name column in the Preference Management utility string in the form <RBINFO>:< RBINFO key> Description: This is the Description column in the Preference Management utility string in the form:
<RBINFO>:<RBINFO key>

Long Description: This description is displayed in the Edit Preference UI, gives a more detailed description including the expected values. string in the form <RBINFO>:<RBINFO key> Default value Value header

In the example below, we will create a new preference named /com/ mycompany/MyNewPreference along with an associated preference category to appear in the Preference Manager UI. 1. Create a resource bundle for labels used for your new preference. Labels are needed for display name and description of preference category which the new preference will be visible under in Preference Manager UI. Labels are also needed for the display name, description and long description of your preference. Create the file mycompanyPreferenceResource.rbInfo in package com.mycompany.pref. In this example, this file would be added to the <Windchill>/src/mycompany/pref directory.
ResourceInfo.class=wt.tools.resource.StringResourceInfo ResourceInfo.customizable=true ResourceInfo.deprecated=false # Preference Category labels MyNewPreferenceCategory.displayName.value=My Preference Category MyNewPreferenceCategory.description.value=Preference Category for my custom preferences. # Preference Definition labels MyNewPreference.displayName.value=Display name of preference /com/my company/ MyNewPreference

296

Windchill Customization Guide

MyNewPreference.description.value=Description of preference /com/myc ompany/ MyNewPreference. MyNewPreference.longDescription.value=Long description of preference /com/mycompany/MyNewPreference.

2. Build the resource bundle by executing the following command from a windchill shell:
ResourceBuild com.mycompany.pref.mycompanyPreferenceResource

3. Restart the servlet engine and the MethodServer. 4. Create Preference load file: createMyNewPreference.xml. It will contain a definition for the new preference category and new preference definition.
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd"> <NmLoader> <csvPreferenceCategory handler="wt.preference.LoadPreference.createPref erenceCategory"> <csvname>CUSTOM_PREFERENCE_CATEGORY CUSTOM_PREFERENCE_CATEGORY</csvname> <csvparentName></csvparentName> <csvdisplayName> com.mycompany.pref.mycompanyPreferenceResource: MyNewPreferenceCategory.displayName </csvdisplayName> <csvdescription> com.mycompany.pref.mycompanyPreferenceResource:MyNewPreferenceCategory. description </csvdescription> </csvPreferenceCategory> <csvPreferenceDefinition handler="wt.preference.LoadPreference.createPref erence Definition"> <csvname>/ / com/mycompany/ com/mycompany/MyNewPreference MyNewPreference</csvname> <csvvisibility>USER USER</csvvisibility> <csvcategoryName>CUSTOM_PREFERENCE_CATEGORY CUSTOM_PREFERENCE_CATEGORY</csvcategoryName> <csvdisplayName>com.mycompany.pref.mycompanyPreferenceResource:MyNew com.mycompany.pref.mycompanyPreferenceResource:MyNew Preference.displayName Preference.displayName</csvdisplayName> <csvdescription>com.mycompany.pref.mycompanyPreferenceResource om.mycompany.pref.mycompanyPreferenceResource: MyNew Preference. Preference description </csvdescription> <csvlongDescription>com.mycompany.pref.mycompanyPreferenceResource com.mycompany.pref.mycompanyPreferenceResource: MyNewPreference. MyNewPreference longDescription </csvlongDescription> <csvdefaultValue>Default Default Value</csvdefaultValue> Value <csvhandler>com.ptc.windchill.enterprise.preference.handler. com.ptc.windchill.enterprise.preference.handler. StringPreferenceValue Handler:4000</csvhandler> Handler:4000 </csvPreferenceDefinition> <csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.set ClientDefinitionLink">

Generic UI Customizations

297

<csvname>/ / com/mycompany/ com/mycompany/MyNewPreference MyNewPreference</csvname> <csvclientName>WINDCHILL WINDCHILL</csvclientName> </csvLinkPreferenceClientDefinition> </NmLoader>

5. Load the preference category and preference definition using the following command:
windchill wt.load.LoadFromFile -d <full path>/createMyNewPreference.xml

Deleting a Preference The deletion of a preference is also done through the use of an XML load file. Using the example from the Creating a Preference section on page 920, we will delete the preference /com/mycompany/MyNewPreference. The deletion of the preference will also remove any preference instances which may have been set for this preference in the UI. 1. Create an XML file, deleteMyNewPreference.xml, containing the following definition to specify the deletion of the preference.
<?xml version="1.0"?><!DOCTYPE NmLoader SYSTEM "standardX10.dtd"> <NmLoader> <csvDeletePreferenceDefinition handler="wt.preference.LoadPreference.deletePreferenceDefinition"> <csvname>/ / com/mycompany/ com/mycompany/MyNewPreference MyNewPreference</csvname> </csvDeletePreferenceDefinition> </NmLoader>

2. Delete the preference definition using the following command:


windchill wt.load.LoadFromFile -d <full path>/deleteMyNewPreference.xml

298

Windchill Customization Guide

Constructing URLs
Information on constructing URLs is contained within the sections on specific components. MVC Components on page 251 Windchill Client Architecture Action Framework Overview on page 486 Constructing Wizards on page 775 Defining Menus on page 540 To add a link to the navigator see the Creating a Link topic in the Windchill Help Center.

Generic UI Customizations

299

Offline Package Customization


Objective
You want offline packages exported fromWindchill to display your company's brand identity.

Background
Offline packages exported from Windchill are zip files containing the exported files. Along with the exported content, an offline viewer is provided which allows users to browse the contents in their web browser. By default, offline packages exported from Windchill display the Windchill logo and brand in the header of the offline view. This document describes how to update certain files on your installation server to have the exported packages display your companys brand identity.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Utilizing this solution will change the format of all packages exported from the server. It will affect all users and organizations that make packages from that server. Intended Outcome The offline view in exported packages display updated brand identity information for your company.

Solution
Update the CSS in the static resources zip file to style the header of the offline view.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Cascading Style Sheets. This guide assumes a good knowledge of how to specify and write new CSS styles, without going into the specifics of how to write correct CSS. Knowledge and access to the Brand Identity standards for your company.

300

Windchill Customization Guide

Solution Elements
Element resources.zip Description This zip file contains the static elements provided in the resources folder in every package generated from the installation server. This file is located in the % WT_HOME%\codebase\com\ptc\netmarkets\wp\ixb directory of your server. CSS Style Contained within the resources.zip file, this Sheet CSS style sheet contains the rules which control the look and feel of the offline view. HTML File The HTML file which is loaded at the top of every page. GIF graphics The background image of the header file GIF graphics Transparent GIF of the Windchill logo. file Type Zip file

wpofflinestyles.css

head.html header.gif logoWC.gif

Procedure update the CSS Styles of the Header 1. Locate the resources.zip file. It is located in the \codebase\com\ptc\netmarkets \wp\ixb directory, relative to the root of your Windchill installation. Normally, you can discover the root by using the environment variable WT_ROOT. 2. Make a backup copy of the original resources.zip before you begin. 3. Unzip the resources.zip to an empty folder on your hard drive. 4. Inside the resources folder, you will find a file named wpofflinestyles.css. Open this file in your favorite CSS editor, or text editor. 5. Edit the styles to customize the look of the brand identity header, using the style rules listed below in the Customization Points on page 302 section. 6. You may need to add updated graphic files or other resources to the resources directory to support your updated styles. 7. You may add links to external resources in the pageHeaderActions div. These links by default appear in the upper right corner of the page. For example, a link to your corporate website. 8. To test your CSS styles, load the resources/head.html file in your browser. Windchill supports Internet Explorer 6, and Firefox 2, be sure to test in both to ensure your styles will work. Note that the generateTabs() JavaScript function will not work correctly while testing in this manner, and errors related to it can be ignored.

Generic UI Customizations

301

9. Once you are satisfied with the look of the header, update the resources.zip file with the updated resources folder and files from your working folder. Make sure the file paths are correct inside the zip file all files should have the path resources\. 10. Test to be sure packages are generated correctly by making some experimental packages from the running server and viewing them offline. Customization Points CSS rule .pageHeader

.wncApplLogo .applLogo

Default Value Dark teal background with Windchill background image (header.gif) and a dark green bottom border. logoWC.gif Height: 55 pixels.

Description Defines the border, background image and color of the header.

.pageHeaderActions(CSS White text links. rule in wpofflinestyles. css) pageHeaderActions(div in Delivered empty head.html) Limitations

Defines logo graphics file. Defines the height of the logo div, normally shown in the upper left corner of the page. Defines the style of links and text normally in the upper right corner of the page. Links can be added to this div.

Updating the resources.zip file in this manner affects every offline package created by the system. It is not currently possible to apply these changes to one package and not to another. Modification of packages after they are created is not possible on the server.

302

Windchill Customization Guide

Sample Code
.pageHeader { border-bottom: 1px solid #20313d; background-image: url(header.gif); background-color: #40637A; background-repeat: no-repeat; } .wncApplLogo { background-image: url(logoWC.gif); } .applLogo { background-repeat: no-repeat; height: 55px; background-position:34px;}

Generic UI Customizations

303

System Banner Alert Message


You can create a system wide banner message that will display on all the pages within the Windchill application.

Turning on the alert banner feature


1. Put the following line code into windchill\codebase\netmarkets\jsp\util
\begin_custom.jspf \begin_custom.jspf
<%@ include file="/netmarkets/jsp/util/banner_custom.jspf"%>

2. Restart Tomcat.

Displaying the alert message on the top of Windchill UI pages


Write the alert message with html format into the following file: <WT_HOME>\codebase\netmarkets\jsp\util\banner.txt For example:
<style type="text/css"> .bannertable {border: 2; background: #E7E8E0; text-align: center; width: 100%;} .bannerfont {color: #BB0000; font-weight: bold; font-size: 1em;} </style> <TABLE class=bannertable cellpadding=0 cellspacing=5> <TR> <TD> <FONT class=bannerfont> <center> <table border=1> <tr bgcolor=white> <td width=800> <font color=red size=+1> <center> Windchill maintenance alert: Windchill server will be shut down soon for maintenance. </center> </font> </td> </tr> </table> </center> </FONT> </TD> </TR> </TABLE>

304

Windchill Customization Guide

Removing the alert message from Windchill UI page


Set windchill_home\codebase\netmarkets\jsp\util\banner.txt as empty file. Turning off the alert banner feature 1. Set windchill\codebase\netmarkets\jsp\util \begin_custom.jspf as an empty file 2. Restart Tomcat.

Generic UI Customizations

305

Adding a Status Glyph


Users want a visual way to quickly see the state of an object. This section describes the different out of the box status glyphs and how to display them for a given object. Terminology The following specialized terms are used in this section: Component Builder : A Java class used to build a UI component, i.e. a UI widget. These builders define properties of your component to tell the infrastructure how to display them. Status Family ID : A string used to reference a status glyph.

Solution
Developers can include status glyphs in their tables and information pages directly from a ComponentBuilder class. Prerequisite Knowledge To achieve this goal, you need to have an understanding of the following: Java Programming General understanding of MVC builders Glyph Name Status Family ID Known Usages General statusFamily _General Share statusFamily _Share Locked Checked out by you Checked out by you in another workspace Checked-out by you in this workspace New Checked out by other Checked-out to a project Out of date Shared to a project Shared from PDM Checked-out from
Windchill Customization Guide

Default Icon

306

Default Icon

Glyph Name Status Family ID Known Usages PDM Message statusFamily System Excluded Mes_Message sage exists Task Change statusFamily _Task statusFamily _Change AML/AVL statusFamily _AML_AVL Security statusFamily _Security Error Messages exists Warning Messages exists Info message exists Reassigned Pending Change Hanging Change New Hanging Change No AML Preferred Do not use Approved Restricted

The OOTB glyphs can easily be included in an info page or table by using its corresponding Status family id. The naming convention for these glyphs is: statusFamily_<family name>

Adding a Status Glyph to an Information Page

The following snippet shows how you can add a status glyph to the information page for a particular business object type. In the builder for that business object type, override the buildInfoConfig() method to add the glyph component to the info page component. For example:
public static InfoConfig buildInfoConfig(InfoComponentConfigFactory factory) throws WTException { InfoConfig infoConfig = factory.newInfoConfig(); ... PropertyConfig statusFamilySecurity = factory.newPropertyConfig

Generic UI Customizations

307

("statusFamily_Security"); statusFamilySecurity.setStatusGlyph(true); infoConfig.addComponent(statusFamilySecurity); ... return infoConfig; }

See Customizing Information Page Components on page 892 for more information.

Adding a Status Glyph to a Table

The following snippet shows how you can add a status glyph to a table for a particular business object type. In the builder for that table, override the buildComponentConfig () method to add the glyph component to the table component. For example:
public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig tableConfig = factory.newTableConfig(); ... ColumnConfig col1 = factory.newColumnConfig("statusFamily_Share", false); tableConfig.addComponent(col1); ... return tableConfig; }

See Constructing and Rendering a Table Using the JSP Framework on page 579 for more information on tables.

Additional Resources
Constructing and Rendering a Table Using the JSP Framework on page 579 Customizing Information Page Components on page 892 Icon Delegates on page 712

308

Windchill Customization Guide

12
Customizing HTML Clients Using the Windchill JSP Framework
Customizing Generic Aspects of JSP Pages .............................................................. 310 Bread Crumbs Component ....................................................................................... 321 Client Tabs.............................................................................................................. 332 Checkin/Checkout ................................................................................................... 345 Component Access Control ...................................................................................... 350 Attachments............................................................................................................ 355 Attribute Panels....................................................................................................... 365 Customizing Access Control For Packages................................................................ 413 Customization Tools Overview .................................................................................. 417 Adding Validation Logic for Actions and Properties ..................................................... 452 Split Pane / Two Pane .............................................................................................. 470 Defining Layouts in a Type Load File ......................................................................... 481

This chapter explains and gives some basic overview of the Windchill Client Architecture UI Framework. Before reading this chapter, you should be familiar with Java, JavaServer Pages (JSP), JavaServer Pages Standard Tag Library (JSTL), and Expression Language (EL).

309

Customizing Generic Aspects of JSP Pages


This section contains the following topics: Customizing UI Branding on page 310 Customizing the UI with Ajax on page 312

Customizing UI Branding
This section describes how to make changes to certain generic items that appear on JSP pages such as logos, site-specific information in headers and footers, and generic error messages.

Note In making changes to .rbInfo files and image files, be sure to follow the coding practices introduced in the Resource Info (.rbInfo) Files on page 1403 section in the Internationalization and Localization on page 1395. Caution Do not change any <key>.constant entries in the .rbInfo files, change only <key>. value entries.
Setup: It is necessary to have an internationalized Java SDK installed so that the classes can be compiled.

1. Modify <Windchill>/src/com/ptc/netmarkets/util/utilResource.rbInfo (and/or any of the other language versions) in a text editor. Change entries 4,5,14,15. There are a few other candidates in this file if one was to make a total conversion. Old
4.value=Powered by <A HREF=http:// www.ptc.com/products/winchill/index.htm>Windchill</a> <sup>&reg;</sup>Windchill 5.value=About Windchill ProjectLink 14.value=Windchill ProjectLink Error 15.value=Windchill ProjectLink Error

New
4.value= <your powered by> 5.value=<your about label> 14.value=<your generic error text>

310

Windchill Customization Guide

15.value=<your generic error text>

2. Compile the changes by executing the following commands in a windchill shell:


ResourceBuild com.ptc.netmarkets.netmarkets.netmarketsResource ResourceBuild com.ptc.netmarkets.util.utilResource

3. Change the icons: Replace <Windchill>/codebase/netmarkets/images/ptclogo.gif with a different image Replace <Windchill>/codebase/netmarkets/images/linklogo.gif with a different image 4. Change the <Windchill>/codebase/presentation.properties Change all of the following to appropriate values. It affects the title on the browser, the cssFiles could be used to plug in more style sheets without replacing the current one:
netmarkets.presentation.website=http\://www.ptc.com netmarkets.presentation.author=PTC netmarkets.presentation.cssFiles=

The colors of JSP clients are derived primarily from the style sheet < Windchill>/ codebase/netmarkets/css/nmstyles.css. See the style sheet for more information.

Logos
To override the logo, add a custom css file that overrides the logo styles:
/**** Application Logos for the header area */ .applLogo {background-repeat: no-repeat; height: 55px; background-position:34px;} .wncApplLogo {background-image: url(../../netmarkets/images/logoWC.gif);} .pjlApplLogo {background-image: url(../../netmarkets/images/logoPJL.gif);} .pdmlApplLogo {background-image: url(../../netmarkets/images/logoPDML.gif);} .proIApplLogo {background-image: url(../../netmarkets/images/logoPROI.gif);} .atcmApplLogo {background-image: url(../../netmarkets/images/logoATCM.gif);} /****/

Customizing HTML Clients Using the Windchill JSP Framework

311

Customizing the UI with Ajax


Objective
This section will describe how to dynamically update a portion of a Windchill page by: 1. Using the partial page refresh capabilities built into the Windchill action and form processing frame work or 2. Making an Ajax call to the Method Server directly from your JavaScript code. Scenario 1 A UI component on your page executes an action. When the action completes, you would like to update a portion of the launch page to reflect the results of an action. Example: A user launches a wizard to create a new part from the folder browser of a product. When the user clicks OK you send the form to the server and create the part. After doing so, you would like to add a row to the folder browser table that displays the part just created. Example: A user clicks a menu item in a product folder browser to delete a document. The menu item action calls a command to delete the object from the database. When the command completes, you would like to delete the row for that object from the folder browser table. Solution: Use the partial page refresh capabilities built into the Windchill action and form/command processing framework

Scenario 2 You would like to refresh an inline element of the page when some event occurs Example: You have a page that displays time values in a default time zone. It also has a button that allows the user to change the time zone. When the user changes the time zone, you want to redisplay the time values accordingly. Solution: Add an onChange event handler for the time zone button that calls therequestHandler.doRequest() JavaScript function to recompute the time display value.

Background To make the Windchill product faster and more scalable, it is necessary to use some Ajax based operations to cut down on the refresh times of pages. All actions should be Ajax based where possible. The only actions that should not be Ajax based are those that require most of the page to be updated.

312

Windchill Customization Guide

Solution
Specify some Ajax based configuration and code in the action to allow the Ajax refresh to work. Solution Elements Element <your actions>.xml

Type XML

<your>formProcessor.java Java

<your wizard step>.jsp FormResult

Jsp Java

Description XML file that defines menu, toolbar, wizard, and other actions in the Windchill action framework A processor that performs operations based on user data submitted in a wizard Jsp to partially refresh in a wizard A class used to communicate results from a form processor back to the framework. A class that provides information to the framework about the type of partial refresh that should be done. The information included is: Oid : the oid that was just created/ updated/deleted. (the new oid in the case of update) locationOid : the oid of the parent location where the object was just created/deleted in a tree, or the oid of the original in the case of update, or just null otherwise

DynamicRefreshInfo

Java

DynamicNmContextRefre- Java shInfo

action : add, update or delete. Use the NmCommandBean constants: DYNAMIC_ADD, DYNAMIC_UPD, DYNAMIC_DELETE Tree specific specialization of the DynamicRefreshInfo for handling tree paths.

Customizing HTML Clients Using the Windchill JSP Framework

313

Refresh a row in a table In the <your actions>.xml file, specify the Ajax attribute of your action to have value of row
<action name="<your action>" ajax= row > <command class="......"...> </action>

In the class <your>formProcessor.java, override the setResultNextAction method to return some dynamic refresh Info:
protected FormResult setResultNextAction(FormResult result, NmCommandBean cb) throws WTException{ DynamicRefreshInfo di = new DynamicRefreshInfo(newOid,oid,NmCommandBean.DYNAMIC_UPD) ; result.addDynamicRefreshInfo result.addDynamicRefreshInfo(di); (di); result.setNextAction(FormResultAction.REFRESH_OPENER); return result; }

Rows can be added and removed from the table by switching the flag on the refreshInfo to be NmCommandBean.DYNAMIC_ADD or DYNAMIC_DELETE respectively. Special tree refresh instructions Dynamically refreshing a row in a tree is more difficult because a particular object can exist in multiple places. In this case, a special sub-class DynamicNmContextRefreshInfo can be used to construct the tree-path that makes the row unique. The tree path is a stack of oids, and in JCA code is called the elementAddress. The second oid or context object passed to the tree refreshInfo is specified to be the parent row. In the case of adding a row to a tree, it is necessary to specify which parent folder to show the new item under. Refresh the whole table To get the whole table to refresh when the action completes, specify the Ajax type to be component.
<action name="<your action>" ajax= component > <command class="......"...> </action>

Making an Ajax Call in Windchill You can make your own Ajax request to the server for data whenever the techniques described above do not meet your needs. Element Type requestHandler.doRequest Javscript Description A Java Script class with

314

Windchill Customization Guide

Element

Type

getElementHTML

Javascript

Description methods for making Ajax requests Javascript function that can update part of the page. Uses the requestHandler to fetch the new html from the server.

Procedure Making an Ajax Call To make Ajax calls in Windchill, use the requestHandler.doRequest() JavaScript method. You provide this method with the URL to call on the server and other optional parameters, if desired. It returns a response, which is a JavaScript XMLHttpRequest object. The following example shows how this method is used in Windchill to reset a hidden field in the DOM called itemTypeInstanceId when the user changes the value in the object type picker of an object creation wizard.
<script> . . . var params = pickerVal= + elementVal; // elementVal is the new value of the type picker var options = { asynchronous: false, parameters: params }; var url = netmarkets/jsp/components/resetItemTypeInstanceId.jsp; var response = requestHandler.doRequest(url, options); var newTypeInstanceId = response.responseText; element = document.getElementById(currentObjectHandle + itemTypeInstanceId); element.value = newTypeInstanceId; . . . </script>

In this case, the pickerVal parameter is passed to the jsp in the request parameters. The jsp makes a call to a server method to compute a new TypeInstanceIdentifier for the object and passes it back in the response:
<% String pickerChoice = request.getParameter("pickerVal"); String typeInstanceIdentifier = createBean.getNewTypeInstanceIdStringForNewItem(pickerChoice); out.clearBuffer(); out.write(tiid);

Customizing HTML Clients Using the Windchill JSP Framework

315

out.flush(); %>

By default, doRequest() will make an asynchronous request so that page processing is not blocked while waiting for a response. If you want the request to be synchronous you must set asynchronous to false in the options passed to the method, as shown above. If the request is to be asynchronous, you will need to provide a JavaScript function to call when the response is received successfully in the options parameter to doRequest(). For example:
var options={ asynchronous: true, parameters: 'oid=' + oid, onSuccess: function(response) { var response = response.responseText; var json = response.evalJSON(); var locationValue = json.locationValue; var folderOid = json.folderOid; setFolder(window, locationValue, folderOid); } };

In the example above, the jsp that is invoked calls a Java tag that writes a JSON object to the response.
<req:getFolderAndContactByOidTag oidString="${param.oid}" />

Rather than define the onSuccess function inline, you can just specify the name of a function to be called:
onSuccess: handleResponse,

In addition to an onSuccess callback, you can optionally specify a onFailure callback function. If you do not specify an onFailure callback, the error response will just be logged to the JavaScript console. Procedure - Batching Ajax Requests If you have to make many Ajax requests to the same URL, you can batch them using a JavaScript BatchRequest object to reduce network traffic. When you create a BatchRequest object, you pass it a configuration object telling it the maximum number of requests to send in one batch request, the URL to call to process the requests, and the callback methods for success or failure. You then add requests to the BatchRequest object. When either the maximum batch size is reached or 500 milliseconds has elapsed, the batch request will automatically be sent asynchronously to the server. In the meantime, you can continue adding requests to the BatchRequest object.

316

Windchill Customization Guide

The BatchRequest object will exist for the life of the page in which it is invoked. When the user navigates away from the current page, the BatchRequest will be killed and any unprocessed requests will be deleted. Below is an example of how to create a BatchRequest in JavaScript. See numericJSRenderer.jsfrag for the complete method.
try { if(!jsca.columns.numericRenderer.batchRequests) { jsca.columns.numericRenderer.batchRequests = new PTC.jca. batch.BatchRequest({ url: getBaseHref() + "ptc1/numeric/", maxBatchSize: 50, successCallback: function(response) { var result = Ext.decode(response.responseText); for (var i=0,length=result.length; i < length; i++) { $(jsca.columns.numericRenderer.uniqueIdPrefix + result[i].uniqueId).innerHTML = result[i].displayValue; } }, failureCallback: function(response) { jsca.columns.numericRenderer.log.error("ERROR in jsca. columns.numericRenderer() getting numeric component data for displaying."); } }); } } catch(e) { Handle error that could be thrown when creating BatchRequest }

//

Once the request is created, you call its addRequest() method to add requests to it, passing it the parameters you would send to the requestHandler. doRequest() method.
jsca.columns.numericRenderer.batchRequests.addRequest({ type : data.type, externalForm : data.rawValue, isPercent : data.isPct, isCurrency : data.isCurrency, uniqueId : uniqueId });

In this example, the batched requests are sent to a servlet engine controller class called NumericController. The individual requests provide information about a number value that needs to be displayed on the page. The controller loops through the individual requests, calls a Java class to create a localized display value for the number, and returns a JSONArray of JSONObjects, each of which contains a display value and a unique id corresponding to the id of a HTML div tag on the page. The success callback function replaces the contents of the div tags with the display values.

Customizing HTML Clients Using the Windchill JSP Framework

317

If you use a controller class to process the batch request, it should be annotated with the Spring @Controller and @RequestMapping annotations. Here is a portion of the NumericController class (see NumericController for the complete class).:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; . . . @Controller @RequestMapping(value = "/numeric/**") public class NumericController { @RequestMapping(method = { RequestMethod.POST, RequestMethod.PUT }) protected void convertToString( @RequestParam("data") final String data, HttpServletRequest request, HttpServletResponse response) throws IOException { JSONArray result = new JSONArray(); try { JSONArray requests = new JSONArray(data); for (int i = 0; i < requests.length(); i++) { JSONObject req = requests.getJSONObject(i); try { String type = req.getString("type"); String externalForm = req.getString("externalForm"); String isPercent = req.optString("isPercent"); String isCurrency = req.optString("isCurrency"); String uniqueId = req.getString("uniqueId"); String displayValue = NumericFormat.formatValueForDisplay(type, externalForm, Boolean.valueOf(isPercent), Boolean.valueOf(isCurrency)); JSONObject singleResponse = new JSONObject(); singleResponse.put("displayValue", displayValue); singleResponse.put("uniqueId", uniqueId); result.put(singleResponse); } catch (Exception e) { . . . } } response.setContentType("application/json; charset=UTF-8"); PrintWriter out = response.getWriter(); out.print(result.toJSONString());

318

Windchill Customization Guide

} catch (Exception e) { log.error("Problem displaying and formatting number in NumericController.", e); }

Refreshing only the top of the Information Page


See the Information Pages on page 891 section for more information.

Refreshing a Large Block of the Page


There is often the need to refresh a section of the page without a full page refresh. In this case there are some helpful javascript functions. In particular, the getElementHtml function is optimized to replace the innerHTML of the given div id with the response from the given url. If the div id is in the response, only the innerHTML of the div will be used as the replacement. See the jsDoc for more information about this function:. getElementHtml( params, divId, true, url)

Sample Code
Examples of usage in out-of-box code. Many examples exist, search actions.xml files for ajax=component ajax=row or the processors for calls to addDynamicrefreshInfo. Flow Diagrams for a Popup Action This is a diagram of the flow of the first request when a popup action dynamically updates the opener page. When the popup action is completed it refreshes the opener window by adding a row to the table. Tomcat is embedded in the Method Server so are there only two large dotted-line boxes but the same internal flow occurs. Notice the FormProcessor returns a FormResult which is then serialized back to the browser which does the updates as necessary.

Customizing HTML Clients Using the Windchill JSP Framework

319

This is a diagram of the second request to the server after a popup action has indicated that a row should be added to the table as the result of a create action. Tomcat is embedded in the Method Server so there only two large dotted-line boxes but the same internal flow occurs.

320

Windchill Customization Guide

Bread Crumbs Component


You can create a list of navigation bread crumbs at the top of a Windchill page. A list of bread crumbs is displayed at the top of many Windchill pages. These bread crumbs show the location of the page in the page hierarchy. Each crumb is a link that will take the user to the corresponding page in the hierarchy. Example bread crumb list:

See the package javadoc for com.ptc.windchill.enterprise. navigation.breadcrumb for information on the classes and process used to produce bread crumbs. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This process should be applied when you want to create bread crumbs for one or more Windchill pages that do not currently have bread crumbs or you want to modify the bread crumbs displayed on a Windchill page. Intended Outcome Bread crumbs are displayed as desired.

Solution
Create and register a BreadCrumbDelegate Java class with an inner class that extends AbstractBreadCrumbGenerator to display the bread crumbs. Prerequisite Knowledge To create the necessary bread crumb classes you will need an understanding of the Java programming language. Solution Elements Element BreadCrumbController

Type Java class

Description The controller class that receives AJAX requests for bread crumbs. It returns a response that is the

Customizing HTML Clients Using the Windchill JSP Framework

321

Element

Type

BreadCrumbDelegateFac- Java class tory

BreadCrumbDelegate

Java interface

AbstractBreadCrumbGen- Java class erator *.wt.properties.xconf Properties xconf file

Description string form of a JSON array of crumbs. A factory used by the BreadCrumbController to locate a BreadCrumbDelegate capable of producing the bread crumbs for a given page. A delegate that contains an inner AbstractBreadCrumbGenerator class and that knows which pages the generator class can produce bread crumbs for. A subclass of this base class creates the bread crumbs for a page. Contains the property com.ptc.windchill.enterprise.breadcrumb.BreadCrumbDelgate that lists all available BreadCrumbDelegates.

Procedure Creating a New BreadCrumbDelegate Class


Creating the BreadCrumbDelegate Class Bread crumb delegate classes should implement the BreadCrumbDelegate interface. This interface has two methods: canHandle() and getGenerator (). The canHandle() method is called by the BreadCrumbDelegateFactory to determine if the delegates inner AbstractBreadCrumbGenerator class (see below) is capable of

322

Windchill Customization Guide

producing bread crumbs for a given page. The canHandle() method is passed the page URL, the context object from the URL, if any, and the container object from the URL, if any. It should return true or false. The BreadCrumbController calls the getGenerator() method of the delegate chosen by the factory to get a new instance of its inner AbstractBreadCrumbGenerator class.

Note Since the factory creates only one static instance of each delegate, the delegate class itself should not use class instance variables or be stateful in any way.
Creating the AbstractBreadCrumbGenerator Inner Class Your delegate class should have an inner class that is a subclass of AbstractBreadCrumbGenerator. The getCrumbs() method of the inner class will be called by the BreadCrumbController to generate the JSONArray of crumbs. A new instance of the inner generator class will be created each time it is called so generator classes may be stateful. The constructor of the generator class will be passed the URL of the page, the context object for the page, if given on the URL, and the container for the page, if given on the URL. The constructor should call the init() method of the superclass. The JSON objects returned in the array by the getCrumbs() method should have the following format:
{text: 'display text', url: 'http://my/url'}

For example:
[{"text":"Products","url":"app/#ptc1/comp/netmarkets.product.list"}, {"text":"Product1","url":"http://<someServer>/Windchill/app/#ptc1/tcomp/infoPage? oid=OR%3Awt.pdmlink.PDMLinkProduct%3A105250&u8=1"}]

See Sample Code on page 324 for example classes.

Procedure Registering the BreadCrumbDelegate


To register your BreadCrumbDelegate you must add it to the list of delegates contained in the wt.property com.ptc.windchill.enterprise. navigation.breadcrumb.BreadCrumbDelegate. This property is defined as follows:
<Property name="com.ptc.windchill.enterprise.navigation.breadcrumb. BreadCrumbDelegate" multivalued="," default= "com.ptc.windchill.enterprise.navigation.breadcrumb. FolderedBreadCrumbDelegate" />

Customizing HTML Clients Using the Windchill JSP Framework

323

The default delegate, FolderedBreadCrumbDelegate, is the delegate that will be called if no other delegate claims a page. The value of the default delegate is hard-coded and cannot be changed. Changing the value in the property will have no effect. Additional delegates may be added to the delegate list in a custom or modulespecific *.xconf file using the AddToProperty tag. For example:
<AddToProperty name="com.ptc.windchill.enterprise.navigation.breadcrumb. BreadCrumbDelegate value="com.ptc.windchill.enterprise.navigation.breadcrumb. WorkspaceBreadCrumbDelegate~10"/>

You can optionally assign a priority to a delegate, as shown above, by appending a ~ followed by a priority value to the delegate class name. A priority value may be any number less than Integer.MAX_VALUE; the lower the number, the higher priority. To see the priorities of existing delegates you can look at the composite property value in <WT_HOME>/codebase/wt.properties. The BreadCrumbDelegateFactory will call the canHandle() methods of delegates in priority order until it finds one that responds affirmatively. Therefore, if there are multiple delegates that could generate the crumbs for a given page, the one with the highest priority will be used. If multiple delegates have the same priority, they will be called in random order. The canHandle() method of delegates which do not have a ~<priority> suffix will be called last, in random order.

Sample Code
The following code is extracted from the AssignmentsBreadCrumbDelegatewhich generates the bread crumbs for an assignment (WorkItem) object.
public class AssignmentBreadCrumbDelegate implements BreadCrumbDelegate { @Override public boolean canHandle(Persistable contextObject, WTContainer container, String url) throws WTException { if (contextObject instanceof WorkItem || contextObject instanceof ActionItem) { return true; } return false; } @Override public AbstractBreadCrumbGenerator getGenerator(Persistable contextObject, WTContainer container, String url) throws WTException {

324

Windchill Customization Guide

return new AssignmentCrumbGenerator(p, container); } public class AssignmentCrumbGenerator extends AbstractBreadCrumbGenerator { /** * IDs for Assignment list components. */ protected static final String PRODUCT_ASSIGNMENTS_LIST_ID = "netmarkets.product.assignments.list"; protected static final String LIBRARY_ASSIGNMENTS_LIST_ID = "netmarkets.library.assignments.list"; protected static final String QUALITY_ASSIGNMENTS_LIST_ID = "com.ptc.qms.listAssignments"; protected static final String PROJECT_ASSIGNMENTS_LIST_ID = "project.assignments"; protected WTContainer container; /** * Initialize as a generator and set instance variable * container so that the Assignments crumb can be made. * First tries to set container to c. Next * tries to set container to contextObject's container (if * contextObject is WTContained). Next tries to set * container to contextObject's source object's container. * Lastly tries to set container to contextObject's * primary business object container. * * @param contextObject * @param c * @throws WTException */ public AssignmentCrumbGenerator(Persistable contextObject, WTContainer c) throws WTException { init(); // If no container is passed in, try to get it from contextObject. if (c == null && contextObject!= null) { WTContained containedItem = null; if (contextObject instanceof WTContained) { // This will either be an ActionItem (which is contained) // or could possibly be a future WorkItem, if it ever // implements WTContained. containedItem = (WTContained) contextObject; } else if (contextObject instanceof WorkItem) { // Use the WorkItem's source if it is contained. ObjectReference sourceRef = ((WorkItem) contextObject). getSource(); if (sourceRef != null) { Persistable source = sourceRef.getObject(); if (source instanceof WTContained) { containedItem = (WTContained) source;

Customizing HTML Clients Using the Windchill JSP Framework

325

} } // If there is still no containedItem, try use the // WorkItem's primary business object. if (containedItem == null) { PersistentReference primaryObjectRef = ((WorkItem) contextObject) .getPrimaryBusinessObject(); if (primaryObjectRef != null) { Persistable primaryObject = primaryObjectRef .getObject(); if (primaryObject instanceof WTContained) { containedItem = (WTContained) primaryObject; } } } } if (containedItem != null) { c = containedItem.getContainer(); } } container = c; } @Override public JSONArray getCrumbs() { try { addContainerCrumbs(container); } catch (Exception e) { log.error("Couldn't create the crumbs for container " + container, e); addCrumb(getSecuredInfoCrumb()); } try { addCrumb(createAssignmentsCrumb()); } catch (Exception e) { log.error("Couldn't create the Assignments Table crumb.", e); addCrumb(getSecuredInfoCrumb()); } return crumbs; } /** * Makes the Assignments List crumb for a given assignment object. * * @return JSONObject * @throws WTException * @throws JSONException */ protected JSONObject createAssignmentsCrumb() throws JSONException, WTException { if (container == null) {

326

Windchill Customization Guide

log.warn("The Assignments list crumb will not be made because container is null."); return null; } String url = getAssignmentsListUrl(container); String localizedText = navigationBundle .getString(navigationRB.ASSIGNMENTS); return createCrumb(url, localizedText); } /** * Given a container, will return a URL for the assignment list table. * Example: * app/#ptc1/comp/netmarkets.product.assignments.list? oid=OR%3Awt * .pdmlink.PDMLinkProduct%3A12345&u8=1 * * @param container * @return String */ protected String getAssignmentsListUrl(WTContainer container) { String url = ""; if (container instanceof PDMLinkProduct) { url = MVCUrlHelper.getComponentURL(PRODUCT_ASSIGNMENTS_ LIST_ID); } else if (container instanceof Project2) { // Could be project or program. Same URL in either case. url = MVCUrlHelper.getComponentURL(PROJECT_ASSIGNMENTS_ LIST_ID); } else if (container instanceof WTLibrary) { WTLibrary libObj = (WTLibrary) container; if (libObj.isQMSTypeContainer()) { // If Quality container then navigate to Quality Assignment // page url = MVCUrlHelper .getComponentURL(QUALITY_ASSIGNMENTS_LIST_ID); } else { // If Library container then navigate to Library Assignment // page url = MVCUrlHelper .getComponentURL(LIBRARY_ASSIGNMENTS_LIST_ID); } } else { // This is the case where container is null or of unsupported // container type. return null; } url = url.replaceFirst("/", MVCUrlHelper.APPPREFIX); String containerOid = "OR:" + container.getPersistInfo().getObjectIdentifier()

Customizing HTML Clients Using the Windchill JSP Framework

327

.toString(); try { containerOid = URLEncoder.encode(containerOid, "UTF-8"); } catch (UnsupportedEncodingException e) { log.error("Could not encode the container oid.", e); } url += "?oid=" + containerOid + "&u8=1"; return url; } } }

Additional Resources
Related Package/Class Package/Class Javadoc com.ptc.jca.mvc.controllers.BreadCrumbController com.ptc.windchill.enterprise.navigation.breadcrumb. BreadCrumbDelegateFactory com.ptc.windchill.enterprise.navigation.breadcrumb.BreadCrumbDelegate com.ptc.windchill.enterprise.navigation.breadcrumb. AbstractBreadCrumbGenerator com.ptc.windchill.enterprise.navigation.breadcrumb. FolderedBreadCrumbDelegate

Packaged Samples
Bread Crumbs Based on the Context Object
This example shows how bread crumbs can be created based on the context object of the page. The bread crumbs for this example were created by the FolderedBreadCrumbDelegate. This is the default delegate that will be called to create bread crumbs, if it can, when no other delegate claims the ability to handle the page. This is accomplished with the following code:
@Override public boolean canHandle(Persistable p, WTContainer container, String url) throws WTException { return true; }

328

Windchill Customization Guide

The FolderedBreadCrumbDelegate first tries to use a passed in WTContainer (container in this case), if any. If no container is passed in, the delegate uses the Persistable context object (p in this case) to determine where the object lives in the system. If the Persistable is itself a container, use that as the crumb. If the Persistable is not a container, attempt to get the Persistables container as the crumb. If all of the previous options fail, simply return an empty crumb.
public class FolderedBreadCrumbDelegate implements BreadCrumbDelegate { @Override public AbstractBreadCrumbGenerator getGenerator(Persistable p, WTContainer container, String url) throws WTException { return new FolderedCrumbGenerator(p, container); } public class FolderedCrumbGenerator extends AbstractBreadCrumbGenerator { protected Persistable p; protected WTContainer container; public FolderedCrumbGenerator(Persistable p, WTContainer container) throws WTException { init(); // // // if If a container is present, use it. Else if p is itself a container, use that. Otherwise get p's container. (container != null) { this.container = container; } else if (p instanceof WTContainer) { this.container = (WTContainer) p; } else if (p instanceof WTContained) { this.container = ((WTContained) p).getContainer(); } this.p = p; } @Override public JSONArray getCrumbs() { // Try to add the container crumbs. try { addContainerCrumbs(container); } catch (Exception e) { addCrumb(getSecuredInfoCrumb()); } // Try to add the trail of parent folder crumbs. try { addFoldersIfNeeded(container, p); } catch (Exception e) {

Customizing HTML Clients Using the Windchill JSP Framework

329

addCrumb(getSecuredInfoCrumb()); } return crumbs; }

When visiting the info page link for our example haiku, you can see the bread crumb shows that this particular object resides under Site Folders . Note: only users with adequate permissions will be able to view this objects info page. Location of Example To navigate to this example in the product go to Customization Component Catalog Bread Crumb Component Bread Crumbs based on the Context Object.

Note The Component Catalog is not enabled in the Windchill UI by default. For instructions on enabling the Component Catalog, see Enable Customization Utilities on page 417.
Actions for this Example None Action Models for this Example None Files Used in This Example com/ptc/windchill/enterprise/navigation/breadcrumb/ FolderedBreadCrumbDelegate.java com/ptc/core/components/components.wt.properties.xconf

Bread Crumbs Based on the URL


This example shows how to create bread crumbs based on the URL path of a given page. The canHandle() method of the CarambolaBreadCrumbDelegate used in this example checks if the URL path contains certain strings. If the URL contains componentCatalog, carambola, apiDocs or jsapi, the method will return true. Its generator class then returns a bread crumb array depending on the contents of the URL. For example, if the URL contains carambola and breadCrumb, the Component Catalog and Bread Crumb Component crumbs will be added.

330

Windchill Customization Guide

Location of Example To navigate to this example in the product go to Customization Component Catalog Bread Crumb Component Bread Crumbs based on the URL.

Note The Component Catalog is not enabled in the Windchill UI by default. For instructions on enabling the Component Catalog, see Enable Customization Utilities on page 417.
Actions for this Example None Action Models for this Example None Files Used in This Example com/ptc/carambola/customization/examples/breadcrumb/ CarambolaBreadCrumbDelegate.java com/ptc/carambola/carambola.wt.properties.xconf com/ptc/carambola/CustomizationPage.java

Customizing HTML Clients Using the Windchill JSP Framework

331

Client Tabs
Users and administrators want to create and configure additional tabs on information pages. Information pages are composed of one to several tabs. Each information page is configured out-of-the-box with a set of tabs, and default content on those tabs. Out-of-the-box tabs are created and configured by creating or editing an action model (see Customizing Information Page Components on page 892 for more information on creating tab sets for an information page). These tabs are then available for that information page for all users. Tabs may also be created dynamically by users, by clicking the + icon on the tab set. These tabs can be configured by adding content. Since these tabs are not defined via an action model as the other tabs, a mechanism to persist the tab and its content is required. Also, administrators may wish to create and configure tabs on information pages that are available for all users in their site and/or organization. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This document assumes you are familiar with configuring Windchill information pages, and configuring information page tab sets in particular. Intended Outcome Upon reading this best practice you should understand how information page tabs can be created and configured by users and administrators. You should also be able to utilize the customization points to customize how tabs are handled for information pages.

Solution
Tabs created dynamically by users and administrators will be persisted in the database. Prerequisite Knowledge To apply this process, you need to have an understanding of the following: Basic development involving Java, XML, and JavaScript particularly JavaScript Object Notation (JSON) An understanding of how information page tabs are created and configured via action models (See Customizing Information Page Components on page 892 for more information)

332

Windchill Customization Guide

Solution Elements Element ClientTab.java

Type Java class

Description Located at <WT_HOME> \com\ptc\core\ui\tab Provides the definition for the persisted tab object in the database. Contains all necessary information needed to associate a tab with its content, the object type, the creator, etc. Located at <WT_HOME> \com\ptc\core\ui\tab Defines the interface for determining the set of tabs to be used for the information component. Located at <WT_HOME> \com\ptc\core\ui\tab Provides the default implementation of the TabSetDelegate interface. This class will determine what tabs to display for an information page. Located at <WT_HOME> \com\ptc\core\ui\tab Used to convert JSON objects from the client to persistable objects on the server. Located at <WT_HOME> \com\ptc\core\ui\tab \server A helper class to provide access to the ClientTab service, as well as other helper methods. Located at <WT_HOME>

TabSetDelegate.java

Java interface

DefaultTabSetDelegate. java

Java class

JSONTabServiceAdapter. Java class java

ClientTabHelper.java

Java class

ClientTabService,java

Java interface

Customizing HTML Clients Using the Windchill JSP Framework

333

Element

Type

Description \com\ptc\core\ui\tab \server Defines the interface for the storage, retrieval, and deletion of the ClientTab objects. Located at <WT_HOME> \com\ptc\core\ui\tab \server Provides the default implementation of the ClientTabService to store, update, and delete ClientTab objects. Located at <WT_HOME> \netmarkets\javascript\util \jsfrags The client code responsible for managing the state of the tabs, including the creation, modification, or deletion of tabs. This client code will interact with the server via AJAX requests. Located at <WT_HOME> \com\ptc\jca\mvc \controllers The server code that is responsible for receiving the HTTP requests from the client and performing the appropriate action (creation, deletion, or modification of a tab). Renders the whole info model (including the tab set) Renders the tab set, has
Windchill Customization Guide

StandardClientTabService.java

Java class

TabManager.jsfrag

Javascript fragment

TabController.java

Java class

RenderInfoPageModelTag.java infoPage.jsfrag
334

Java class

Javascript fragment

Element

Type

InfoPageTabSetDataUtili- Java class ty.java

Description code to update the tab set as user adds/removes tabs or tables from the tabs. Looks up the tab delegate to use for finding the info page tab set.

Below is a diagram illustrating the relationship of some of the more important components listed above:

The tabs that a user sees an information page are thus a combination of the actions defined by the actions model XML, any tabs created by the site administrator, any tabs created by the organization administrator, and any tabs created by the user. It is important to note that information tabs are linked to an object type. That is, if Tab A is created for a document, then Tab A will be seen on every document information page, but not on information pages for other object types (i.e. Part). The default implementation of the TabSetDelegate follows the following algorithm for determining what tabs to display for a given information page: Retrieve the tabs defined by the action model Retrieve the tabs defined by the site administrator for the object type Retrieve the tabs defined by the user s organization administrator for the object type Retrieve the tabs defined by the user for the object type

Customizing HTML Clients Using the Windchill JSP Framework

335

This behavior can be customized by writing your own TabSetDelegate. See Customizing Tabs by Implementing Custom TabSetDelegate on page 341 for more information.

Customization Points
This section contains the following topics: Customizing Tabs via Windchill UI on page 336 Customizing Tabs by Implementing Custom TabSetDelegate on page 341 Customizing Tabs by Implementing Custom TabController on page 342

Customizing Tabs via Windchill UI


This section contains the following topics: General Procedure on page 336 Out-of-the-Box (OOTB) Tabs on page 339 Customizing Tabs Site Administrator on page 340 Customizing Tabs Organization Administrator on page 340 Customizing Tabs Standard User on page 341 Reordering Tab Content Items on page 341

General Procedure Users can create and configure a tab by visiting an information page for the type you wish to configure. Click the tab with the + icon to create a new tab, and configure the tab as needed. It is important to note that throughout this process the tab is being saved, without any explicit action required. The very act of creating a new tab creates a new tab object in the database. Any actions to the tab, including changing its name, adding content, or deleting it, are immediately saved on the server. The general procedure for adding and configuring a tab for a specific type is illustrated below. In this example, we will create and configure a tab that will display history information for documents: 1. Visit the information page of any document, and create a new tab by clicking the + tab:

336

Windchill Customization Guide

2. This will create a new tab, named New Tab 1 (or New Tab 2 or some variation, depending on how many newly created tabs there are):

3. You can than rename this tab to something more meaningful. In this case, since this tab will be used to display history information, we will rename it to History by right-clicking on the tab itself, and invoking the Rename Tab action:

4. Enter the desired name into the resulting dialog, and you should see the tabs new name:

Customizing HTML Clients Using the Windchill JSP Framework

337

5. New tabs are initially added to the right most end of the tab set. You can move your new tab to a different position in the tab set using a left-mouse click and drag-and-drop:

6. At this point, we have created a tab, given it a descriptive name, and moved it to the desired position in the tab set. We have yet to add any content to it, however, so it is not very useful yet. Well add content to the tab by clicking the Customize link. The Customize menu shows the content items that can be added to the tab. Content items are typically tables or attribute panels. The main Customize menu shows categories of content items. Each category has a submenu showing the content items in that category. You can select all the content items in a category by checking the box associated with the category or you can select individual content items within a category. Well add the Version table to our new tab by selecting it in the Customize menu:

7. Now we have a History tab, with the Version component added to it. Depending on the administrative role of the user performing this action, this tab and its content will either be unique to the user, available for all users within the organization, or available for all users within the site, for all documents. This is explained in the following sections. In order to delete any user created tab, you can delete by right clicking on the tab itself and invoking Close Tab action.

338

Windchill Customization Guide

8. You will get below confirmation dialog, by clicking OK, the tab will get deleted and by clicking Cancel you will be returned to the page.

9. The tab can also be deleted by clicking x on the tab itself.

Out-of-the-Box (OOTB) Tabs A set of tabs can be configured out-of-the-box. These tabs are configured in an actionModels.xml file, like this:
<model name=partInfoPageTabSet resource=com.ptc.core.ui.navigationRB> <submodel name=partInfoDefaultDetails type=object/> <action name=productStructureGWT type=psb/> </model>

The model can contain the following elements: submodel : specifies the tab name (display name mapped to the name of the submodel) and the items (tables) to render on the tab. Each action defined within the submodel, a corresponding item (table) is rendered to the body of the tab. action : specifies the tab name (display name mapped to the name of the action) and the component or JSP to include as the tab body. The HTML returned from the action is rendered as the body of the tab.

Customizing HTML Clients Using the Windchill JSP Framework

339

The action model is set in the component builder for the given component. Please refer to Sample Code on page 344 for usages of Client Tabs for a specific component. Out-of-the-box tabs can only be modified by changing the action definition in the XML file. Users (site administrator, organization administrator, or standard users) are not allowed to change the name of the tab, change the contents of the tab, or remove the tab. All users will have the ability to change the order in which the tabs appear, this includes out-of-the-box tabs. Customizing Tabs Site Administrator A site administrator can create and configure tabs, per object type, that will be available for all users in that site. If the site administrator creates a History tab, for example, as detailed in General Procedure on page 336, that tab will be seen on all document information pages, for all users in the site. The site administrator will not see all the tabs for all of the organizations. They will just see what tabs are at the site level. Tabs created by a site administrator, can only be managed by a site administrator. That is, only a site administrator can change the name of the tab, can change the contents (including the ordering of the contents) of the tab , or remove the tab. All users will have the ability to change the order in which the tabs appear, this includes out-of-the-box tabs and tabs created by a site administrator. Customizing Tabs Organization Administrator An organization administrator can create and configure tabs, per object type, that will be available for all users in that organization. If the organization administrator creates a History tab, for example, as illustrated in General Procedure on page 336, that tab will be seen on all document information pages, for all users in that organization. Tabs created by an organization administrator, can only be managed by an organization administrator. That is, only an organization administrator can change the name of the tab, can change the contents (including the ordering of the contents) of the tab, or remove the tab. A site administrator will not be able to manage a tab created by an organization administrator. All users will have the ability to change the order in which the tabs appear, this includes out-of-the-box tabs and tabs created by an organization or site administrator.

340

Windchill Customization Guide

Customizing Tabs Standard User A standard user can also create and configure tabs, per object type, that will be available for only that user. If the user creates a History tab, for example, as illustrated in General Procedure on page 336, that tab will be seen on all document information pages, for only that user. Tabs created by a standard user, can only be managed by that user. That is, only that user can change the name of the tab, can change the contents (including the ordering of the contents) of the tab, or remove the tab. A site administrator or organization administrator will not be able to manage a tab created by a standard user. All users will have the ability to change the order in which the tabs appear, this includes out-of-the-box tabs and tabs created by administrators. Reordering Tab Content Items If a tab contains more than one content item, the content items may be reordered using the Table of Contents links on the tab. Left-click on a content item link and drag-and-drop the link to the position corresponding to where you want the item to appear on the tab:

As stated earlier, administrators can only reorder the contents of tabs created by administrators and users can only reorder the contents of tabs they created. If you do not have the ability to modify the order of the contents, the content items will not be displayed as links in the Table of Contents.

Customizing Tabs by Implementing Custom TabSetDelegate


It is possible to control a different algorithm for displaying the tabs. The TabSetDelegate class is what brings together tabs from the *actions.xml and tabs that are stored in the database. The RenderInfoPageModelTag will take the output from the TabSetDelegate.getDefaultAndDynamicTabs() and render out JSON that will display the tabs on the client. The code could look something similar to the following:
public class DefaultTabSetDelegate implements TabSetDelegate { /**

Customizing HTML Clients Using the Windchill JSP Framework

341

* This is the main method to add the site, org and user tabs along side * the default set that was in the action model. */ public NmHTMLActionModel getDefaultAndDynamicTabs() {code here}

To add your own TabSetDelegate class you can specify the following in the service.properties file:
<Service context="default" name="com.ptc.core.ui.tab.TabSetDelegate"> <Option serviceClass="com.ptc.core.ui.tab.your.package. CustomizedClassDelegate" requestor="infoPage" selector="wt.part.WTPart"/> </Service>

The selector is specified for the type of wt.part.WTPart. This means that the delegate will be called for part information pages and all soft types of WTPart.

Customizing Tabs by Implementing Custom TabController


Ajax requests are sent to the TabController in order to have the information persisted into the database. This can be customized by extending or creating a new controller with a request mapping that would be similar to the following example code:
@Controller @RequestMapping(value = "/tab/**") public class MyTabController { /** * Creates, Updates, or deletes the tab by calling the @link {JSONTabServiceAdapter}. * * @param data - String version of the JSON object * @param action will be set to one of the following values: [create, update, delete] * @param request * @param response * @throws IOException */ @RequestMapping(method = { RequestMethod.POST, RequestMethod.PUT }) protected void createAndUpdateTab(@RequestParam("data") final String data, @RequestParam("action") final String action, HttpServletRequest request, HttpServletResponse response) throws IOException {code here}

Exporting and Importing Client Tabs


Exporting You can export client tabs using a command line application. 1. From the Windchill shell, enter: java com.ptc.core.ui.ixb. ClientTabExport tabname
Windchill Customization Guide

342

The required tabname parameter is the name of the tab to export. For a home page, this should be the string homepage. For other tabs, the name is that shown on the tab in the UI. To export a tab that includes spaces in the name, double-quote the parameter: My Custom Tab.

2. You will be prompted for a Windchill user name and password. Enter the Site Administrator s credentials. 3. Wildcards are added internally; the resulting query is: select * from CLIENTTAB where NAME like %tabname%; 4. The export utility reports the names of exported tabs, and the location of the . jar file it produces:
> java com.ptc.core.ui.ixb.ClientTabExport a 2011-10-14 09:55:38,377 INFO [main] com.ptc.core.ui.ixb.ClientTabExport - Exporting tab OrgAttr 2011-10-14 09:55:38,393 INFO [main] com.ptc.core.ui.ixb.ClientTabExport - Exporting tab my custom tab 2011-10-14 09:55:38,393 INFO [main] com.ptc.core.ui.ixb.ClientTabExport - Exporting tab jcrpage 2011-10-14 09:55:38,393 INFO [main] com.ptc.core.ui.ixb.ClientTabExport - Exporting tab homepage 2011-10-14 09:55:40,127 INFO [main] com.ptc.core.ui.ixb.ClientTabExport - Exported to <WT_HOME>\Windchill\temp\IXBExpImp\1279724139377-1977404926 \Export5586892419340327596.jar

Importing Importing ClientTab records is performed from the Windchill Import/Export


Management utility.

1. Log into Windchill on the destination system as the Site Administrator. 2. From the Site Utilities System Administration Import/Export Management . 3. The Windchill Import/Export Management utility presents an option to import or export. 4. Choose Import . In the import dialog box, paste or browse to the path of the exported .jar file.

Note If the container or user of an imported tab (whichever applies) is not present on the destination system, that tab is not imported. A warning will be displayed.

Customizing HTML Clients Using the Windchill JSP Framework

343

Sample Code
Examples of Usage in Windchill Code Information Page The information page uses Client Tabs to manage out-of-the-box, site defined, organization defined, and user defined tabs. The information page will set the default action model (the model specified in the actions model XML file that defines tabs and their contents) on the TabSetDelegate, and then query the TabSetDelegate for any administrator or user created tabs. The default, out-of-the-box implementation of the TabSetDelegate will return an action model that is the default action model, plus all administrator and user-defined tabs. For more information about defining tabs for an information page, please refer to Customizing Information Page Components on page 892. Packaged Samples
Information Page .

There is a carambola information page underCustomization Example http://<machineNam>/<webApp>/app/#ptc1/tcomp/infoPage? typeIdForTypeLookup=com.ptc.carambola.customization. examples.infoPage.Carambola

344

Windchill Customization Guide

Checkin/Checkout Checkin/Checkout
Objective
You want to be able to checkin and checkout an object.

Background
The ability to check in and checkout gives the ability to track changes to an object by providing an iteration history of each change. Also if a user has an object checked out, no other user may modify the object until it has been checked back in. In order for an object to work with the checkin/checkout common component it must implement the wt.vc.wip.Workable interface.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


The object implements either the Workable interface. Familiarity with the actions framework Familiarity with the basic concepts of checkin/checkout

Customizing HTML Clients Using the Windchill JSP Framework

345

Intended Outcome By following these procedures you should be able to add or modify the checkin and checkout actions. Checkout action (no wizard involved)

Checkout status icon after the object is checked out

346

Windchill Customization Guide

Checkin wizard (in this case with primary content but the primary attachment component will not appear if your object does not support it).

Solution
Use the Checkin/Checkout common components with your object.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Windchill work in progress checkin/checkout concepts. The actions framework in the Windchill client architecture. Basic development involving HTML forms, JSP, and XML.

Procedure Adding checkin/checkout actions to a business object In the action model xml file that defines the action model with the menufor attribute for your object type add the following actions. This will provide checkin, checkout, checkout & download, undo checkout, replace content, and checkout &

Customizing HTML Clients Using the Windchill JSP Framework

347

edit actions for your object. Note, only add checkout & download and replace content actions if you are adding these actions for an object that implements the FormatContentHolder interface and you expect it may have primary content.
<action name="checkin" <action name="checkout" <action name="checkout_and_download" <action name="undocheckout" <action name="replace_content" <action name=" checkoutAndEdit " ACTIONS XML"/> type="wip"/> type="object"/> type="wip"/> type="object"/> type="wip"/> type="YOUR TYPE FROM YOUR TYPES

Checkout and edit however requires additional coding. Create an additional action definition in the actions.xml file for your object type. Name the action checkoutAndEdit so that the validation framework will pick it up properly. Then set the url attribute to point to your wizards edit jsp file. Example:
<action name="checkoutAndEdit"> <command class="com.ptc.core.components.forms.EditObjectFormProcessor" method="execute" url="netmarkets/jsp/document/edit.jsp" windowType="popup" / </action>

Add the appropriate entries for this action in your rbinfo file (see actions framework documentation). In your edit jsp file you will need to add the following tag above the wizard declaration.
<%@ taglib prefix="wip" uri="http://www.ptc.com/windchill/taglib/workinprogress"%> <wip:autoCheckOutItem />

This will allow the wizard to checkout the object if the object is not already checked out.

Caution Using this tag on wizards other than edit or without a processor that is extending EditObjectFormProcessor is not supported and may result in unstable code.

Sample Code
Examples of Usage in Windchill Code
To view a sample action model with checkin/checkout actions see the document action models (<Windchill>\codebase\config\actions\DocumentManagementactionmodels.xml)

348

Windchill Customization Guide

To view a sample checkout and edit action see the action definition in the document actions definitions (<Windchill> \codebase\netmarkets\jsp\document \edit.jsp) and the document edit JSP file (<Windchill>\codebase\config\actions \DocumentManagement-actions.xml)

Customizing HTML Clients Using the Windchill JSP Framework

349

Component Access Control


Objective
You want to use a consistent interface to view and manipulate access control permissions on individual Windchill objects.

Background
The Common Access Control Component was developed to provide a consistent interface for Windchill ProjectLink and Windchill PDMLink users to view and manipulate access control permissions on individual Windchill objects. The feature is available in the out of the box Security Clerk through the Manage Security action and also in the Create Document and Create Part wizards. This feature for individual object instances is implemented using ad hoc ACLS. The access component for a folder also has the additional capability of defining permissions and propagating them throughout the folder contents. Preferences are supported to permit sites to tailor the visibility and updatability of individual access control permissions to meet their specific access control requirements.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This feature only applies to objects that implement the wt.access.AdHocControlled interface. The AdHocControlled interface holds information that controls access to a specific instance of an object class. The ad hoc ACL specifies only positive permissions. It cannot be used to deny access to an object. If the ad hoc ACL grants a permission that is denied in the policy ACL, the ad hoc rule supersedes the policy rule, and the access right is granted. The feature may be used in two ways: The Manage Security action can be added to the objects action model. The Access Control Component can be included as a step in the objects Create wizard.

Intended Outcome Manage Security Action When the Manage Security action is included in an objects action model, the action will available in the objects action list.

350

Windchill Customization Guide

Note The visibility of the action may be constrained by profiles defined in the Role Based UI. See the Windchill Business Administrator's Guide for more details about profile- and role-based visibility administration.
Create Wizard When the component is included in an objects Create wizard it appears as an optional Access Control step in the create process. The Set Access Control step should be the highlighted step in the wizard at this point. It is not being correctly rendered in the current build.

Solution
Use the Access Control Component to provide an interface to view and manipulate access control on Ad Hoc controlled objects.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Windchill client architecture Basic development involving HTML forms, JSP, and tag libraries. The actions framework in the Windchill client architecture.

Solution Elements
Element actionmodels.xml Type XML Description Windchill\codebase\actionmodels.xml The actionmodels file defines the actions available in named action models. The outer jsp file defining a create wizard

Create<myObject>.jsp JSP

Procedure - Adding a Manage Security action to an action model


Include the following in the desired action model in your object's actionmodels. xml:
<action name="ManageSecurity" type="accessPermission"/>

Customizing HTML Clients Using the Windchill JSP Framework

351

Procedure - Including an Access Control Step in a Create Wizard Update the main Create<myObject>.jsp to define the JCA tag library:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components" %>

Include the access control wizard step:


<jca:wizardStep action="setAccessControlWizStep" type="object"/>

Customization Points
Configuring the access permissions
The permissions presented for view and update in the common access control component are configurable at the site, org, and application container with the preference service. At each container level, administrators can select the permissions that members of the container will be permitted to view and potentially update. The initial values for the permission configurations are loaded from Windchill \loadFiles\preference.foundation.xml with a csvcategoryName of SECURITY_PERMISSION_CATEGORY. Below is an example loading the initial system configuration for the Read permission.
<csvPreferenceDefinition handler="wt.preference.LoadPreference.createPreferenceDefinition"> <csvname>security/accessPermissionRead</csvname> <csvvisibility>HIDDEN</csvvisibility> <csvcategoryName>SECURITY_PERMISSION_CATEGORY</csvcategoryName> <csvdisplayName>com.ptc.core.security.securityResource:READ</csvdisplay Name> <csvdescription>com.ptc.core.security.securityResource:READ</csvdescript ion> <csvlongDescription>com.ptc.core.security.securityResource:READ</csvlong Description> <csvdefaultValue>UPDATE</csvdefaultValue> <csvhandler>com.ptc.windchill.enterprise.preference.handler.ChoiceMultiPr eferenceValue Handler:readPermission:HIDE,com.ptc.core.security.securityResource,HIDE:V IEW,com.ptc. core.security.securityResource,VIEW:UPDATE,com.ptc.core.security.security Resource, UPDATE</csvhandler> </csvPreferenceDefinition>

352

Windchill Customization Guide

<csvLinkPreferenceClientDefinition handler="wt.preference.LoadPreference.setClientDefinitionLink"> <csvname>security/accessPermissionRead</csvname> <csvclientName>WINDCHILL</csvclientName> </csvLinkPreferenceClientDefinition>

The initial state of the permission configuration can be modified by changing the csvdefaultValue for the permission entry. The possible values are HIDE, READ, and UPDATE.

Sample Code
Examples of usage in OOTB code
Manage Security Action in document action model The Manage Security is an action available in the action list on a document info page. The action is included in the docs details page actions action model defined in Windchill\codebase\actionmodels.xml
<!-- list used on document details page --> <model name="docs details page actions"> <action name="oldedit" type="document"/> <action name="download" type="document"/> <action name="route" type="workflow"/> <action name="setState" type="lifecycle"/> <action name="createSubscription" type="subscription"/> <action name="checkout" type="object"/> <action name="checkin" type="document"/> <action name="undocheckout" type="object"/> <action name="rollupIterations" type="object"/> <action name="update" type="document"/> <action name="rename" type="document"/> <action action name="ManageSecurity" type="accessPermission"/> type="accessPermission" <action name="delete" type="object"/> <action name="bookmarkIt" type="bookmark"/> <action name="create_deli" type="deliverable"/> <action name="cut" type="object"/> <action name="copy" type="object"/> <action name="export" type="object"/> <action name="viewInProductView" type="document"/> <action name="pdmCheckInApply" type="object"/> <action name="SBSendToPdm" type="sandbox"/> <action name="sandboxUndoCheckoutDetails" type="object"/> <action name="removeShare" type="object"/> <action name="EDA_COMPARE" type="EDAcompare"/> <action name="VALIDATION_MANAGER" type="EDAcompare"/> <action name="SETUP_FILE" type="EDAcompare"/> <action name="wtObjCompare" type="ocmp"/> </model>

Customizing HTML Clients Using the Windchill JSP Framework

353

Access Control Step in Create Document Wizard The Create Document wizard is an example of Access Control as a step in a create wizard. Source file: wcEnterprise\DocumentManagement\src_web\netmarkets\jsp \document\create.jsp
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components" %> <%@ taglib prefix="docmgnt" uri="http://www.ptc.com/windchill/taglib/docmgnt" %> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <jca:initializeItem operation="${createBean.create}"/> <docmgnt:validateNameJSTag/> <jca:wizard title="${param.titleString}"> <jca:wizardStep action="setContextWizStep" type="object"/> <jca:wizardStep action="defineItemWizStep" type="object"/> <jca:wizardStep action="setAttributesWizStep" type="object" /> <jca:wizardStep action="attachments_step" type="attachments" /> <jca: jca:wizardStep wizardStep action="setAccessControlWizStep" type="object"/> type="object" </jca:wizard> <jca:action actionName="fileSelectionAndUploadApplet" actionType="attachments" /> <script type="text/javascript"> setUserSubmitFunction(submitFileContent); </script> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

The definition of setAccessControlWizStep is in Source file: Windchill\codebase\config\actions\Security-actions.xml defines


<action name="setAccessControlWizStep setAccessControlWizStep" id="setAccessControlWizStep" preloadWizardPage="false"> <command class="com.ptc.core.security.forms.UpdatePermissionsFormDelegate" method="" windowType="wizard_step"/> </action>

354

Windchill Customization Guide

Attachments
Objective
You want to add or modify the ability to add, modify, and download content from a format content holder or content holder business object

Background
The ability to add attachments to an object is the ability to upload and associate a file, link to a url, or describe an external location of content and associate that content data with this object. For example you may create a document and upload one or more files. You may also add multiple urls that point to additional information as supporting material for a change request. Object types such as documents implement an interface called FormatContentHolder which allows them to associate one piece of content as primary content. There can only be one primary content though. Object types such as a change requests implement ContentHolder which allow them to have multiple secondary content but not primary attachments. Objects that implement FormatContentHolder however can have both primary and secondary attachments because FormatContentHolder is a specialization of the ContentHolder interface.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Assumptions: The wizard that is using the attachment components implements either the FormatContentHolder or the ContentHolder interfaces. The wizard is using the Windchill Client Architecture wizard framework The user is familiar with the actions framework

Intended Outcome By following these procedures you should be able to add or modify the following components to your UI.

Customizing HTML Clients Using the Windchill JSP Framework

355

Primary content component in a wizard (object must be a FormatContentHolder)

Secondary attachments component in a wizard (object must be a ContentHolder)

356

Windchill Customization Guide

Attachments table in a details page (object must be a ContentHolder)

Primary content component in an info page properties panel (object must be a FormatContentHolder)

Primary content component in an info page properties panel (object must be a FormatContentHolder)

Solution
Use the Attachments Common Components with customized JSP clients associated to that object type.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving HTML forms, JSP, and JSP custom tags The wizard is using the Windchill Client Architecture wizard framework The user is familiar with the actions framework

Solution Elements
Element attachments.tld Type Java tag definition Description Defines any common component tags you will need to use the attachments common components. Runtime location:

Customizing HTML Clients Using the Windchill JSP Framework

357

Element

Type

Description codebase\WEB-INF\tlds\ attachments.tld Servlet that redirects download to the appropriate file for the object. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar Supporting methods for validating various attachments related actions. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar General form processing delegate that provides shared attachments functionality to the primary and secondary form processors. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar Form processing delegate that attaches primary attachments to the object. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar Form processing delegate that attaches secondary attachments to the object. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar Supporting methods for displaying attachments data in a data
Windchill Customization Guide

AttachmentsDownload AppletServlet.class

Java file

AttachmentsValidation Helper. class

Java file

AbstractAttachments SubForm- Java file Processor.class

PrimayAttachment SubFormProcessor.class

Java file

SecondaryAttachments SubFormProcessor.class

Java file

AttachmentsDataUtility Helper. Java file class

358

Element

Type

Description utility. Runtime location: codebase\WEB-INF\lib\ wncWeb.jar

Procedures
Adding primary content to a wizard To add primary attachment support to a wizard of an object that implements the FormatContentHolder interface you will need to add the applet tag to the main wizard jsp and the primary attachment tag to a wizard step. On the main wizard jsp (which defines the <jca:wizard tag and the wizard steps) add the following tag definition and fileSelectionAndUploadApplet tag. The tag will render a tiny invisible applet which is used for file browsing and file uploading.
<%@taglib prefix="attachments" uri="http://www.ptc.com/windchill/taglib/attachments" %> <attachments:fileSelectionAndUploadApplet/>v

On the wizard step you will need to add the same taglib definition above (but not the applet tag) and the following tag. This tag will render the actual primary attachment input components such as the file chooser or the url inputs.
<attachments:primaryAttachment/>

Adding secondary attachments to a wizard To add secondary attachment support to a wizard of an object that implements the ContentHolder interface you will need to add the applet tag to the main wizard jsp and the attachments wizard step. On the main wizard jsp (which defines the <jca:wizard tag and the wizard steps) add the following tag definition and fileSelectionAndUploadApplet tag. The tag will render a tiny applet which is used for file browsing and file uploading.
<%@taglib prefix="attachments" uri="http://www.ptc.com/windchill/taglib/attachments" %> <attachments:fileSelectionAndUploadApplet/>

Customizing HTML Clients Using the Windchill JSP Framework

359

Inside your wizard definition (inside the <jca:wizard tags) add the following wizard step in the order that you would like it to appear.
<jca:wizardStep action="attachments_step" type="attachments" />

Adding primary attachments to an info page


On your info page jsp you will need to add the following inside the describePropertyPanel tags to get the primary attachment info and download icon included in the info page attributes.
<jca:describeProperty id="primaryAttachmentProperties" label="${primaryLabel}"/>

To get it on the additional attributes info page add this to your object's attributes.jsp
<jsp:include page="/netmarkets/jsp/attachments/attachments_table.jsp" flush="true"> <jsp:param name="role" value="PRIMARY" /> </jsp:include>

Adding secondary attachments to an info page On your object's attributes.jsp add the following to get the secondary attachments to show up under the more attributes sub navigation of the info page.
<jsp:include page="/netmarkets/jsp/attachments/attachments_table.jsp" flush="true"> <jsp:param name="role" value="SECONDARY" /> </jsp:include>

Adding Primary attachment actions to an object In the action model xml file that defines the action model with the menufor attribute for your object type add the following actions. This will provide download or url redirect actions depending on if the object has a primary file or url.
<action name="download_primary_attachment" type="attachments"/> <action name="redirect_primary_attachment" type="attachments"/> <action name="checkout_and_download" <action name="replace_content" type="wip"/> type="wip"/>

360

Windchill Customization Guide

Customization Points
<primaryAttachment> tag attributes Parameter allowFile allowUrl allowExternal Default Value true true true Possible Values True/False True/False True/False Req? no no no Description Allows the Local File option to be displayed. Allows the URL Link option to be displayed. Allows the External Storage option to be displayed. Renders the file path specified instead of allowing the user to choose the file. If fixedFileUpload param on this tag and the forceApplet param on the fileSelectionAndUpload Applet tag are both set this can be used to force the specified file to be uploaded and attached to the object. Determines if we should force the applet to be rendered regardless of the upload mechanism preference

fixedFilePath

null

Valid file path

no

forceApplet

False

True/False

no

How to hide primary content for an object


In order to hide primary content for an object you will need to do the reverse of the above five procedural steps by removing those entries from the wizards, jsps, and the action model. You will also need to modify \codebase\netmarkets\jsp\wip\checkin_step.jsp and remove the if block for FormatContentHolder with the page include for the FormatContentHolder page (leave the getRespectiveNonFormatContentHolderPage include there).

Customizing HTML Clients Using the Windchill JSP Framework

361

Additional notes about documents:


For documents only (not other FormatContentHolders) you will find similar entries in the wizard jsps but they may slightly vary by referring to an MSOI tag which extends the attachments tags. Removing these tags will remove primary attachments from documents but it will also render desktop integration useless since desktop integration depends on having file primary attachments. You will also need to remove the createMulti action from all action models since it depends on primary content. How to remove url & external data options On the primaryAttachment tag you may set the allowUrl and allowExternal attributes to false. In the event that you wish to disable url and external data options for documents only you can modify the following file.
codebase\WEB-INF\tags\primaryAttachmentWithMSOI.tag

Limitations
Primary content
For primary attachments code to function properly you need both the primaryAttachment tag as well as the fileSelectionAndUploadApplet tag, regardless of whether or not you are using applet upload. While some behavior can be controlled by custom code we highly recommend that you first try adjusting the site level preferences and tag attributes to accomplish your goal before customizing your code. The fileSelectionAndUploadApplet tag must be on the jsp that defines the wizard but outside of the wizard tags or it will not function properly. Secondary content For secondary attachments code to function properly you need attachments step defined in your wizard as well as the fileSelectionAndUploadApplet tag, regardless of whether or not you are using applet upload. The fileSelectionAndUploadApplet tag must be on the jsp that defines the wizard but outside of the wizard tags or it will not function properly.

362

Windchill Customization Guide

Sample Code
Examples of Usage in Windchill Code
Secondary attachments Excerpt from the create change request wizard ( <Windchill>\codebase\ netmarkets\jsp\changeRequest \create.jsp).
... %><%@taglib prefix="attachments" uri="http://www.ptc.com/windchill/taglib/attachments" ... <jca:wizard helpSelectorKey="change_createChangeRequest" buttonList="DefaultWizardButtonsWithSubmitPrompt" formProcessorController="com.ptc.windchill.enterprise.change2.form s.controllers.ChangeRequestFormProcessorController"> ... <jca:wizardStep action="attachments_step" type="attachments" /> ... </jca:wizard> <attachments:fileSelectionAndUploadApplet/> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Primary attachments Wizard JSP


<%@taglib prefix="attachments" uri="http://www.ptc.com/windchill/taglib/attachments" %> ... <jca:wizard buttonList="DefaultWizardButtonsWithSubmitPrompt"> ... <jca:wizardStep action="attributes_step" type="attachments" /> ... </jca:wizard>

Customizing HTML Clients Using the Windchill JSP Framework

363

.<attachments:fileSelectionAndUploadApplet/> ...

Attributes Step JSP


<%@taglib prefix="attachments" uri="http://www.ptc.com/windchill/taglib/attachments" %> ... <attachments:primaryAttachment> ...

364

Windchill Customization Guide

Attribute Panels
You want to display attributes of a Windchill object in a name: value format. The attribute values could be read-only or editable. The practices described in this section should be used when you want to display attributes of a single Windchill object for viewing or editing. Both hard and soft attributes can be displayed. The attribute panel object may or may not be TypeManaged, however to configure the panel from a layout it must be TypeManaged. Intended Outcome After reading this document you should be able to create simple and advanced attribute panels in either edit or view mode. Specifically, you will learn how to: Create advanced attribute panels using Type Management layouts Create simple and advanced attributes panels by manually configuring the panels in a Java builder class Create simple attribute panels using JSP tags Include your panel in a JSP page Convert custom attribute panels/tables created in Windchill Release 9.0 or later to Windchill Release 10.0 attribute panels

Background
Windchill provides an attribute panel component that can be used to display attributes of a Windchill object. Typically, these are used to display attributes in read-only mode on object info pages or in edit mode in wizards. Attribute panels can be configured to be a simple list of name:value pairs or they can be configured to have a more complex layout with: A border Attribute groups, each with a title and expand-collapse capability Multiple columns

The former will be referred to in this document as simple attribute panels and the latter as advanced attribute panels. Attribute Panel Examples This is an example of a simple view-only attribute panel:

Customizing HTML Clients Using the Windchill JSP Framework

365

This is an example of a simple editable attribute panel:

This is an example of an advanced view-only attribute panel with two groups and multiple columns in each group:

This is an example of an editable advanced attribute panel with a single group and one column:

366

Windchill Customization Guide

The advanced panel layout features are new for Windchill Release 10.0. Previously, only simple attribute panels, formerly called property panels, were used:

Also, prior to Windchill Release 10.0, object attributes were sometimes displayed in table format rather than in panels:

Customizing HTML Clients Using the Windchill JSP Framework

367

The attribute table format is no longer used in Windchill 10.0, although customizations using the attribute table component will continue to work.

Definition of Terms
Definition of terms used in this section. Term simple attribute panel advanced attribute panel Definition A single-column list of attribute name: value pairs Attribute name:value pairs contained in one or more groups, each with a title and an example-collapse feature. Groups may have multiple columns of attribute pairs. A border surrounds the entire panel. The context object for a panel, typically derived from a URL parameter such as oid The object that is passed to the data utilities that create the data model for the panel. The datum is created by the buildComponentData() method of builder classes. Also sometimes
Windchill Customization Guide

context object

datum object

368

Term

target object

Definition called row object. See NmObject Utilities on page 562 for more information. May be used when the datum for the panel is a composite object. The target object specifies the specific member of the datum object that should be used for the panel or attribute within the panel. For example, if your datum was a WTPartUsageLink, you could specify a target object of RoleAObject. The target object must be addressable from the datum object. See NmObject Utilities on page 562 for more information.

Solutions
Prerequisite Knowledge
To apply this best practice, you need to have an understanding of the following: The JSP-based client architecture framework in Windchill The Windchill MVC builder framework Lightweight Customization (LWC) in Windchill using the Windchill Type and
Attribute Management utility

JSPs, tag libraries, and JSTL

The Additional Resources on page 401 section includes references to many or all of these subjects.

Overview
Both simple and advanced attribute panels can be created using Java builder classes. Simple attribute panels can also be created using only JSP tags in certain limited cases. When a builder class is used to create a panel for a TypeManaged object, the contents and configuration of the panel can be defined in a layout in the Type and Attribute Management utility and retrieved by the builder class. Alternatively, the contents and configuration of the panel can also be defined in the builder itself. The recommended approach is to:

Customizing HTML Clients Using the Windchill JSP Framework

369

Use a layout-based based panel created by a Java builder whenever possible. This provides: easier customization a UI for ease of configuration greater reusability a more consistent product

Use a non-layout based panel created by a Java builder if: The object type being displayed is not TypeManaged or The type is TypeManaged but layouts are already defined for all related screen types and none are appropriate for your purpose

Use a JSP-tag based panel only if: You want to create a simple attributes panel and You only want to display a few attributes which do not require complex configurations and You dont want the overhead of creating a builder class

The system provides OOTB builders for several layout-based advanced attribute panels used for common, shared actions. These actions are: Action Name visualizationAndAttributes Action Object Type object Component Builder ID ComponentId.VIS_AND_ATTRIBUTES Description

primaryAttrbutes

object

attributes

object

Used to display the Visualization and Attributes panel on information pages ComponentId.PRI- Used to display the MARY_ATTRIAttributes panel on information paBUTES ges of object types that have no visualization component ComponentId. Used to display the ATTRIBUTES_ID More Attributes panel on information pages

370

Windchill Customization Guide

To display these panels you just specify the appropriate component builder id in the URL or action used to generate the panel on your page. You do not need to write any Java code or JSPs. The system also provides OOTB builders for the layout-based Attributes panels in object create and edit wizards that can be displayed by using the common step actions for wizards. To display a panel for a different layout or create a manually-configured panel you can extend an existing Java builder class. The decision diagram below provides general guidelines for how you should determine which builder to use for your panel, with references to the section of this document that describes the builder.

Customizing HTML Clients Using the Windchill JSP Framework

371

Solution Elements
Element Type and Attribute Management utility
372

Type Application

Description The application where you can:


Windchill Customization Guide

Element

Type

Description Define attributes on a type Define attribute layouts Configure the display properties of an attribute

MVC Builder

Java class

AttributePanelConfig

Java class

GroupConfig

Java class

AttributeConfig

Java class

ComponentConfigFactory Java class

See Type and Attribute Management for more information about this utility. Creates the configuration and datum object for the panel. Also can be used to specify the view (JSP) for the panel if a custom view is desired. The object that contains the GroupConfig(s) for an attribute panel. Also has several properties that can be used to configure the panel. The object that contains the AttributeConfig (s) for an attribute panel. Also has several properties that can be used to configure the group. Contains information about one attribute to be displayed in the panel, including its name and properties that control how the attribute should be displayed. A factory that generates AttributePanelConfigs,

Customizing HTML Clients Using the Windchill JSP Framework

373

Element

Type

TypedAttrLayOutFactory Java class

ScreenDefinitionName

Java enum

Description GroupConfigs, and AttributeConfigs A factory capable of generating an attribute panel configuration from a Type Management layout for a given object type and screen type Identifiers for the screen types shown in the Type
and Attribute Management utility Layouts tab. For a

ComponentId

Java class

ComponentMode

Java enum

ComponentType

Java enum

given object type each screen type maps to one layout. However, a layout may map to more than one screen type. Contains constants for some widely used component builder ids. Determines whether viewonly or input fields are displayed for attributes. Indicates how the attribute panel is being used. The ComponentType can affect such things as whether or not an attribute is visible or hidden, how an attribute is displayed (e.g., link vs text), and the HTML name given to an input field. If the ComponentType is WIZARD_ATTRIBUTES_TABLE the system will give attribute input fields HTML names that the system can use to set the attribute values on the

374

Windchill Customization Guide

Element

Type

<WT_HOME>/codebase/ JSP WEB-INF/jsp/components/attributePanel.jsp.

<WT_HOME>/codebase/ JSP WEB-INF/jsp/components/simpleAttributePanel.jsp

Description object for you. If you want to set all the attribute values yourself in a form processor, you should use the component type WIZARD_TABLE. Default view JSP for an advanced attribute panel. Occasionally, you may need to use a custom JSP for the view if you want to display additional components on the page or include additional javascript. Default view JSP for a simple attribute panel. Occasionally, you may need to use a custom JSP for the view if you want to display additional components on the page or include additional javascript.

Solution Create an Advanced Attribute Panel with a Visualization Component Using the Primary Attributes Layout
This is a composite panel comprised of: 1. The visualization component for the object type, if any, and 2. The attributes in the layout that maps to the screen type Information Page Primary Attributes " (ScreenDefinitionName.INFO) for the type of the object displayed in the panel This builder is invoked by the visualizationAndAttributes action defined for the type object. This action is widely used to display the Visualization and Attributes component on object info pages:

Customizing HTML Clients Using the Windchill JSP Framework

375

The component builder id for this builder is visualizationAndAttributes (ComponentId. VIZ_AND_ATTRIBUTES). See the javadoc for VisualizationAttributesBuilder for more information. To include this panel in your page you only need to specify the component builder id in the panel action or URL. See How to Find an Attribute Name/Id on page 392 for more information on how to include panels in a JSP page. If you have created a new Windchill type for which you would like to define a unique Visualization and Attributes panel, you will typically only need to define a layout for the INFO screen type in the Type and Attribute Management utility and possibly create a visualization delegate to display the visualization component. In the rare cases where you need to modify some aspect of the panel, such as the view JSP, you should create a custom builder extending the VisualizationAttributesBuilder. You might want to modify the view JSP to include additional components or javascript on the page. See Customizing Information Page Components on page 892 for more information.

Solution Create an Advanced Attribute Panel Without a Visualization Component Using the Primary Attributes Layout
This is a panel identical to that described the previous section, but with no visualization component. It is created using the builder class PrimaryAttributesPanelBuilder. The component builder id for this panel is primaryAttributes (ComponentId.PRIMARY_ATTRIBUTES). This builder is invoked by the primaryAttributes action defined for the type object. This action is used to display the Attributes component on object information pages for types that do not have a visualization component:

376

Windchill Customization Guide

See the javadoc for PrimaryAttributesPanelBuilder for more information. To include this panel in your page you only need to specify the component builder id in the panel action or URL. See How to Find an Attribute Name/Id on page 392 for more information on how to include panels in a JSP page.

Solution Create an Advanced Attribute Panel Using the Create, Edit, or More Attributes Screen Type Layout
The system provides the builder TypedAttributesPanelBuilder: Information Page More Attributes (ScreenDefinitionName. MORE_ATTRIBUTES) Create New (ScreenDefinitionName.CREATE ) Edit (ScreenDefinitionName.UPDATE)

Note For a few objects the system has defined subclasses of PrimaryAttributesPanelBuilder for the default builder.
This builder has the component builder id attributesTable (ComponentId.ATTRIBUTES_ID) and is used for the following actions defined for object type object: attributes The action typically used to display the component typically labeled More Attributes on object information pages defineItemAttributesWizStep Action which uses this builder indirectly to create the Attributes panel in object creation wizards. See Customizing Reusable Wizard Steps on page 860 for more information.

Customizing HTML Clients Using the Windchill JSP Framework

377

editAttributesWizStep Action which uses this builder indirectly to create the Attributes panel in object edit wizards. See Customizing Reusable Wizard Steps on page 860 for more information.

378

Windchill Customization Guide

See the javadoc for TypedAttributesPanelBuilder for more information on the ComponentMode, ComponentType, view JSP, and datum object used for these panels. Note that the wizard panels have a ComponentType of ComponentType.WIZARD_ATTRIBUTES_TABLE so that the editable fields will be given HTML names such that the wizard processing framework can identify the attributes that it should automatically set on the object being created or edited. See Building Wizards to Create a Single Object on page 823 for more information. To include the Information Page More Attributes panel in your page you only need to specify the component builder id in the panel action or URL See How to Find an Attribute Name/Id on page 392 for more information on how to include panels in a JSP page. To include the wizard panels in a wizard, use the common wizard step actions shown above. If you have created a new Windchill type for which you would like to display one of these panels, you will typically only need to define a layout for the appropriate screen type in the Type and Attribute Management utility. In the rare cases where you need to modify some aspect of the panel, such as the view JSP, you should create a custom builder extending the TypedAttributesPanelBuilder. See Customizing Information Page Components on page 892 for more information.

Customizing HTML Clients Using the Windchill JSP Framework

379

To modify the attributes displayed in these panels and their display properties you can modify the layout in the Type and Attribute Management utility. If it is necessary to modify a configuration property or the view JSP for a special use case, you can extend TypedAttributesPanelBuilder and override the buildAttributeComponentConfig() method (see Solution Create an Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute Management Utility on page 380). However, this should be avoided if at all possible as it will make the product less consistent. The following configuration properties are not overridable: ComponentMode of the panel ComponentType of the panel Datum object

If you want to modify any of these elements, you should write a custom builder extending AbstractComponentBuilder. See Solution Create an Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute Management Utility on page 380for more information.

Solution Create an Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute Management Utility
Create an advanced attribute panel using a layout defined in the Type and Attribute Management utility. Attributes may be editable, view-only, or a combination of editable and view-only. 1. The attributes of the object type and their display properties are defined in the Type and Attribute Management utility and in the Java class file for the type. 2. The layout and content of the attribute panel are defined in the Type and Attribute Management utility. 3. A MVC Java builder class builds the panel configuration from the layout definition using the TypedAttrLayOutFactory. It also retrieves/creates the datum object for the panel. 4. GUI components for the attributes are created by data utilities. 5. The attributes and their data are rendered in a view JSP by the rendering framework using the configuration and data model created by the builder and the data utilities. See Advanced Panel with Modified Context Object on page 405 for an example of this solution.

380

Windchill Customization Guide

Procedure Creating the Attribute Panel Either the builder com.ptc.jca.mvc. buildersTypedAttributesPanelBuilder or the builder com.ptc. mvc.components.AbstractComponentBuilder can be extended for creating a panel that is layout-based. If want to use the ComponentMode, ComponentType, and datum object set by the TypedAttributesPanelBuilder (refer to Solution Create an Advanced Attribute Panel Using the Create, Edit, or More Attributes Screen Type Layout on page 377 above) , you can extend the TypedAttributesPanelBuilder for convenience. Otherwise, you should extend the AbstractComponentBuilder. Extending the TypedAttributesPanelBuilder The panel produced by this builder by default is described in Solution Create an Advanced Attribute Panel Using the Create, Edit, or More Attributes Screen Type Layout on page 377. This builder calls the TypedAttrLayOutFactory to create the AttributePanelConfig and nested GroupConfigs and AttributeConfigs for the panel. In your custom builder you can modify the screen type used to look up the layout for the panel or the view used to render the panel. Typically, the configuration of the group(s) and attributes in the panel should be done in the Type and Attribute Management utility layout for consistency of the product. However, on rare cases you might have the need to modify a configuration property. For such a special use case, you can also postprocess the config objects created by the factory to modify configuration properties, such as the title of a group, the display mode of an attribute (editable/view-only), or the selection list style of a Boolean attribute. Most of the group and attribute configuration properties set in the Type and Attribute Management utility can be overridden in the builder class by setting properties on the GroupConfigs or AttributeConfigs. See Customization Points on page 395 for a list of configurable properties. Modifying the Panel Configuration To modify the panel configuation, override the buildAttributePanelConfig() method. The buildAttributePanelConfig() method creates an AttributePanelConfig. Examples of some configuration changes you might want to make are:

Customizing HTML Clients Using the Windchill JSP Framework

381

The Type and Attribute Management utility layout to be used for the panel. To use a different screen type for the layout lookup, use the TypedAttrLayOutFactory to retrieve a different AttributePanelConfig :
getTypedAttrLayOutFactory().getAttributePanelConfig(getComponentConfigFactory(), params, ScreenDefinitionName.<your screen type>);

The class ScreenDefinitionName lists the available screen types. Change the ComponentMode of one or more of the attribute fields to viewonly in an editable attribute panel or vice versa. If the component mode is not specifically set on the attributes ComponentConfig, the component mode defined for the panel will be used. See Modifying a Property of an AttributeConfig in an AttributePanelConfig Created by the TypedAttrLayOutFactory on page 400 example code in for how to make a single field editable or view-only. The label for a group within the panel or an individual attribute. This can be specified by calling setLabel() method on the group or attribute config. Modifying the Panel View (JSP) See How to Modify the Panel View JSP on page 392 Modifying the Panel Context Object See How to Modify the Panel Context Object on page 393 Extending the AbstractComponentBuilder Because you want a layout-based panel, your custom builder should implement com.ptc.mvc.components.TypedAttrLayOutFactoryAware, which will give you access to an instance of the TypedAttrLayOutFactory which you will need to obtain configs based on a layout. The AbstractComponentBuilder does not provide any default behavior so you will need to write the following methods from scratch: public void setTypedAttrLayOutFactory(TypedAttrLayOutFactory factory) protected AttributePanelConfig buildComponentConfig(ComponentParams params) public Object buildComponentData(ComponentConfig config, ComponentParams params)

382

Windchill Customization Guide

setTypedAttrLayOutFactory() setTypedAttrLayOutFactory() The TypedAttrLayOutFactory is used to create panel configs based a given screen type. You should declare a global variable of that type and implement this method, as follows:
TypedAttrLayOutFactory tfactory; public void setTypedAttrLayOutFactory(TypedAttrLayOutFactory factory) { this.tfactory = factory; }

The framework will call this method to provide you with an instance of the factory. buildComponentConfig() buildComponentConfig() This method should create the AttributePanelConfig by calling the TypedAttrLayOutFactory and passing it the ScreenDefinitionName corresponding to the layout you want to use for your panel. For example:
AttributePanelConfig panelConfig = tfactory.getAttributePanelConfig(getComponentConfigFactory(), params, ScreenDefinitionName.CREATE);

The AttributePanelConfig that is returned will have nested GroupConfigs and AttributeConfigs as defined in the layout. If desired, you can tweak the configs that are returned by the factory to modify any of the configuration properties listed in Customization Points on page 395. See Procedure Creating the Attribute Panel on page 381 for some examples. Also see How to Modify the Panel View JSP on page 392 and How to Modify the Panel Context Object on page 393 buildComponentData() buildComponentData() This method should return a single datum object for the panel. For view-only panels, this is typically a Persistable object instance. For wizards, this should usually be a TypeInstance, which will contain the constraints that have been defined for the attributes in addition to the attribute values. To return a Persistable datum object, it is typically appropriate just to return the context object, as follows: Object datumObject = params. getContextObject(); Alternatively, you could query for the Persistable object. To obtain a TypeInstance datum object for a create or edit wizard, you can call CreateAndEditModelGetter.getItemAttributes() as described in Obtaining a TypeInstance Datum Object on page 400. Alternatively, you could use TypeInstance APIs to obtain the TypeInstance.

Customizing HTML Clients Using the Windchill JSP Framework

383

Solution Create a Simple or Advanced Attribute Panel Using a Configuration Created in a Java Builder Class
Overview Create a simple or advanced attribute panel using a configuration defined in a Java builder class. Attributes may be editable, view-only, or a combination of editable and view-only. This approach is applicable for object types that are not TypeManaged. It may also be used for TypeManaged objects, but we recommend you use layout-based panels for those types whenever possible, for ease of customization and other reasons cited earlier. 1. The attributes of the object type and their display properties are defined in the Java object class file or in the Type and Attribute Management utility. 2. A MVC Java builder class creates the panel configuration and retrieves/creates the datum object for the panel. 3. GUI components for the attributes are created by data utilities. 4. The attributes and their data are rendered in a view JSP by the rendering framework using the configuration and data model created by the builder and the data utilities. Examples of this solution are given in: Advanced Attribute Panel on page 402 Advanced Attribute Panel in a Wizard on page 403 Advanced Attribute Panel on an Information Page on page 404 Simple Attribute Panel using a Java Builder on page 407 Simple and Advanced Attribute Panels in a Wizard on page 409

Procedure Creating the Attribute Panel Either the builder com.ptc.jca.mvc.builders. AbstractAttributesComponentBuilder or the builder com.ptc. mvc.components.AbstractComponentBuilder can be extended for creating a panel that is not layout-based. . The AbstractAttributesComponentBuilder sets the ComponentMode and datum object as described in the class javadoc. These configurations are not overridable. If you want your panel to be configured as described, you can extend AbstractAttributesComponentBuilder for convenience. Otherwise, you should extend AbstractComponentBuilder.

384

Windchill Customization Guide

Extending AbstractAttributesComponentBuilder Creating the Panel Configuration 1. Implement the buildAttributesComponentConfig() method to create the panel configuration. a. Create the panel config. Call the ComponentConfigFactory embedded in the class to create an AttributePanelConfig.
ComponentConfigFactory factory = getComponentConfigFactory(); AttributePanelConfig panelConfig = factory.newAttributePanelConfig (<id of your component>);

Set the desired properties on the panel config. See AttributePanelConfig Properties on page 395 for configuration points. Do not set the component mode as it will be overridden by the parent class. Also, do not set the ComponentType in this method, that can be done in step 2. b. Create the attribute and group configs. Every panel must have at least one group. Simple attribute panels must have only one group, which will not be visible in the UI. For simple attribute panels, you can use the technique described in Case 1 below, which will automatically create a group config for you. For advanced attribute panels, use the technique in Case 2 below to create one or more groups with labels of you choosing. Case 1: Simple attribute panel i. Create one attribute config for each attribute you want to display using the ComponentConfigFactory :
AttributeConfig attrConfig = factory.newAttributeConfig (<attribute name>);

Set additional properties on the AttributeConfig if desired. See AttributeConfig Properties on page 397 for configuration points. Note you should not set rowPos, colPos, or colSpan properties on AttributeConfigs for simple attribute panels. ii. Add the attribute configs to the panel as follows:
panelConfig.addComponent(attrConfig);

The addComponent() method will create a group config automatically the first time it is called.

Customizing HTML Clients Using the Windchill JSP Framework

385

Case 2: Advanced attribute panel i. Create at least one GroupConfig using the ComponentConfigFactory :
GroupConfig groupConfig = factory.newGroupConfig ("<id of your group>"); groupConfig.setLabel("<your group label>");

The label is the title that will be displayed in the UI and should be localized from a resource file if appropriate:

Set the desired properties on the GroupConfig. See GroupConfig Properties on page 397 for configuration points. ii. Create the attribute configs and add them to the group config. Create an AttributeConfig for each attribute you want to display in the panel using the ComponentConfigFactory. For example:
AttributeConfig attrConfig = factory.newAttributeConfig(< attribute name>);

Set the desired properties on each attribute config. See AttributeConfig Properties on page 397 for configuration points. Add each AttributeConfig to the GroupConfig :
groupConfig.addComponent(attrConfig);

iii. Add the group config to the panel config.


panelConfig.addComponent(groupConfig);

2. Override the getComponentType() method to set the component type of the panel, if desired. If you do not override this method, the parent class will set the ComponentType as described below. If ComponentMode is ComponentMode.VIEW, ComponentType is set to ComponentType.INFO_ATTRIBUTES_TABLE Otherwise, ComponentType is set to ComponentType.TABLE

If the panel is to be displayed in a create or edit wizard and contains attributes you want the framework form processors to set automatically for you, you should return component type ComponentType. WIZARD_ATTRIBUTES_TABLE. Otherwise, you can accept the default setting for wizard panels. Modifying the Panel View (JSP) See How to Modify the Panel View JSP on page 392 for more information.

386

Windchill Customization Guide

Modifying the Panel Context Object See How to Modify the Panel Context Object on page 393 for more information. Extending AbstractComponentBuilder You will need to implement two methods in your builder: ComponentConfig buildComponentConfig(ComponentParams params) Object buildComponentData(ComponentConfig config, ComponentParams params)

buildComponentConfig() buildComponentConfig() This can be implemented as described in Procedure Creating the Attribute Panel on page 384 above except that you will also need to set the ComponentMode and ComponentType of the panel in this method. You do that by calling the following methods on the AttributePanelConfig :
setComponentMode(ComponentMode) setComponentType(ComponentType)

This is also where you should set a custom view JSP, if desired. buildComponentData() buildComponentData() See Procedure Creating the Attribute Panel on page 381 for more information.

Solution - Create a Simple Panel Using JSP Tags


Overview Use JSP tags to configure, acquire the data for, and display a simple attribute panel. Attributes may be editable, view-only, or a combination of editable and view-only. The type of the context object may or may not be TypeManaged. 1. Use the describePropertyPanel tag to define the attributes to be displayed in the panel and other configuration properties. 2. Use the getModel tag to specify a server method that should be called to retrieve the datum object for the panel. 3. The getModel tag calls data utilities to create GUI components for the attributes 4. Use the renderPropertyPanel tag to display the panel on the JSP page. An example of this solution is given in section Simple Attribute Panels using JSP Tags on page 408.

Customizing HTML Clients Using the Windchill JSP Framework

387

Procedure Creating the Attribute Panel Create the JSP page in which you want to display your panel. This could have other components in addition to your attribute panel. Include the following taglib directive in your JSP page:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%>

Describe the Attribute Panel To describe the property panel use the describePropertyPanel and describeProperty tags:
<jca:describePropertyPanel var="<name of the descriptor>">> <jca:describeProperty id="<attribute name>" /> <jca:describeProperty id="<attribute name>" /> <jca:describeProperty id="<attribute name>" /> </jca:describePropertyPanel>

The name of the descriptor can be any name that identifies your panel. It will be used as the name of the variable in the JSP context that holds the panel descriptor object. Both of these tags have optional attributes that can be used to configure how the GUI components for attributes are created and/or displayed. See the javadoc for the tags for more information. Acquire the Data Model for the Attribute Panel The getModel tag will acquire a datum object for the panel by calling a service method you specify. It will then call the data utilities to produce the GUI components for the attributes using the datum object. For example:
<jca:getModel var="<name of the data model>" descriptor="${<name of the descriptor>}" serviceName="wt.fc.StandardPersistenceManager" methodName="refresh"> <jca:addServiceArgument value="${commandBean.primaryOid.oid}" type="wt.fc.ObjectIdentifier" /> </jca:getModel>

The value for <name of the data model> can be any name you wish to assign to your model. It will be used as the name of a scoped variable in the JSP context that will hold the created data model. The value for <name of the descriptor> should be that used in your describePropertyPanel tag. The serviceName and methodName parameters specify a service method that should be called to acquire the datum object for the model. The addServiceArgument subtag can be used to pass parameters to the service

388

Windchill Customization Guide

method. Typically, the StandardPersistenceManager.refresh() method is used to acquire a Persistable for the daum object of view-only panels. For example:
<jca:getModel var="propertyModel" descriptor="${propertyPanelDesc} "serviceName="wt.fc.StandardPersistenceManager" methodName="refresh"> <jca:addServiceArgument value="${commandBean.primaryOid.oid} " type="wt.fc.ObjectIdentifier" /> </jca:getModel>

Alternatively, a query command or service method can be called to retrieve the datum object. The datum object for a wizard panel should typically be a TypeInstance. The CreateAndEditModelGetter.getItemAttributes() method can be used to acquire a TypeInstance datum object for wizards that include an initializeItem tag. For example:
<jca:getModel var="attributesTableModel" descriptor="${meetingPanelModel}" serviceName="com.ptc.core.components.forms.CreateAndEditModelGetter" methodName="getItemAttributes"> <jca:addServiceArgument value="${ meetingPanelDescriptor }" type="com.ptc.core.components.descriptor.ComponentDescriptor"/> <jca:addServiceArgument value="${commandBean}" type="com.ptc.netmarkets.util.beans.NmCommandBean"/> <jca:addServiceArgument value="${nmcontext.context}" type="com.ptc.netmarkets.util.misc.NmContext"/> </jca:getModel>

See the getModel tag javadoc for more information. Render the Property Panel To render the property panel use the renderPropertyPanel tag. For example:
<jca:renderPropertyPanel model="${<name of the data model>}"/>

The value for <name of the data model> should be that used in your getModel tag.

Converting a Tag-based Tag-based Attribute Panel to a MVC Attribute Panel


In prior releases all attribute panels, known as property panels, were created and displayed using the tag-based approach described in the preceding section. Also, in prior releases, it was possible to create attribute tables, which were very similar in construction except that a describeAttributesTable tag was used instead of a describePropertyPanel tag and a renderTable tag was used instead of a renderPropertyPanel tag.

Customizing HTML Clients Using the Windchill JSP Framework

389

Such panels and attribute tables can fairly easy be converted to MVC attribute panels, as outlined below. Note that if you convert a panel or table to a MVC panel, you should be sure to remove any *typedservices.properties. xconf file entries related to the panel or table in addition to removing the related JSP files. If the panel is for a custom object type that is Typed and it corresponds to one of the screen types for which an OOTB builder class is available (see section Solution Create an Advanced Attribute Panel with a Visualization Component Using the Primary Attributes Layout on page 375, Solution Create an Advanced Attribute Panel Without a Visualization Component Using the Primary Attributes Layout on page 376, and Solution Create an Advanced Attribute Panel Using the Create, Edit, or More Attributes Screen Type Layout on page 377), you should simply define a layout for that screen type in the Type and Attribute Management utility. Add each attribute included in your describePropertyPanel/ describeAttributesTable tag to the layout. Most of the configuration attributes available for the tags can be defined in the Type and Attribute Management utility. To display your panel, use one of the techniques described in How to Include an Attribute Panel in a JSP Page on page 393. You do not need to write a Java builder class unless you need to use a different view JSP or datum object than that defined by the OOTB builder. Note: if your custom object type does not implement Typed, you can modify it to implement TypeManaged so that it will be displayed in the Type and Attribute Management utility and layouts can be defined for it. If your custom object type is Typed or TypeManaged and your panel is for one of the screen types available in the Type and Attribute Management utility for which no OOTB builder exists, you should create a layout in the Type and Attribute Management utility for that screen type. Add each attribute included in your describePropertyPanel/ describeAttributeTable tag to the layout and configure its display in the Type and Attribute Management utility based on the attributes you had included in your describeProperty tag. You will also need to create a Java builder class to create an AttributePanelConfig from the layout (see Solution Create an Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute Management Utility on page 380). In your Java builder class, you should include a buildComponentData() method that creates the panel datum object by calling the same method invoked by your getModelTag(). To render the panel, use one of the techniques described in How to Include an Attribute Panel in a JSP Page on page 393.

390

Windchill Customization Guide

If you choose not to make your object type TypeManaged or the panel is not for one of the available screen types, create a Java builder class for your panel as described in Solution Create a Simple or Advanced Attribute Panel Using a Configuration Created in a Java Builder Class on page 384, following the techniques for a simple attribute panel. Note that: The AttributePanelConfig created by your builder s buildComponentConfig() or buildAttributesComponentConfig() method corresponds to the config created by your describePropertyPanel/ describeAttributesTable tag. Translate any attributes on your tag to the equivalent properties on the AttributePanelConfig. See How to Modify the Panel Context Object on page 393 for how to modify the panel context object, which corresponds to the oid attribute of the describePropertyPanel tag. The AttributeConfigs created by your builder correspond to the configs created by your describeProperty tag. Translate any attributes on your describeProperty tag to the equivalent properties on the AttributeConfig. The buildComponentData() method of the builder corresponds to the getModel tag. You can call the same method to acquire the panel datum object in your buildComponentData() method as you did from your getModel() tag. The tag <mvc:simpleAttributePanel> corresponds to the renderPropertyPanel/renderTable tag. This tag is called by the view JSP <WT_HOME>/codebase/WEB-INF/jsp/components/ simpleAttributePanel.jsp. Typically, you should specify that JSP view by calling the setView() method on the AttributePanelConfig in your builder. Note that the default component id used for AttributePanelConfigs is attributePanel. If you specified a compId attribute on your tag you may need to create a custom JSP view page for your panel and set the view to that JSP. In your custom JSP, you should set the component id by including a compIdattribute on the <mvc: simpleAttributePanel> tag.

Customizing HTML Clients Using the Windchill JSP Framework

391

General Procedures
How to Annotate Your Custom Builder Class You should annotate your builder class with the component builder id you will use for your panel. You should also include a TypeBased annotation if you want to use different builders for different object types for the same component builder id. For example:
@ComponentBuilder(exampleBuilderId) @TypeBased(value = "com.acme.SomeType") public class ExamplePanelBuilder extends TypedAttributesPanelBuilder

How to Find an Attribute Name/Id When creating an AttributeConfig or a describeProperty tag you must specify the name/id of the attribute. See How to Find an Attribute ID on page 671 for more information. How to Access Request and Context Information in Builder Methods The ComponentParams parameter passed to buildComponentConfig() and uildComponentData () method is an instance of the concrete class JcaComponentParams. This class provides you access to all the request parameter values and attributes, as well as the typical beans used by JCA clients, such as the NmCommandBean, NmSessionBean, and NmContextBean. See Windchill Client Architecture Common Objects Overview on page 239 for more information on these classes. How to Modify the Panel View JSP The view is defined in the AttributePanelConfig. By default it is <WT_HOME>/codebase/WEB-INF/jsp/components/ attributePanel.jsp, which is the view for an advanced attribute panel. If you are creating a simple attribute panel, you should modify the view to use <WT_HOME>/codebase/WEB-INF/jsp/components/ simpleAttributePanel.jsp. You can modify the view in the buildAttributePanelConfig() method by calling the setView() method on the AttributePanelConfig. For example:
panelConfig.setView("/components/simpleAttributePanel.jsp";

392

Windchill Customization Guide

You could also modify the view to use a custom JSP if you want to display other components on the page or include additional javascript. The path name of the JSP passed to the setView() method should be relative to <WT_HOME>/ codebase./WEB-INF/jsp. To display your advanced panel in your custom JSP use the following tag for an advanced panel:
<mvc:attributePanel/>

or this tag for a simple attribute panel:


<mvc:simpleAttributePanel/>

You should include the following taglib directive in your custom JSP:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%>

Note that any JSP page that renders a MVC component should include the following directive before rendering any page content:
%@include file="/netmarkets/jsp/util/begin_comp.jspf"%

and the following directive at the end of the page:


<%@ include file="/netmarkets/jsp/util/end_comp.jspf"%>

These should be used in lieu of any other include directives for *begin* or *end* files. How to Modify the Panel Context Object The TypedAttributesPanelBuilder and AbstractAttributesComponentBuilder use the context object from the request to create the datum object for a panel. On rare occasions, it might be necessary to use a different context object for a panel. This should be done with extreme care. It must be done before any of the panel configs are created. Also, it could have unwanted side effects if other components are displayed on the page. This technique should only be used for view-only panels. Within a wizard, the context object or type is always determined from the wizard step context. To specify a different context object, change the context object prior to building the panel config as follows: ((JcaComponentParams)params). setContextObject(container); How to Include an Attribute Panel in a JSP Page The techniques below apply to attribute panels created using Java builders. To display attribute panels on information pages, see Customizing Information Page Components on page 892 for more information.

Customizing HTML Clients Using the Windchill JSP Framework

393

To Display a Link or Button That Launches Your Panel To include a link or button that will launch your panel on a JSP page, create an action for your panel in your custom-actions.xml file and reference the action in an action tag in your JSP page. Your action should have a component subtag whose name is the id for your component builder. Example action:
<action name="myAttributePanel"> <component name="myPanelComponent" typeBased="true" windowType="page" /> </action>

See Windchill Client Architecture Action Framework Overview on page 486 for more information on actions and action attributes. Example action tag:
<%@ tagliburi="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> . . . <jca:action actionName="myAttributePanel" actionType="object" showIcon="false/>

See the javadoc for the action tag for more information on the available tag attributes. An alternative way to include a link to your panel is to use an <a> tag with a href constructed using the getComponentURL tag or getTypeBasedComponentURL tag. The former would be used when there is a single builder for a component builder id. The latter would be used when there are alternative builders for the builder id based on the type of the panel object. For example:
%@page import="com.ptc.netmarkets.util.misc.NetmarketURL"% <%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%> . . . <a href="<%=NetmarketURL.APPPREFIX%>${mvc:getTypeBasedComponentURL (myPanelComponent)}">

In this example myPanelComponent is the component builder id. To Include Your Panel Inline on a JSP Page Use the getComponentURL or getTypeBasedComponentURL tag to include your panel in a page. For example:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc"%> . . . <jsp:include page="${mvc:getComponentURL(attributesTable)}" />

394

Windchill Customization Guide

The getTypeBasedComponentURL should be used with builders that have a TypeBased annotation. It will generate a URLwith a tcomp handler key that tells the system to do a type-based lookup of the builder class. For example:
Windchill/ptc1/tcomp/attributesTable?typeBased=%27true%27& typeIdForTypeLookup=%27wt.doc.WTDocument%27&portlet=component

If the panel builder is not TypeBased, use the getComponentURL tag.

Customization Points
AttributePanelConfig Properties
The following parameters may be set using methods on the AttributePanelConfig class. Parameter id Default Value attributePanel Possible values Any string Req? no Description The id given to the ComponentDefinition for the panel. Also appears in the HTML div names wrapping the component. If specified, you will need to use a custom view JSP for the panel and pass this id as the compId parameter to the <mvc: attribubtePanel> or <mvc:simpleAttributePanel> tag in the JSP.

Customizing HTML Clients Using the Windchill JSP Framework

395

Parameter view (JSP)

Default Possible values Value <WT_HOM- Any JSP E>/codebase/ WEB-INF/jsp/ components/attributePanel. jsp.

Req? no

Description The view will receive the ComponentDefinition defined by the builder and controllers and render it. See Solution Elements on page 372 The value for the panel config will be applied to attribute configs unless overridden See Solution Elements on page 372 The value for the panel config will be applied to attribute configs unless overridden See Solution Elements on page 372

componentMode

ComponentMode.VIEW

See Solution Elements on page 372

yes

componentType

ComponentSee Solution Mode.TABLE Elements on page 372

yes

targetObject

The value for the panel config will be applied attribute configs unless overridden The following parameters on the parent interface are NOT applicable to AttributePanelConfigs:
Windchill Customization Guide

The datum ob- See Solution ject is the tar- Elements on get object by page 372 default

no

396

Parameter helpContext actionModel label type

Default Value

Possible values

Req?

Description

GroupConfig Properties
The following parameters are applicable to AttributeGroupConfigs and may be set using methods on the GroupConfig class. Parameter sortOrder Default Value none Possible Required? values Integer number yes Description

The position of the group in the panel. none yes id Any string The id that will be applied to HTML div tags containing the group. none no label Any String The label displayed at the top of the group The following parameters on the parent interface are NOT applicable to GroupConfigs: helpContext actionModel componentMode componentType targetObject

AttributeConfig Properties
The following properties are applicable to AttributeConfigs and may be set using methods on that class. Many additional properties are available on the parent interface PropertyConfig. See Attribute Customization on page 630 for more information on these.

Customizing HTML Clients Using the Windchill JSP Framework

397

Parameter colPos

Default Value 1

Possible values Any number

Required? no

Description The column position of the attribute within the group. Only applicable to advanced attribute panels. Set the number of columns the attribute should span. A column is one name: value pair. Only applicable to advanced attribute panels. See the javadoc for AttributeConfig for more information. See Solution Elements on page 372 If not specified, the value for the panel config will used. The identifier for the attribute. See How to Find an Attribute Name/ Id on page 392 The label displayed for the attribute. If not specified, the

colSpan

Any positive number

no

componentMode

See the javadoc for ComponentMode

no

id

none

Any string

yes

label

none

Any String

no

398

Windchill Customization Guide

Parameter

Default Value

Possible values

Required?

Description label will be determined as described in Attribute Customization on page 630. The row position of the attribute within the group. If not specified, attributes will displayed in the order added to the group config. Only applicable to advanced attribute panels. See Definition of Terms on page 368 .

rowPos

Any number

no

targetObject

See Definition no of Terms on page 368

If not specified, the value for the panel config will be used, if any. The following parameters on the parent interfaces are NOT applicable to AttributeConfigs: componentType helpContext actionModel type

Customizing HTML Clients Using the Windchill JSP Framework

399

Sample Code
Example of Usage in Windchill Code
Modifying a Property of an AttributeConfig in an AttributePanelConfig Created by the TypedAttrLayOutFactory This shows how you might modify an AttributeConfig in an AttributePanelConfig created by the TypedAttrLayOutFactory.
List<ComponentConfig> components = attributePanelConfig.getComponents(); for (ComponentConfig componentConfig : components) { if( componentConfig instanceof JcaGroupConfig){ List<ComponentConfig> attributeConfigs = ((JcaGroupConfig) componentConfig).getComponents(); for (ComponentConfig attributeConfig : attributeConfigs) { String attributeName =((AttributeConfig)attributeConfig).getId(); if(attributeName.equals("name")){ attributeConfig.setComponentMode(ComponentMode.EDIT); } if(attributeName.equals("folder.id")){ ((JcaAttributeConfig)attributeConfig).setDataUtilityId ("saveAsVariantSpecLocationDataUtility"); } } } }

Obtaining a TypeInstance Datum Object For a panel in an object creation or edit wizard, you should typically return a TypeInstance datum object so the data utilities will have access to constraints that may have been defined for attributes. This code shows how to use the CreateAndEditModelGetter.getItemAttributes() method to obtain a TypeInstance in your builder s buildComponentData() method. This method requires that the panel is displayed within the context of a wizard with an initializeItem tag.
JcaComponentParams jcaParams = (JcaComponentParams) params; ComponentDescriptor cdesc = jcaParams.getDescriptor(); NmCommandBean commandBean = jcaParams.getHelperBean().getNmCommandBean(); NmContext nmContext = jcaParams.getHelperBean().getNmContextBean().getContext(); ArrayList typeInstances = CreateAndEditModelGetter. getItemAttributes (cdesc, commandBean, nmContext);

400

Windchill Customization Guide

Additional Resources
Related Customization Documentation Windchill Client Architecture Overview on page 226 Windchill Client Architecture Action Framework Overview on page 486 NmObject Utilities on page 562 Attribute Customization on page 630 Windchill Client Architecture Common Objects Overview on page 239 Acquiring Data via Info*Engine on page 556 Customizing Role-Based UI Functions - Attribute Visibility on page 282 Customizing Information Page Components on page 892 Building Wizards to Create a Single Object on page 823 Building Wizards to Edit a Single Object on page 846

Related Package/Class Package/Class Javadoc com.ptc.core.components.forms.CreateAndEditModelGetter com.ptc.core.lwc.common.ScreenDefintionName com.ptc.core.ui.resources.ComponentMode com.ptc.core.ui.resources.ComponentType com.ptc.jca.mvc.components.JcaComponentParams com.ptc.jca.mvc.builders.PrimaryAttributesBuilder com.ptc.jca.mvc.builders TypedAttributesPanelBuilder com.ptc.jca.mvc.builders VisualizationAttributesBuilder com.ptc.jca.mvc.components.AbstractAttributesComponentBuilder com.ptc.mvc.components.AbstractComponentBuilder com.ptc.mvc.components.AttributeConfig com.ptc.mvc.components.AttributePanelConfig com.ptc.mvc.components.ComponentConfig com.ptc.mvc.components.ComponentConfigBuilder com.ptc.mvc.components.ComponentId com.ptc.mvc.components.GroupConfig com.ptc.mvc.components. TypedAttrLayOutFactory com.ptc.mvc.components. TypedAttrLayOutFactoryAware

Customizing HTML Clients Using the Windchill JSP Framework

401

com.ptc.netmarkets.util.misc.NetmarketURL Common Components Tag Lib Javadoc

Packaged Samples
The examples described below can be viewed on the Customization tab of the Windchill product. See Customization Tools Overview on page 417 for information on enabling the customization examples.

Advanced Attribute Panel


This example demonstrates how to create a non-layout-based advanced attribute panel using a Java builder class. It constructs a panel for an object of type AttributePanelExampleObject, a fake business object type that has getter methods for all the attributes displayed in the panel. The builder class has the builder id ComponendId.ATTRIBUTES_ID, which is the id used for the common action attributes to display the More Attributes panel on information pages. So that the system will use this builder instead of the AbstractAttributesComponentBuilder (which has the same id) for the panel, it has a TypeBased annotation specifying it is for the AttributePanelExampleObject type. If you take a look at the getter methods of the AttributePanelExampleObject class, you will notice that some of them return GuiComponents for the attribute value. Although this would not typically be done in a production client, the Windchill Client Architecture framework will handle these values. See Solution Create a Simple or Advanced Attribute Panel Using a Configuration Created in a Java Builder Class on page 384 for more information on creating nonlayout-based advanced attribute panels. Location of Example To navigate to this example in the produce go to Customization Component Catalog Attribute Panel Advanced Attribute Panel. . Actions for this Example Action Name attributePanel Object Type Name carambola File /config/actions/Carambola-actions.xml

402

Windchill Customization Guide

Action Models for this Example None Files Used in This Example Source File /com/ptc/mvc/builders/carambola/ CarambolaAttributePanelBuilder /com/ptc/carambola/customization/examples/attributePanel/AttributePanelExampleObject.java codebase/config/actions/Carambola-actions.xml Description Builder that creates the configuration and datum object for the panel The Java class for the object type represented in the panel Contains the action for the example

Advanced Attribute Panel in a Wizard


This panel is the same one used in the Advanced Attribute Panel example, only displayed in a wizard. The wizard step on which the panel is displayed is constructed by the DefineItemAttributesWizStepBuilder, which is used to create the Set Attributes step for most Windchill object creation wizards. The step builder has the view JSP defineItemAttributesWizStep.jsp. That JSP contains the tag <mvc:attributesTableWizComponent/>, which creates and displays the attribute panel using the builder with the id ComponentId. ATTRIBUTES_ID for the wizard object type. The builder with that component builder id for the AttributePanelExampleObject type is the CarambolaAttributePanelBuilder. See the Advanced Attribute Panel on page 402 for more information about this builder Location of Example To navigate to this example in the produce go to Customization Component Catalog Attribute Panel Advanced Attribute Panel in a Wizard . Actions for this Example Action Name attributeWizardExample attributePanelWizStep Object Type Name object carambola File /config/actions/Carambola-actions.xml /config/actions/Carambola-actions.xml

Customizing HTML Clients Using the Windchill JSP Framework

403

Action Models for this Example None Files Used in This Example Source File /com/ptc/mvc/builders/carambola/ CarambolaAttributePanelBuilder codebase//netmarkets/jsp/carambola/ customization/examples/wizard/attributeWizardExample.jsp codebase/WEB-INF/jsp/object/defineItemAttributesWizStep.jsp Description Builder that creates the configuration and datum object for the panel The main JSP for the wizard

The common JSP used by most Windchill create wizards for the Set Attributes wizard step /com/ptc/carambola/customization/ex- The Java class for the object type repreamples/attributePanel/AttributePanelEx- sented in the panel ampleObject.java codebase/config/actions/Carambola-ac- Contains the actions for the example tions.xml

Advanced Attribute Panel on an Information Page


This panel is the same one used in the Advanced Attribute Panel on page 402 example, only displayed on a tab in the information page for the Carambola object type. The action for this panel is the information page for the Carambola object type:
<action name="infoPageExample"> <command url="ptc1/tcomp/infoPage?typeIdForTypeLookup=com.ptc.carambola. customization.examples.infoPage.Carambola" windowType="page"/> </action>

The action tag used to invoke the action from the JSP adds the parameters tlnAction and tlnType to the infoPage URL to tell the system to navigate to the tab in the Carambola information page that has the attributePanel action component.
<% HashMap<String,String> advPanelInfoPageParams = new HashMap<String,String>(); // automatically forward to the tab for attribute panel. advPanelInfoPageParams.put("tlnAction", "attributePanel"); advPanelInfoPageParams.put("tlnType","carambola"); %> <jca:action actionName="infoPageExample" actionType="carambola" button="false" params="<%=advPanelInfoPageParams%>" shellURL="true"/>

404

Windchill Customization Guide

The attributePanel action (defined for object type carambola) is the same one used to display the panel in the Advanced Attribute Panel on page 402example:
<action name="attributePanel"> <component name="attributesTable" typeBased="true" windowType="page" urlParams="typeIdForTypeLookup=com.ptc.carambola.customization.examples. attributePanel.AttributePanelExampleObject" <label>Advanced Attribute Panel</label> </action>

Although the attributePanel action is in the information page table of contents action model, it is not in the tab set action model for the Carambola type so the system creates a new tab in the information page for it. Note that the panel is for an AttributePanelExampleObject even though the information page is for a Carambola object. This is because the datum object returned by the panel builder is an AttributePanelExampleObject. See the Advanced Attribute Panel on page 402 example for more information about the panel and builder used to produce it. Location of Example To navigate to this example in the produce go to Customization Component Catalog Attribute Panel Advanced Attribute Panel on an Information Page . Actions for this Example Action Name infoPageExample Object Type Name carambola File /config/actions/Carambola-actions.xml

Action Models for this Example None

Advanced Panel with Modified Context Object


This is a view-only attribute panel based on a layout defined in the Type and Attribute Management utility. It displays the layout that maps to the screen type Information Page More Attributes (ScreenDefinitionName. MORE_ATTRIBUTES) for the container of a Poem object. It is displayed on a new tab in a Poem info page. Note: To display this example, the Poem type must have been loaded into your Windchill system.

Customizing HTML Clients Using the Windchill JSP Framework

405

Also, to see this layout-based panel, you must create an object of type Poem in a product, project, or library container using the New Document wizard. If you dont have a Poem object in one of those containers you will see a non-layout-based panel showing only the container name. The example illustrates: How to create a layout-based panel using a Java builder class How to use a context object for the panel that is different from the page context object How to change the title of an attribute panel group

The panel was configured using a Java MVC builder class that extends TypedAttributesPanelBuilder. The builder overrides the buildAttributePanelConfig() method of its superclass so that it can reset the context object for the panel and set the title of the single panel group. The builder resets the context object by calling JcaComponentParams. setContextObject(). Resetting the context object should be done with care. It must be done before the panel configs are created and can have unintended consequences if other components are displayed on the page. To reset the title of the group the builder calls the setLabel() method on the group config. If it did not reset the title, the group would have the title specified in the Type and Attribute Management utility. Like the example Advanced Attribute Panel on an Information Page on page 404, the attribute panel is displayed on a new tab of the Poem information page by specifying tlnaction and tlntype parameters on the info page URL. See Advanced Attribute Panel on an Information Page on page 404 for more information on how this is done. See Solution Create an Advanced Attribute Panel Using Any Layout Defined in the Type and Attribute Management Utility on page 380for more information on creating layout-based attribute panels. Location of Example To navigate to this example in the product go to Customization Component Catalog Attribute Panel lAdvanced Panel with Modified Context Object . Actions Models Used in This Example None

406

Windchill Customization Guide

Actions Used in This Example None Files Used in This Example Source File Description Com/ptc/mvc/builders/carambola/Liter- Builder that creates the configuration atureContextObjectAttributePanelBuild- and datum object for the panel er

Simple Attribute Panel using a Java Builder


This example, which uses the SimpleAttributesPanelBuilder, is similar to the Advanced Attribute Panel on page 402 example except it configures the panel as a simple list of name:value pairs. The builder makes this a simple attribute panel by doing the following three things: 1. It creates only one GroupConfig. In this example, the GroupConfig is created implicitly by the AttributePanelConfig the first time an AttributeConfig is added to it. 2. It does not specify rowPos, colPos, or colSpan properties on the AttributeConfigs. 3. It explicitly sets the view for the panel config to "/components/ simpleAttributePanel.jsp. The buildComponentData() method of the builder for this panel illustrates how you can you something other than a Persistable object as the panel datum object. Although panel objects will typically be Windchill business objects, that does not have to be the case. Any object from which it is possible to access the attribute values via a bean-style getter method or a Map-style get() method can be used. In this case, the row data is a HashMap. See Windchill Client Architecture Common Objects Overview on page 239 for more information. See Solution Create a Simple or Advanced Attribute Panel Using a Configuration Created in a Java Builder Class on page 384 for more information on creating simple attribute panels using Java builders. Location of Example To navigate to this example in the produce go to Customization Component Catalog Attribute Panel Simple Attribute Panel Using a Java Builder . Actions Models Used in This Example None
Customizing HTML Clients Using the Windchill JSP Framework 407

Actions Used in This Example None Files Used in This Example Source File com/ptc/mvc/builders/carambola/attributePanel/SimpleAttributesPanelBuilder. java com/ptc/carambola/property/PropertyUtils.java Description Builder that creates the configuration and datum object for the panel Contains the method getExamplePropertyPanelData(), which constructs the HashMap that is the datum for this panel.

Simple Attribute Panels using JSP Tags


This example shows two attribute panels. The first panel is the same one shown in the Simple Attribute Panel Using a Java Builder example, but in this case the panel is created and displayed using JSP tags. See the Simple Attribute Panel using a Java Builder on page 407 example for more information about the panel datum object. The second panel shows how you can create and render GUIComponents directly on a JSP page using GUI component wrapper tags. No describePropertyPanel tag was used for this panel because the GUI components are being created and configured by the wrapper tags and not by data utilities. No getModel tags were used because the data for the panel is acquired and placed in the page context by a different tag. See Solution - Create a Simple Panel Using JSP Tags on page 387 for more information on creating simple panels using JSP tags. Location of Example To navigate to this example in the produce go to Customization Component Catalog Attribute Panel Simple Attribute Panel Using JSP Tags . Actions Models Used in This Example None Actions Used in This Example None

408

Windchill Customization Guide

Files Used in This Example Source File codebase/netmarkets/jsp/carambola/customization/examples/attributePanel/simplePanelUsingTags.jsp com/ptc/carambola/property/PropertyUtils.java Description JSP for panel

Contains the method getExamplePropertyPanelData(), which is called by the getModel tag in the JSP

Simple and Advanced Attribute Panels in a Wizard


This is a composite example displaying four attribute panels in the Set Attributes step for a new object of type Novel. (Note: this is not a working wizard as no FormProcessor has been defined for it). Panel 1 This is a composite component that displays: A simple panel containing a single attribute the name of the container for the new object The type of object being created Note that if this object type had subtypes, a type picker would be displayed here instead of a read-only field A simple panel with an input field for Organization Id (only displayed if the preference Display Expose Organization is set to Yes) An advanced panel titled Attributes , which contains most of the non-driver attributes of the new object. This panel is based on the layout for the screen type Create New (ScreenDefinitionName.CREATE) for the parent WTDocument type.

This composite panel is created automatically by the JCA framework when we included the contents of the file <WT_HOME>/codebase/WEB-INF/jsp/ object/defineItemAttributesWizStep.jsp in our wizard step JSP. That file is the default JSP for the Set Attributes wizard step. If we had not wanted to include additional panels in this wizard step, we could have used the default action defineItemAttributesWizStep in the wizardStep tag and not had to write any JSPs or Java code for the wizard.

Customizing HTML Clients Using the Windchill JSP Framework

409

Panel 2 This panel, titled Additional Attributes is an advanced attribute panel displaying two attributes of Novel that were not included in the Create New layout for the Novel type. This panel is created by the following statement in the step jsp:
<jsp:include page="${mvc:getComponentURL('carambola.attributePanel. WizardPanelForEnabledAndDepartment')}"/>

This statement tells the JCA framework to look for a Java builder class with the component builder id carambola.attributePanel. WizardPanelForEnabledAndDepartment. It will find the builder class EnabledAndDepartmentPanelBuilder, which will configure the panel, acquire the data for it, and set the JSP that will display the panel. Some things to note about this builder are: The buildComponentData() method returns a TypeInstance for a new Novel object. If the panel object is a Windchill business object, it is important that datum object be a TypeInstance so that any constraints defined for the attributes are captured and made available to the data utilities. The panel component type is set to ComponentType. WIZARD_ATTRIBUTES_TABLE. This is needed so that the HTML names of the input fields are created such that the framework can identify the attributes it needs to set on the object after the wizard is submitted.

See Solution Create a Simple or Advanced Attribute Panel Using a Configuration Created in a Java Builder Class on page 384 for more information about this technique for creating attribute panels. Panel 3 This is a simple attribute panel with one property, Copyrighted, that is not an attribute of the Novel object type. You might use this technique when you want to capture some additional information from the user besides the objects attributes. Note that because the Copyrighted information is not an object attribute, a custom FormProcessor or FormProcessorDelegate would be needed to handle this information when the wizard is submitted. This panel is created by the following statement in the step JSP:
<jsp:include page="${mvc:getComponentURL ('carambola.attributePanel.WizardPanelForCopyrightInfo')}"/>

Just as in the previous example, this statement tells the JCA framework to call a MVC Java builder class, which, in this case, is the class CopyrightAttributePanelBuilder. Some things to note about this example builder are:
Windchill Customization Guide

410

In this case we dont set the component type of the panel to ComponentType.WIZARD_ATTRIBUTES_TABLE because we dont want the framework to create an HTML name for the input field such that the framework form processors would try to set the value of the field as an attribute on the object. Instead, we want the HTML name to be such that our custom form processor can find the property value in the form data and process it. In this case, the value will have the key copyrighted, which is the column name set in the buildComponentData() method. We set the view to components/simpleAttributePanel.jsp in our panel config because we do not want a border around our panel or other advanced features. The buildComponentData() method of the builder returns a HashMap as the datum that will be passed to the data utilities. The key is the string copyrighted and the value is a BooleanInputComponent. We need to create the input component because the DefaultDataUtility would not know the type of the property we want to display and could not determine which type-specific data utility should be used. Alternatively, we could have created and registered a data utility for this property.

See Solution Create a Simple or Advanced Attribute Panel Using a Configuration Created in a Java Builder Class on page 384 for more information about this technique for creating attribute panels. Panel 4 This is a simple attribute panel containing one attribute of the panel object type. In this case the panel was created using JSP tags in the wizard step JSP. See Solution - Create a Simple Panel Using JSP Tags on page 387 for more information about this technique for creating attribute panels. Actions Models Used in This Example None Actions Used in This Example Action Name Object Type Name wizardWithAttributePaattributePanel nels defineItemAttributesWiz- Novel StepForAttrPanelWizard File /config/actions/Carambola-actions.xml /config/actions/Carambola-actions.xml

Customizing HTML Clients Using the Windchill JSP Framework

411

Files Used in This Example Source File codebase/netmarkets/jsp/carambola/customization/examples/attributePanel/wizardWithAttributePanels.jsp /com/ptc/mvc/builders/carambola/attributePanel/DefineItemAttributesWizStepBuilderForAttrPanelWizard codebase/WEB-INF/jsp/carambola/attributePanel/defineItemAttributesWizStepForAttrPanelWizard.jsp com/ptc/mvc/builders/carambola/attributePanel/EnabledAndDepartmentPanelBuilder.java com/ptc/mvc/builders/carambola/attributePanel/CopyrightAttributePanelBuilder.java codebase/config/actions/Carambola-actions.xml com/ptc/carambola/customization/examples/attributePanel/AttributePanelExampleResource.java Description Main wizard JSP

Builder for the wizard step

JSP for the wizard step

Builder for the Additional Attributes panel Builder for the Copyrighted panel

Contains the actions for the example UI text for example

412

Windchill Customization Guide

Customizing Access Control For Packages


Objective
You want to customize the default roles, domain structure, or access control policy rules associated with Packages across all contexts.

Background
Before you can use packages within a context, you must first enable packages for that context. When you enables packages for a given context, the system loads a site-wide package template XML file. The package template file contains package specific roles that are applied to the container team, the default domain structure for packages, and package-related policies. The default domain structure will create a Package domain specific to the current context. All packages created within the context, as well as all of the objects created within the packages (collections, folders, documents, links, and deliveries) will use this package domain by default. Out of the box, the package domain is Private. This means that it won't inherit any policies from the container's default domain.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This guide assumes that you want to customize the default roles, domain structure, or access control policy rules associated with Packages across all contexts. You should be familiar with managing Packages, teams, and administering access control for Windchill business objects. Intended Outcome Customize the default roles, domain structure, or access control policy rules associated with Packages across all contexts.

Solution
Use the package template XML file to customize the default roles, domain structure, and access control policy rules associated with Packages across all contexts.

Customizing HTML Clients Using the Windchill JSP Framework

413

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Administering Packages Creating business XML files for templates Windchill team concepts Administering Domains and Policies Access Control

Solution Elements
Element packageTemplate.xml Type Description XML The XML file that contains the roles, domain structure, and policies associated with Packages. This file is loaded when you enable packages for a context. Location: <WT_HOME>/ loadXMLFiles XML The XML file that contains the shared team roles. This file is loaded in addition to the packageTemplate. xml file when you enable packages for a context that is using a shared team that isnt extended. Location: <WT_HOME>/ loadXMLFiles

packageSharedTeamTemplate

Procedure - Modifying Domain Structure


The packageTemplate.xml file supports customization of the roles, domain structure, and access control policy rules. Modifying these elements is documented in the appendix of the Windchill Business Administrator's Guide . To modify the roles, refer to the projectMember element described in Creating Business XML Files for each context. To modify the domain structure, refer to the DomainStructure Element section. To modify the access control policy rules, refer to the Common AccessControlRule Element section. If you modify the domain structure in the packageTemplate.xml file, you must update the Default Domain Path for Packages site-level preference. This is because the domain path must be the same in both places. The existence of the domain

414

Windchill Customization Guide

specified in the preference is used to determine if packages have been enabled for a context. It is also used to determine the default domain associated with a Package when it is created.

Limitations
The packageTemplate.xml applies to the entire site which means you cannot customize it for specific contexts or specific packages. If you change the default domain path, you may have to enable packages again. If the domain already exists in a context, you won't be prompted to enable packages again. If the context is using a shared team that isn't extended, the roles from packagedSharedTeamTemplate.xml will be used and the roles from packageTeam. xml will be ignored.

Sample Code
Examples of Usage in Windchill Code
Filename: <WT_HOME>/loadXMLfiles/packageTemplate.xml Package Team Role:
<projectMember> <Role roleType="PACKAGE MANAGER"/> </projectMember>

Package Domain Structure:


<OrgStructure> <DomainStructure> <domainLevel> <parentDomain>private</parentDomain> <domainName>package</domainName> <description>The default domain for packages.</description> </domainLevel> </DomainStructure> </OrgStructure>

Package Access Control Policy Rule:


<AccessControlRule> <domainName>package</domainName> <externalTypeId>WCTYPE|wt.fc.WTObject</externalTypeId> <lifecycleState>ALL</lifecycleState> <WTPrincipleReference isInternal="true"> <groupName>PACKAGE MANAGER<groupName> <groupType>ALL</groudType> </WTPrincipleReference> <grantPermissionSet>

Customizing HTML Clients Using the Windchill JSP Framework

415

<AccessPermissionSet> <permissionField name="ALL"/> </AccessPermissionSet> </grantPermissionSet> </AccessControlRule>

Additional Resources
Other Related Windchill Documentation
Access Control chapter in the Windchill Business Administrator's Guide Team chapter in the Windchill Business Administrator's Guide Creating XML Files for Templates and Shared Teams section in the Windchill Business Administrator's Guide

416

Windchill Customization Guide

Customization Tools Overview


Enable Customization Utilities There are a number of customization utilities included within the Windchill user interface. They are not enabled by default. To enable the customization utilities: 1. Navigate to: Navigator Browse Site Utilities Preference Manager 2. Navigate the tree to Client Customization and expand the entry. 3. Right click on Client Customization , select Set Preference , and set the value to Yes. 4. Refresh your browser. 5. Navigator Browse Site and select the Customization icon ( 6. Select Tools from the Customization menu. ).

Note The direct URL to the menu is: <server>/<webapp>/app/#ptc1/carambola/tools/ list?tab=customization

Customization Source Code Examples


Customization source code examples are available for download from the following location: http://www.ptc.com/view?im_dbkey=127957

Customizing HTML Clients Using the Windchill JSP Framework

417

Reports
The following reports are documented in this section. Report Action Report on page 419 Action Model Report on page 423 Available Attributes Report on page 427 Reload Action on page 428 MVC Builder Search on page 429 MVC Builder Scan Report Mini on page 430 Description Find an Action Find an Action Model Generates a report on the attributes available for a Windchill Type. Reload action configurations Finds MVC component builders by ID

MVC Builder Scan Report Full on page 431 Modeled Objects on page 432

Finds a Modeled Object

418

Windchill Customization Guide

Action Report
Action reports provide details on the actions used in the Windchill UI to launch wizards and execute operations. Such details include the action label, action name, the Java class used to validate whether the action is available to the user, the file in which the action is defined, and many others. Action reports also enable you to modify the label and tool tip of an action. Reports may be generated for any action managed by the StandardNmActionService. Report Location
Navigator Browser Customization Tools Action

Generating an Action Report Search for the action whose details you desire using the search criteria on the Action Report page:

Search supports: Multiple search parameters Regular expressions Case-insensitive matching For Label (aka Description): remove ==> Matches: "remove", "list_delete", "related_delete_described_part", etc. For Action Name : remov.* ==> Matches: "remove", "remove_deliverable", "removeUses", etc.

Search Examples:

Customizing HTML Clients Using the Windchill JSP Framework

419

r[a-z]* ==> Matches: "reply", "REVISEITEMS", "reassignLC", etc. .*move ==> Matches: "remove", "CONTAINERMOVE", "WFMOVE", etc. .* ==> Matches: everything For Hot Key: m ==> Matches: "home" .* ==> Matches: "home", "productStructure", "documentStructure", etc. For Action Model File/Action Definition File: files must be located under WT_HOME\codebase\config\actions you only need to specify the file name in the search criteria, not the file path. For example, BaselineClient.* ==> Matches: WT_HOME\codebase \config\actions\BaselineClient-actions.xml Some matches may be deceiving due to include tags in xml files Once you have entered your search criteria, click the Search button to display the matching actions:

420

Windchill Customization Guide

To display the full action report for one of the displayed actions, click the icon for it:

If there is no information for an attribute of a particular action, the line is shown blank. Features New actions can be created from the Actions table by selecting Create Action from the Actions menu. Actions can be copied to Clipboard from the Actions table. Select Required is added as a column to the action report. Icon Path is added as a column to the action report. Select Required is added as a property to the action details page. Ability to persist the user changes in a new location (coming from wt. properties) and change in framework to give precedence to these new persisted files. The modified action changes actions are saved to xml. Property to be added in the wt.properties for actions is com.ptc.netmarkets.util.misc. customActions. The value for the property would be complete path to the custom xml alongwith the file name. Example entry in wt.properties on Windows: com.ptc.netmarkets.util.misc.customActions=D\:\ \myCustomActions.xml If the property is not specified, user changes would be persisted in: <wt-codebase>/config/actions/custom-actions.xml

Customizing HTML Clients Using the Windchill JSP Framework

421

Troubleshooting Search returning "No Objects to Display" If the method server is restarted after a search has already been attempted, another search will return "No Objects to Display" no matter what you search for. This is due to the fact that the page relies on a session variable to get the information from the method server. To fix this problem, simply restart your browser. Wrong Definition File? Some matches may be deceiving due to include tags in xml files. Check the included files to find your particular actions.

422

Windchill Customization Guide

Action Model Report


Action model reports provide details about action sets, such as the set of actions displayed in a table row for an object of a certain type or the set of actions displayed on the toolbar of a table. Such details include the action model name and the name of the file in which the action model is defined. Reports may be generated for any action managed by the StandardNmActionService.
Navigator Browser Customization Tools Action Model

Generating an Action Model Report Search for the action whose details you desire using the search criteria on the Action Model Report page:

Search supports: Multiple search parameters Regular expressions Case-insensitive matching For Action Model: Default.* ==> Matches: "DefaultWizardButtons", "DefaultWizardButtons", etc. .*actions ==> Matches: "dti actions", "bookmark actions", "workitem actions", etc. [a-z]*s ==> Matches: "ScmiWizardButtons", "relatedItems", "EditWizardButtons", etc. .* ==> Matches: everything For Model File: files must be located under WT_HOME\codebase\config\actions

Search Examples

Customizing HTML Clients Using the Windchill JSP Framework

423

you only need to specify the file name in the search criteria, not the file path. For example, Preference.* ==> Matches: WT_HOME\codebase \config\actions\Preference-actionModels.xml Some matches may be deceiving due to include tags in xml files Once you have entered your search criteria, click the Search button to display the matching action models:

424

Windchill Customization Guide

To display the full action model report for one of the displayed action models, click the icon for it:

The Description attribute of the action model represents the text entered for the description subtag of the actionmodel tag, if any. The Order attribute of an action is the order of the action within the actionmodel xml file. If there is no information for an attribute of a particular action model, the line is shown blank. New Features Ability to create a new action (prototype) or remove an existing action in action model table is added. Clipboard paste on ActionModel table. Separator action is added into the action model display. Reordering of actions in action model can be done using the drag and drop functionality. Ability to persist the user changes made in a action model to a new location (coming from wt.properties) and Change in framework to give precedence to these new persisted files. The modified action models are saved to xml. A property required to be added in the wt.properties for action models is com.

Customizing HTML Clients Using the Windchill JSP Framework

425

ptc.netmarkets.util.misc.customActionModels. The value for the property would be complete path to the custom action model xml. Example entry in wt. properties on Windows: com.ptc.netmarkets.util.misc.customActionModels=D \:\\myCustomActionModels.xml If the property is not specified, user changes would be persisted in <wtcodebase>/config/actions/custom-actionModels.xml Inline actions can be created in an action model. Their scope would be limited to only that action model.

426

Windchill Customization Guide

Available Attributes Report


The Available Attributes Report is a search page that returns the details of attributes that can be configured for a given object type. This report can be accessed from any running Windchill installation to find the list of supported attributes for a given object type (eg: wt.part.WTPart). The report includes information about the attribute such as the id used to reference the attribute and the label used for that attribute in the UI, the data utility mapped to that component, etc. Note that you must specify a fully qualified type name, including the full package, to find its attributes. Also note that case is important, wt.part.wtpart will not find wt.part.WTPart. Find it at : Navigator > Browse > Customization > Tools > Available Attributes Report Search Supports Any valid, fully qualifed class that implements Persistable JCA ID JS ID Schema ID View Wizard Label Table Column Label Data Utility componentRB Label Column Descriptor Factory Label Introspected Label Results Table

Note If there is no information for the property of a particular attribute, the cell is shown blank.

Customizing HTML Clients Using the Windchill JSP Framework

427

Reload Action
http://<your machine name>/<app-name>/app/#ptc1/ carambola/tools/list This tool reloads the action models from their xml files without having to restart the method server.

428

Windchill Customization Guide

MVC Builder Search


You can search for the implementations of ComponentConfigBuilder and ComponentDataBuilder registered in the server. The value provided will be matched against the bean name and we support ant style wildcards for the search.

Customizing HTML Clients Using the Windchill JSP Framework

429

MVC Builder Scan Report Mini


You can register your component builders using the MVC scan functionality. This report will give a breakup of the time spend at various activities involved in the scan. To get the report you need to enable log4j loggers. (update WT_HOME \codebase\WEB-INF\ log4jMethodServer.properties to add log4j.logger.com.ptc. mvc.scan=INFO and restart the servers)

430

Windchill Customization Guide

MVC Builder Scan Report Full


Apart from the information captured in the Mini report, this provides some more additional information like the configuration files scanned, the builders registered, time spend in each scan etc. This can be used to make sure that the builder registered using the scan has been really picked up or not. We recommend not using the scan if the number of builders registered for a base package is less than 10. This report lists the configuration files that are deviating from this recommendation. To get the report you need to enable log4j loggers. (update WT_HOME\codebase \WEB-INF\ log4jMethodServer.properties to add log4j.logger.com.ptc.mvc. scan=INFO and restart the servers)

Customizing HTML Clients Using the Windchill JSP Framework

431

Modeled Objects
Windchill manages many types of business and administrative concepts. The concepts are modeled as objects in Java and instances of those objects are stored in a database. The Modeled Objects page provides information about all modeled objects on the current system. It provides a report that lists all of the modeled objects, and then a link to a details pages for each one. The detailed information pages can include information about the meta data for the object, the persistance mapping between the Java object and a database table, UML diagrams and links to Javadoc. Use these pages to learn about the modeled objects, how they are related, and how they are stored in the database. Location: Navigator > Browser > Customization > Tools > Modeled Objects Support The report, and corresponding detail pages, are generated dynamically for all modeled objects installed on the current system, whether they are exposed to end users or not. This includes custom modeled objects created by customers.

Modeled Objects The Modeled_Objects_Index view of Modeled Objects shows a table of all the modeled objects in the current Windchill system. Display Name The name of the object as it is exposed to end users. "Link to Detailed Information Page" A link to detailed information page for the object. Class Name The fully qualifed Java class name for the object. Java Type "class" or "interface" Table Name If there is a corresponding database table name for the object, then it is listed here. Not all modeled objects correspond directly to a database table.

Columns:

432

Windchill Customization Guide

Detailed Information Page : The detailed information page for each object has two tabs, one for the Database Information and one for the Java Information. Only objects that have a corresponding database table will have a Database Information tab. Database Information : The Database Information tab has four sections of information about the object's database table Table Attributes : A list of single valued attributes that describe the database table. At the moment, the only value is the Table Name.

Column Descriptors A table of Column Descriptors. There is one row for each column in the database table. Within the Windchill meta data, this information is stored in a "Column Descriptor" class, thus the name "Column Descriptor". Column Name "Link to Detailed Information Page" Column Name SQL Type Description The generated name of the column descriptor. A link to detailed information page for the object. The database column name The type of the database column

Customizing HTML Clients Using the Windchill JSP Framework

433

Column Length Mapped Property Descriptor

Description The length of the database column (or 0 if none) Each column is mapped from a Property Descriptor. This a link to an information page about that Property Descriptor.

Composite Unique Indices A table of composite unique indices on the database table. Each row shows the index number and the list of columns included in the index. Java Information The Java Information tab has seven sections of information about the object's Java class. Attributes A list of single valued attributes that describe the class. Attribute Display Name Icon Description The name of the object as it is exposed to end users. An image of the icon used to represent instances of this object in the Windchill UI The fully qualified Java class name "Yes" or "No". Only concrete, persistable classes will have a corresponding database table. The direct, Java, parent class. This will be a link to that class's information page (if the page exists). The corresponding database table name (if any) Java Type "class" or "interface" "Yes" or "No" depending on if this is a Link Class.

Class Name Persistable

Parent Class

Table Name Link Class

434

Windchill Customization Guide

Parent Interfaces : A table of the names of the modeled interfaces implemented directly by this class. Descendents : A table of the modeled descendant classes of this class. Property Descriptors : A table of Property Descriptors. Within the Windchill meta data, this information is stored in a "Property Descriptor" class, thus the name "Property Descriptor". Columns Name : The name of the property descriptor. Display Name : The name of the property as it is exposed to end users. "Link to Detailed Information Page" : A link to detailed information page for the property descriptor. Property Type : The Java type of the property Defined As : The fully qualified internal name of this property

Role Descriptors : A table of Role Descriptors. Within the Windchill meta data, this information is stored in a "Role Descriptor" class, thus the name "Property Descriptor". An association in Windchill is between two classes. Each of the two classes plays a "role" with respect to that association and this is what is represented by a Role Descriptor. Columns Name : The name of the property descriptor. Display Name : The name of the Role or Association as it is exposed to end users. "Link to Detailed Information Page" : A link to detailed information page for the role descriptor. Link Information : A link to the Information Page for the link class corresponding to this role.

Customizing HTML Clients Using the Windchill JSP Framework

435

Valid Class Information : A link to the Information Page for the class that plays the other side role on the corresponding link class.

UML Diagram : A UML diagram for the class (not all classes have UML diagrams). Javadoc : A link to the Javadoc for this class. Will only appear if the class itself is included in the Windchill Supported API.

436

Windchill Customization Guide

Column Descriptor Information Page : The Information Page for a Column Descriptor shows a panel of single valued attributes of the column Name - The name of the column descriptor Column Name - The name of the corresponding table column Java Type - The type of the value represented in Java SQL Type - The type of the value represent in the database Length - The maximum length of a string column. Updateable - "Yes" or "No" Always "Yes" Required - The column is required to be set by the Windchill method server. Indexed - "Yes" or "No" depending on if the column was designated to be indexed in the model Unique - "Yes" or "No" dependin on if the model specified that the corresponding value should be unique across all instances

Customizing HTML Clients Using the Windchill JSP Framework

437

Property Descriptor - The fully qualified name of the Property Descriptor that maps to this Column Descriptor Mapped Property Descriptor - A link to the corresponding property descriptor

Property Descriptor Information Page : The Information Page for a Property Descriptor shows a panel of single valued attributes of the property: Name The internal name of the property Display name The name of the property as it is exposed to end users. Property Type The Java type or they property Bound (not used) Derived "true" or "false" depending on if this property was modeled as a derived attribute or not. Persistent "true" or "false" depending on if this property is persistent or transient Query Name The name used to represent this property in programmatic queries. String Case Mixed, Upper or Lower. Default is Mixed. Initial Value The modeled, initial value if any. Required "true" or "false" depending on if this property is required in order to create a new instance of the corresponding object. Lower Limit For a string, the minimum number of characters. For numbers, the minimum value. Upper Limit For a string, the maximum number of characters. For numbers, the maximum value.

438

Windchill Customization Guide

Changeable One of "Default", "Frozen" or "Via Other Means". (See the Javadoc for com.ptc.windchill.annotations.metadata.Changeable) Constrained Type (not used)

Role Descriptor Information Page : The Information Page for a Role Descriptor shows a panel of single valued attributes of the role. Name The internal name of the property Display name The name of the property as it is exposed to end users. Link Information A link to the modeled link object Valid Class Info A link to the modeled class that is the type of this role. Cardinality (not used) Multiple (not used) Auto Navigate "Yes" or "No". (see the Javadoc for com.ptc.windchill. annotations.metadata.ForeignKeyRole autoNavigate element) Owner "Yes" or "No" (see the Javadoc for com.ptc.windchill.annotations. metadata.GeneratedRole owner element) Cascade "Yes" or "No" (see the Javadoc for com.ptc.windchill. annotations.metadata.GeneratedRole cascade element)

Customizing HTML Clients Using the Windchill JSP Framework

439

Other Role The name of the other side role descriptor

440

Windchill Customization Guide

API Documentation
You can access documentation on how to use the Application Programming Interfaces for the JCA framework from a running instance of Windchill. Documentation is available on the following: Tags: Several tags and taglibs are delivered as part of the framework. These taglibs contain a set of handlers for including components and other common functionality into your pages. JavaDoc: Industry standard documentation for the Java classes available for your use. JSDoc: Documentation on the JavaScript functions and objects available for use. Note that there are substantially more Javascript objects available than in previous releases.

Note The JSDoc files are not installed by default. See JavaScript Documentation on page 9 for information on how to download the JSDoc files.
Best Practices: A number of the customization best practice topics available in the help center are listed here.

You can find links to the documentation at the following location Browser > Customization > Documentation.

Customizing HTML Clients Using the Windchill JSP Framework

441

Debugging
This section describes how to activate and use the JCA Debug tool.

Using jcaDebug
To enable the JCA debug feature, simply add &jcaDebug=true to the URL of a Windchill page displayed in the browser s address field, as described below. A convenience link to turn on jcaDebug is available at Navigator > Browser > Customization > Tools Content Area To put jcaDebug output on the content area of the page, put the parameter at the end of the URL, using the ampersand. For example: http://<server>/Windchill/app/#ptc1/tcomp/infoPage? typeIdForTypeLoo...&jcaDebug=true Entire Shell To put jcaDebug output on the entire Windchill page, including the Navigator and header, put the jcaDebug parameter before the # token. Use a ? since it becomes the first parameter. http://<server>/Windchill/app/?jcaDebug=true#ptc1/ tcomp/... Once added, the jcaDebug parameter will automatically be applied to all subsequent Windchill pages. To turn off the feature, remove the jcaDebug parameter from the URL of the current page.

What information does jcaDebug display?


Add the jcaDebug parameter to the URL to show this kind of information: which Java class is handling data that's displayed in a table cell what kind of component is rendering the data in a table cell which Java validator class is responsible for hiding/enabling/disabling an action a link to the action model report for any action model for example, the actions menu, table menu bar, table toolbar, info page table of contents menus, and top tab set of the info page. information about what ComponentConfigBuilder and ComponentDataBuilder created the table or info page

442

Windchill Customization Guide

Some of this information for example, action validator classes, is displayed directly on the Windchill page. Ladybug icons ( ) indicate the availability of other information, which can be displayed by mousing over or clicking the icon. In addition, the jcaDebug parameter will: log the JavaScript that is executed when you click a toolbar or menu action to the JavaScript console window turn on the jsDebug feature, so JavaScript can be inspected/debugged as well

Tables The following information is shown for tables (refer to the picture below): 1. MVC tables will have a ladybug to the right of the table name whose tooltip shows the component config builder and component data builder for the table. 2. A ladybug shows the action model report for the toolbar actions when clicked. Menu bar menus will have a similar action as the last action in the menu. 3. The column headers are extended to include the name of the validator class that enables the column.. 4. The table cells have a ladybug icon that you can mouse over to display a tooltip. The tooltip displays the following information: Attribute Display Utility: Gui Component Type: Column ID: Row Object: Description the data utility used to create the gui component(s) for the cell the gui component returned by the getDataValue() API of the data utility the ID used to look up the data utility the object whose attributes are being displayed this is the datum passed into the data utility.

Customizing HTML Clients Using the Windchill JSP Framework

443

In some cases, a table that should display this debug information will not show any data rows at all, even though the object count at the top contains non-zero values. If this occurs, you should paste the URL into a new browser session.

444

Windchill Customization Guide

Information Page The following information is shown (refer to the picture below). 1. The component config builder and data builder are shown at the top of MVC info pages. The JSP used for the page is shown at the top of non-MVC info pages. 2. The action models used for the top tab set and within the 'Customize' table of contents menu are shown.

Actions Menu The following information is shown: 1. The object type and action name from the action definition are shown for each item in the menu. To see more details about the action you can go to the action report for that type and name. For example http://<server>/Windchill/app/ #ptc1/carambola/tools/actionReport/actionDetails? actionName=addToBaselineSingle&objectType=baseline 2. The Java validator class for each action 3. For template processor actions only, the URLActionDelegate for the action 4. The name of the action model used for the menu. When clicked this action opens the action model report. For example http://<server>/Windchillapp/ #/ptc1/carambola/tools/actionReport/actionModelDetails? actionModelName=epmdocuments+details+page+actions

Customizing HTML Clients Using the Windchill JSP Framework

445

Navigation The action name, object type and validator for the currently selected tab are shown. There are also links to the action model report at the bottom of each expanded navigation node.

446

Windchill Customization Guide

JavaScript for Actions When JCA debug is enabled, the JavaScript executed for a toolbar or menu action is logged to the console when you click the action. For example, when you click the 'Copy' action in the toolbar of a table you'd see something like this logged to the console:
JCA_DEBUG - if(onClickValidation( event, 'list_copy' )) {JavaScript:noContentAction('list_copy', 'ptc1/object/list_copy', ,,,,,,,,,,,,'portlet', 'poppedup', 'context', 'folder$folderContentTable$OR:wt.pdmlink.PDMLinkProduct:22199$',, , 'folder$folderContentTable$OR:wt.pdmlink.PDMLinkProduct:22199$', 'none', 'com.ptc.netmarkets.model.NmObjectCommands', 'list_copy', 'height=300,width=300', 'com.ptc.netmarkets.util.utilResource.ADD_CLIP','com.ptc.netmarkets.util.utilResource. NONE_CHECKED', false, 'P4118748557893740', 'component', ,true, 'table__folderbrowser.PDM_TABLE')};

Customizing HTML Clients Using the Windchill JSP Framework

447

Using jsDebug
Windchill JavaScript code is now combined and minified. This is done to improve download times and execution speed. A whitespace compression is being used to minify the JavaScript. This means that all the comments and whitespace are taken out of the JavaScript. Minification is applied to most third party libraries as well as the Windchill main.js file.

Why Enable jsDebug?


Get debug versions of js files If you use Firebug, or Internet Explorer's "Developer Tools", you will not be able to easily debug the combined and minified JavaScript files. jsDebug will give you access to the original uncompressed versions of the files. Bust IE's cache IE caches the responses for any js files loaded via PTC.navigation.loadScript() API. Without jsDebug enabled, IE browser just returns the cached version of the js file even if the timestamp of the js file in codebase is newer than that of the cached file. For active development it can be handy to enable jsDebug so you aren't working with cached js files in IE. The Firefox browser loads the modified js file right away as expected.

Note To ensure patched js files would take effect regardless of browser caching, PTC. navigation.loadScript() adds a cache buster URL parameter to force reload of the js files at least every Sunday.

How to Enable jsDebug


jsDebug can be enabled in one of the following ways:

448

Windchill Customization Guide

Add the jcaDebug parameter to the url of a Windchill page This will: 1. Turn on JCA Debugging (see Using jcaDebug on page 442). 2. Split and decompress the JavaScript files, using the jsDebug feature, as documented below. If you put jcaDebug at the root of the URL, it will turn on debugging for the entire shell, including the navigator, header, etc, and the JavaScript files will be split immediately.
/Windchill/app/?jcaDebug=true

If you put jcaDebug at the end of the URL (after the # token), it will turn on debugging only for the content area of the page, and the JavaScript files will only be split if you manually refresh the page (using Ctrl-R or F5 in your browser)
/Windchill/app/#ptc1/home/overview?jcaDebug=true

Add the jsDebug parameter to the url of a Windchill page This sets a user session variable. Any value of jsDebug other than "false" will turn on jsDebug. Explicitly setting jsDebug to "false" turns off the feature. Clearing your browser cookies or restarting the browser will also turn it off. If you put jsDebug at the root of the URL, the page will refresh in your browser automatically, and split the files immediately . If you put jsDebug at the end of the URL, after the # token, you will need to refresh the browser page manually to get the js files to split.

Turn on the jsDebug feature using log4j Add the following to the log4jMethodServer.properties file:
log4j.logger.com.ptc.jca.js=DEBUG

From the Tool Page A convenience link to turn on jsDebug is available at Navigator > Browser > Customization > Tools

JavaScript Logging
Windchill now includes a JavaScript logging package, called log4javascript, which is a 3rd party js library from log4javascript.

Customizing HTML Clients Using the Windchill JSP Framework

449

Putting in Logging Statements While this package is made to work and act just like log4j, there are a few choices about how to do things. Windchill provides loggers for navigation and other components that start with the PTC package name and this is a good practice that other developers should follow. See full documentation at: http://log4javascript.org/docs/index.html Here is one simple example about a typical developer usage:
var mylogger = log4javascript.getLogger("PTC.mypackage"); mylogger.trace("..."); mylogger.debug(...); myLogger.time("timername"); myLogger.timeEnd("timername");

By default all the messages logged under the PTC top level logger will be pushed to the browser console (Firefox) or shown in a popup browser window (the PopUpAppender for IE). Also, the messages will be logged to the server's log4j file by the Log4JavascriptController's logger (using property log4j.logger.com.ptc. jca.mvc.controllers.Log4JavascriptController=INFO in \codebase\WEB-INF \log4jMethodServer.properties). Turning on Logging Logging may be turned on in one of the following ways: Add a jsLog URL parameter To turn on global logging, append jsLog=true to the end of a Windchill URL in the browser s address field:
http://ah-lisa.ptcnet.ptc.com:1600/Windchill/app/#ptc1/comp/home.overview? oid=OR%3Awt.org. WTUser%3A21639&u8=1&jsLog=true &jsLog=true

This is the same as turning on TRACE level logging on the PTC logger. Programmatically (in JavaScript code or in the console) To programmatically turn on logging, include the following:
var mylogger = log4javascript.getLogger("PTC.mypackage"); mylogger.setLevel(log4javascript.Level.TRACE);

Using a UI Enter the URL address javascript:PTC.log.startLogger()" to launch a UI that lets you enable logging. Just hit "Ok" to enable all loggers or enter a logger name to enable a specific logger.

From the Tools Page A convenience link to turn on jsLog is available at Navigator > Browser > Customization > Tools

450

Windchill Customization Guide

See Additional information in the javadoc for the PTC.log object JavaScript.

Log4j
Log4j loggers can be enabled from the UI, accessible from the Tools page. Note that this feature works only for Site Administrators. This and many other site tools are also available under Site Utilities Server Status Monitoring Tools .

Customizing HTML Clients Using the Windchill JSP Framework

451

Adding Validation Logic for Actions and Properties


This section provides developers with the information required for implementing a validation delegate (aka validator) to perform validation on a specific action or UI component.

Objective
The UI Component Validation Service was created to give Windchill clients a central service to call to perform validation for actions and other components appearing in the Windchill UI. Calls to the service and interpretation of the results should be managed by many of the common components developed in release 9.0. The main responsibility for an application developer would be development of Validator classes that are called by the validation service to validate a specific action or UI component. This documentation outlines the process and best practices for authoring Validator classes.

Applicability
This documentation should be used by a developer who is responsible for authoring one or more Validators to determine whether or not an action or UI component is valid on a given page/context/etc. The documentation should walk through an example of each type of validation operation that a Validator could be called upon to perform.

Structure
All of the classes in the UI Validation Service (except where noted) are defined in the com.ptc.core.ui.validation package. A Validator developer will not need to interact with all of the classes in this diagram, but many of them are applicable. The various classes will be discussed throughout this document, but to begin with, a developer writing a Validator should always define their Validator class to extend DefaultUIComponentValidator.

Note It is also important to note that as requirements evolve, these classes may be updated. To get the latest set of methods and attributes defined in each of the classes see the Windchill Javadoc.

452

Windchill Customization Guide

Participants
The readers of this section should have a general understanding of the Java programming language, and also some familiarity with the Windchill solution suite.

Collaborations
Validator developers need to collaborate with common component developers and other callers of the Validation Service. This collaboration is necessary to ensure that a caller of the service is passing all of the data to the service that a given Validator will need to perform validation. It is strongly recommended that Validator developers include a list of the data required in a given validation method in that methods Javadoc. It is also helpful to include a list of Validation keys (action names) that the method is designed to account for. For example:
public class DefaultWIPValidator extends DefaultUIComponentValidator { /** * This implementation of performLimitedPreValidation will check the checkout * state of all the Workable objects in the ValidationCriteria's targetObjects * WTCollection, and base its validation results on whether an object in the * given state can have the specified action performed on it. (e.g., an object * in the checked-in state can not have an undo checkout action performed on it) * * At a minimum, a caller of this method should provide the targetObjects * WTCollection in the validationCriteria argument. * * The expected validationKey arguments for this method are: * checkin * checkout * undocheckout * * <BR><BR><B>Supported API: </B>false * * @param validationKey The String identifying the action or component being validated. * @param validationCriteria Object holding information required to perform validation tasks. * @param locale The user's Locale. If a <i>null</i> value is passed in, the session locale will be used. * @return UIValidationResultSet **/ public UIValidationResultSet performLimitedPreValidation (String validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { } }

Customizing HTML Clients Using the Windchill JSP Framework

453

Consequences
By using this documentation as a reference, developers should create consistent, performant Validators. A caller of the validation service should be confident that whatever action or UI component they are validating will be validated in a consistent manner.

Implementation
Overview
It is probably helpful to begin with a definition of the term validation. For the purposes of this discussion, the term validation refers to activities performed to determine what a user can see or do. For example: Should we display the Create Part action? Should we allow the checkout of this object? Is everything the user entered in this create wizard OK?

For the purposes of our discussion, validation can be broken down into three broad categories: Pre-Validation Pre-Validation Attempts to answer the questions: Should something appear to the user in the UI? And, if so, should it be editable/selectable? For example, Should we display and enable the Create Part action for user A in container B? Pre-Validation can be performed for actions or other UI components (status glyphs, attributes, tables, etc.)

Post-Select Post-Select Validation Attempts to answer the question: Should the operation that was just selected in the UI be allowed to proceed? For example, Can we allow the checkout of parts A, B, and C?

Post-Submit Post-Submit Validation Attempts to answer the question: is the data the user just entered valid? For example, When the user clicks Next in the Create Part wizard, are we going to let them go to the next step, or do they need to modify some data (e.g., name, number) in the current step?

454

Windchill Customization Guide

The UI Component (Action) Validation Service exposes one or more APIs for each of the types of validation listed above. From a high level, a common component or some other client invokes a validation API on the Validation Service, passing one or more validation keys (which can be thought of as an action name, like create, for instance) and a UIValidationCriteria bean, which contains data known by the client that is required to perform validation. The Validation Service uses the validation key(s) to perform a lookup and identify the Validator class(es) that should be called to carry out the validation activity. The service then passes the key and UIValidationCriteria on to the identified Validator(s) and awaits a (set of) result(s). When the service has the result(s) from the Validator(s), it (creates a bundle of results and) returns it to the client.

This documentation will concentrate on the authoring of Validator classes and methods.

Packaging/Modularization Packaging/Modularization
All of the classes related to the UI Component Validation Service are packaged in com.ptc.core.ui.validation. Their source is located in the module \Windchill\src \com\ptc\core\ui\validation. It is strongly recommended that any time a developer is doing Validator development, they update all of the files in this directory and compile the latest versions of the Java classes.

Customizing HTML Clients Using the Windchill JSP Framework

455

Developers writing Validators should put their Validator classes in a package or module that is meaningful for the action(s)/UI component(s) that the Validator validates.

Authoring a Validator Class


Action and UI Component owners will be responsible for writing the Validators that validate those actions and UI components. To create a Validator, youll need to create a subclass of com.ptc.core.ui.validation.DefaultUIComponentValidator.java. There are currently five public methods defined in DefaultUIComponentValidator. java. Your subclass can override one to all of them:
performFullPreValidation() performLimitedPreValidation() validateFormSubmission() validateSelectedAction() validateSelectedMultiSelectAction()

For those methods which you do not override, the default behavior (always enable/ permit) will be inherited from the DefaultUIComponentValidator class. You will also need to create a properties entry to associate your Validator class with a particular validation key (action). The validation service uses these entries to find the right Validator for a given validation key (action). The entry will go in service.properties, or your application teams service properties file (ask your group lead where you should put your entry), and should have this format:
wt.services/rsc/default/com.ptc.core.ui.UIComponentValidator/<validationKey> <validationKey>/ null/0=com.ptc.my.validators.MyValidator com.ptc.my.validators.MyValidator

Where <validationKey> is the validation key for your action/component and the right-side value is the fully-qualified class name of your Validator. There are three types of checks you should never have to perform in your Validator implementations. These checks are performed by the validation service before the Validators are called. They include: Role-based checking (visibility of actions based on input into the RBUI system, which is not to be confused with access control checking, which needs to be done in the Validators.) Install-based checking (should an action or UI component be available given the set of solutions installed on a given system?) Client-based checking (should an action or UI component be available in a given client, like DTI or PSE?)

456

Windchill Customization Guide

Implementing a validateSelectedAction Method One of the methods you may choose to override in your Validator implementation is validateSelectedAction. As the method name suggests, this method is called by a client application wanting to know whether or not an action selected by a user from the UI can be performed. For example, A user selects revise from a list of actions for a document. Should the revise action proceed? The method signature for validateSelectedAction looks like this:
public UIValidationResult validateSelectedAction (String validationKey, UIValidationCriteria validationCriteria, Locale locale)

As you can see, the method takes three arguments: 1. A string indicating the key that was used by the client to identify the action being validated (think of this as the action name) 2. A UIValidationCriteria object (more on this in a second...), and 3. A Locale The first and third arguments should be fairly self-explanatory. The UIValidationCriteria object is the validation criteria bean that was previously mentioned. It holds data that the client set and passed to the validation service (e.g., user, container, context object(s), etc.). The return type is UIValidationResult whose attributes include a status indicating whether or not the action should be permitted. Pseudo-code for a validateSelectedAction implementation would look like this:
import com.ptc.core.ui.validation.*; public class MyValidator extends DefaultUIComponentValidator{ public UIValidationResult validateSelectedAction (String a_key, UIValidationCriteria a_criteria, Locale a_locale) { // get required info from UIValidationCriteria WTContainerRef parentContainer = a_criteria.getParentContainer(); WTReference contextObject = a_criteria.getContextObject(); WTPrincipalReference userRef = a_criteria.getUser(); // create status and message objects to pass back UIValidationStatus status = null; UIValidationFeedbackMsg msg = null; // perform validation logic if (we can allow this action to proceed){ status = UIValidationStatus.PERMITTED; } else{ status = UIValidationStatus.DENIED; msg = new UIValidationMsg(localized text,

Customizing HTML Clients Using the Windchill JSP Framework

457

UIValidationMsgType.INFO) } // return a validation result with the calculated status and message return new UIValidationResult(a_key, contextObject, status, msg); } }

Implementing a validateSelectedMultiSelectAction Method Another of the methods that you can override in your Validator implementation is called validateSelectedMultiSelectAction. It is similar to the validateSelectedAction method. The only difference is that this method will be called to validate a multi-select action, and will therefore return multiple results. For example, A user selects checkout from a table header to perform the checkout of several selected parts in the table. Should we allow all of the parts to be checked out? The method signature for validateSelectedMultiSelectAction looks like this:
public UIValidationResultSet validateSelectedAction (String validationKey, UIValidationCriteria validationCriteria, Locale locale)

Note that the arguments are identical to those passed to validateSelectedAction. The only difference is that this method returns an object of type UIValidationResultSet, which, as the name suggests, is just a set of UIValidationResult objects. Pseudo-code for the validateSelectedMultiSelectAction would look like this:
import com.ptc.core.ui.validation.*; public class MyValidator extends DefaultUIComponentValidator{ public UIValidationResultSet validateSelectedMultiSelectAction (String a_key, UIValidationCriteria a_criteria, Locale a_locale){ // get required info from UIValidationCriteria WTContainerRef parentContainer = a_criteria.getParentContainer(); WTCollection targetObjects = a_criteria.getTargetObjects(); WTPrincipalReference userRef = a_criteria.getUser(); // create result set to return UIValidationResultSet resultSet = new UIValidationResultSet(); // iterate through target objects Iterator targetRefIterator = targetObjects.referenceIterator(); while (targetRefIterator.hasNext()){ WTReference targetRef = (WTReference)targetRefIterator.next(); if (we can allow this action to proceed for this object ){ resultSet.addResult(new UIValidationResult(a_key, targetRef,

458

Windchill Customization Guide

UIValidationStatus.PERMITTED, null)); } else{ resultSet.addResult(new UIValidationResult(a_key, targetRef, UIValidationStatus.DENIED, new UIValidationMsg (localized text, UIValidationMsgType.INFO))); } } // return the result set return resultSet } }

Implementing a validateFormSubmission Method A third method you can override in your Validator implementation is validateFormSubmission. This method would be invoked on the service by a client wanting to validate whether or not the user-entered data in a form is valid. For example, A user clicks next after entering data on the details step of a create part wizard. Should we allow them to go to the next step, based on what theyve entered? The method arguments and return type for validateFormSubmission are identical to those for validateSelectedAction:
public UIValidationResult validateFormSubmission (String validationKey, UIValidationCriteria validationCriteria, Locale locale)

Similarly, a pseudo-implementation of this method would be similar to what we provided for validateSelectedAction. Implementing Pre-Validation Methods The last two methods you can override in your Validator implementation are performFullPreValidation and performLimitedPreValidation. The methods provide similar functionality, as they are both called by clients wanting to know whether an action (or other UI component) should be enabled, disabled, or hidden in the UI. The intended usage of performLimitedPreValidation is that a client would call it when they want to do a quick check of whether or not an action should appear in the UI. A client calling this method should know that they are not guaranteed that actions will be accurately hidden in all cases we are sacrificing accuracy in favor of performance. On the other hand, a client would call performFullPreValidation in cases where they want accurate results, at the potential cost of decreased performance. Some examples of Pre-Validation include:

Customizing HTML Clients Using the Windchill JSP Framework

459

Example 1: We are rendering a table in which each row could have action icons for check-out, check-in, revise, or delete. Given the objects in the table, which actions should be enabled in which row?

Note In this case, we would probably want to perform limited pre-validation for performance reasons.
Example 2: We are rendering a dropdown list of actions on a doc details page. Given a list of several actions, which ones should be available for this particular doc?

Note In this case, we would probably want to perform full pre-validation, since performance is not as much of an issue (only one object, as opposed to several in the first example), and accuracy is more important.
The argument list and return types for each Pre-Validation method are identical:
public UIValidationResultSet performFullPreValidation (String validationKey, UIValidationCriteria validationCriteria, Locale locale) public UIValidationResultSet performLimitedPreValidation (String validationKey, UIValidationCriteria validationCriteria, Locale locale)

A pseudo-implementation of performFullPreValidation would take the following form:


import com.ptc.core.ui.validation.*; public class MyValidator extends DefaultUIComponentValidator{ public UIValidationResultSet performFullPreValidation (String a_key, UIValidationCriteria a_criteria, Locale a_locale){ // get required info from UIValidationCriteria WTContainerRef parentContainer = a_criteria.getParentContainer(); WTCollection targetObjects = a_criteria.getTargetObjects(); WTPrincipalReference userRef = a_criteria.getUser(); // create result set to return UIValidationResultSet resultSet = new UIValidationResultSet(); // iterate through target objects Iterator targetRefIterator = targetObjects.referenceIterator(); while (targetRefIterator.hasNext()){ WTReference targetRef = (WTReference)targetRefIterator.next();

460

Windchill Customization Guide

if (we can allow this action to proceed for this object ){ resultSet.addResult(new UIValidationResult(a_key, targetRef, UIValidationStatus.PERMITTED, null)); } else{ resultSet.addResult(new UIValidationResult(a_key, targetRef, UIValidationStatus.DENIED, new UIValidationMsg (localized text, UIValidationMsgType.INFO))); } } // return the result set return resultSet } }

Pseudo-code for a performLimitedPreValidation would look identical to the example above for performFullPreValidation. The only difference in the actual implementation is that the level of scrutiny used to determine validity may be higher (and less performant) in the full pre-validation example. However, its important to note that in practice its possible that the limited pre-validation and the full pre-validation checks to be identical (in this case, we would likely be saying that there are no significant performance impacts of performing full pre-validation all the time).

Sample Code
Example Validator DefaultWIPValidator.java DefaultWIPValidator.java
Note This source code can be found at the following location: \<WT_HOME>\src\com\ptc\windchill\enterprise\ wip \DefaultWIPValidator.java
/* bcwti * * Copyright (c) 2004 Parametric Technology Corporation (PTC). All Rights * Reserved. * * This software is the confidential and proprietary information of PTC. * You shall not disclose such confidential information and shall use it * only in accordance with the terms of the license agreement. * * ecwti */ package com.ptc.windchill.enterprise.wip;

Customizing HTML Clients Using the Windchill JSP Framework

461

import com.ptc.core.ui.validation.*; import import import import java.lang.ClassNotFoundException; java.util.ArrayList; java.util.Iterator; java.util.Locale;

import org.apache.log4j.Logger; import import import import import import import import import import import import import import import import import import import import import import import import wt.access.AccessPermission; wt.access.AccessControlHelper; wt.epm.workspaces.EPMWorkspaceHelper; wt.fc.Persistable; wt.fc.ReferenceFactory; wt.fc.WTReference; wt.fc.collections.WTArrayList; wt.fc.collections.WTCollection; wt.folder.CabinetBased; wt.folder.CabinetMember; wt.folder.Foldered; wt.folder.FolderHelper; wt.inf.container.WTContained; wt.inf.container.WTContainerHelper; wt.log4j.LogR; wt.org.WTUser; wt.sandbox.SandboxHelper; wt.session.SessionHelper; wt.util.WTException; wt.vc.Iterated; wt.vc.VersionControlHelper; wt.vc.wip.Workable; wt.vc.wip.WorkInProgressHelper; wt.vc.wip.WorkInProgressState;

public class DefaultWIPValidator extends DefaultUIComponentValidator { logger private = LogR.getLogger("wt.method.server.httpgw"); Logger private ReferenceFactory refFactory = null; private static final String FULL = "full"; private static final String LIMITED = "limited"; private static final String SELECTED = "selected"; /** * This implementation of performLimitedPreValidation will check the checkout * state of all the Workable objects in the ValidationCriteria's targetObjects * WTCollection, and base its validation results on whether an object in the * given state can have the specified action performed on it. (e.g., an object * in the checked-in state can not have an undo checkout action performed on it) * * At a minimum, a caller of this method should provide the targetObjects * WTCollection in the validationCriteria argument. * * The expected validationKey arguments for this method are: * checkin * checkout

462

Windchill Customization Guide

* undocheckout * * <BR><BR><B>Supported API: </B>false * * @param validationKey The String identifying the action or component being validated. * @param validationCriteria Object holding information required to per form validation tasks. * @param locale The user's Locale. If a null value is passed in, the session locale will be used. * @return UIValidationResultSet **/ public UIValidationResultSet performLimitedPreValidation (String valida tionKey, UIValidationCriteria validationCriteria, Locale loc ale) throws WTException { logger.debug("ENTERING DefaultWIPValidator.performLimitedPreValidati on"); logger.trace(" validtionKey -> " + validationKey); logger.trace(" validationCriteria -> " + validationCriteria.toStrin g()); UIValidationResultSet resultSet = performWIPValidation(validationKey, validationCriteria, locale, LIMITED); logger.trace("RETURNING " + resultSet.toString()); logger.debug("EXITING DefaultWIPValidator.performLimitedPreValidat ion"); return resultSet; }

public UIValidationResultSet performFullPreValidation (String validation Key, UIValidationCriteria validationCriteria, Locale loca le) throws WTException { logger.debug("ENTERING DefaultWIPValidator.performFullPreValidation"); logger.trace(" validtionKey -> " + validationKey); logger.trace(" validationCriteria -> " + validationCriteria.toString( )); UIValidationResultSet resultSet = performWIPValidation(validationKey, validationCriteria, locale, FULL); logger.trace("RETURNING " + resultSet.toString()); logger.debug("EXITING DefaultWIPValidator.performFullPreValidation"); return resultSet; } public UIValidationResult validateSelectedAction (String validation Key, UIValidationCriteria validationCriteria, Locale locale)

Customizing HTML Clients Using the Windchill JSP Framework

463

throws WTException { logger.debug("ENTERING DefaultWIPValidator.validateSelectedAction"); logger.trace(" validtionKey -> " + validationKey); logger.trace(" validationCriteria -> " + validationCriteria.toString( )); UIValidationResult result = null; WTReference wtRef = validationCriteria.getContextObject(); Persistable persistable = wtRef.getObject(); if (!(persistable instanceof Workable)){ return new UIValidationResult(validationKey, wtRef, UIValidat ion Status.DENIED, null); } Workable workable = (Workable)persistable; if (validationKey.equalsIgnoreCase("checkin") || validationKey.equals IgnoreCase("undocheckout")){ result = performCheckinValidation(validationKey, workable, SELE CTED, (WTUser)(validationCriteria.getUser().getPrincipal())); } else if (validationKey.equalsIgnoreCase("checkout")){ result = performCheckoutValidation(validationKey, workable, SELE CTED); } logger.trace("RETURNING " + result.toString()); logger.debug("EXITING DefaultWIPValidator.validateSelectedAction"); return result; }

public UIValidationResultSet validateSelectedMultiSelectAction (String vali dationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { logger.debug("ENTERING DefaultWIPValidator.validateSelectedMultiSelectAc tion"); logger.trace(" validtionKey -> " + validationKey); logger.trace(" validationCriteria -> " + validationCriteria.toString()); UIValidationResultSet resultSet = performWIPValidation(validationKey, validationCriteria, locale, SELECTED); logger.trace("RETURNING " + resultSet.toString()); logger.debug("EXITING DefaultWIPValidator.validateSelectedMultiSelect Action"); return resultSet; } // ***NOTE:

464

Windchill Customization Guide

// // // // //

There is no post-submit validation for the WIP actions (checkin, checkout, undocheckout), since there is no wizard launched when one of the actions is performed. Therefore, there is no need to define a validateFormSubmission method in this class.

// public UIValidationResult validateFormSubmission (String validationKey, UIValidaitonCriteria // validationCriteria, Locale locale)

private UIValidationResultSet performWIPValidation(String validationKey, UIValidationCriteria validationCriteria, Locale locale, String validationType) throws WTException { UIValidationResultSet resultSet = new UIValidationResultSet(); WTCollection targetObjects = new WTArrayList(validationCriteria.get TargetObjects()); Iterator workableIter = getWorkableIterator(targetObjects); Workable workable = null; while (workableIter.hasNext()){ workable = (Workable)workableIter.next(); if (validationKey.equalsIgnoreCase("checkin") || validationKey.equal sIgnoreCase("undocheckout")){ resultSet.addResult(performCheckinValidation(validationKey, worka ble, validationType, (WTUser)(validationCriteria.getUser().getPrincipal()))); } else if (validationKey.equalsIgnoreCase("checkout")){ resultSet.addResult(performCheckoutValidation(validationKey, worka ble, validationType)); } } resultSet.appendResults(processNonWorkables(targetObjects, validationKey, validationType)); return resultSet; }

private UIValidationResult performCheckinValidation(String validationKey, Workable workable, String validationType, WTUser user) throws WTException { WTReference wtRef = getWTReference(workable); if (validationType.equals(LIMITED)){ WorkInProgressState state = workable.getCheckoutInfo().getState(); if (state.equals(WorkInProgressState.CHECKED_OUT) || state.equals( WorkInProgressState. CHECKED_OUT_TO_SANDBOX)){ return new UIValidationResult(validationKey, wtRef, UIValidation Status.ENABLED, null); } else{ return new UIValidationResult(validationKey, wtRef, UIValidation

Customizing HTML Clients Using the Windchill JSP Framework

465

Status.DISABLED, null); } } else if (validationType.equals(FULL) || validationType.equals(SELECTED)){ UIValidationStatus goodStatus = null; UIValidationStatus badStatus = null; if (validationType.equals(FULL)){ goodStatus = UIValidationStatus.ENABLED; badStatus = UIValidationStatus.DISABLED; } else{ goodStatus = UIValidationStatus.PERMITTED; badStatus = UIValidationStatus.DENIED; } if (workable instanceof CabinetBased){ CabinetBased orig; if (WorkInProgressHelper.isWorkingCopy(workable)) { orig = (CabinetBased)WorkInProgressHelper.service.originalCopyOf (workable); } else { orig = (CabinetBased)workable; } if (isNewInWorkspace(orig)){ return new UIValidationResult(validationKey, wtRef, badStatus, null); } } if (WorkInProgressHelper.isCheckedOut(workable, user) || (WorkInProgressHelper.isCheckedOut(workable) && WTContainerHelper.service.isAdministrator(((WTContained)workable). getContainerReference(), user))){ return new UIValidationResult(validationKey, wtRef, goodStatus, null); } else{ return new UIValidationResult(validationKey, wtRef, badStatus, null); } } return new UIValidationResult(validationKey, wtRef, UIValidationStatus. ENABLED, null); }

private UIValidationResult performCheckoutValidation(String validationKey, Workable workable, String validationType) throws WTException { WTReference wtRef = getWTReference(workable);

466

Windchill Customization Guide

if (validationType.equals(LIMITED)){ WorkInProgressState state = workable.getCheckoutInfo().getState(); if (state.equals(WorkInProgressState.CHECKED_OUT) || state.equals( WorkInProgress State.CHECKED_OUT_TO_SANDBOX)){ return new UIValidationResult(validationKey, wtRef, UIValidation Status.DISABLED,null); } else{ return new UIValidationResult(validationKey, wtRef, UIValidation Status.ENABLED, null); } } else if (validationType.equals(FULL) || validationType.equals(SELECTED)){ UIValidationStatus goodStatus = null; UIValidationStatus badStatus = null; if (validationType.equals(FULL)){ goodStatus = UIValidationStatus.ENABLED; badStatus = UIValidationStatus.DISABLED; } else{ goodStatus = UIValidationStatus.PERMITTED; badStatus = UIValidationStatus.DENIED; } if (isNewInWorkspace(workable)){ return new UIValidationResult(validationKey, wtRef, badStatus, null); } if ((AccessControlHelper.manager.hasAccess(workable, AccessPermis sion.MODIFY)) && (!WorkInProgressHelper.isCheckedOut(workable) && (VersionControlHelper.isLatestIteration((Iterated)workable)) && (!SandboxHelper.isCheckedOutToSandbox(workable)))){ return new UIValidationResult(validationKey, wtRef, goodStatus, null); } else{ return new UIValidationResult(validationKey, wtRef, badStatus, null); } } return new UIValidationResult(validationKey, wtRef, UIValidationStat us.ENABLED, null); }

private Iterator getWorkableIterator(WTCollection targetObjects) { try{ return targetObjects.persistableIterator(Class.forName("wt.vc.wip. Workable"), true);

Customizing HTML Clients Using the Windchill JSP Framework

467

} catch(Exception e){ return (new ArrayList(0)).iterator(); } }

private WTReference getWTReference(Workable workable) { if (refFactory == null){ refFactory = new ReferenceFactory(); } try{ return refFactory.getReference(workable); } catch(WTException wte){ return null; } }

private static boolean isNewInWorkspace(Object object) throws WTException { if(object instanceof Foldered || object instanceof CabinetMember) { WTArrayList objArray = new WTArrayList(); objArray.add(object); if(FolderHelper.service.getObjsInPersonalCabinets(objArray).size() > 0) { if(EPMWorkspaceHelper.manager.getNewObjects(objArray).size() > 0) { return true; } } } return false; }

private UIValidationResultSet processNonWorkables(WTCollection targetObjects, String validationKey, String validationType) { UIValidationResultSet resultSet = new UIValidationResultSet(); UIValidationStatus status = null; if (validationType.equals(SELECTED)) status = UIValidationStatus.DENIED; else status = UIValidationStatus.HIDDEN; try{ targetObjects.removeAll(Class.forName("wt.vc.wip.Workable"), true); } catch(ClassNotFoundException cnfe){ // do nothing } Iterator nonWorkableIter = targetObjects.referenceIterator();

468

Windchill Customization Guide

WTReference wtRef = null; while(nonWorkableIter.hasNext()){ wtRef = (WTReference)nonWorkableIter.next(); resultSet.addResult(new UIValidationResult(validationKey, wtRef, status, null)); } return resultSet; } }

Known Uses
This documentation should be used by any developer responsible for writing a Validator for an action or UI component.

Customizing HTML Clients Using the Windchill JSP Framework

469

Split Pane / Two Pane


You want to display information from two different pages in one logical UI component. Background The two pane component is a way to present the data from two JSPs into one logical UI component. The panes can be laid out horizontally or vertically. Theres a separator between the two panes (left/right or top/bottom) that allows the user to dynamically change the size of the panes. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This information should be applied by a developer or customizer who is responsible for laying out the two pane component for their functional area in Windchill. This documentation assumes that : You have some service method to provide data for the two pane component.

Intended Outcome Two Pane - Horizontal

470

Windchill Customization Guide

Two Pane - Vertical

Solution
Use the two pane common component tag, renderTwoPanes. This is included in the JCA common components library (http://www.ptc.com/windchill/taglib/ components). Prerequisite knowledge To use the two pane component, you need to have an understanding of the following: JSPs, tag libraries, and JSTL The JSP-based client architecture framework in Windchill

Solution Elements Using this component, a developer needs to configure the left and right pane JSP, while the layout of the page is provided by the renderTwoPanes taglib. Element Type RenderTwoPanesTag.java Java class Description The tag that renders out the two pane component in a JSP Renders the component to the DOM The JSP to have displayed in the left or top pane,

navigation.jsfrag <your_left_pane>.jsp

JavaScript Fragment JSP

Customizing HTML Clients Using the Windchill JSP Framework

471

Element

Type

<your_right_pane>.jsp

JSP

<your_header_pane>.jsp

JSP

<your_javascript_file>.js

JavaScript file

Description depending on the orientation value (horizontal| vertical). The JSP to have displayed in the right or bottom pane, depending on the orientation value (horizontal|vertical). The JSP to have displayed in the top pane when orientation is set to horizontal. Contains your click handler function (if specified). The click handler is a Javascript function that will be called for every click event fired from either pane (left/right or top/ bottom). The click handle will most likely make an AJAX call to get the data to display. Typically, when something is clicked in one pane youll want to have something happen in the other pane.

Two pane in wizard step This component can also be used in wizard step but the following pieces are required. Place the following fragments in the wizard step JSP where the two pane component will be used:

472

Windchill Customization Guide

1. Create an empty DIV element. The two pane component will render itself to this DIV: <div id="twoPaneExample"></div> 2. Override the viewport object. The two pane component will be added to the viewport. By default, the wizard does not create a viewport object, thus we need to define the PTC.navigation.loadViewPort JavaScript function.

Note Ensure the value for the renderTo attribute matches the id given to the DIV element in previous step.
PTC.navigation.loadViewPort = function(pageItems){ var verticalPanel = new Ext.Panel({ layout:'fit', id: 'jca_viewport', renderTo: 'twoPaneExample', width : 800, height: 600, items: pageItems }); }

3. Load the pop-up shell by calling the following JavaScript function:


PTC.navigation.loadShell loadShell (PTC.navigation.POPUP_SHELL);

4. If the wizard step is not the first step, then you may need to add this JavaScript code snippet so that your split pane component will be visible when the step is rendered:
PTC.wizard.on(wizardStepReady, function(stepId) { if (stepId === thisWizardStepId) { PTC.wizard.showSplitPaneOnWizardStep(jca_viewport, {left:20, right: 80}, vertical); } });

In the above code example, you would substitute thisWizardStepId for the actual Id of your wizard step. The left and right parameters correspond to the leftPaneSize and rightPaneSize that you configured using the renderTwoPanes tag, as does the orientation (vertical in this example). For wizard references, please see Constructing Wizards on page 775.

Customizing HTML Clients Using the Windchill JSP Framework

473

Customization Points
renderTwoPanes tag attributes The renderTwoPanes tag is a custom JSP tag that you insert in the JSP. Parameter orientation Default Value horizontal Possible Values horizontal, vertical Req? No Description Lays out the inner panels either side by side or stacked URI to the file to be rendered in the left/top pane URI to the file to be rendered in the right/ bottom pane JSP file to be rendered in the top pane. This is only used when orientation is set to horizontal. Function called for every click event fired from either pane (left/right or top/bottom). The click handle will most likely make an AJAX call to get the data to display. Typically, when something is clicked in one pane youll

leftPane

Relative or ab- Yes solute path to a JSP page Relative or ab- Yes solute path to a JSP page Relative or ab- No solute path to a JSP

rightPane

headerPane

onClick

Name of a val- No id JavaScript function

474

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req?

Description want to have something happen in the other pane. Specifies the width/height (depending on the orientation value) of the panel. Specifies the width/height (depending on the orientation value) of the panel. Specifies the height of the panel. Specified as an absolute pixel size (i.e. 150)

leftPaneSize

25

0-100 (Percentage)

No

rightPaneSize

75

0-100 (Percentage)

No

headerPaneHeight

Absolute Pixel No size

Limitations
When the left or right pane is resized, some of the components within that pane may not get resized properly. The underlying framework manages the layout of the components it knows about in its component hierarchy, so that (among other things) it can recalculate the layout on resize events. For example, when a resize event happens, it would recalculate the layout of its children, and those childrens children, and so on. Because the two pane component simply renders its contents to the DIV corresponding to the pane, and does not actually add its contents as a child of the panes panel, nesting components (especially those components that are containers to house other components) within a pane may not behave as expected.

Customizing HTML Clients Using the Windchill JSP Framework

475

Sample Code
The following snippet can be inserted to your JSP to display two pages in the Two Pane component.
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <jca:renderTwoPanes headerPane="/netmarkets/jsp/carambola/customization/examples/twoPanePanels /headerPane.jsp?dynamicUpdate=true" headerPaneHeight="150"leftPane="/netmarkets/jsp/carambola/customization/ examples/twoPanePanels /leftOrTopPane.jsp? dynamicUpdate=true "leftPaneSize="30"r ightPane="/netmarkets/jsp/carambola/customization/examples/twoPanePanels/ rightOrBottomPane.jsp?dynamicUpdate=true "rightPaneSize=70 orientation="horizontal"onClick= "PTC.carambola.twoPane.onClickHandler"/>

The following is an example onClick javascript handler. This example handles the click event in the left/top pane and will render the response to the right/bottom pane.
PTC.carambola.twoPane.onClickHandler = function(evt) { var button = PTC.carambola.twoPane.getChildNodeByTag(evt.target, 'BUTTON'); if(button != undefined) { var cp = Ext.getCmp(PTC.navigation.cardManager); var contentPanel; var renderToDiv = 'twoPanes_RIGHTPANE2'; // get the content pane that corresponds how the two pane component is laid out (i.e. right or bottom pane) if(cp.layout.activeItem.CONTENT_DIV === renderToDiv) { contentPanel = Ext.getCmp (PTC.navigation.contentTabID + '_twoPanes_center'); } else { renderToDiv = 'twoPanes_BOTTOMPANE'; contentPanel = Ext.getCmp (PTC.navigation.contentTabID + '_twoPanes_bottom'); } // make an AJAX call to get the HTML to render in the right/bottom pane if(contentPanel !== undefined) { contentPanel.clearCardContents(); var options = { asynchronous: false, method: 'get', parameters: { buttonId: button.innerHTML, dynamicUpdate: true } }; var transport = requestHandler.doRequest(getBaseHref() + 'netmarkets/jsp/carambola/customization/examples/two

476

Windchill Customization Guide

PanePanels/rightOrBottomPane.jsp', options); // render the HTML returned from the AJAX response to the right/bottom DIV var panel = new Ext.Panel ({ id: 'test', renderTo: renderToDiv, html: transport.responseText }); } // render out the new right/bottom pane panel.doLayout(); } }

Customizing HTML Clients Using the Windchill JSP Framework

477

Examples of Usage in Windchill Code


Folders Page for Product/Project/ Product/Project/Library Library The Folders page for Product/Project/Library use the Two Pane component to layout the data horizontally

Publish Monitor The Publish Monitor (available under Site Utilities or Organization Utilities ), use the Two Pane component to layout the data vertically.

478

Windchill Customization Guide

Packaged Samples There is a Carambola example that is available under the Customization tab. The Two Pane carambola example shows the component rendered horizontally and vertically. Two Pane Example <WT_HOME>\codebase\netmarkets\jsp\carambola \customization\examples\twoPanePanels \horizontalSplitPaneExample.jsp <WT_HOME>\codebase\netmarkets\jsp\carambola \customization\examples\twoPanePanels \verticalSplitPaneExample.jsp Two Pane Wizard Example <WT_HOME>\codebase\netmarkets\jsp\carambola \customization\examples\wizard\twoPaneWizardExample. jsp <WT_HOME>\codebase\netmarkets\jsp\carambola

Customizing HTML Clients Using the Windchill JSP Framework

479

\customization\examples\wizard \twoPaneWizardExampleTwo.jsp <WT_HOME>\codebase\netmarkets\jsp\carambola \customization\examples\wizard\setStepOneWizStep.jsp <WT_HOME>\codebase\netmarkets\jsp\carambola \customization\examples\wizard\setStepTwoWizStep.jsp

480

Windchill Customization Guide

Defining Layouts in a Type Load File


1. How many default layout exists on a type? Every type has one and only one default layout which doesnt associate with any Profile or Screen. 2. How can subtype inherit layouts? Layouts are automatically inherited by the subtypes. That means, its unnecessary to redefine the same layout in the subtypes (that actually could cause unexpected result see point 4). If subtypes share the same layout, you should consider to move up the layout on the type hierarchy tree. 3. Can inherited layouts be updated by subtypes? Yes, by defining the layout with the <csvtypeContext>Parent-TypeName</csvtypeContext> tag in the subtype, you are overriding the layout in the subtype. Overriding means that you can add new groups to the existing layout, or add new attributes (inherited or non-inherited) to the existing groups, or redefine group/group members properties, e.g. coordinates. 4. Can subtypes create their own layouts? Yes, by leaving the <csvtypeContext/> tag empty or setting it to the subtype name, you are creating a layout within the subtype context. Please note that once a subtype creates its own layout, even defining the same inherited layout but within its own context, it no longer inherits any layout from its parent type, being dissected from all inherited layouts. 5. How to add new attributes to a layout on a subtype? Whether inherited or not, attributes defined as group members have to exist on that type first. That means if you want to add a new(non-inherited) attribute on a layout on the subtype, you have to first create the attribute on the subtype. 6. How to create a dynamic group to load batch attributes? By setting isStatic to false, you create a dynamic group which could have 0-1 group member. This group member must be an attribute of LWCAttributeSetAttribute class which may have a mapping property that points to a batch attribute, e.g. SCA|ALL_IBAS.

Customizing HTML Clients Using the Windchill JSP Framework

481

Load File Example The following example adds a layout and its meta data to the wt.change2. WTChangeOrder2 type.
!-- beginning to define a new layout --> csvBeginLayoutDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader. beginProcessLayoutDefinition"> csvname>mini_info_page_layout/csvname> !-- name of the layout --> csvisDefault>false/csvisDefault> !-- whether this is the default layout to use --> csvtypeContext>/csvtypeContext> !-- By default, it's the current type. It is a must have to indicate an inherited layout --> csvdefaultGroup>groupA/csvdefaultGroup> !-- the default group of the layout, has to be one of the groups defined below --> csvprofiles>/csvprofiles> !-- a combination of typeContext, profiles, and screens uniquely identifies a layout --> csvscreens>Mini_Info_Page/csvscreens> !-- available screens must have been defined in the BaseDefinitionLoader.xml --> /csvBeginLayoutDefView>

!-- beginning of defining a group within the layout --> csvBeginGroupDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader. beginProcessGroupDefinition"> csvname>groupA/csvname> !-- name of the group, uniquely identify a group within a layout --> csvisStatic>true/csvisStatic> !-- in most cases, it's true --> csvstyle>List/csvstyle> !-- available group styles must have been defined in the BaseDefinitionLoader.xml --> /csvBeginGroupDefView>

!-- defining properties of the group: 3 in total --> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader. processGroupPropertyValue"> csvname>displayName/csvname> !-- name of the property --> csvvalue>groupA/csvvalue> !-- value --> csvlocale_en_us>EN_US groupA/csvlocale_en_us> !-the following are localized values --> csvlocale_en_gb>EN_GB groupA/csvlocale_en_gb> csvlocale_fr>FR groupA/csvlocale_fr> csvlocale_de>DE groupA/csvlocale_de> csvlocale_es>ES groupA/csvlocale_es> csvlocale_ja>JA groupA/csvlocale_ja> csvlocale_it>IT groupA/csvlocale_it> csvlocale_ko>KO groupA/csvlocale_ko> csvlocale_zh_cn>ZH_CN groupA/csvlocale_zh_cn> csvlocale_zh_tw>ZH_TW groupA/csvlocale_zh_tw> /csvPropertyValue> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader. processGroupPropertyValue">csvname>description/csvname> csvvalue>groupA/csvvalue> csvlocale_en_us>EN_US groupA/csvlocale_en_us> csvlocale_en_gb>EN_GB groupA/csvlocale_en_gb> csvlocale_fr>FR groupA/csvlocale_fr> csvlocale_de>DE groupA/csvlocale_de>

482

Windchill Customization Guide

csvlocale_es>ES groupA/csvlocale_es> csvlocale_ja>JA groupA/csvlocale_ja> csvlocale_it>IT groupA/csvlocale_it> csvlocale_ko>KO groupA/csvlocale_ko> csvlocale_zh_cn>ZH_CN groupA/csvlocale_zh_cn> csvlocale_zh_tw>ZH_TW groupA/csvlocale_zh_tw> /csvPropertyValue> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader. processGroupPropertyValue"> csvname>sort_order/csvname> csvvalue>1/csvvalue> /csvPropertyValue>

!-- beginning of defining a membership of the group: --> csvBeginGroupMemberView handler="com.ptc.core.lwc.server.TypeDefinitionLoader .beginProcessGroupMembership"> csvname>number/csvname> /csvBeginGroupMemberView>

!-- beginning of defining properties (coordinates) of the membership --> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.process GroupMembershipPropertyValue"> csvname>col_coord/csvname> csvvalue>1/csvvalue> /csvPropertyValue> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.process GroupMembershipPropertyValue"> csvname>row_coord/csvname> csvvalue>1/csvvalue> /csvPropertyValue> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.process GroupMembershipPropertyValue"> csvname>col_span/csvname> csvvalue>1/csvvalue> /csvPropertyValue> csvPropertyValue handler="com.ptc.core.lwc.server.TypeDefinitionLoader.process GroupMembershipPropertyValue"> csvname>row_span/csvname> csvvalue>1/csvvalue> /csvPropertyValue>

!-- ending of defining a membership of the group --> csvEndGroupMemberView handler="com.ptc.core.lwc.server.TypeDefinitionLoader. endProcessGroupMembership"/> !-- more memberships can be defined here --> !-- ending of defining a group within the layout --> csvEndGroupDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader.end ProcessGroupDefinition"/> !-- more groups can be defined here --> !-- ending of defining a new layout --> csvEndLayoutDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader.end ProcessLayoutDefinition"/> !-- more layouts can be defined here -->

Customizing HTML Clients Using the Windchill JSP Framework

483

!-- ending of defining a type --> csvEndTypeDefView handler="com.ptc.core.lwc.server.TypeDefinitionLoader.end ProcessTypeDefinition"/>

484

Windchill Customization Guide

13
Adding Actions and Hooking Them Up in the UI
Windchill Client Architecture Action Framework Overview ........................................... 486 Tab Models ............................................................................................................. 518 Customizing Role-based Visibility ............................................................................. 528 User Interface Stickiness.......................................................................................... 539 Defining Menus ....................................................................................................... 540

This chapter describes how to customize actions and add them to the user interface.

485

Windchill Client Architecture Action Framework Overview


Objective
You want to add a new action that will be exposed in the user interface. You want to add a new action model to the system. You want to remove an action from an action model.

Background
The action framework for the Windchill client architecture supports the ability to configure new actions and action models in the system.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This section describes the action framework for the Windchill Client Architecture. It does not include information on how to control the display of the action. For more information on controlling the display see Related Documentation on page 517.

Intended Outcome
When you are finished reading this, you should understand how the action framework works, and how to register actions and action models into the action framework. You should also be familiar with the tools and debug settings that can help in your development.

Solutions
Define a new action and add it to an action model. Define a new action model to the system. Remove an action from an action model.

Prerequisite knowledge XML file structures

Solution Elements
Element StandardNmAction Service Type .java Description The

486

Windchill Customization Guide

Element (and corresponding helper and forwarder)

Type

Description StandardNmActionService manages the actions and actionmodels in the system. Run time Location: <Windchill> \codebase\com \ptc \netmarkets\util \misc Default system xml file for defining actions in the system. Run time Location: <Windchill> \codebase\config \actions Default system xml file for defining action models ins the system. Run time Location: <Windchill> \codebase\config \actions Default system dtd file for defining structure of an actions*.xml Run time Location: <Windchill> \codebase\config \actions Default system dtd file for defining structure of an actionsmodels*.xml Run time Location: <Windchill> \codebase\config \actions

actions.xml

.xml

actionmodels.xml

*.xml

actions.dtd

.xml

actionmodels.dtd

*.xml

Adding Actions and Hooking Them Up in the UI

487

The action framework provides a way to define actions and action models within the system. A service, called the StandardNmActionService manages the set of actions and action models in the system. Actions and action models are defined via xml files referred to as actions*.xml and actionmodels*. xml. There is one default actions.xml and actionmodels.xml file that is delivered with the system. However, each functional area may also have its own xml file as well which is also managed by the action service. For customization purposes, a custom-actions.xml and custom-actionmodels.xml is delivered with the product and are found in codebase/config/actions relative to the Windchill installation directory. All other out of the box actions.xml and actionmodels.xml files are also located in <WT_HOME>/codebase/config/actions. The default actions.xml and actionmodels.xml files contain commonly used actions, such as copy, cut, and commonly used action models such as wizard buttons. Additional actions*.xml and actionmodels*.xml files contain actions. and action models related to their functional areas. (e.g. ChangeManagementactions.xml contains actions related to change management, PartManagement-actions.xml contains actions related to part management). In general, as a developer you would not have to directly make calls to the StandardNmActionService. These calls are done via the components that support display of actions and action models, for example tables, trees, information pages. For details about how to configure the action model to use for a component, see related sections: See the Constructing Wizards on page 775 for more detailed information on wizards. See the information on tables and trees in Presenting Information in the UI on page 573 . See the information in Information Pages on page 891.

Procedure Defining a new action


Actions in the system are uniquely identified by the name of the action and the object type. They should be defined in an xml file that follows the structure based on the codebase/config/actions/actions.dtd. Here is an example of an action definition for the New Document wizard.
<objecttype name="document" class="wt.doc.WTDocument" resourceBundle="com.ptc.windchill.enterprise.doc.documentResource"> <action name="create" uicomponent="CREATE_DOC" dtiUpload="true"> <command

488

Windchill Customization Guide

class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcessor" method="execute" windowType="popup" onClick="validateCreateLocation(event)"/> <includeFilter name="projectM4D" /> <nonSupportedTypes value="wt.part.WTPart"/> <supportedTypes value="wt.doc.WTDocument"/> </action> </objecttype>

Objecttype tag The objecttype name is a way to create a name space as well as packaging for actions related to a specific object or functional area. In the above example, the name document creates a unique name space for actions that apply to wt.doc. WTDocuments. Naming conventions for the name of an objecttype can be any combination of alpha-numeric characters. Most objecttypes are an alias for the persistable object to which the actions relate. Actions that apply to any object type, such as copy, can be put within the objecttype of object. It is recommend that all custom objecttypes have a prefix specific to the company to prevent collisions with object types delivered with the product. The table below describes the valid parameters for a objecttype. Details about these parameters can also be found in the codebase/config/actions/actions.dtd. Parameter name Default Value n/a Possible Req? Values any Yes combination of alpha-numeric characters A valid java class Yes Description The name used to reference this objecttype Object class for the enclosed actions Class name for the default resource bundle to use for the properties of the actions that are to be localized

class

n/a

resourceBundle

n/a

Any valid resource bundle class name

No

Adding Actions and Hooking Them Up in the UI

489

Action tag The action name is a unique identifier for an action within the context of the object type. The object type in conjunction with the action name make the action unique within the system. The URL attribute of the command subtag of the action tag can be used to specify the location of the jsp associated with the action. The value should be the path of the jsp relative to <WT_HOME>/codebase. Naming conventions for the name of an action can be any combination of alphanumeric characters. We recommend that all your actions have a prefix specific to your company to prevent collisions with names of actions delivered with the product. Possible Object Type Attributes The action name is a unique identifier for an action within the context of the object type. The object type in conjunction with the action name makes the action unique within the system. By default, the action name corresponds to the name of a jsp within the package named for the objecttype. The packaging is relative to codebase/netmarkets/jsp. For example, the action name in the xml above, called create, within the objecttype of document corresponds to codebase/netmarkets/jsp/document/create.jsp. Naming conventions for the name of an action can be any combination of alphanumeric characters. We recommend that all your actions have a prefix specific to your company to prevent collisions with names of actions delivered with the product. The table below describes the valid parameters for a action. Details about these parameters can also be found in the codebase/config/actions/actions.dtd. Parameter Default Value name n/a ajax n/a Possible values all Page Component Row thirdLevelNav cad false popupMenu true No Indicates if this action is only valid within the Wildfire
Windchill Customization Guide

Req? Yes No

Description This is the name by which the action will be referenced Specifies the scope of the AJAX refresh

490

Parameter Default Value enabledwhensuspended installType false

Possible values true

Req? No

Description embedded browser Deprecated. Enabled when the project is suspended/ cancelled/completed Applicable actions based on the installed components. This is for legacy purposes only.

n/a

WINDCHILL PDM PDM PJL PDM false / true

No

multiselect

false

No

selectRequired

false

false / true

No

afterJS

n/a

No

beforeJS

n/a

No

afterVK

n/a

No

Used to indicate that multiselection of row data can be used for this action. This will hold true only if selectRequired attribute is also set to true for such an action. Determines if the UI should allow the action to proceed if nothing has been selected. Results in "Nothing Selected" popup. NOTE: if an onClick action handler is defined, the onClick function will need to check if items are selected. To do this, call the JavaScript function table. getSelectionModel(). hasSelection() JS function name to invoke on client side validation for a wizard step after the step is completed. JS function name to invoke client side validation for a wizard step when the step is loaded Server validator name to

Adding Actions and Hooking Them Up in the UI

491

Parameter Default Value

Possible values

Req?

Description invoke client side validation for a wizard step after it is finished. Server validator name to invoke client side validation for a wizard step when the step is loaded. Overrides the id of the wizard step (default is objecttype.action) Specifies that the wizard step is to be downloaded when the wizard is launched A wizard step to be hidden first, or that an action is rendered as non-clickable Used for an wizard action that represents a step in the wizard. Specifies the wizard step is required. Class name for the resource bundle to use for the properties of the actions that are to be localized Default http://<host> /<webapp> General: http://<host> /<webapp> <command.method> General with context: http://<host> /<webapp> <command.method> ?oid=... PDM: url generated by URLactionDelegate; used for template processing References entry n roleaccessprefs. xml (uic.

beforeVK

n/a

No

id

preloadWizard Page hidden

objecttype . action true

No

false / true

No

false

false / true

No

required

false

false / true

No

resourceBundle

No

renderType

PDM

No

uicomponent

No

492

Windchill Customization Guide

Parameter Default Value

Possible values

Req?

Description name) to specify role-based access. The javascript function executed executed before a wizard step is loaded or displayed. The javascript function is executed after a wizard step is loaded into memory, but before it is displayed to the user.

preloadJS

No

postloadJS

No

If necessary, place a <command> or <component> tag in the body of the <action> tag to define the processing aspects of the action.
<command class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcessor" method="execute" windowType="popup" onClick="validateCreateLocation(event)"/>

Or:
<component name="my.component.id" windowType="page" />

The class attribute defines what class to use for processing. The method attribute defines what method to execute in the class. The windowType attribute determines what window action to take. In the example above the command is for the New Document action which is a Wizard so the windowType is popup. The framework will add javascript that launches this action in a new window. The specified class and method are executed upon submit of the wizard. Possible Command Attributes Parameter Default Possible Values Value class n/a method n/a

Req? No No

Description The class to handle post The method in the class to execute and handle post Used to override the generated url Specified an additional onClick function to call. Useful for confirming with

url onClick

n/a n/a

No No

Adding Actions and Hooking Them Up in the UI

493

Parameter

Default Value

Possible Values

Req?

Description the user whether to execute a special action. The following are in scope variables that the onClick function can pass as arguments. For example: doFunction (event, target, table) event The browser event target The Ext object representing the UI component that was clicked table The Ext table that contains the action. This is null if the action is not contained within a table.

Certain places where actions are used (e.g. menu bar menu or toolbar on a table) the onClick needs to be a valid expression for an if statement, so the onclick should just be a call to a function. The onclick should not contain semi-colons or return statements.

494

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req?

Description For example: onClick="doFoo()" or onClick="doFoo (event)" are ok. But these would cause js errors: onClick="doFoo();doBar();" or onclick="doFoo(); Event.stop(event);" When the actions are parsed, the action framework will try to repair troublesome onclick definitions and if unsuccessful at repairing will just replace the onclick with an alert. There are warnings logged if the action was repaired, there are errors logged if the onclick couldn't be repaired. Also, please note that the use of the html encoded character "'" to use a single quote is not necessary; just use a regular single quote instead. If the selectRequired attribute is set on the action, the onClick handler will get called before any other handlers. Thus,

Adding Actions and Hooking Them Up in the UI

495

Parameter

Default Value

Possible Values

Req?

Description the onClick handler will need to check if there are items selected in the table. Please refer to the Action attributes section above for more information about the selectRequired attribute. New: Looks but is launched differently. All of the form data in the window is submitted to the popup window making more information available. But the extra form data may overlap with form data in the wizard so use this option as a last resort. It may be easier to override the action url to add additional information., no_content: The browser will ignore the response from the server from this request. This value is not recommended, rather create ajax request manually through a js function. normal: default, submit the form

windowType

page

new no_con- No tent normal page popup wizard_step

496

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req?

Description wizard_step: display the action as a wizard step page: display a new page popup: create a non-modal popup wizard window dialog: typically a wizard. Sets come form of data

Possible Component Attributes Component attributes are very similar to the Command Attributes above in that its another way to do the same thing. But instead of providing a direct URL, the URL is generated given the MVC component ID. The MVC component can determine the correct URL in the MVC delegate. Some common example and further explanation of how the MVC delegates interact with the component xml tag are described here. See MVC Components on page 251 for more information. Parameter name Default Value n/a Possible Values Req? Yes Description The MVC component id that should be used to display when this action is clicked. Values are from: com.ptc. core.ui.resources.ComponentType The type can change the url to typeBased under certain conditions such as INFO.

componentType

n/a

No INFO| PICKER| SEARCH| TABLE| WIZARD| WIZARD_TABLE| WIZARD_ATTRIBUTES _TABLE| IN-

Adding Actions and Hooking Them Up in the UI

497

Parameter

Default Value

Possible Values FO_ATTRIBUTES_ TABLE| SIMPLE| MINI_INFO| PRIMARY_ATTRIBUTES

Req?

Description The componentType will affect whether objects rendered on the resulting page are editable, read-only, or validated out. Some actions are only available under certain componentTypes URL parameters that will be added to the generated MVC url each time the action is rendered Determines if the MVC delegate lookup should include the type of object being acted upon. The MVC url that is generated will be /tcomp/ instead of /comp/ for type-based components. Specified an additional onClick function to call. Useful for confirming
Windchill Customization Guide

urlParams

n/a

typeBased

n/a

false | true

onClick

n/a

498

Parameter

Default Value

Possible Values

Req?

Description with the user whether to execute a special action. The following are in scope variables that the onClick function can pass as arguments. For example: doFunction (event, target, table) Var NaName event DeDescriscription The browser event target The Ext object representing the UI component that was clicked table The Ext table that

Adding Actions and Hooking Them Up in the UI

499

Parameter

Default Value

Possible Values

Req?

Description Var NaName DeDescriscription contains the action. This is null if the action is not contained within a table.

Certain places where actions are used (e.g. menu bar menu or toolbar on a table) the onClick needs to be a valid expression for an if statement, so the onclick should just be a call to a function. The onclick should not contain semi-colons or return statements. For example: onClick="doFoo
Windchill Customization Guide

500

Parameter

Default Value

Possible Values

Req?

Description ()" or onClick="doFoo (event)" are ok. But these would cause js errors: onClick="doFoo ();doBar();" or onclick="doFoo();Event. stop(event);" When the actions are parsed, the action framework will try to repair troublesome onclick definitions and if unsuccessful at repairing will just replace the onclick with an alert. There are warnings logged if the action was repaired, there are errors logged if the onclick couldn't be repaired. Also, please note that the use of the html encoded character "'" to use a

Adding Actions and Hooking Them Up in the UI

501

Parameter

Default Value

Possible Values

Req?

Description single quote is not necessary; just use a regular single quote instead. If the selectRequired attribute is set on the action, the onClick handler will get called before any other handlers. Thus, the onClick handler will need to check if there are items selected in the table. Please refer to the Action attributes section above for more information about the selectRequired attribute. New: looks but is launched differently. All of the form data in the window is submitted to the popup window making more information available. But the extra

windowType

page

new|no_content| normal| page| popup| wizard_step

502

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req?

Description form data may overlap with form data in the wizard so use this option as a last resort. It may be easier to override the action url to add additional information., no_content: The browser will ignore the response from the server from this request. This value is not recommended, rather create ajax request manually through a js function. normal: default, submit the form wizard_step: display the action as a wizard step page: display a new page

Adding Actions and Hooking Them Up in the UI

503

Parameter

Default Value

Possible Values

Req?

Description popup: create a non-modal popup wizard window dialog: typically a wizard. Sets come form of data

Possible NonSupportedType Attributes Parameter value Default Value n/a Possible Values Any object types. It can be comma separated. Req? Yes Description This action will be disabled for the object type/s mentioned in the "Possible values". Actions will be disabled in Third Level Navigation, Row Level action. No filtering will be done for MenuBar and Table Tool Bar actions. Whether or not you want the type to apply to inherited soft types. If true then all sub types will be nonsupported as well. If false then only the types specified will be nonsupported.

applyToDescendants true

true/false

No

Note The NonSupported types can also be added via xconf properties See Defining NonSupported and Support Types in XConf on page 506 for more information.

504

Windchill Customization Guide

Possible SupportedType Attributes Parameter value Default Value n/a Possible Values Any object types. It can be comma separated. Req? Yes Description This action will be enabled only for the objecttype/s mentioned in the "Possible values". Actions will be enabled in Third Level Navigation, Row Level action. No filtering will be done for MenuBar and Table Tool Bar actions. Whether or not you want the type to apply to inherited soft types. If true then all sub types will be nonsupported as well. If false then only the types specified will be nonsupported.

applyToDescendants true

true/false

No

By specifying SupportedTypeAttribute or NonSupportedTypeAttribute, the Action Framework will either enable or disable the Actions depending upon the object types mentioned. This filtering will be applied only for Customized menu. Also this will be carried out before calling any other Filtering ( Validation service ) class defined by application developers. In short it is a Universal Filter. If an action is disabled by this Universal Filter, Custom Validators written will not get executed. If an action is enabled by this Universal Filter, Custom Validators will get invoked. Example:
<objecttype name="object" class="java.lang.Object" > <action name="reports" enabledwhensuspended="true"> <command url="netmarkets/jsp/carambola/customization/reports/base.jsp"/> <nonSupportedTypes value="wt.doc.WTDocument,wt.part.WTPart"/> </action>

Adding Actions and Hooking Them Up in the UI

505

</objecttype> Alternatively you can also do it as:<objecttype name="object" class="java.lang.Object" > <action name="reports" enabledwhensuspended="true"> <command url="netmarkets/jsp/carambola/customization/reports/base.jsp"/> <nonSupportedTypes> <type value="wt.doc.WTDocument" /> <type value=" wt.part.WTPart " /> </nonSupportedTypes> </action> </objecttype>

You can specify that the supported or non-supported types will not apply to sub types. By default, if you have a soft type of wt.part.WTPart it will inherit to the soft types. You may want to turn this functionality off by adding the additional attribute applyToDescendants. As an example:
<supportedTypes> <type value="wt.foo.Bar" applyToDescendants=false /> </supportedTypes>

Note The Supported types can also be added via xconf properties See Defining NonSupported and Support Types in XConf on page 506 for more information.
Defining NonSupported and Support Types in XConf The NonSupported and Supported types can also be added via xconf properties. There is a TypeBasedXconfActionFilter which looks through the typeBasedActionFilter.properties file. Specify the property in the following format:
<Property name=<action object>.<action name>. <supportedTypes or nonSupportedTypes> value=com.foo.Bar />

For example:
<Property name="annotation.annotationSets.nonSupportedTypes" value="wt.part.WTPart" target=codebase/typeBasedActionFilter.properties/>

Procedure - Localizing an Action To have the localized properties for your action you would use rbinfo files. For more information see the Resource Info (.rbInfo) Files on page 1403 section of Internationalization and Localization on page 1395.

506

Windchill Customization Guide

The format for the entries in the rbinfo files for actions is:
<objecttype name>.<action name>.<purpose>.value=<value>

Element objecttype name action name purpose

Possible Values all all title description tooltip icon morurlinfo hotkey

Description Corresponds to the name of the objecttype specified in the actions.xml file. Corresponds to the name of the action specified in the actions.xml file. title: localizable text for the title bar if the action is for a wizard description: the localizable text for the label of the action tooltip: the localizable text shown on mouse over of the action icon: image file, relative to codebase/ netmarkets/images moreurlinfo: parameters used to size the window for this action hotkey: the alphanumeric key to trigger this action. The actual value for the entry.

value For example:

all

<objecttype name="document" class="wt.doc.WTDocument" resourceBundle="com.ptc.windchill.enterprise.doc.documentResource"> <action name="create" uicomponent="CREATE_DOC" dtiUpload="true"> <command class="com.ptc.windchill.enterprise.doc.forms.CreateDocFormProcessor" method="execute" windowType="popup" onClick="validateCreateLocation(event)"/> <includeFilter name="projectM4D" /> </action> </objecttype>

The documentResource.rbinfo file contains an entry as follows:


document.create.title.value=New Document document.create.description.value=New Document document.create.tooltip.value=Add a new document with or without attached content document.create.icon.value=newdoc.gif document.create.moreurlinfo.value=height=1000,width=820

Adding Actions and Hooking Them Up in the UI

507

icon and tooltip shown here in the toolbar and also in the menus. Note that icons for actions in the menus will only be displayed for actions that also display in the toolbar:

title shown here:

icon and description shown here:

508

Windchill Customization Guide

You can also specify a resourceBundle property on the on the <objecttype> element. If an <action> element does not specify a resourceBundle property, the resourceBundle property specified on the <objecttype> element for that action will be used.

Procedure Defining a new action model


Action models are defined in an xml file that follows the structure based on the codebase/config/actions/actionsmodels.dtd. Here is a simple example of an action model definition used for the folder browser toolbar.
<!-- default toolbar for the Folder page --> <model name="folder_list_toolbar"> <action name="list_cut" <action name="list_copy" <action name="fbpaste" <action name="pasteAsCopy" <action name="list_paste_sharing" <action name="list_delete" <action name="CONTAINERMOVE" <action name="PAGERELOADINGMULTICHECKOUT" <action name="WFADDTOWORKSPACE" <action name="separator" <action name="create" <action name="create_share_folder" <action name="create" <action name="create_shared_doc" <action name="createMulti" <action name="createFromTemplateWizard" <action name="createPartWizard" <action name="createMultiPart" <action name="add_link" <action name="create" <action name="create" <action name="create" <action name="SBUpdatePrj" <action name="separator" </model> type="object"/> type="object"/> type="object"/> type="saveas"/> type="folder"/> type="object"/> type="pdmObject"/> type="folder"/> type="folder"/> type="separator"/> type="folder"/> type="folder"/> type="document"/> type="document"/> type="document"/> type="document"/> type="part"/> type="part"/> type="bookmark"/> type="problemReport"/> type="changeRequest"/> type="changeNotice"/> type="sandbox"/> type="separator"/>

The objecttype name is a way to create a name space as well as packaging for actions related to a specific object or functional area. In the above example, the name document creates a unique name space for actions that apply to wt.doc. WTDocument. It is also possible to create an action model which itself references another action model. The folder browser File menu contains a submodel for the New group of actions. The action model for the New group of actions is defined as (only a subset of the actions are included here):
<model name=folder_file_new resourceBundle=com.ptc.core.ui.tableRB> <action name=create type=document resourceBundle=com.ptc.core.ui.tableRB /> <!-- More actions here --!> </model>

Adding Actions and Hooking Them Up in the UI

509

Then, in the action model for the File menu, we include the submodel folder_file_new:
<model name=folder_file> <submodel name=folder_file_new/> <action name=createSubscriptionMultiObj type=subscription/> <!-- More actions here --!> </model>

See the figure below for how this appears in the UI:

Possible Model Attributes Details about these parameters can also be found in the codebase/config/actions/actionsmodels.dtd. Parameter name Default Value Possible values n/a all Req? Yes Description This is the name by which the action model will be referenced Specifies which action should be highlighted by default. This is only applicable if the model is used as a third level nav bar Specifies which action should be highlighted by default. This is

menufor

n/a

Any valid class name.

No

defaultActionName

First action in the model is used by default

Action name for one of the actions in the model.

510

Windchill Customization Guide

Parameter

Default Value Possible values

Req?

Description only applicable if the model is used as a third level navigation bar.

defaultActionType

First action in the model is used by default

Object type of one of the actions in the model. Class name for the resource bundle to use for the properties of the action models that are to be localized

resourceBundle

Possible Action Attributes Details about these parameters can also be found in the codebase/config/actions/actionsmodels.dtd. Parameter name Default Value Possible values n/a Name of any action defined in an actions. xml file n/a Name of any objecttype defined in an actions.xml file n/a true/false Req? Yes Description This is the name of an action defined in an actions.xml file This is the name of an objecttype defined in an actions.xml file. This will determine whether an action is displayed as a shortcut icon in the toolbar.

type

Yes

shortcut

No

Adding Actions and Hooking Them Up in the UI

511

Naming conventions for the name of an action model can be any combination of alpha-numeric characters. Most action models are names include the component that they are used in. Your action models should have a prefix specific to your company to prevent collisions with other action models delivered with the product.

Note The action service is designed to hide the icons in the actions menu (or menu bar menus) for any icon which is not contained in a toolbar somewhere else in the system. The StandardNmActionService builds/keeps a list of all known toolbar icons on server startup. The StandardNmActionService is relying on the name of the model to know whether its a toolbar. Therefore, the name of a model used as a toolbar should contain toolbar If the toolbar model naming convention is not followed the action service won't be able to show icons as designed. No functionality will break if the naming convention is not followed.
The action model name which follows naming convention of a toolbar will be displayed as an Action Menu as follows:

Commonly used shortcut actions (recommended maximum up to five) can be configured to appear on toolbar shortcut area by an attribute shortcut. The above screenshot has 5 actions configured as shortcut. Example configuration for folder browser table:
<model name="folder_list_toolbar"> .. <action name="CONTAINERMOVE" type="pdmObject" shortcut = "true"/> "true" <action name="PAGERELOADINGMULTICHECKOUT" type="folder" shortcut = "true"/> "true" <action name="WFADDTOWORKSPACE" type="folder" shortcut = "true"/> "true" . <action name="create" type="folder" shortcut = "true"/> "true" <action name="create" type="document" shortcut = "true"/> "true"

512

Windchill Customization Guide

</model>

An action will be a shortcut action only in the context of that specific model. Note that icons for actions in the menus will only be displayed for actions that also display in the toolbar. Possible SubModel Attributes Details about these parameters can also be found in the codebase/config/actions/ actionsmodels.dtd. Parameter Default Possible Req? Description Values Value name Yes n/a Name of any This is the name action model of an action defined in an model defined in actionmodels. an actionmodels. xml file xml file. An example of where an action model with submodels is used is for the File menu on the Folders table.

Procedure Adding validation logic for your action


When creating a new action, there may be logic that you want executed to determine if that action should be enabled, disabled, or hidden in the UI. You can write this logic in a class called a validator. See UI Validation on page 718 for details about the validation service, writing a validator, and registering the validator for your action.

Procedure Localizing an actionmodel


Some action models need display label (e.g. third level navigation action models or menu bar action models). You can specify the rbInfo to use on your action model:
<model name=relatedItems resourceBundle=com.ptc.core.ui.navigationRB>

The entries follow the same format as that of the actions, as noted in Procedure Localizing an Action on page 506.
object.relatedItems.description.value=<U class='mnemonic'>R</U>elated Objects

Adding Actions and Hooking Them Up in the UI

513

object.relatedItems.description.comment=Used for the text on the Related Objects third level navigation menu. The <U class=mnemonic> </U> tag should be put around the character that is the access key. object.relatedItems.hotkey.value=r object.relatedItems.hotkey.comment=Mnemonic for the Related Objects third level navigation menu. This should be a character that matches the character surrounded by the <U class=mnemonic> </U> tag in the value line above.

Procedure Reporting tools for actions and actionmodels.


We support modularized actions and actionmodels within the system, so to find what file an action is defined in, or what action models the action is used in, there is a reporting tool that can be used. On a running Windchill installation, you can use the Actions and ActionModels reports. See the Customization Tools Overview on page 417 section in the Customizing HTML Clients Using the Windchill JSP Framework on page 309 chapter for information on the Action Report and the Action Models Report. Action Report http://<your machine name>/<app-name>/ app/#ptc1/ carambola/tools/actionReport/action The Action report allows you to search for actions managed by the StandardNmActionService. You can search by several properties for the action including the label (aka Description), action name, objecttype. The search supports multiple search parameters, regular expressions and caseinsensitive matching. See Action Report on page 419 for more information.

514

Windchill Customization Guide

Action Model Report http://<your machine name>/<app-name>/app/#ptc1/ carambola/tools/actionReport/actionModel The Action model report allows you to search for action models managed by the StandardNmActionService. You can search by action model name, description and model file. The search supports multiple search parameters, regular expressions and case-insensitive matching. See Action Model Report on page 423 for more information. Debug Tool There is also a debug mode that can be enabled in the UI that can help track down information about a particular action on a page. See Debugging on page 442 for information on enabling and using this tool. Reload Action(s) Action(s) http://<your machine name>/<app-name>/app/#ptc1/carambola/tools/list This tool reloads the action models from their xml files without having to restart the method server. See Reload Action on page 428 for more information.

Customization Points
As mention earlier in Solution Elements on page 486 section, there are two files, custom-actions.xml and custom-actionmodels.xml, that are delivered with the product. If you want to add/modify an action/actionmodel you can put the changes in these files. It is important to note that if you have an <objecttype> element in the custom-actions.xml file, and that type exists within another actions.xml file, the actions from your file will be added to the full set of actions supported for that type. This custom-actions.xml is read in last of all the actions.xml files, so if action names are duplicated, the one in this file will be used. It is also important to note that if you have a <model> element in the custom-actionmodels.xml file, and a model by that name already exists, your model will completely wipe out the ones read in before yours. Be very careful in the naming of your models so that you don't wipe out others from files read in prior unless that is the intent.

Adding Actions and Hooking Them Up in the UI

515

Sample Code
Action Model - configurtion for a soft type
This is an example of an action model configuration for a soft type.
<!-- Copied from ChangeManagement-actionModels.xml --> <!-- Originally copied from menu for wt.change2.WTChangeRequest2 --> <model name="sample change request actions" menufor="WCTYPE| wt.change2.WTChangeRequest2|org.default.www.SampleChangeRequest"> <action name="view" type="object"/> <action name="SETLIFECYCLESTATE" type="pdmObject"/> <action name="createSubscription" type="subscription"/> <action name="separator" type="separator"/> <action name="reviseChangeItems" type="change"/> <action name="editCapabilityPackage" type="capabilityPackage"/> <action name="create" type="approach" /> <action name="create" type="capabilityImplementationProject" /> <action name="separator" type="separator"/> <action name="sandboxAddToProject" type="object"/> <action name="SBAddToPrj" type="sandbox"/> <action name="removeShare" type="object"/> <action name="separator" type="separator"/> <action name="ManageSecurity" type="accessPermission"/> <action name="renameObjectWizard" type="object"/> <action name="delete" type="object"/> <action name="separator" type="separator"/> <action name="separator" type="separator"/> <action name="discuss" type="forum"/> <action name="copy" type="object"/> </model>

Where org.default.www.SampleChangeRequest is the Name of the soft type entered in Type and Attribute Management.

516

Windchill Customization Guide

Related Documentation
Windchill Client Architecture Wizard on page 776 Constructing and Rendering a Table Using the JSP Framework on page 579 Windchill Client Architecture Tree on page 614 Information Pages on page 891 Customization Tools Overview on page 417

Adding Actions and Hooking Them Up in the UI

517

Tab Models
Objective
You want to change something in the navigator section of the page. For example, you want to add or remove tabs in the navigator.

Background
The tabs rendered in navigator are nothing but actions in action lists just like any other actions in the system. Adding tabs and tabs under them is very much like adding any other action into the system, but there are some additional special considerations. Scope/Applicability/Assumptions Assume you need to add a new tab to the main navigation of the navigator. Assume you need to remove an existing tab from the main navigation of the navigator. Assume you need to add/remove links in the second level navigation.

Solution
Create new actions, an action model, and JSPs for the tab and sub tabs to be added. Prerequisite knowledge To achieve this objective, you need to have an understanding of the following: Basic development involving CSS, JSP and XML. The actions framework in the Windchill client architecture. For more information see, Windchill Client Architecture Action Framework Overview on page 486

The management of RBINFO file customizations. For more information see, Procedure - Localizing an Action on page 506. Solution Elements Element Type codebase\config\actions\naviga- XML tion-actions.xml

codebase\config\actions\custom- XML

Description This file contains the action definitions for the actions that represent the tabs and sub tabs in the Windchill system This file is used for adding
Windchill Customization Guide

518

Element actions.xml

Type

codebase\config\actions\naviga- XML tion-actionModels.xml

codebase\config\actions\custom- XML actionModels.xml codebase\action.properties or an rbinfo rbinfo file <mytab>/<list>.jsp JSP

Description custom actions and customizing existing actions. This file contains the action model definitions used in the navigation. Including the main tab list, the sub tab list, the recent lists, and the header actions lists. This file is used for adding custom action models and updating existing action models. Preference files This is the JSP file you will create as the default content for the tab you are adding. You can create as many additional JSPs to associate with sub tabs as you need.

Procedure - Adding Tabs in the Navigator at Different Levels The tabs in the red circle are the navigator tabs, the tabs in the blue circle are the first level navigation tabs, and the items in the green circle are the second level navigation. The following sections will detail how to add tabs at different levels.

Adding Actions and Hooking Them Up in the UI

519

Adding navigator tab The following sections detail how to add custom navigator tab. Adding navigator tab - Create an action in custom-actions. custom-actions.xml xml Create an action for your new tab in custom-actions.xml. You can create any type of action for a first level tab. In this example we will create an action that maps to the JSP. See Windchill Client Architecture Action Framework Overview on page 486 for further details.
<objecttype name=" myType " class="com.ptc.myTabClass"> <action name=" myNavigatorTabAction1" > <command windowType="page"/> </action> <action name=" myNavigatorTabAction2" > <command windowType="page"/> </action> </objecttype>

Create an entry in resource file Create localization strings for your action in your own resource file. See the Windchill Client Architecture Action Framework Overview on page 486 for more detailed information.

520

Windchill Customization Guide

Create and define action model Create an action model using newly defined actions as below in custom-actionModels.xml. Define rbinfo entries for this action model.
<model name=myNavigatorTab navigation> <action name=myNavigatorTabAction1 type=myType /> <action name=myNavigatorTabAction2 type=myType /> </model>

Add action model to navigator action model Copy definition of navigator tab action model (model name= navigator) from navigation-actionModels.xml <model name=navigator> to custom-actionModels.xml. Add the new action model entry to it.
<submodel name=search navigation /> <submodel name=main navigation /> <submodel submodel name= myNavigatorTab navigation / > </model>

Adding first level tab in navigator This section details how to add custom first level tab in navigator. Create an action in custom-actions. custom-actions.xml xml Create an action for your new tab in custom-actions.xml. If your action requires stickiness you should use the navigation servlet for your action.
<objecttype name="navigation" class=""> <action name="mytab" renderType="GENERAL"> <command class="netmarkets" method="servlet/Navigation?tab=mytab" windowType="page"/> </action> </objecttype>

Add your action to the main navigation action model in customactionModels.xml actionModels.xml Copy the main navigation action model from navigationactionModels.xml to custom-actionModels.xml. Add above created action mytab to the action model.
<!-- Main navigation --> <model name="main navigation"> <action name="home" type="navigation"/> <action name="product" type="navigation"/> <action name="project" type="navigation"/> <action name="change" type="navigation"/> <action name="library" type="navigation"/> <action name= mytab type= navigation /> <action name="org" type="navigation"/>

Adding Actions and Hooking Them Up in the UI

521

<action name="site" type="navigation"/> </model>

Create an entry in a rbinfo file Create localization strings for your action in action.properties or your own rbInfo file. See Windchill Client Architecture Action Framework Overview on page 486 for more detailed information. Adding second level navigation links in navigator This section details how to add custom second level navigation link in navigator. Create a new sub model for your tab in custom-actionModels. custom-actionModels.xml xml Your new first level tab will need a sub model to define second level navigation. In order for the navigation to find the sub model it must be named after the main tab that it belongs to. For sub models the parameters defaultActionType and defaultActionName are required. These parameters tell the system which action is the default when the user has never visited this tab before. In our example we will need to create a new action model called mytab navigation like this:
<model name="mytab navigation" defaultActionType="mytab" defaultActionName="list"> </model>

You can now add second level navigation links to your new action model following the instructions in Adding second level navigation links in navigator on page 522. You must create at least one second level navigation link whose name and type match the defaults specified in the action model tag.

Customization Points
See Windchill Client Architecture Action Framework Overview on page 486 for more information. Procedure - Removing a Main Tab Copy the main navigation action model from navigationactionModels.xml to custom-actionModels.xml. Remove the required action model.
<!-- Main navigation --> <model name="main navigation"> <action name="home" type="navigation"/> <action name="product" type="navigation"/> <action name="project" type="navigation"/> <action name="change" type="navigation"/>

522

Windchill Customization Guide

<action <action <action <action </model>

name="library" type="navigation"/> name=mytab type=navigation/> name="org" type="navigation"/> name="site" type="navigation"/>

After removing the change tab from the main navigation action model above. The list will look like this:
<!-- Main navigation --> <model name="main navigation"> <action name="home" type="navigation"/> <action name="product" type="navigation"/> <action name="project" type="navigation"/> <action name="library" type="navigation"/> <action name=mytab type=navigation/> <action name="org" type="navigation"/> <action name="site" type="navigation"/> </model>

Procedure Removing a Second Level Navigation Link Copy the action model definition which needs to be updated to customactionModels.xml from navigation-actionModels.xml. Update the action model definition by removing the action definition from it. Original definition of product navigation action model :
<model name="product navigation"> <action name="list" <action name="separator" <action name="view" <action name="listFiles" <action name="listTeam" <action name="listProduct" <action name="changeMonitor" <action name="view_forum" <action name="MyWorkspace" <action name="listTemplates" <action name="listUtilities" </model> type="product"/> type="separator"/> type="object"/> type="product"/> type="product"/> type="work"/> type="product"/> type="project"/> type="product"/> type="product"/> type="product"/>

After removing the Change Monitor action from the product action list above, the list will look like this:
<model name="product navigation"> <action name="list" <action name="separator" <action name="view" <action name="listFiles" <action name="listTeam" <action name="listProduct" <action name="view_forum" <action name="MyWorkspace" <action name="listTemplates" <action name="listUtilities" type="product"/> type="separator"/> type="object"/> type="product"/> type="product"/> type="work"/> type="project"/> type="product"/> type="product"/> type="product"/>

Adding Actions and Hooking Them Up in the UI

523

</model>

Procedure Customize a Navigator If required, there is a way to override default navigation behavior in the navigator. This can be achieved by implementing com.ptc.windchill.enterprise. navigation.NavigationListDelegate and providing a custom behavior. For example, there is a requirement that a particular first level navigation tab should show all the nodes instead of showing only recently accessed nodes. The following section will illustrate an example of showing all the context nodes instead of default behavior of showing only recently accessed ones. Create a Custom Navigation List Delegate In general it is not recommended to implement the interface NavigationListDelegate directly. You should subclass one of the existing out of the box implementations like com.ptc.windchill.enterprise. navigation.delegates.DefaultNavigationListDelegate. Example:
public class MyTabNavigationListDelegate extends DefaultNavigationListDelegate { /** * Returns list of all the c. */ @Override public Vector<ObjectVisitedInfo> getRecentStack(String node, Vector<ObjectVisitedInfo> recent) throws WTException { // Specific code for getting all the contexts for that particular tab return recent; } }

There are also other methods that you may wish to override but getRecentStack() is the only one required for this particular use case. Register MyTabNavigationListDelegate To register this custom delegate, the property should be added to a specific customized service.properties.xconf file or site.xconf. In the above example you would register it something like the following:
<Service name="com.ptc.jca.navigation.NavigationListDelegate"> <Option serviceClass="com.ptc.myTab.navigation.MyTabNavigationListDelegate" requestor="java.lang.Object" selector="MyTab"/> </Service>

After registering you will need to run xconfmanager p from a windchill shell and restart the method server.

524

Windchill Customization Guide

Adding Multiple Levels in the Navigation Tree Out of the box, browse tab in navigator has a tree with two levels. More levels can be added by adding a sub-model to existing action model. Example: Original tree

To add a new navigation hierarchy: 1. Create a model in custom-actionModels.xml.


<model name="productNav1"> <action name="info" type="product"/> <action name="listFiles" type="product"/> </model>

2. Copy the existing action model in navigation-actionModels.xml to custom-actionModels.xml. Add above model as a submodel to this action model definition.
<model name="product navigation" defaultActionName="list" defaultActionType="product"> <description> Sub tabs under the product main tab </description> <action name="info" type="product"/> <action name="aspsStructure" type="asps" /> <action name="listPubStructures" type="arbortext"/> <action name="listFiles" type="product"/> <action name="structureSubTab" type="product"/> <action name="MyWorkspace" type="workspaces"/> <action name="listNetwork" type="network"/> <action name="list" type="wp"/> <action name="listTeam" type="product"/>

Adding Actions and Hooking Them Up in the UI

525

<action name="listProductAssignments" type="work"/> <action name="changeMonitor" type="change"/> <action name="view_forum" type="project"/> <action name="listTemplates" type="product"/> <action name="reports" type="product"/> <action name="listAgreements" type="agreements"/> <action name="listUtilities" type="product"/> <submodel name="productNav1" /> </model>

The new Navigation tree will look like:

The sub-model can be nested into other submodel to add multiple levels of navigation Example: The above model can have more submodels as
<model name="productNav1"> <action name="info" type="product"/> <action name="listFiles" type="product"/> <submodel name="productNav2" /> </model>

Where
<model name="productNav2"> <action name="someAction" type="object"/> <action name="someMoreAction" type="object"/>

526

Windchill Customization Guide

. </model>

Limitations
In order to get your tab to display and highlight correctly you must follow the following conventions You must place your JSPs in a directory that exactly matches the name you gave to your main tab in Adding navigator tab on page 520. In that example the main tab name is mytab. You must create a JSP whose name exactly matches the defaultActionName and whose directory exactly matches the defaultActionType you specified on the action model in Adding second level navigation links in navigator on page 522. In this example the JSP would be mytab\list. jsp. You must name your JSP exactly the same as your action. In this example both are named list.

Additional Resources
Windchill Client Architecture Action Framework Overview on page 486

Adding Actions and Hooking Them Up in the UI

527

Customizing Role-based Role-based Visibility


Objective
You want to customize the set of UI components (actions or other UI elements) that the administrators of the site, organization or containers can manage using the role-based visibility feature.

Background
The role-based UI functionality enables administrators to optimize the number of actions presented to users, so as not to confuse users by seeing actions they don't need or use for their role. Initially this support was just for container managers (in particular, project managers). It has been extended to a concept called profiles which sets action visibility at the site or organization level. A site administrator, organization administrator or container administrator can specify which users have visibility to the actions defined. For site and organization administrators this can be done through profiles. Profiles can be created at Site>Profiles or Org->Profiles. The actions defined will be presented with their default settings, and the administrator can choose to hide those actions. The administrator can then specify which participants (users, groups, orgs) belong to the profile. All members of the profile will have that visibility. If a member is in multiple profiles, the greatest visibility is provided. At the container level, the administrator can specify the visibility based on user roles. Anyone in those roles will have the visibility specified. Container-level role visibility will override any profile in which the member might be a participant. See theWindchill Business Administrator's Guide for more details about profileand role-based visibility administration.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


The role-based visibility administration capability is turned on, that is, the preference com.ptc.netmarkets.roleAccess.enabled is set to true. The customization can be performed while the capability is turned off, but the results will not appear in the UI until the capability is turned on. The customizer can manage both out-of-the-box UI components and customized UI components with this capability.

528

Windchill Customization Guide

Intended Outcome When configuring visibility by roles and configuring profiles, the administrator is presented with a list of UI components that can be managed. The administrator is unable to manage the visibility for any UI components that are not included in this list. As a customizer, you have the ability to customize the list of UI components available to administrators. You can: add UI components to the list, remove UI components from the list, specify default visibility settings for UI components, change the order that UI components appear in the list, and change the labels for the UI components on the list.

At the site or organization level your intention is to manage the list presented when creating profiles:

Adding Actions and Hooking Them Up in the UI

529

At the container level, you are managing the equivalent list presented when configuring visibility by roles:

Solution
Modify the roleaccessprefs.xml file (and associated files as needed).

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: The behavior of user roles in Windchill The administration of ad hoc access control policies in Windchill The actions framework in the Windchill client architecture The navigation framework in the Windchill client architecture The management of XML file customizations The management of RBINFO file customizations

530

Windchill Customization Guide

Solution Elements Element *actions.xml

Description Files where actions and other UI components are defined. Actions are optionally given a uicomponent value.Actions. xml is located in <Windchill>/codebase; other *actions.xml files are generally in <Windchill>/codebase/config/actions. XML Roleaccessprefs.xml File for assigning default visibility to UI components. Setting items in this file can make them not appear at all for the site or containers. Whether or not the container manager can override the default value can also be changed here.Located in <Windchill>/codebase. RoleAccessResource.rbInfo RBINFO Defines the labels to provide in the Uis for the actions or UI components.Located in <Windchill>/wtCustom/com/ ptc/netmar kets/roleAccess/.

Type XML

In actions.xml (and all *actions.xml files), an action can be assigned a uicomponent attribute value. The uicomponent attribute provides a name for a UI component that can be referenced from the roleaccessprefs.xml and roleAccessResource.rbInfo files. Multiple actions can use the same uicomponent value; this provides the ability to manage those actions as a single UI component. If an action does not have a uicomponent, then the action name can be used to reference it as a UI component instead. However, in this case it cannot be grouped with other actions into a single UI component. The roleaccessprefs.xml file consists of a <uics> element containing several elements (or sections) that correspond to the primary tabs in the Windchill user interface. For example, the <project> section corresponds to the Project tab. Each section contains zero or more <uic> elements, each representing a UI component whose visibility within that tab can be administered. Each UI component, specified with the name attribute of the <uic> element, can appear in one or more sections. This allows the default visibility settings for that UI component to be assigned independently for different tabs. The roleaccessprefs.xml file applies to the UI component lists for visibility administration based both on profiles (at the site and organization levels) and on roles (at the container levels). However, the <global> section applies only to visibility administration using profiles. If a UI component is not tied to a specific

Adding Actions and Hooking Them Up in the UI

531

tab (such as is the case with the Search link in the Windchill UI header) or the UI component is a first-level tab itself, it should be listed in the <global> section of roleaccessprefs.xml. Each UI component must have an entry in roleAccessResource.rbInfo that provides a user-friendly label for that UI component. These labels are used for the UI components in the lists that are presented to the administrator when configuring visibility. In this file the resource entry constant identifies the UI component; it must match either the uicomponent from the action definition or the action name if the action has no uicomponent. The resource entry value provides the userfriendly label.

Note Your UI component label should be a verb phrase. If your action/UI component name is not already a verb phrase, place 'View' in front, for example "View Team Page."
Procedure - Making an Action Available to Visibility Administration In this example, you provide the administrator with the ability to manage the visibility of the Create Folder action in the Project, Program, Product, and Library tabs.

Note This example assumes that the Create Folder action is not already available for role-based visibility management; in the actual product, it is available out of the box.
1. Add a new <uic> to the roleaccessprefs.xml under the sections <project>, <program>, <product>, and <library>:
<uic name="PROJECT_CREATE_FOLDERS" order="00" enabled="true" defaultAll="true" defaultManager="true" defaultGuest="false" managerEnabled="true" guestEnabled="false"/>

See the section onThe uic Element on page 533 for attribute descriptions.

Note For actions that are valid for multiple tab types, put the entry under all the section you want it to affect.
2. In roleAccessResource.rbInfo, add a new resource entry for the action display name:
31.value=Create Folders 31.constant=PROJECT_CREATE_FOLDERS

Regenerate your bundles. The name of the uic should be the same as the constant for the entry in the resource bundle.

532

Windchill Customization Guide

3. In <Windchill>/codebase/actions.xml, modify the create folder action by: adding the attribute uicomponent="PROJECT_CREATE_FOLDERS"
<action name=" folder_create" checkaccess="true" uicomponent="PROJECT_CREATE_FOLDERS">

Caution Follow best practices in backing up your XML files when customizing them.
4. Restart the servlet engine and the method server. Steps 1 through 3 above can be performed in any order. Note that "PROJECT_CREATE_FOLDERS" is used for the uic name, the resource entry constant (but without the quotes), and the action uicomponent. It is necessary for all three of these items to share the same value in order to tie the customized behavior together. Upon completion of this procedure, an administrator can now configure the visibility to the Create Folder action under the Project, Program, Product, and Library tabs, based on profiles defined at the site or organization level, and based on roles at the container level.

Customization Points
The uic Element
Each UIC in roleaccessprefs.xml represents a UIComponent or action to be controlled. Parameter Default Possible values Req? Description Value name Y n/a string The name of the UI component. This must match the value of the uicomponent (or name) attribute on an action element in actions.xml. This must also match the value of a resource entry constant in the resource bundle. N Order ? Non-negative? The position of this UI component in the Integer wizard. UI components with

Adding Actions and Hooking Them Up in the UI

533

Parameter

Default Value

Possible values

Req? Description lower numbers are placed before those with higher numbers. Whether or not this uicomponent will be shown in the wizard and utilized by the system. The default visibility value for All Members. The default visibility value for Project Managers. The permissions are a union of all permissions across all roles; if you set defaultManager to false; you should also defaultAll to false, otherwise managers will still have access through the ALL_MEMBERS role. The default visibility value for people in the Guest role. Guests are not technically members of the Project; they are not unioned with the ALL_MEMBERS role. Whether or not this uicomponent can

Enabled

true

true | false

DefaultAll

true

true | false

DefaultManager

true

true | false

DefaultGuest

true

true | false

ManagerEnabled true

true | false

534

Windchill Customization Guide

Parameter

Default Value

Possible values

Req? Description affect the manager role. Do not change this value in out-ofthe-box UICs. For customized UICs, you may choose your own setting. Whether or not this uicomponent can affect the guest role. Do not change this value in out-of-thebox UICs. For customized UICs, you may choose your own setting. The class on which runMethod exists The method to run when the UIAccess is changed. This represents the name of a method that will be run when a UIAccess element associated with this UIComponent is updated. The signature of this method must be: void foo (WTPrincipal principal, WTContainer container, boolean isRender)

GuestEnabled

true

true | false

RunClass runMethod

Java class name Java method name

N N

Adding Actions and Hooking Them Up in the UI

535

Parameter

Default Value

Possible values

Req? Description The principal passed in will be the group or user on which to operate. The boolean isRender is the updated value for the UIAccess.

Making a Customized Tab Available to Visibility Administration


Making a customized action available to visibility administration is essentially the same procedure as making an out of the box action available. A tab, however, cannot be managed by container administrators (configuring role-based visibility). Therefore you can only make a customized tab available to site and organization administrators for configuring visibility profiles. This means you can add a <uic> element for the tab only to the <global> section of roleaccessprefs.xml. For example, assume that you have already created a customized tab, and have an associated <MyTab>actions.xml file. You can add the tab to the list for profilebased visibility administration as follows: 1. Add a new uic element to roleaccessprefs.xml under the <global global> section with a unique name, for example, CUSTOMIZED_TAB.
<uic name="CUSTOMIZED_TAB" order="190" enabled="true" defaultAll="true"/>

2. Associate the appropriate actions in actions.xml with the UIComponent.


< oolean pe name="customization" > <action name="list2" uicomponent="CUSTOMIZED_TAB"> uicomponent="CUSTOMIZED_TAB" <command windowType="page"/> </action>

3. Add a new entry to roleAccessResource.rbInfo with a constant that is the same as the uic name. The value is what will be displayed in the profile actions UI.
40.value=View View Customized Tab 40.constant=CUSTOMIZED_TAB constant=CUSTOMIZED_TAB

4. Restart the servlet engine and the MethodServer. Assigning One uicomponent to Multiple Actions If you want to tie one UI component to multiple actions, you need to specify the uicomponent attribute for each of those actions, using the same value. For example, the procedure described in theProcedure - Making an Action Available to
Windchill Customization Guide

536

Visibility Administration on page 532 creates a UI component called PROJECT_CREATE_FOLDERS associated with the folder_create action. You can assign the list_create_folder action to the same UI component by specifying the uicomponent attribute for that action in actions.xml as follows:
<action name="list_create_folder" uicomponent="PROJECT_CREATE_FOLDERS PROJECT_CREATE_FOLDERS" ajax="row">

As a result, the "Create Folders" entry in the Configure Roles and Create Profile pages will affect the visibility for both folder_create and list_create_folder actions.

Changing the Labels for a UI Component


You can alter the label used for a UI component in the Configure Roles or Create Profile pages, without making any other changes to that UI component. Simply change the associated resource entry value in the roleAccessResource.rbInfo file, and regenerate your bundles. For example:
31.value=Create Create Folders - My New Label 31.constant=PROJECT_CREATE_FOLDERS PROJECT_CREATE_FOLDERS

Updating Access Control (Advanced Role-Based UI) It is possible to extend user permissions using Role-Based UI. This can be used for updating real access control (in the form of ad hoc or policy access control lists), or for doing potentially anything else. This is accomplished by specifying a class/method combination on the uic in the configuration file. The method will be called when the UIComponent it is associated with is updated. For example, part of the Role-Based UI feature includes the ability to extend Modify Team permissions. The uic element in the configuration file includes two additional attributes that identify the class and method to call:
<uic name="PROJECT_MODIFY_TEAM" order="30" enabled="true" defaultAll="false" defaultManager="true" defaultGuest="false" managerEnabled="false" guestEnabled="false" runClass="com.ptc. runClass="com.ptc.netmarkets. netmarkets.roleAccess. roleAccess.StandardNmRoleAccessService" StandardNmRoleAccessService" runMethod="modifyTeamPermissions"/> runMethod="modifyTeamPermissions"/>

The only restriction on runClass is that it needs to be accessible from the MethodServer. Given runMethod="myRunMethod", then myRunMethod must have the following signature:
public static void myRunMethod(WTPrincipal principal, WTContainer container, boolean isRender) throws WTException

Adding Actions and Hooking Them Up in the UI

537

The principal passed in will be the group or user on which to operate. The boolean isRender is what the field in the UIAccess table was just set to for the passed in principal.

Sample Code
Examples of Usage in out-ofout-of-thethe-box box Code
An example of multiple actions using the same uicomponent is the Team pages in Product/Project/Library share the same code, but each action is defined separately for each object. Each action has the same uicomponent of "PROJECT_TEAM". This allows the same resource (rbInfo) entry to be used, and helps to minimize the size of the action display table in the Create Profile page. PROJECT_TEAM still needs to be defined in roleaccessprefs.xml for each tab type in which it is used, and different defaults can be set for each.

Additional Resources
Related Customization Documentation
Managing Customizations on page 112.

Other Related Windchill Documentation


Windchill Business Administrator's Guide Role-Based Visibility Administration Windchill Business Administrator's Guide Access Control (ad hoc policies)

538

Windchill Customization Guide

User Interface Stickiness


When the page is refreshed, the current state of the page is not kept intact. HTTP cookies could be used to maintain some state, but they are limited in size, and are transmitted back to the server with each request. Some client state information should also be restored when the user logs in on different machines. Background As a user navigates within Windchill, they may make changes that affect the user interface display, such as selecting a tab on the information page (for example, selecting My Tab). If the browser is refreshed, the user may expect to remain on their last active tab. To retain this information, some sort of persistence mechanism is required to refresh the page to the correct state . There are two persistence mechanisms available for use. The Client State Provider will store information in the browser and will be specific to that particular browser on that particular machine. The Server State Provider will store information in the database and will make the information available for that user on any browser and any machine.

Resetting Stickiness
If user interface stickiness is causing issues or acting strangely, you may need to reset the stickiness. Server state stickiness and client state stickiness are reset differently, and you dont necessarily need to reset both, depending on what is acting strangely. To reset the server state stickiness, navigate to http://<host>/<webapp>/app/ netmarkets/jsp/user/utilitiesList.jsp and click Reset Server Stickiness. This action will popup a confirmation box and by clicking OK all your server state stickiness will be reset to the default state. This includes both Information Page tab order and Information Page table order. Various actions may clear the client state provider stickiness information depending upon your browser. To ensure that all client stickiness is removed, delete all your temporary internet files (usually in the Tools menu), close all browser windows, and restart the browser.

Adding Actions and Hooking Them Up in the UI

539

Defining Menus
You want to have a set of actions be displayed in one of the following areas: Actions column in a table Toolbar actions for a table Menu bar actions for a table Actions menu on an information page

Background There are several documents that describe certain aspects of the Action Model framework. This documentation is intended to provide concrete examples for a few of the main uses of action models within the Windchill application. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This documentation is intended to be used as a starting point for developers wanting to configure an actions menu to be rendered in the UI using the JCA framework. This information has references to other sources of information which will cover specific topics in greater detail.

Intended Outcome
The following sections provide a screenshot for the main areas where action models are used.

540

Windchill Customization Guide

Actions Column in a Table


By default the actions column is not displayed, and users cannot see it through configuration. Users can get to those actions by right-clicking anywhere within the row.

Toolbar Actions for a Table

Adding Actions and Hooking Them Up in the UI

541

Menu Bar Actions for a Table

Actions Menu on an Information Page

542

Windchill Customization Guide

Displaying Actions
You want to have a set of actions be displayed in one of the following areas: Actions column in a table Toolbar actions for a table Menu bar actions for a table Actions menu on an information page

Displaying Actions Column in a Table


Note You can no longer add the actions column to tables. The actions column is in the data store, but not available in the UI. The actions menu is only available by rightclicking each row
1. Define the actions in an actions.xml file (see Procedure Defining a new action model on page 509) 2. Add the actions to an action model (see sProcedure Defining a new action model on page 509). There are multiple levels where the action model can be set for a particular table. They are listed below in ascending order of complexity: a. Define a menufor a business object type. In the action model definition (in the XML file), set the attribute menufor for the object type that you are defining the actions for.
<model name="part actions" menufor="wt.part.WTPart"> menufor="wt.part.WTPar <action name="view" type="object"/> ..... </model>

Adding Actions and Hooking Them Up in the UI

543

To get a menu to fly out from the main menu, add a submenu to the action model.

<model name="part actions" menufor="wt.part.WTPart"> menufor="wt.part.WTPart" <action name="action_1" type="object"/> <submodel name="submenu_new"/> </model> <model name="submenu_new"> <action name="newViewVersion" type="part"/> </model>

b. Set action model in a Builder. There can only be one action model per type with the menufor attribute. If you would like to override the default action model for your table you can specify a different model in your table builder. See MVC Components on page 251 for information on creating a table builder class.
public ComponentConfig buildComponentConfig (ComponentParams params) { ComponentConfigFactory factory = getComponentConfigFactory (); JcaTableConfig table = (JcaTableConfig) factory.newTableConfig (); ColumnConfig actionsMenu = setComponentConfigFactory(). newColumnConfig(DescriptorConstants.ColumnIdentifiers.NM_ACTIONS, true); (JcaColumnConfig)actionsMenu).setDescriptorProperty (DescriptorConstants.ActionProperties.ACTION_MODEL, "model_name_here model_name_here");

544

Windchill Customization Guide

table.addComponent(actionsMenu); .... return table; }

c. Create a custom Data Utility. If you cant rely on a menufor action model for your table because you need to calculate which action model to use dynamically, then youll need to create a data utility for the actions column. You will need to extend NmActionDataUtility and override the getDataValue() method. Set the property DescriptorConstants.ActionProperties.ACTION_MODEL on the component descriptor to the name of the action model you want to use:
public class CustomNmActionDataUtility extends NmActionDataUtility { @Override public Object getDataValue(String component_id, Object datum, ModelContext mc) throws WTException { String modelName = "foo"; if(...) { modelName = "bar"; } else { modelName = "baz"; } mc.getDescriptor mc.getDescriptor(). ().setProperty setProperty( ( DescriptorConstants. ActionProperties.ACTION_MODEL, ActionProperties.ACTION_MODEL, modelName); return super.getDataValue super.getDataValue(component_id, (component_id, datum, mc); } }

You can specify different action models for different types of datums (row objects) or use other logic based on information in the model context to determine the action model to use.

Note If you dont want to display any actions in the actions column you can set the action model to EMPTY_ACTION_MODEL. When you do that, the text No Actions to Display will appear in the actions column.
After creating your data utility, add a column to the table in the builder. Use a custom column id (i.e customNmActions) instead of DescriptorConstants.ColumnIdentifiers.NM_ACTIONS:
public ComponentConfig buildComponentConfig (ComponentParams params) { ComponentConfigFactory factory = getComponentConfigFactory (); JcaTableConfig table = (JcaTableConfig) factory.newTableConfig (); ColumnConfig actionsMenu = setComponentConfigFactory(). setComponentConfigFactory(). newColumnConfig( newColumnConfig( customNmActions , true); ....

Adding Actions and Hooking Them Up in the UI

545

table.addComponent(actionsMenu); .... return table; }

Finally, youll need to register your data utility for the custom column id in an *.xconf entry, e.g:
<!-- Sample XCONF Entry --> <Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.ptc.windchill.dataUtilities. com.ptc.windchill.dataUtilities. CustomNmActionDataUtility" CustomNmActionDataUtility requestor="java.lang.Object" selector="customNmActions customNmActions" cardinality="singleton"/></Service>

Trouble Shooting Problem Solution Description Action Column does By default, the actions column is not displayed. Users are not appear in Table not allowed to see it. Right-clicking a row is the only way to see the row actions. Icons for some acTo follow UI standards, the action service is designed to tions are missing only show the icons in the actions menu if those icons also appear in some toolbar anywhere in the system. If you need to workaround this for some action that doesnt belong in any toolbar, you could create a dummy model with your action such as:
<model name=toolbarModelNotUsedAnywhere> <action name=myAction type=myActionType/> </model>

Then the action service will show the icon defined for that action in the actions menu. User right clicks and gets the following error message: No AcActions to Display

Ensure menufor attribute is defined on the action model (in the XML file) for your type: menufor=your.type.Here (Or you can define which model should be used in the builder when you add the column to the table config)

Add the NmActions column identifier to the table config in the MVC builder:
public ComponentConfig buildComponentConfig (ComponentParams params) { ComponentConfigFactory factory = getComponentConfigFactory (); JcaTableConfig table = (JcaTableConfig) factory.newTableConfig (); table.addComponent (factory.newColumnConfig

546

Windchill Customization Guide

Problem Description

Solution
(DescriptorConstants.ColumnIdentifiers.NM_ACTIONS , true)); .... return table; }

Using fiddler/firebug, check what the oid parameter is on the servlet/ActionsMenu request that is made when you right click. If its not the oid you expected, or if there is no oid at all, the infrastructure was not able to make the correct NmOid from the backing objects used for the table. See the NmObjectUtility documentation for more details of how to control what oid will be used for actions in the table. If you are defining the action model to be used for the table/column (as described in Actions Column in a Table on page 541). Using fiddler/firebug check what the actions parameter is on the servlet/ActionsMenu request made when you click to get the menu. Is the actions param the model name you defined? If actions=EMPTY_ACTION_MODEL it means the action column is not defined in the current table view. The actions column is required for the right click menu to work. Try using the View->Customize option to add the actions column to the current table view. Change the table builder to make the actions column one of the default columns.

not have access to this object or it does not exist

Check the validators defined on the actions in the model. Did all the actions get validated as hidden? If that was the case, then adding jcaDebug=true as a URL param should show the list of actions that were hidden as disabled actions in the menu. User right clicks and This message is ok if the user really does not have access gets the following er- to the row object. ror message: You do If the user should have access (for example they are able to get to the information page and see the actions menu there) Then using fiddler/firebug, check what the oid parameter is on the servlet/ActionsMenu request that is made when you right click. If its not the oid you expected, or if there is no oid at all, the infrastructure was not able to

Adding Actions and Hooking Them Up in the UI

547

Problem Description

Solution make the correct NmOid from the backing objects used for the table. See the NmObjectUtility documentation for more details of how to control what oid will be used for actions in the table. There may be a validator configured on it which may hide the action in certain conditions. See Windchill Client Architecture Action Framework Overview on page 486 for information on configuring an action with a validator. Add jcaDebug=true to the url to see even the hidden actions. With the jcaDebug option enabled, youll see more information in the menu, and there will be an action at the end of the list that takes you to the action model report for that menu.

Some actions dont appear in the list in the UI

Wrong set of actions is showing.

Add jcaDebug=true and check what vaildators are on the actions in the menu. Check that the validators are working as youd expect. 1. If you expect the action model to be found by type (described in Actions Column in a Table on page 541) , is menuFor defined on the action model for the object type? To see what the action service is finding for the type of object in the row, turn on log4j logger : com.ptc. netmarkets.util.misc. StandardNmActionService 2. If the model to use is defined on the table/column (described in Actions Column in a Table on page 541): To see what action model the default data utility is returning turn on log4j logger: com.ptc.core.components.factory.dataUtilities.NmActionDataUtility The jcaDebug param will also produce a link to the action model report at the bottom of the menu. The action model report will have the model name, the set of actions in that model, where the model is defined, whether the model overrides any other models, etc.

548

Windchill Customization Guide

Problem Description

Solution Make sure the model is defined as youd expect. If you made a custom data utility for the column, make sure the correct column is getting used. Set jcaDebug=true on the URL and inspect the column header DOM element to make sure the column id is as youd expect. Each column will have header text that starts with the column id, for example the default actions column would have header text like: nmActions validated by: .

Displaying Toolbar Actions for a Table


1. Define the actions in an actions.xml file. See Procedure Defining a new action on page 488 for more information. 2. Add the actions to an action model . See Procedure Defining a new action on page 488 for more information. Action models that used in the toolbar need to contain toolbar in the name of the action model.
<model name="part toolbar actions"> <action name="create" type="Part"/> <action name="create" type="Document"/> </model>

3. 4. Add the action model to your table by calling the setActionModel (action_model_name) in your MVC builder:
public ComponentConfig buildComponentConfig (ComponentParams params) { ComponentConfigFactory factory = getComponentConfigFactory (); JcaTableConfig table = (JcaTableConfig) factory.newTableConfig (); // add the toolbar action model to the table table.setActionModel (part toolbar actions); .... return table; }

Trouble Shooting Problem Description Some actions dont appear in the list in the UI Solution There may be a validator configured on it which may hide the action in certain conditions. See Windchill Client Architecture Action Framework Overview on page 486 for information on configuring an action with a validator.

Adding Actions and Hooking Them Up in the UI

549

Problem Description

Solution Add jcaDebug=true to the url to see even the hidden actions. With the jcaDebug option enabled, youll see more information in the menu, and there will be an action at the end of the list that takes you to the action model report for that menu.

Displaying Menu Bar Actions for a Table


1. Define the actions in an actions.xml file. See Procedure Defining a new action on page 488 for more information. 2. Add the actions to an action model. See Procedure Defining a new action on page 488 for more information. Action models that are used in the menu bar

550

Windchill Customization Guide

need to contain menubar in the name of the action model. To get a menu to fly out from the main menu, add a submenu to the action model:

<!-- Menu Bar Action Model <model name="folders table <submodel name="folder <submodel name="folder </model>

for the Folders table --> menubar"> file menu"/> edit menu"/>

<!-- File Menu Action Model for the Folders table --> <model name=" folder file menu"> <submodel name="submenu file new"/> <action name="action1" type="folder"/> </model> <!-- Edit Menu Action Model for the Folders table --> <model name=" folder edit menu"> <action name="copy" type="Object"/> <action name="paste" type="Object"/> </model>

Adding Actions and Hooking Them Up in the UI

551

<!-- File > New Menu Action Model for the Folders table --> <model name=" submenu file new "> <action name="create" type="part"/> <action name="create" type="document"/> </model>

3. Add the action model to your table by calling the setMenubarName (action_model_name) in your MVC builder.
public ComponentConfig buildComponentConfig (ComponentParams params) { ComponentConfigFactory factory = getComponentConfigFactory (); JcaTableConfig table = (JcaTableConfig) factory.newTableConfig (); // add the menu bar action model to the table table.setMenubarName ( folders table menubar ) ; .... return table; }

Trouble Shooting Problem Description Icons for some actions are missing Solution Only the actions that are displayed in a table toolbar have icons in the actions menu. There may be a validator configured on it which may hide the action in certain conditions. See Windchill Client Architecture Action Framework Overview on page 486 for information on configuring an action with a validator. Add jcaDebug=true to the url to see even the hidden actions. With the jcaDebug option enabled, youll see more information in the menu, and there will be an action at the end of the list that takes you to the action model report for that menu.

Some actions dont appear in the list in the UI

552

Windchill Customization Guide

Displaying Actions Menu on an Information Page


1. Define the actions in an actions.xml file. See Procedure Defining a new action on page 488 for more information. 2. Add the actions to an action model. See Procedure Defining a new action on page 488 for more information. When defining the action model, you will need to add the attribute menufor for the object type that you are defining the actions for.
<model name="part actions" menufor="wt.part.WTPart"> menufor="wt.part.WTPart <action name="view" type="object"/> ..... </model>

To get a menu to fly out from the main menu, add a submenu to the action model.

<model name="part actions" menufor="wt.part.WTPart"> menufor="wt.part.WTPart <action name="action_1" type="object"/> <submodel name="submenu_new"/> </model> <model name="submenu_new"> <action name="newViewVersion" type="part"/>

Adding Actions and Hooking Them Up in the UI

553

</model>

3. If you dont want to rely on the menufor action model, you can specify an action model by calling setActionListName(action_model_name) in your info page builder:
public InfoConfig buildInfoConfig(ComponentParams params) throws WTException { InfoComponentConfigFactory factory = getComponentConfigFactory(); InfoConfig infoConfig = factory.newInfoConfig(); // override the menufor action model with a different Action Model infoConfig.setActionListName("my type infopage actions"); .... return infoConfig; }

Note Your builder should extend DefaultInfoComponentBuilder or AbstractInfoComponentBuilder .


Trouble Shooting Problem Description Icons for some actions are missing Solution Only the actions that are displayed in a table toolbar have icons in the actions menu. There may be a validator configured on it which may hide the action in certain conditions. See Windchill Client Architecture Action Framework Overview on page 486 for information on configuring an action with a validator. Add jcaDebug=true to the url to see even the hidden actions. With the jcaDebug option enabled, youll see more information in the menu, and there will be an action at the end of the list that takes you to the action model report for that menu.

Some actions dont appear in the list in the UI

554

Windchill Customization Guide

14
Gathering the Data for the UI
Acquiring Data via Info*Engine ................................................................................. 556 NmObject Utilities .................................................................................................... 562 File Download ......................................................................................................... 568

This chapter describes how to gather data to be used in the user interface.

555

Acquiring Data via Info*Engine


Objective
You want to use an Info*Engine task to get the data for a Windchill Client Architecture table component.

Background
The Windchill Client Architecture provides IeTaskInfo to be returned from its ComponentDataBuilder for retrieving data using the Info*Engine task. Its action maps to an Info*Engine task, which will be executed to get the data for the component. Intended Outcome A Windchill Client Architecture table that has its data populated by an Info*Engine task.

Solution
Return an IeTaskInfo from a Windchill Client Architecture tables component data builder.

Prerequisite knowledge
Readers should be familiar with Info*Engine as well as with the basic Windchill Client Architecture data acquisition concepts.

Solution Elements
Element ComponentDataBuilder Type Java interface Description Creates the data model for the component Encapsulates information about the Info*Engine task and the parameters that can be passed to the task

IeTaskInfo

Java class

556

Windchill Customization Guide

Procedure Implementing the Component Data Builder


Your ComponentDataBuilder should return a well populated IeTaskInfo object. It takes the action name as the constructor which gives information of the task that need to be executed to get the data For example, the following code snippet demonstrates the use of the jca-Search task .
public class MyDataBuilderWithIETask implements ComponentDataBuilder { @Override public Object buildComponentData(ComponentConfig config, ComponentParams params) throws WTException { //pass the task name as constructor IeTaskInfo taskInfo = new IeTaskInfo("jca-Search"); .. return taskInfo; } }

You can provide parameters to the Get-Model webject using the setParam (Param param) method on the IeTaskInfo. In addition if you want to pass parameters to the underlying task using FORM group, can use addFormParam (String name, Object data) method. Configuring task selection Internally, it uses Info*Engines Dispatch-Tasks webject to look up the task implementation for the action task name that is provided in the IeTaskInfo. Several parameters which are passed on to the Dispatch-Tasks are exposed, using which its possible to choose the right implementation task. Refer to Dispatch-Tasks in the Management Webjects section of the Info*Engine User's Guide for more information on how these parameters work:
//pass the taskName as constructor IeTaskInfo taskInfo = new IeTaskInfo("jca-Search"); //parameter passed on to the Dispatch-Tasks taskInfo.setParam(new Param("GROUP_IN", "<groupInName>")); taskInfo.setParam(new Param("TYPE", "<typeName>")); taskInfo.setParam(new Param("CLIMBER", "<climberName>")); return taskInfo;

Supplying form data to the task By default, any request parameters in your JSP page will be supplied as part of the form data to your task. So, if the pages URL ends with something like /somePage.jsp?foo=bar, then in your task implementation, @FORM[] foo[] will map to bar.

Gathering the Data for the UI

557

If you want to explicitly configure the form data for your task, then you can do this by creating the form group and then specifying the name of the group as follows:
//pass the taskName as constructor IeTaskInfo taskInfo = new IeTaskInfo("jca-Search"); //create your FORM group Group groupIn = new Group("FORM"); taskInfo.setGroupIn(groupIn); return taskInfo;

Using Information Supplied to the Task by the Windchill Client Architecture Windchill Client Architecture supplies information to your task about the attributes displayed by the requesting component and current table view (if the component uses configurable tables). Your task can then use this information to query for the right resulting data. The additional parameters supplied to your task map to a subset of those accepted by the Query-Objects webject: ATTRIBUTE: This contains the list of attributes the component wants to display SORTBY: What attributes to sort by SORTED: The sort direction for each attribute WHERE: Filter criteria TYPE: The type or types to search for. VERSION: Whether LATEST or ALL versions should be returned. ITERATION: Whether LATEST or ALL iterations should be returned ATTRIBUTE_TYPE_CONTEXT: When multiple types are supplied, the type that should be used as a context to look up attribute definitions PAGE_LIMIT: The number of results per page (Not a customization point as paging is not supported in Tables in Windchill Release 10.0) PAGE_OFFSET: The first result row to return from the paging session, if any (Not a customization point as paging is not supported in Tables in Windchill Release 10.0) PAGING_SESSION_ID: The current paging session id, if any

Most of these parameter names can be reconfigured to some other value using setParam(Param param). See Customizations Points on page 558 for details.

Customizations Points
Parameter Default Value None action Possible Values Any valid task name API Req? Constructor Yes of DescripDescription The name of the task to

558

Windchill Customization Guide

Parameter Default Value form

Possible Values

API

Req? No

IeTaskInfo The current Name of a setGroupIn request valid group (Group parameters in the page groupIn) VDB

DescripDescription execute A group that contains form data for the task

setParam(Param setParam(Param param) customization points The following are all parameters that can be specified using setParam(Param param) Parameter Default Value GROUP_OUT output Possible Values Any Req? No Description The name of the resulting group The name of the group in to supply to Dispatch-Tasks The name of the type to supply to Dispatch-Tasks The name of the climber to supply to Dispatch-Tasks The name of the attribute to put the requested attribute list in The name of the attribute to put the sort criteria in The name of the attribute to put the sort direction

GROUP_IN

None

Any

No

TYPE

None

Any

No

CLIMBER

None

Any

No

ATTRIBUATTRIBTE_PARAM_- UTE NAME

Any

No

SORTBY_PARAM_NAME SORTED_PARAM_NAME

SORTBY

Any

No

SORTED

Any

No

Gathering the Data for the UI

559

Parameter WHERE_PARAM_NAME TYPE_PARAM_NAME

Default Value WHERE

Possible Values Any

Req? No

Description criteria in The name of the attribute to put the filter criteria in The name of the attribute to put the type criteria in The name of the attribute to put the version criterion in The name of the attribute to put the iteration criterion in The name of the attribute to put the attribute type context criterion in

TYPE

Any

No

VERSION_PARAM_NAME

VERSION

Any

No

ITERATION_- ITERATION Any PARAM_NAME

No

ATTRIBUTE_TYPE_CONTEXT_PARAM_NAME

ATTRIBUTE_TYPE_CONTEXT

Any

No

addFormParam(java.lang.String, java.lang.Object) can be used to pass parameters using the FORM group, which can be readily accessed from your task.

Limitations
None.

Sample Code
Look for the builder examples available in carambola

560

Windchill Customization Guide

com.ptc.mvc.builders.carambola.table.MvcTableBuilderWithIETask com.ptc.mvc.builders.carambola.table. DataSourceASyncTableBuilderWithIETask com.ptc.mvc.builders.carambola.table. DataSourceSyncTableBuilderWithIETask

Examples of Usage in Windchill Code


Few Change tables.

Related Documentation

Info*Engine User's Guide Windchill Adapter Guide (Info*Engine)

Gathering the Data for the UI

561

NmObject Utilities
The value of an attribute in an attribute panel or table/tree cell needs to be extracted from a different object than the datum object for the panel or table/tree row. Problem: The object identifier used to identify a selected table/tree row or construct the actions menu for a table/tree row cannot or should not be that of the row datum object. Background Each attribute panel and each row in a JCA table or tree has a datum object from which the data for the attribute or table cell values is extracted and the object identifier for row actions and for row selections is obtained. The datum object is provided by the buildComponent() method of a Java builder class or by a getModel() or getIEModel() JSP tag. Datum objects are typically Persistable objects or, in the case of create and edit wizards, TypeInstances representing Persistable objects. However, other types of Java objects (for example, a HashMap) can be used. Retrieving Attribute Values from Datum Objects JCA provides ways to configure how datum objects are processed by data utilities to extract the attribute values that are displayed in the UI. Without additional configuration, JCA handles datum objects in the same way that the JSP EL handles Java beans, meaning that you can refer to a property name and the infrastructure will look for a corresponding getter on your object. For example, if you have described a table that has a column with the name foo, the infrastructure will look for a "getFoo" method on the datum object. If the method isn't found, the infrastructure does not fail but instead will simply return a null value for the UI component to process in whatever way it chooses. By default, the UI components just render a blank in this case. You are not limited to simple properties of the datum object. In fact, anything you can do with the JSP EL can also be accomplished with JCA. For example, you can use the dot notation to refer to nested properties. In addition, JCA treats Map objects as beans, so if your API returns a Map or has a nested Map property, you can refer to it just as if it had getter methods. For complete information on what you can specify in bean notation, refer to the documentation for beanutils, the core package that JCA uses to process bean properties. More examples:

562

Windchill Customization Guide

bar[0]: get the first value of the bar property. This works if bar maps to a List or an Array. foo.bar: get the nested "bar" property of a "foo" property. If getFoo() returns a Map, then this would correspond to getFoo().get("bar")

In addition to bean-style properties, JCA is able to look up the values for soft attributes if the datum object is a Persistable or TypeInstance. Also, JCA provides a number of data utilities that are able to create values for attribute ids that are not properties of the datum object. Some of these do additional data acquisition to find necessary information that does not exist in the datum object. Retrieving Row Identifiers from Datum Objects Without additional configuration, the JCA table and tree framework assumes that each row object they are processing is a Windchill Persistable object whose object identifier can uniquely identify the object when a row is selected or when a rowlevel actions menu needs to be displayed. The correct target object has been specified for the panel, table or tree.

Solution
When the value of an attribute should be extracted from an object other than the datum object you can configure a different target object from which attribute values should be obtained. The target object will be passed as the datum to data utilities instead of the datum object. Note that the specified target object must be addressable from the datum object. See Procedure Configure a different target object In cases where the datum object for a table or tree is not a Persistable object whose identifier can be used for table row actions or row selection you can configure how the row object identifier should be obtained. In order of preference, your options are: Procedure Implement getOid() on your row data object Procedure Configure a diferent target object

Prerequisite Knowledge You need to have an understanding of the following: Windchill application context (service.properties) JCA Overview MVC Overview JCA NmObjects Overview

Gathering the Data for the UI

563

Related Information on page 567 includes references to many or all of these subjects. Definition of Terms Term Definition datum object The objects returned by the getComponentData method of the panel, tree, or table builder class. For example, a Collection of BinaryLinks. row data Same as datum objects target objects The objects that will be sent into the data utilities. By default, the target objects are the same as the row data. This can be overridden per column where necessary. (For instance, the target objects could be BinaryLinks for the first column, role A objects for second column, role B objects for the third column etc.) Warning - If you use both for the table, make sure the NmObjectUtility will look to see what the target object is so that creates the right NmObject. This can effect whether the Number column works for example.

Implement getOid() getOid() on your row data object


This procedure describes the preferred technique for specifying the identifier that should be used for table/tree row selections and actions when the row object is not a Persistable object. This technique is not applicable for specifying a target object that is different from the datum object for determining attribute values. To use this technique you should modify the row objects to expose an API called getOid(), which should return a unique identifier for the row. The getOid() method should return one the following data types: String which will map to a NmSimpleOid if its not a valid WTReference ObjectIdentifier NmOid

If is not possible to provide a getOid() method for example, if such an API already exists and is not appropriate, you can specify a target object for the panel or row. See Configure a Different Target Object on page 564 for more information.

564

Windchill Customization Guide

Configure a Different Target Object


This procedure describes how to specify a target object for an attribute panel or a row that is different than the datum object. The unique identifier for row selections and actions will be obtained from the target object and the target object is also what will be passed to the data utility that creates the value displayed for an attribute. The target object must be obtainable from the datum object via a getter method. For tables and trees, a target object can be specified for the entire table or tree or for just certain columns. For panels, a target object can be specified for the entire panel or just certain attributes. The target object must be retrievable via a getter method on the datum object. When you configure a different target object for a table or tree that has row selection and/or row action menus, the target object should be one of the following types so that a unique row identifier can be determined: Persistable WTReference ObjectIdentifeir NmObject NmOid NmSimpleOid JCATableConfig.setTargetObject() to set the target object for an entire table or tree JCAColumnConfig.setTargetObject() to set the target object for a specific table or tree column AttributePanelConfig.setTargetObject() to set the target object for an entire attribute panel AttributeConfig.setTargetObject() to set the target object for a single attribute in a panel

Use one of the following methods to set the target object:

If you set the target object for the whole panel or table, that target object will be used for every attribute/column unless overridden by the AttributeConfig or JCAColumnConfig. If a target object is specified for the entire panel or table and you want to use the datum object for a specific attribute or column, you can set the target object to on the attribute or column config. For example:
JcaTableConfig table = (JcaTableConfig)factory.newTableConfig(); table.setTargetObject(foo); ColumnConfig c = factory.newColumnConfig("name",label,false);

Gathering the Data for the UI

565

ColumnConfig col = factory.newColumnConfig("thing1",label,false); col.setTargetObject(""); ColumnConfig col2 = factory.newColumnConfig("thing2",label,false); col2.setTargetObject("bar");

In the above example, for each column the DefaultNmObjectDataUtility will try to create an NmObject from the targetObject. For the name column, the targetObject is retrieved by calling getFoo() on the row datum because foo is the target object configured for the table and it has not been overridden for the name column. For thing1, the targetObject is the row datum because is configured. For thing2, the targetObject is retrieved by calling getBar() on the row datum. How is this different than configuring bean properties? You may be wondering how this configuration of targetObject differs from a configuration that uses bean-style property configuration. For example the following configurations both end up displaying getFoo().getBaz() of the row objects returned for your table:
ColumnConfig colA = factory.newColumnConfig("thing1",label,false); colA.setTargetObject("foo"); colA.setNeed("baz"); ColumnConfig colB = factory.newColumnConfig("thing2",label,false); colB.setTargetObject(""); colB.setNeed("foo.baz");

The small difference is that colA would use foo as the target object sent into the DefaultNmObjectUtility and the DataUtility for the row etc. And colB would use the original row object.

Limitations
The infrastructure will try to get a target object for every row even if you do not need one. There is no way to tell the infrastructure not to do this. If you do not have your table configured correctly you may see an error like 2011-02-24 16:42:10,883 TRACE [TP-Processor7] com.ptc. core.components.factory.dataUtilities. DefaultNmObjectUtility wcadmin - nmObject 2011-02-24 16:42:10,883 DEBUG [TP-Processor7] com.ptc. core.components.factory.dataUtilities. DefaultNmObjectUtility wcadmin - Exception occured trying to get an oid property.

566

Windchill Customization Guide

java.lang.NoSuchMethodException: Unknown property 'oid' on class 'class com.ptc.core.meta.type.common.impl. DefaultTypeInstance' ... If the table does not have any row actions or row selection, this error can be ignored. It is harmless. It is not important to have the right target object if there are no actions. The error message can be ignored or removed by implementing a getOid method on the row data. If the table has row selection and/or actions, use the guidelines in this document to correct the configuration and get the right oid.

Related Information
Windchill Client Architecture Overview on page 226 Windchill Client Architecture Common Objects Overview on page 239 MVC Components on page 251

Gathering the Data for the UI

567

File Download
You want to export data, identified by a Windchill URL, to a file in the user s file system, without interrupting any active AJAX requests. This information applies to any coding scenario that involves exporting (downloading to the client) a word processing document, spreadsheet, compressed archive, etc. See Limitations on page 572 for file types not suited for this technique. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions You have one of the following: JavaScript code A JSP page or fragment A Java class that descends from DefaultObjectFormProcessor, or another use of a FormResult object

The code needs to allow a user to download a file, identifiable by a URL, to the users computer. The download must not interfere with any pending AJAX transaction, and must run in the background without preempting the Windchill UI. For example, you might have a wizard that guides a user to select a document, and a class <MyWizardFormProcessor>.java to process the form on closure. The form processor can return a FormResult with the next action set to FormResultAction.JAVASCRIPT, that includes a JavaScript call to download the selected file. Intended Outcome The user s web browser will present its standard file-save dialog box:

568

Windchill Customization Guide

Solution
Call the JavaScript function PTC.util.downloadUrl(url) to initiate the file download. See Customization Points on page 571 for information about the url parameter. You can call directly from JavaScript, within a <script> section in JSP, or by returning a FormResult from Java with a next action type of FormResultAction. JAVASCRIPT. Prerequisite Knowledge To achieve this result, you need to understand: Basic development of Windchill web pages JavaScript Web server configuration and content-disposition URL security best practices

Solution Elements
Element main.js Type JavaScript Description This file includes the JavaScript fragment util.

Gathering the Data for the UI

569

Element

Type

JavaScript (whole or <MyScript.js> or <MyScriptPart.jsfrag> fragment) JSP (whole or fragment) <MyPage.jsp> or <MyPagePart.jspf> <MyWizardFormProcessor.java> Java class

Description jsf, which defines the PTC.util.downloadUrl(url) function. It is located in //codebase/ netmarkets/ javascript/util Code a call to PTC. util.downloadUrl (url) directly in JavaScript or inside a <script> tag in JSP. Use a FormResult object to pass JavaScript to the client for execution. The general pattern is: formResult.setStatus(FormProcessingStatus. SUCCESS); // or prior value formResult.setJavascript(js); // where js is a string of JavaScript code formResult.setNextAction(FormResultAction. JAVASCRIPT); The JavaScript string should include a call to PTC. util.downloadUrl (url); it may also contain other necessary code. If handling the OK button click in a wizard, you should run the download in the opening window:

570

Windchill Customization Guide

Element

Type

Description window.opener. PTC.util.downloadUrl(theURL); and close the wizard: window.close();

Procedure Downloading a Windchill URL


Because PTC.util.downloadURL(url) is a utility function that might be used under many circumstances, no single procedure can anticipate them. For Javascript and JSP, create or modify the code that needs to initiate the download, calculate or look up the URL of the desired file, and call PTC.util. downloadURL(url) where needed. For server-side initiation in Java, see Packaged Samples on page 572.

URL Security
Your file download implementation must take security issues into account. Information about the server s file structure should never be displayed to the user. This includes URLs. Users should not be allowed to traverse the file structure of the server when downloading a file. Users should not be allowed to change a parameter, such as filename, when downloading a file. Users should never be allowed unauthorized access to any file through such traversals or modifications.

Customization Points
ParameParame- Default ter Value None url Possible Values A full URL (protocol:// credentials@server/path1/ path2) A root-relative ReRequired Yes Description The URL of the file to be downloaded to the client.

Gathering the Data for the UI

571

ParameParame- Default ter Value

Possible Values URL (/path1/ path2) The current Windchill root (from getBaseHref ()) will be prepended to the parameter. A current locationrelative URL (path1/ path2)

ReRequired

Description

Limitations
This practice is limited to content types that web browsers cannot display. It cannot be used for text, HTML, XML, or common image formats such as PNG, JPEG, or GIF. The downloadURL function works by setting the source of a hidden <iframe> to the specified URL. The browser will render text, HTML, images, etc. in the <iframe>, rather than initiating a download.

Packaged Samples
There is an example that illustrates use of the downloadURL function in a wizard. If you have the Client Customization utility enabled naivgate to Navigator Customization Test Clients Download File Example to see the example. The Client Customization utility is not enabled by default. See Enable Customization Utilities on page 417 for instructions on how to enable the utility.

572

Windchill Customization Guide

15
Presenting Information in the UI
Soft Attributes and SCAs.......................................................................................... 574 Constructing and Rendering a Table Using the JSP Framework................................... 579 Windchill Client Architecture Tree.............................................................................. 614 Attribute Customization ............................................................................................ 630 Adding Custom Modeled Attributes to all Table Views ................................................. 701 Attribute Tables ....................................................................................................... 702 Generating the Name Attribute Server ....................................................................... 707 Icon Delegates ........................................................................................................ 712 UI Validation............................................................................................................ 718 Customizing the Find Number Field........................................................................... 766 Inline Messaging ..................................................................................................... 771

This chapter describes how to customize information that is displayed in the user interface.

573

Soft Attributes and SCAs


The values returned for following logical attributes will be instances of AttribtueTypeIdentifierSet. The values represent the collection of AttributeTypeIdentifiers associated with that attribute. In addition, values for each of the attributes that is a member of the set will also be returned in the retrieved TypeInstance. Attribute ALL_SOFT_ATTRIBUTES Description Returns a list of all soft attributes associated with the retrieved object as well as values for all of those attributes. Returns a list of all soft attributes associated with the classification(s) of the retrieved object as well as values for all of those attributes.

ALL_SOFT_CLASSIFICATION_ATTRIBUTES

ALL_SOFT_NON_SCHEMA_ATTRI- Returns a list of all soft attributes BUTES associated with the retrieved object which are NOT associated with the type of the retrieved object as well as values for all of those attributes. ALL_SOFT_SCHEMA_ATTRIBUTES Returns a list of all soft attributes associated with the type of the retrieved object as well as values for all of those attributes. ALL_SOFT_SCHEMA_ATTRIBUReturns a list of all soft attributes TES_FOR_INPUT_TYPE associated with the type indicated by the context of the constructed AttributeTypeIdentifier as well as values for all of those attributes. ALL_SOFT_NON_CLASSIFICATIO- Returns a list of all soft attributes N_ATTRIBUTES associated with the retrieved object which are NOT associated with the classification(s) of the object, as well as the values for those attributes.

Example:
TypeIdentifier type_x = ...; AttributeTypeIdentifier ati = (AttributeTypeIdentifier) IDENTIFIER_FACTORY.get("ALL_SOFT_SCHEMA_ATTRIBUTES_FOR_INPUT_TYPE" ,type_x);

574

Windchill Customization Guide

If 'ati' is requested to be returned when a TypeInstance is retrieved, it will return a list of only the attributes associated with type_x, regardless of the actual type of the retrieved object. This attribute is typically used for tables of objects which may or may not be of the same type, but all have a common supertype which defines the appropriate columns to display. Attribute ALL_SOFT_NON_CLASSIFICATION_SCHEMA_ATTRIBUTES Description Returns a list of all soft attributes associated with the type of the retrieved object which are NOT associated with the classification(s) of the retrieved object as well as values for all of those attributes. Returns a list of all custom hard attributes associated with the type indicated by the context of the constructed AttributeTypeIdentifier as well as values for all of those attributes. 'Custom' hard attributes are defined to be all modeled attributes which are not inherited from classes in the 'wt' or 'com.ptc' packages.

ALL_CUSTOM_HARD_ATTRIBUTES_FOR_INPUT_TYPE

Presenting Information in the UI

575

Defining Soft Attributes


Standard Standard attributes are soft attributes that can only store zero or one value for an attribute. Sometimes these are informally known as flex attributes. The following data types are supported: String Localizable String Rich Text Boolean Integer Number Real Number Real Number with Units Timestamp Reference Hyperlink

These values of these attributes are stored in one or more modeled columns in the table associated with the class. A class must be explicitly modeled to include these flex columns in order for this feature to be available. They will be added through annotations. For more information on to do this, please refer to Adding Columns to Types on page 1020 Global Global attributes are soft attributes that can store zero or more values for an attribute. The following data types are supported: String Boolean Integer Number Real Number Real Number with Units Timestamp Reference (currently limited to a small number of legal targets) Hyperlink
Windchill Customization Guide

576

These values of these attributes are stored in global dedicated tables. Alias Alias attributes are non-persisted attributes that are an alias for a different attribute on a related object. Informally these attributes called logical attributes. They are functionally the same as logical attributes defined in LogicalAttributes.xml, but the can be defined in the UI. Any data type of any other type of attribute is supported, and they may have zero to many values. These attributes have a mapping property which must be set to define the real attribute that this attribute is an alias for. The following is the syntax for the mapping property:
<mapping> = <attribute_name> or < navigation> or < navigation>~<mapping> or where <navigation> = <attribute_name>^<type_name> or <attribute_name>@<type_name> or <attribute_name>=<attribute_name>@<typename>

Here are some sample mappings that might be defined on wt.part.WTPart:


masterReference^wt.part.WTPartMaster~alternateFor@wt.part.WTPartAlternateLink

Navigate the masterReference attribute to the WTPartMaster and then to the WTPartAlternatLink(s) whose alternateFor attribute references the same WTPartMaster
masterReference^wt.part.WTPartMaster~addressedPartMasterReference@ wt.change2.ChangeAction

Navigate the masterReference attribute to the WTPartMaster and then to the ChangeAction(s) whose addressedPartMasterReference attribute references the same WTPartMaster.
name=name@wt.doc.WTDocument~number

Presenting Information in the UI

577

Navigate to the number attribute of the WTDocument(s) whose name is equal to the name of this WTPart. The <attribute_name>=<attribute_name>@<typename> is only supported for hard attributes on each side of the =. Calculated Calculated attributes are non-persisted attributes that are calculated from the values of other attributes They are sometimes called SCA attributes. Any data type of any other type of attribute is supported, and they may have zero to many values. These attributes have mapping and formula properties, one of which must be set to define the calculation. The following is the syntax for the mapping property: A formula of a+b*c would give this attribute the value of attribute b multiplied by the value of attribute c plus the value of attribute a. A mapping value can be set to map the attribute to an AttributeContainerFunction by specifying the SCA attribute name in LogicalAttributes.xml. Dynamic Logical Dynamic logical attributes are uncommon and are not available as an option in the UI when an Administrator creates a new soft attribute. Dynamic Logical attributes are non-persisted attributes that are an alias for a different attribute that must be determined at runtime. However, they are functionally the same as logical attributes defined in LogicalAttributes.xml with the resolver syntax, but the can be defined in the UI. Any data type of any other type of attribute is supported, and they may have zero to many values. These attributes have a resolver property which must be set to define the resolver class that calculated the mapping at runtime. Example resolver: com.ptc.core.meta.classification. command.model.server.impl. ClassificationIdentifierResolver

578

Windchill Customization Guide

Constructing and Rendering a Table Using the JSP Framework


Objective
You want to present the information in a tabular format and optionally execute actions on the presented data.

Background
The table common component presents information in a tabular format to help users scan, locate, compare, and take actions on related data. Users may control how to view data in the table using sorting and views. The following tables details the specific elements within a table. Element Title Bar Description The title bar area tells users what information is displayed in the table. The table title bar is located at the top of the table and may contain: a table title, an object count, the Current View pulldown list, and several action icons - Help etc. Menu Bar Tables with many actions will display a menu bar. Each menu title provides a pulldown list of actions. Shortcut Tool The shortcut tool bar displays a subset of actions from the Bar menu bar. These are actions that are frequently used. The shortcut tool bar may be used without the menu bar when a table contains few actions. Column Header/ Sorting allows the user to control the presentation of table Sorting data. Selection The checkbox column allows users to select and deselect objects within the table that they wish to perform an action upon. A user can also select the rows across the multiple pages and perform the desired actions on the same. Status Glyph The status glyph column(s) convey status and messaging Columns information about individual objects in the table. Object Icon The object icon column displays the appropriate icon for that Column object. Action Column The action columns in the content area of a table contain the (s) row-level actions for specific objects in a table. Data Rows The data rows of a table contain attributes for a given object in the table. This section covers table scroll bars. Footer The table footer is located at the bottom of the table. It

Presenting Information in the UI

579

Element

Description provides visual closure to the table and contains the paging and View All functionality, if used.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Table common component should be used when there is a requirement to display Windchill business objects in tabular form and not just for displaying the HTML Table.

Intended Outcome
Depending upon the configuration, Table can be displayed in different formats. Following is a general layout of a Table:

Solution
Implement MVC table builders to create or convert a JCA table component.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following JCA techniques: Data utilities GUI component Actions framework Configurable table views Java annotations

580

Windchill Customization Guide

Solution Elements
Element ComponentDataBuilder ComponentConfigBuilder ConfigurableTableBuilder AbstractConfigurableTableBuilder ComponentConfig Type Java interface Java interface Java interface Java class Java interface Description Creates the data model for the component Creates the configuration for the component Creates the configurable table views for tables and trees Base class that builders typically extend Base interface for component configurations Creates ComponentConfig implementations Configures the component id used to look up a component builder

ComponentConfig- Java interface Factory ComponentBuilder Java annotation

Procedure Configuring Table Common Component Creating a new Builder class A table builder class corresponds to a table configuration. All the table-level as well as column-level properties should be configured in the builder class. When creating a new builder class, you should typically extend one of the abstract base classes provided by the MVC infrastructure: AbstractConfigurableTableBuilder Use this base class if you are implementating a tree or table that supports configurable table views. This base class is located in the CoreHtmlComp module due to its dependency on the configurable table infrastructure. AbstractComponentBuilder Use this base class for tables and trees that do not support configurable tables AbstractComponentConfigBuilder Use this base class for info pages. You can also use this if you wish to separate your table or tree config builder from its data builder (not a typical use case). AbstractComponentDataBuilder Use this base class for table and tree implementations where you have chosen to separate the config and data builder implementations (not a typical use case).

Presenting Information in the UI

581

Implementing the ComponentConfigBuilder API The table and column level configuration options can be specified by implementing ComponentConfigBuilder. ComponentConfigBuilder currently defines one method:
ComponentConfig buildComponentConfig(ComponentParams params);

The responsibility of this method roughly corresponds to what the describeTable tag does in 9.x versions. The ComponentConfig hierarchy:

Using ComponentConfigFactory to get Table/column Table/column ComponentConfig objects It is not necessary to create a ComponentConfig directly, instead use a ComponentConfigFactory. When extending the abstract base builder classes, the factory is available by calling getComponentConfigFactory(). When directly implementing ComponentConfigBuilder, also implement ComponentConfigFactoryAware. This will get you a reference to the factory when the builder is initialized. Instance of TableConfig and ColumnConfig need to be used to specify table level and columns level customizations respectively. An example to get the TableConfig/ ColumnConfig instance look like this:
ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); ColumnConfig col1 = factory.newColumnConfig(column1Id, false);

582

Windchill Customization Guide

table.addComponent(col1);

Since column component is a nested component of table component, ColumnConfig can be added to the TableConfig using the addComponent() API as shown in above code snippet. Setting properties on TableConfig and ColumnConfig: Customization points available for the config classes are described in Customization Points on page 586. Refer to the JavaDoc for more details on the properties and capabilities of each config class. Localizing your configs To localize values within your config builder, the Mvc infrastructure provides a new ClientMessageSource class. If you are extending one of the abstract configuration base classes, then you can call getMessageSource(String) to create a message source for a given resource bundle class name. ClientMessageSource works like WTMessage, but ensures that the locale that you use is the client locale, rather than the locale that the server is running with. Specifying the view JSP Implementing the ComponentDataBuilder API The data acquisition mechanism for table can be configured using ComponentDataBuilder interface. The data builder class needs to implement ComponentDataBuilder interface. ComponentDataBuilder currently defines one method:
Object buildComponentData(ComponentConfig config, ComponentParams params)

The responsibility of this method roughly corresponds to what the getModel/ getIeModel tag do in JCA in the 9.x release stream. Registering your ConfigurableTable If your ComponentConfigBuilder implementation also implements ConfigurableTableBuilder, then you do not need to register your ConfigurableTable implementation in service.properties. You cannot register ConfigurableTableBuilder implementations themselves, independent from a ComponentConfigBuilder implementation.

Presenting Information in the UI

583

Implementing your ConfigurableTable You may choose to implement your ConfigurableTable as a static inner class of your builder, or to put it in a separate file. If you only intend to use it from within the builder implementation, then we recommend defining it as a private static inner class. An example:
public class MyTableBuilder extends AbstractConfigurableTableBuilder { @Override public ConfigurableTable buildConfigurableTable(String tableId) throws WTException { return new MyConfigurableTable(); } private static class MyConfigurableTable extends JCAConfigurableTable { } }

Configuring separate config and data builders If you wish to implement your config and data builders in separate classes, then you must supply an additional ComponentBuilderType parameter to the @ComponentBuilder annotation. For config builders, this looks like:
@ComponentBuilder(value=my.component.id, type=ComponentBuilderType.CONFIG) public class MyConfigBuilder implements ComponentConfigBuilder

For data builders, this looks like:


@ComponentBuilder(value=my.component.id, type=ComponentBuilderType.DATA) public class MyDataBuilder implements ComponentDataBuilder

If you wish to configure separate builders without using annotations, then the bean ids you choose must have the .configBuilder or .dataBuilder suffix. For example to configure a config builder, you would do the following:
<bean name=myComponent.configBuilder class=my.config.builder.class.name/>

Registering MVC builders MVC builders can be registered using ComponentBuilder annotation or via explicit configuration, or by automated scanning. Automated scanning. After registering the table builders, the table component can be configured into the application in actions.xml just as JSP-based JCA components.

584

Windchill Customization Guide

See MVC Components on page 251 and Constructing and Rendering a Table Using the JSP Framework on page 579 for more information on registering/ configuring the table component. Converting an Existing Table Implementation to MVC Overview This section describes the mapping of attributes from the 9.x legacy tags to the corresponding attributes on the new MVC table builders. describeTable The content of the describeTable tag is now specified in the buildComponentConfig method of ComponentConfigBuilder interface JSP code was like this:
<jca:describeTable var="tableDescriptor" id="netmarkets_project_list" configurable="true" type="wt.projmgmt.admin.Project2" label="${projectListLabel}">

MVC code will look like this:


@ComponentBuilder(netmarkets_project_list) public class ProjectListBuilder extends AbstractConfigurableTableBuilder { @Override public ComponentConfig buildComponentConfig(ComponentParams params) { ComponentConfigFacory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); table.setLabel(ClientMessage.get(RESOURCE,"PROJECT_LIST_NAME" "PROJECT_LIST_NAME"); table.setType("wt.projmgmt.admin.Project2"); return table; }

describeColumn The content of the describeColumn tag is also specified in the buildComponentConfig method of ComponentConfigBuilder interface. As the column component is an child component of the table component, it is added to the table config. JSP code was like this:
<describeTable var="tableDescriptor" type="wt.part.WTPart" id=" test.table" label="testTable" > <describeColumn id="name" sortable=true/> <describeColumn id="number"/> </describeTable>

MVC code will look like this:


TableConfig table = factory.newTableConfig();

Presenting Information in the UI

585

table.addComponent(factory.newColumnConfig(name,true)); table.addComponent(factory.newColumnConfig(number,false));

renderTable The content of the renderTable tag is also specified in the buildComponentConfig method of ComponentConfigBuilder interface. JSP code was like this:
<jca:renderTable showCustomViewLink="false" model="${tableModel}" showCount="true" showPagingLinks="true" />

MVC code will look like this:


TableConfig table = factory.newTableConfig(); table.setShowCount(true); table.setShowCustomViewLink(false);

getModel The content of the getModel tag is specified in the buildComponentData method of ComponentDataBuilder interface. JSP code was like this:
<jca:getModel var="tableModel" descriptor="${tableDescriptor}" serviceName="com.ptc.netmarkets.projmgmt.ProjectCommands" methodName="getProjects" . > <jca:addServiceArgument value="${user}" type="wt.org.WTUser"/> <jca:addServiceArgument value="${pseudoType}" type="java.lang.Integer"/> </jca:getModel>

MVC code will look like this:


@Override public QueryResult buildComponentData(ComponentConfig config, ComponentParams params) { WTPrincipal user = SessionHelper.getPrincipal(); return ProjectCommands.getProjects(user,0) }

Customization Points
JcaTableConfig class APIs can be explored for various table level customization points. JcaColumnConfig class APIs can be explored for various table column level customization points.

586

Windchill Customization Guide

Configuring a custom view jsp for table component


The MVC infrastructure provides default JSPs for tables and trees. In most cases you should not need to override the default view. If you need to render your table model in a custom way, you can set a view path on your table or tree config object to do this. Note that the view path must be relative to WEB-INF/jsp, to ensure that the JSP is only accessed by MVC builders, rather than being directly accessible to clients. This means you JSP must be checked in to a subfolder of <ModuleRoot>/ src_web/WEB-INF/jsp/<ModuleDirectory>/aCustomView.jsp In table builder class:
TableConfig table = factory.newTableConfig (); table.setView("/myModule/aCustomView.jsp");

The custom view jsp ( /WEB-INF/jsp/<ModuleDirectory>/aCustomView.jsp) will look something like this:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%> /* custom code here */ <mvc:table/> /* custom code here */

Presenting Information in the UI

587

Reuse of a Table Builder Class


An API defined in one builder could be reused while writing a new builder. In general, it is preferable to keep the needed builder as an instance field of the table implementation, rather than extending the other builder. This follows the general rule of thumb of favoring composition over inheritance. If reuse of a a config builder is intended, it should be ensured to set the component config factory on it. An example:
@ComponentBuilder("my.builder") public class MyBuilder extends AbstractComponentBuilder { private final OtherBuilder otherBuilder = new OtherBuilder (); @Override public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException{ } @Override public void setComponentConfigFactory(ComponentConfigFactory configFactory) { super.setComponentConfigFactory(configFactory); otherBuilder.setComponentConfigFactory(configFactory); } }

Setting Sortable Columns


Sorting Behavior Table is sorted at client side in following scenarios: 1. It is an asynchronous datasource enabled table and application team has not specified preSorted property in result processor from builder to true. 2. If user explicitly changes the sort criteria and user revisits the table. (Sort stickiness). Table is not sorted at client side in following scenarios: 1. If the application team set preSorted property to true on the result processor of table builder. 2. In case of synchronous datasource enabled table. During client side sorting, when the data chunk come to the client, they are added to the store as per the client sort criteria. If the user clicks sort while the data is loading, the data gets sorted at client side. Also the data chunks that come later are also added in sorted order.

588

Windchill Customization Guide

Multi-column sorting: Multiclick to sort feature allows the user to sort multiple columns at a time there by pressing the shift key and then sorting. The limitation is maximum three columns are allowed to sort at a time. In case of sorting on version column, sorting happens at server side.

Setting Default Sort A table column can be as a default sort column by using setDefaultSort(true) for the column. For setting the direction setAscending() can be provided with value true for ascending sort and false for descending sort.
ColumnConfig col = factory.newColumnConfig(name, true); col.setDefaultSort(true); col.setAscending(false);

Configuring the column as above in table builder will cause a table to be displayed as:

Configuring Strikethrough Feature


JCA Table component has ability to "redline" individual rows.

Presenting Information in the UI

589

The following configuration points are available for specifying which row(s) will be struckthrough. Configuring strikethrough on a hidden column Add dataStoreOnly column with id "strikeThroughRow". Provide need attribute for boolean column. An example:
ColumnConfig strikeThroughColumn = factory.newColumnConfig("strikeThroughRow", false); strikeThroughColumn.setDataStoreOnly(true); strikeThroughColumn.setNeed("someColumnId");

Configuring strikethrough on a row value A new datautility that extends AbstractBooleanValueDataUtility should be defined for the column. The only abstract method getBooleanAttributeValue() should be defined to return a Boolean. Custom code can be written to determine the returning Boolean. The Boolean will decide if the row should be strikethroughed or not. An example: Column defined in builder to be added to JcaTableConfig:
ColumnConfig col = factory.newColumnConfig("myCol" "myCol", false);

Corresponding mapping of the datautility for the column:


<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.ptc.windchill.enterprise.myModule.dataUtilities .MyStrikeThroughRowDataUtility" requestor="java.lang.Object" selector="myCol" cardinality="duplicate"/> </Service>

590

Windchill Customization Guide

New datautility class:


public class MyStrikeThroughRowDataUtility extends AbstractBooleanValueDataUtility { public boolean getBooleanAttributeValue (String component_id, Object datum, ModelContext mc) throws WTException { /* some logic to return Boolean value*/ } }

Configuring already present Boolean column as a strikethrough column The Boolean value column can be set as the strikethrough column in the table builder. So the value of this column can be used to determine if the row will be strikethrough. An example:
TableConfig tableconfig = factory.newTableConfig(myTable); ColumnConfig aBooleanColumn = factory.newColumnConfig("aBooleanColumn", Tableconfig.setRowStrikeThroughColumn setRowStrikeThroughColumn(aBooleanColumn); false);

Configuring Search in List


By default the Search In List feature is enabled for the table. A user can enter text and hit Enter or Search In List icon to execute the search. After applying the search in list filter, the table will be displayed with the records matching with the text entered. Only the values in the visible columns will be searched. The Search in List filter will be sticky across component/page refreshes.

Disabling Search In List feature Search in list can be disabled from a table by setting false in setFindInTableEnabled.
TableConfig tableconfig = factory.newTableConfig('myTable'); tableConfig.setFindInTableEnabled(false);

Search In List modes There are multiple modes available for Search in List. The Search in list mode can be set using setFindInTableMode() method.

Presenting Information in the UI

591

The search in list modes available are: 1. FindInTableMode.CLIENT_AND_SERVER(default mode): Perform the search in table on the client or server data. 2. FindInTableMode.CLIENT_ONLY: Perform search in table on the client data only. 3. FindInTableMode.DISABLED: Search in list panel is not displayed.

Configuring Non-Selectable Non-Selectable Rows


Non selectable row based on an existing visible column Non-selectable rows can be set depending upon a column that has a Boolean value. An example:
TableConfig table = factory.newTableConfig (); //a column that is suppose to hold a boolean ColumnConfig col1= factory.newColumnConfig (aBooleanColumn, table.setNonSelectableColumn setNonSelectableColumn (col1);

false);

Configuring Non selectable rows based on a boolean attribute value available in the backing object The data utility com.ptc.core.components.factory.dataUtilities. DefaultBooleanValueDataUtility is provided out of the box for configuring non selectable rows. This data utility is mapped to column id com.ptc.core. components.descriptor.DescriptorConstants.ColumnIdentifiers. NON_SELECTABLE_COLUMN. There are two ways to set this data utility for a column in a table: Use NON_SELECTABLE_COL as the column id Create a column with an Id as com.ptc.core.components.descriptor. DescriptorConstants.ColumnIdentifiers.NON_SELECTABLE_COLUMN. Set the attribute as the need. An example:
TableConfig table = factory.newTableConfig (); ColumnConfig col = factory.newColumnConfig (NON_SELECTABLE_COLUMN, false); col.setNeed (<Attribute>); // Specify the attribute which will decide the row is selectable or not. col.setDataStoreOnly (true); // this will make your Column hidden table.addComponent (col); table.setNonSelectableColumn setNonSelectableColumn (col);

Setting datautility id to NON_SELECTABLE_COLUMN

592

Windchill Customization Guide

Create a column with any Id, set the attribute as the need and set the Datautility Id as com.ptc.core.components.descriptor.DescriptorConstants. ColumnIdentifiers.NON_SELECTABLE_COLUMN. An example:
TableConfig table = factory.newTableConfig (); ColumnConfig col = factory.newColumnConfig(<columnId>, false); col.setNeed (<Attribute>); // Specify the attribute which will decide the row is selectable or not. ((JcaColumnConfig)col)setDataUtilityId setDataUtilityId (NON_SELECTABLE_COLUMN); col.setDataStoreOnly (true); // this will make your Column hidden table.addComponent (col); table.setNonSelectableColumn setNonSelectableColumn (col);

Non selectable row based on a custom data utility Create and register a custom data utility for the column to be used as a nonselectable column. Create a custom data utility A custom data utility for controlling non selectable rows should extend com. ptc.core.components.factory.dataUtilities.AbstractBooleanValueDataUtility. The method getBooleanAttributeValue() method can be overridden with custom logic: An example:
package com.customPkg; import com.ptc.core.components.factory.dataUtilities. AbstractBooleanValueDataUtility; public class TestCustomDataUtility extends AbstractNonSelectableRowDataUtility {

public boolean getBooleanAttributeValue (String component_id, Object datum, ModelContext mc) throws WTException { /* this method will return true if the row is not selectable */ } }

Register the custom data utility: Configure the newly created data utility against the column id:
<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.customPkg.TestCustomDataUtility " requestor="java.lang.Object" selector="col1 cardinality="duplicate"/> </Service>

Non-selected rows are displayed as follows:

Presenting Information in the UI

593

Configuring Data Store Only Column


Setting a column as data store only would make the column value available in data store, but the column will not be displayed in the table. For example:
TableConfig table = new TableConfig('testTable'); ColumnConfig dataStoreOnlyColumn = factory.newColumnConfig ("dataStoreOnlyColumn", false); dataStoreOnlyColumn.setDataStoreOnly setDataStoreOnly(true); table.addComponent(dataStoreOnlyColumn);

Configuring Column as a Hidden Column


A column can be set as hidden so that it is not displayed on the table. However, hidden column is available in the column list and thereby can be made un-hidden. For example:
TableConfig table = new TableConfig("testTable"); ColumnConfig stateColumn = factory.newColumnConfig("state", true); stateColumn.setHidden setHidden(true); table.addComponent(stateColumn);

594

Windchill Customization Guide

Adding a Toolbar
In order to add a toolbar, the key attribute must be set to actionModel and the value attribute must be set to the name of the action model that contains the toolbar actions. For example:
TableConfig table = factory.newTableConfig(); table.setActionModel setActionModel("customToolbar");

This example uses a toolbar named customToolbar that contains pre-existing folder actions. If the table uses a new action model for the toolbar, it must be registered in the actionModels.xml file.
<model name="CustomToolbar"> <action name="list_cut" type="object"/> <action name="list_copy" type="object"/> <action name="fbpaste" type="object"/> <action name="list_delete" type="object"/> <action name="separator" type="separator"/> <action name="create" type="folder" shortcut="true" /> </model>

Configuring above action will produce an toolbar action model displayed as:

Presenting Information in the UI

595

The *actions.xml and *actionModels.xml files can be modularized with logical packaging. These files are located in <Windchill>/codebase/config/actions. There is also a custom-actions.xml and custom-actionModels.xml file available to register new actions and action models. The customToolbar action model is registered in the custom-actionModels.xml file. If the user selects few records and does a right click on the selected records, table toolbar action model shall be displayed. But note, only the actions having attributes selectRequired=true and multiSelect=true shall be displayed.

Configuring the Menubar


Menubar can be set for the table using setMenubarName() in table builder. For example:
ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); table.setMenubarName setMenubarName("customMenubar");

This example uses an action model named customMenubar. The action model must also be registered in the *action-models.xml file. Action models can be nested using the submodel tag.
<model name="customMenubar"> <submodel name="fileMenu"/> <submodel name="editMenu"/> </model> <model name="fileMenu"> <action name="list_cut" type="object"/> <action name="list_copy" type="object"/> <action name="fbpaste" type="object"/> <action name="list_delete" type="object"/> </model> <model name="editMenu"> <action name="create" type="folder"/> </model>

596

Windchill Customization Guide

In order to label each menu, the description must be set for the File and Edit submodels The action properties must be included in either the action.properties file or in a resource bundle The properties depicted below are the entries that get added to the action.properties file The entries for the File and Edit actionModels would look like:
object.fileMenu.description.value=File object.editMenu.description.value=Edit

Adding the menu bar will produce the following results:

Configuring Table Enabling a Row Selection


Making the rows selectable can be done by using setSelectable() on table config. To make the table non-selectable the value must be set to false. By default, table is selectable. For example: For setting non-selectable table.
ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); table.setSelectable(false);

Presenting Information in the UI

597

Configuring Single Select Table


We can have the single select facility to the table. This restricts the user to select only one record at a time from the table. This can be done by setting the singleSelect property on the table. A true value will present the table in a single select (radio buttons) mode whereas a false value presents it in a multi select (checkboxes) mode. For example:
ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); Table.setSingleSelect(true);

Configuring non- Pre-Selection Pre-Selection rows


Pre-Selection row depends on an existing visible column Pre-selectable rows can be set depending upon a column that has a Boolean value. The column should return a GUIComponent that has comparable value true/ false. An example:
TableConfig table = factory.newTableConfig (); //a column that is suppose to hold a boolean ColumnConfig colX = factory.newColumnConfig(<columnId>, table.setPreSelectableColumn(colX);

false);

598

Windchill Customization Guide

Configuring Pre selectable rows based on a boolean attribute value available in the backing object The com.ptc.core.components.factory.dataUtilities. DefaultBooleanValueDataUtility is out of box datautility provided for this case. This will simply return the value of the given column. There are two ways to set this data utility for a column in a table: Use PRE_SELECTABLE_COL as the column Id Create a column with an Id as com.ptc.core.components.descriptor. DescriptorConstants.ColumnIdentifiers.PRE_SELECTABLE_COLUMN (against this the dataUtility has been registered) and set the attribute as the need.. An example:
TableConfig table = factory.newTableConfig (); --------ColumnConfig col = factory.newColumnConfig (PRE_SELECTABLE_COLUMN, false); col.setNeed (<Attribute>); // Specify the attribute which will decide the row is pre-selectable or not. col.setDataStoreOnly (true);// this will make your column available on store only table.addComponent (col); table.setPreSelectableColumn (col);

Setting datautility Id to PRE_SELECTABLE_COLUMN Create a column with any Id, set the attribute as the need and set the Datautility Id as com.ptc.core.components.descriptor.DescriptorConstants.ColumnIdentifiers. PRE_SELECTABLE_COLUMN.. An example:
TableConfig table = factory.newTableConfig (); -------ColumnConfig col = factory.newColumnConfig(<columnId>, false); col.setNeed (<Attribute>); // Specify the attribute which will decide the row is selectable or not. ((JcaColumnConfig)col)setDataUtilityId (PRE_SELECTABLE_COLUMN); col.setDataStoreOnly (true); // this will make your Column hidden table.addComponent (col); table.setPreSelectableColumn (col);

Pre selectable rows based on a custom data utility Create and register a custom data utility for the column to be used as a preselectable column. Create a custom data utility Create your own DataUtility by extending com.ptc.core.components.factory. dataUtilities.AbstractBooleanValueDataUtility.

Presenting Information in the UI

599

Override getBooleanAttributeValue () method. An example:


package com.customPkg; import com.ptc.core.components.factory.dataUtilities.AbstractBooleanValueDataUtility; public class TestCustomDataUtility extends AbstractBooleanValueDataUtility { public boolean getBooleanAttributeValue(String component_id, Object datum, ModelContext mc) throws WTException { /* this method will return true if the row is pre selectable */ } }

Register the custom data utility 1. Configure the newly created data utility against the column id:
<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.customPkg.TestCustomDataUtility " requestor="java.lang.Object" selector="col1 cardinality="duplicate"/> </Service> TableConfig table = factory.newTableConfig (); -------ColumnConfig col = factory.newColumnConfig(<'''columnId'''>, false); col.setNeed (<Attribute>); // Specify the attribute which will decide the row is pre selectable or not. col.setDataStoreOnly (true); // this will make your Column hidden table.addComponent (col); table.setPreSelectableColumn (col);

2. Configure the newly created data utility against the Selector id:
<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="<DataUtility>" requestor="java.lang.Object" selector="<selectorId> cardinality="duplicate"/> </Service> TableConfig table = factory.newTableConfig (); -------ColumnConfig col = factory.newColumnConfig(<columnId>, false); col.setNeed (<Attribute>); // Specify the attribute which will decide the row is selectable or not. ((JcaColumnConfig)col) setDataUtilityId (<selectorId>); col.setDataStoreOnly (true); // this will make your Column hidden table.addComponent (col); table.setPreSelectableColumn (col);

600

Windchill Customization Guide

Additional attributes set via the setComponentProperty sub tag


getModel tag attributes getModel Creates a component model based on the supplied component descriptor and query parameters. The resulting model is assigned to a scoped variable specified by the var attribute. Its tag class is com.ptc.core.components.tags. components.GetModelTag and the body content is scriptless

Configuring a Table Adding a Help Icon


The help button will appear in the upper right corner of the table/tree if you set a help context in your builder:
// sets the help topic to use from the Windchill Help Center tableConfig.setHelpContext("HelpTopicName");

If your table/tree is still defined in a jsp instead of with a builder, adding the help topic would be as follows:
<renderTable model="${tableModel}" helpContext=" HelpTopicName"/>

On click of the ? button, a pop up window will open which will show the help topic for the table. See Linking to Help Topics on page 1013 for more information.

Specifying Datautility for Columns


Data utilities allow developers to post-process and/or augment the data returned by the low-level data acquisition API. The additional information can be returned by an additional query, a call to a service, or whatever else you can get at via Java code. To specify the data utility for a column can be done by using setDataUtilityId () in table config.
ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); ColumnConfig col = factory.newColumnConfig("iconType", true); col.setDataUtilityId setDataUtilityId("typePicker.iconType"); table.addComponent(col);

Presenting Information in the UI

601

To register the dataUtility, you need to put in *service.properties. An example entry is:
<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.ptc.windchill.enterprise.picker.type. dataUtilities.IconTypeDataUtility" requestor="java.lang.Object" selector="typePicker.iconType" cardinality="duplicate"/> </Service>

Configuring Table Columns as Hyperlinks


Adding hyperlink to the table data. We can specify the link to the particular columns in the table. When the user clicks on that link, the new page (Infopage) will open up. This can be done by setting setInfoPageLink() to true in table builder. For example:
ComponentConfigFactory factory = getComponentConfigFactory(); TableConfig table = factory.newTableConfig(); ColumnConfig col = factory.newColumnConfig("name", true); col.setInfoPageLink setInfoPageLink(true); table.addComponent(col);

This result in the name column displayed as hyperlink.

602

Windchill Customization Guide

Configuring a Table Creating a Customized View


If the table is to be configured to have customized views, table builder should implement interface ConfigurableTableBuilder. The interface, ConfigurableTableBuilder has only method:
ConfigurableTable buildConfigurableTable(String id) throws WTException;

The method should return an instance of a class implementing interface ConfigurableTable. Default JCA implementation is provided by class JCAConfigurableTable. Table views intended for JCA are required to extend the com.ptc.core.htmlcomp. components.JCAConfigurableTable class. As in 9.x versions, no mapping in service.properties.xconf to this class is required. When implementing getOOTBTableViews and defining OOTB views, it is important to use the correct column ids. Column ids for common attributes are defined in com.ptc.core.components.descriptor.DescriptorConstants. ColumnIdentifiers. If the column is not found here, then it is best to use the available attribute report for the types contained in the table. Available Attributes report link is available under Customization tab inside Tools link. If more than one table view was implemented, then the current view displayed would be either the first view on the list (alphabetically) or the table view set in the getOOTBActiveViewName method. Selecting Customize from the current view list launches a pop-up displaying the configurable table views. From there, additional table views can be added and removed using the toolbar actions. For each view in that list, there is an action to set that view as active. By using this action, any view can be set as the default. An example:
public class MyTableBuilder extends AbstractConfigurableTableBuilder { @Override public ConfigurableTable buildConfigurableTable(String tableId) throws WTException { return new MyConfigurableTable(); } /* an internal static class */ private static class MyConfigurableTable extends JCAConfigurableTable { } }

Presenting Information in the UI

603

Setting Table Size Limits


The maximum number of rows that can be fetched in a table on a client can be set using the table size limit preference.

If the table has more data than the table size set in the preference, next/ previous links are displayed at the footer to navigate through the data:

604

Windchill Customization Guide

Using Tables in Wizards


Saving Form Data The table component can be used to edit data. Since the table is using a buffered view and not all objects are kept in the DOM at all times there can be some special handling needed to ensure the data is getting saved as desired. The data for the table is all saved behind the scenes in the tables datastore. When the user updates a field there is default handling in place that saves the updates to this store. In some cases this default handling may not work. Additionally when a wizard is submitted any hidden rows in a table are rendered to ensure that all data is available in the form as it has always been. Customizing Saved Data at the Column Level If you have written a custom edit component for a column and its updated value is not getting saved properly by the default processing code you can write your own custom handling. To do this, in the javascript rendering for your component you will add an onChange listener which will know how to get the data and save it to the store.

Presenting Information in the UI

605

Customizing Saved Data at the Table Level The table component can be overridden and extended to get custom data saving behavior for the entire table. The table component supports custom xtypes. To define custom logic to save table data you should create your table with a custom xtype and override the method submitAllTableData
//First create a custom type. MyCompany.CustomGrid = function(rowConfig) { MyCompany.CustomGrid .superclass.constructor.call(this, config); // add other logic init logic }; //Extend the table component. Ext.extend(MyCompany.CustomGrid, PTC.jca.TableGrid); //Register the xtype Ext.ComponentMgr.registerType('mycustomgrid', MyCompany.CustomGrid);

Wizard Table Limitations Due to browser security restrictions, browser file input fields cannot be saved to the tables datastore and re-rendered with a value. This means that any values entered into browser file input fields will be lost when doing operations that refresh the grid from the store (drag and drop, locking, scrolling in a buffered table, etc.). Because of these limitations, it is recommended that you do not place a file input field inside an editable table. If you must include a file input field in your editable table, you should configure it to disable the grid features that cause the values to be lost. The following grid features will be disabled: Drag and drop of columns Column locking Row buffering for performance improvements of large tables Find in table View selected objects only Performance improvements for mass removal of rows in the table.

It will only disable grid features if the File Upload preference is set to use the default browser file input. To do this, add the following tag to your wizard JSP:
<jca:setTablePlugin ptype=gridfileinputhandler/>

606

Windchill Customization Guide

The Attributes table in the Create Multiple Documents wizard, and the Attachments table in the Attachments wizard step found in many wizards (new Document, new Change Request, for example) have been configured to turn off grid features because they contain a file input field in an editable table.

Limitations
None.

Other Resources
Related Customization Documentation Adding Actions and Hooking Them Up in the UI on page 485 Customizing the UI with Ajax on page 312 MVC Components on page 251 Windchill Client Architecture Action Framework Overview on page 486 User Interface Stickiness on page 539

Related Package/Class Package/Class Javadoc com.ptc.core.htmlcomp.components.AbstractConfigurableTableBuilder com.ptc.core.htmlcomp.components.JCAConfigurableTable com.ptc.jca.mvc.components.JcaTableConfig com.ptc.jca.mvc.components.JcaColumnConfig com.ptc.mvc.components.ColumnConfig; com.ptc.mvc.components.ComponentConfig; com.ptc.mvc.components.TableConfig; com.ptc.mvc.components.AbstractComponentConfigBuilder com.ptc.mvc.components.AbstractComponentBuilder com.ptc.mvc.components.ComponentConfigFactory com.ptc.mvc.components.AbstractComponentDataBuilder com.ptc.mvc.util.ClientMessageSource

Related Websites The Spring Framework: http://www.springframework.org

Presenting Information in the UI

607

Sample Code
Examples of Usage in Windchill Code Product > Folders table Product > Templates table Recent Updates table on Home page. Organization > Profiles table.

Example Table with DataSources Enabled


This is an example of MVC table implementation that uses synchronous datasource mode. The table is enabled with configurable views. Location of the Example To navigate to this example navigate to Customization Component Catalog Table Table with DataSources Enabled ( in the example section). Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table\DataSourceSyncTableBuilder.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Example Table (Separate Builders)


This is an example of MVC table implementation that uses a separate config builder and data builder classes for configuration.

608

Windchill Customization Guide

Location of the Example To navigate to this example navigate to Customization Component Catalog Table Table (Separate Builders) ( in the example section). Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table\MvcTableConfigBuilder.java com\ptc\mvc\builders\carambola\table\ MvcTableDataBuilder.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Example Table (Info*Engine)


This is an example of MVC table implementation that use Info*Engine tasks as the source of data. Location of the Example To navigate to this example navigate to Customization Component Catalog Table Table(Info*Engine) ( in the example section). Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

Presenting Information in the UI

609

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table \DataSourceSyncTableBuilderWithIETask.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Example Table With DataSources Enabled


This is an example of MVC table implementation that uses asynchronous datasource mode. The table is enabled with configurable views. Location of the Example To navigate to this example navigate to Customization Component Catalog Table Table or Table - Async ( in the example section). Select Table for table that uses default OOTB result processor. Select Table - Async for table that uses a custom result processor.

Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table\MvcTableBuilder.java com\ptc\mvc\builders\carambola\table\DataSourceASyncTableBuilder.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

610

Windchill Customization Guide

Example Table(Info*Engine) Table(Info*Engine)


This is an example of MVC table implementation that use Info*Engine tasks as the source of data. This is a synchronous data source example. Location of the Example To navigate to this example go to Customization Component Catalog Table , and in the example section, select Table(Info*Engine). Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table \DataSourceSyncTableBuilderWithIETask.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Example Table Async


This is an example of MVC table implementation that uses asynchronous datasource mode. The table is enabled with configurable views. Location of the Example To navigate to this example go to Customization Component Catalog Table in the example section, select: Table for table that uses default OOTB result processor. Table - Async for table that uses a custom result processor.

Presenting Information in the UI

611

Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table\MvcTableBuilder.java com\ptc\mvc\builders\carambola\table\DataSourceASyncTableBuilder.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Example Table (Info*Engine) Async


This is an example of MVC table implementation that use Info*Engine tasks as the source of data. Location of the Example To navigate to this example navigate to Customization Component Catalog Table Table (Info*Engine) or Table (Info*Engine) - Async ( in the example section). Select Table (Info*Engine) for table using asynchronous data source mode. Select Table (Info*Engine) - Async for table using asynchronous data source mode with configurable views.

Actions for this Example sortByState reloadTable strikeThroughRows clearStrikeThrough CustEx_exportlisttofile_submenu

612

Windchill Customization Guide

Action Models for this Example mvc_tables_toolbar

Files Used in This Example com\ptc\mvc\builders\carambola\table \DataSourceASyncTableBuilderWithIETask.java com\ptc\mvc\builders\carambola\table\MvcTableBuilderWithIETask.java com\ptc\mvc\builders\carambola\table\AbstractCarambolaTableConfigBuilder. java WEB-INF\jsp\carambola\carambolaMVCExampleTable.jsp

Presenting Information in the UI

613

Windchill Client Architecture Tree


Objective
You want to implement a Windchill Client Architecture Tree for the display of Windchill business objects.

Background
A tree view is used to display hierarchical data organized in the form of a tree. In other words, a Tree is a visualization of a hierarchy. In a tree structure, there are parent and child nodes. The hierarchy level is shown by indentation on the left side of the Tree nodes. Implementing a Windchill Client Architecture tree is the same as implementing a Windchill Client Architecture table. In tree, as opposed to specifying a service method or QuerySpec, a TreeHandler is specified to populate the content. Following are the few key salient features of a Windchill Client Architecture Tree with respect to a Windchill Client Architecture Table Expand/Collapse Behavior The expand/collapse functionality is used to traverse the hierarchy of the tree. Your expansion of the tree will be sticky within a session and will return to the default between sessions. You can expand or collapse a tree in two ways: By using the Expand and Collapse actions in the menu or toolbar. Expand action enlarged to show detail

614

Windchill Customization Guide

Collapse action enlarged to show detail

If used in combination with the selection radio button/checkboxes, the selected nodes will only be expanded to the last level. If you try to expand or collapse without checking any nodes, then all the nodes will be expanded to the last level. By using the Expand/Collapse icons: Expand icon enlarged to show detail

Collapse icon enlarged to show detail

The expand icon will populate its next level children, where as the Collapse icon merely changes the node from an open to a closed state. Scrolling Behavior You will loose your sense of the structure if the tree is divided among pages and hence paging is inappropriate for trees. If there is large data to be presented, the tree can be made to scroll with column header remaining static. Expand/Collapse Behavior When Data Size in Tree is More Than Result Limit The tree component respects the result limit set for table component. But it doesnt provide next previous links, since user loose sense of structure if parent nodes are removed. When result limit is reached user is provided with the option to load all data or stop loading. If user wish to load data above result limit, based on the expansion state of tree all possible nodes are displayed. If user cancels loading of all data, number of nodes equal to result limit value are displayed.

Presenting Information in the UI

615

Sorting Behavior Columns in a tree will sort similarly to tables with the following exception: as the structure of the tree must remain intact the sorting will occur level-by-level. For example, in a folder tree when sorting alphabetically by name, first level folders are sorted as a group, then objects in individual folders are sort as a group, and so on.

616

Windchill Customization Guide

Intended Outcome

Solution
Use Windchill Client Architecture Tree to display Windchill business objects in Tree format.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: The actions framework in the Windchill client architecture. JCA Table component Data acquisitions, Data Utility, GUI component. JSP, JavaScript and Custom taglibs. Java annotations

Presenting Information in the UI

617

Solution Elements
Element <your_ConfigBuilder> <your_DataBuilder> Type java java Description TreeConfiguration is defined here Data fetching service/ commands are defined here View rendering logic is defined here DataUtilities and services are defined here. Action attributes defined here. Actions can be defined here. Action models can be defined here.

<your_view_page>.jsp

jsp

<your>service.properties. xconf xconf <your>action.rbInfo rbInfo <your>actions.xml xml

<your>actionModels.xml xml

Implementing Tree Component using Asynchronous DataSource To implement a tree component using Asynchronous DataSource, TreeDataBuilderAsync interface needs to be implemented. It has a single method to be implemented by the concrete class:
void buildNodeData(Object node, ComponentResultProcessor resultProcessor) throws Exception

It Fetches children for each node.The first call to this method from infrastructure will always pass first argument as TreeNode.RootNode.This first call ensures that all rootNodes are fetched for subsequent calls. The subsequent calls will always pass a treeNode for which child nodes are required to be fetched. E.g. The code should handle this case similar to following code snippet:
List nodes; if (node == TreeNode.RootNode){ nodes = getRootNodes(); resultProcessor.addElements(nodes); }else { getNodes(node); nodes = resultProcessor.addElements(nodes); }

618

Windchill Customization Guide

Implementing Tree Component without using DataSources To implement Tree component without DataSources, TreeHandler interface needs to be implemented. TreeHandlerAdapter provides default implementation. TreeHandler is a JAVA interface ,which is responsible for populating the tree content.Following methods are provided by TreeHandler : ModelContext getModelContext() :- Get the handler's model context void setModelContext(ModelContext mc) throws WTException :- Sets the contextual information about the tree that is being built, like the descriptor, command bean etc. This should be initialized before data is requested from the handler. List getRootNodes() throws WTException :- Get the list of root nodes for the tree. Map<Object,List> getNodes(List parents) throws WTException :- Get a mapping of the child nodes for each of the parent nodes in the given list This is the only method that will be called for the expand action, so this method must be able to initialize the handler properly so that it can answer the question of what are the children of the parent. boolean isExpandNeeded(Object node, int level) throws WTException :Determines whether or not the given node needs to be expanded. The default implementation looks at the session state of the list of nodes already expanded or configured by the tag. boolean hasChildren(Object node) throws WTException :- Determines whether or not the given node should show the expand norgie if its collapsed. Override this method to improve performance or to get custom behavior. The default implementation calls the getNodes and sees if the size is larger than 0. void addExpandedNode(Object node) throws WTException :- Add a node to the expanded node list. This list is returned and used in session state to remember what the tree expansion is.

Trees need to be carefully created because of their recursive nature that causes many queries to the database. The Treehandler class can save tree state information as private attributes on the class and reused for each getNodes call. In addition, you can take advantage of knowing which tree rows are expanded by the user with the isExpandNeeded method. TreeHandlerAdapter is an abstract class which implements TreeHandler which you can extent. Following is an example getRootNodes() determine what the root nodes should be. The TreeHandler has access to the ModelContext, which can be used to access required information.
public List getRootNodes() getRootNodes throws WTException {

Presenting Information in the UI

619

NmCommandBean cb = getModelContext().getNmCommandBean(); WTPart part; NmOid oid = cb.getPageOid(); if (oid == null) { log.debug("No oid found in request, trying GOLF_CART"); part = getGolfCart(); }else { if (!oid.isA(WTPart.class)) { throw new ClassCastException("Expected part, but was: " + oid); } part = (WTPart)oid.getRef(); } if (part == null) { log.debug("Couldn't get part"); return null; } configSpec = ConfigHelper.service.getConfigSpecFor(part); return Collections.singletonList(part); }

The method first retrieves the NmCommandBean from the model context and extracts the primary oid from it. If no oid was requested from the user, then it uses the GOLF_CART part instead by calling the getGolfCart method. The getGolfCart method simply queries and returns the GOLF_CART. If the user did specify an oid in the request parameter, it checks to make sure the oid is a WTPart. Otherwise, it throws a ClassCastException. If its the expected oid, it continues by retrieving the part from the oid via the getRef method. This method inflates the referenced object, which then can be cast into a WTPart. The last thing it checks is if the part retrieved either from the oid or the GOLF_CART is null and if so return null. The configSpec variable is assigned the ConfigSpec of the part using the ConfigHelper class. This helper class contains a service that helps obtain Iterated objects from Mastered objects. Lastly, an immutable List containing the part is returned. getNodes(List parents) Get a mapping of the child nodes for each of the parent nodes in the given list. It can be called directly without calling the getRootNodes() method first. E.g. (expand action). This means that this method must be able to initialize the handler properly so that it can answer the question of what are the children of the parent. The given example, generates a hierarchy of WTPart based on the WTPartUsageLinks.
public Map<Object,List> getNodes(List getNodes parents) throws WTException { if (configSpec == null) { configSpec = getDefaultConfigSpec(); } Map<Object,List> result = new HashMap<Object,List>(); //API returns a 3D array where the 1st dim is the parent parts, //the 2nd dim is the list of children for a given parent,

620

Windchill Customization Guide

//and the 3rd dim is 2 element array w/the link obj at 0 and the child part at 1 Persistable[][][] all_children = WTPartHelper.service.getUsesWTParts( new WTArrayList(parents), configSpec); for (ListIterator i = parents.listIterator(); i.hasNext();) { WTPart parent = (WTPart)i.next(); Persistable[][] branch = all_children[i.previousIndex()]; if (branch == null) { continue; } List children = new ArrayList(branch.length); result.put(parent,children); for (Persistable[] child : branch) { children.add(child[1]); } } log.debug("ParentsToChildren: " + result); return result; } private ConfigSpec getDefaultConfigSpec() throws WTException { return ConfigHelper.service.getDefaultConfigSpecFor(WTPart.class); }

Custom tree handlers need to be registered. Please refer Refererence to <DataUtilities Document> for information on how to register services. Following is a sample tree handler entry.
<Service context="default" name="com.ptc.core.components.beans.TreeHandler"> <Option requestor="your_object your_object" selector="your_treeHandler your_treeHandler" serviceClass="your_treeHandler_class your_treeHandler_class" cardinality="duplicate"/> </Service>

If you want to show non-persistables in a Tree, you are recommended to return Element for getRootNodes & getNodes methods. If your element doesnt have a valid ufid value available or obid attribute, you need to provide NmObject for each row object. This can be done in two ways. 1. Author a DataUtility which extends DefaultNmObjectUtility and override its getTargetObject() method which will return a NmObject for the row object. Please refer to NmObject Utilities on page 562 for more information. 2. Your Element will have an attribute named "nmObject" with its value an instanceof NmObject Otherwise, to show non-persistables, you can write a wrapper class extending from NmObject and override getOid() method to return proper NmOid.

Presenting Information in the UI

621

Procedure Configuring JCA Tree


Implementing ComponentConfigBuiler and ComponentDataBuilder Defining View

Implementing ComponentConfigBuiler and ComponentDataBuilder There are two approaches: Separate builder approach Single builder approach

Separate Builder Approach In this case separate classes are written for ComponentConfigBuiler and ComponentDataBuilder Using Asynchronous DataSource Implementing ComponentConfigBuilder Example:
@ComponentBuilder(value = "custom.treeExample.seperate", type = ComponentBuilderType.CONFIG_ONLY) public class TreeExampleConfigBuilder extends AbstractComponentConfigBuilder { private static final String RESOURCE = "com.ptc.carambola.carambolaResource"; @Override public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { ComponentConfigFactory factory = getComponentConfigFactory(); //Create TreeConfig TreeConfig tree = factory.newTreeConfig(); // Need to set DataSOurceModes explicitely to DataSourceMode.ASYNCHRONOUS ((JcaTreeConfig) tree).setDataSourceMode(DataSourceMode.ASYNCHRONOUS); // Set expansion level . Default is TableTreeProperties.ONE_EXPAND (expand by one level) ((JcaTreeConfig) tree).setExpansionLevel(TableTreeProperties.FULL_EXPAND); tree.setLabel((new ResourceBundleClientMessageSource(RESOURCE)).getMessage ("PART_TREE_LABEL"));

//Add Columns to the config tree.addComponent(factory.newColumnConfig(NAME, true)); tree.addComponent(factory.newColumnConfig(NUMBER, true)); //Set column to which expand/collapse norgie should appear tree.setNodeColumn(NUMBER); return tree; }

622

Windchill Customization Guide

Important Points: 1. To use Asynchronous DataSource DataSource mode should be explicitely set to DataSourceMode.ASYNCHRONOUS. 2. setNodeColumn method, allows to choose the column for which expand/ collapse norgie is required. Default is name column. Implementing ComponentDataBuilder The concrete class should implement interface com.ptc.mvc.components. TreeDataBuilderAsync. Please check Java API documentation for more details. Example:
@ComponentBuilder(value = "custom.treeExample.seperate", type = ComponentBuilderType.DATA_ONLY) public class TreeExampleComponentDataBuilder implements TreeDataBuilderAsync { @Override public void buildNodeData(Object node, ComponentResultProcessor resultProcessor) throws Exception { if (node == TreeNode.RootNode) { List<Object> objects = getRootNodes(); resultProcessor.addElements(objects); } else { List nodeList = new ArrayList(); nodeList.add(node); Map<Object, List> map = getNodes(nodeList); Set keySet = map.keySet(); for (Object key : keySet) { resultProcessor.addElements(map.get(key)); } } } private List<Object> getRootNodes(){ // Add code to find RootNodes} private List<Object> getNodes(List<Object> nodeList){ // Add code to find ChildNodes} }

Advanced Configurations by implementing TreeExpansionStateManager TreeExpansionStateManager provides following APIs


boolean isExpandNeeded(DefaultMutableTreeNode node, ComponentConfig config, ComponentParams params) throws WTException; void addExpandedNode(Object node, ComponentConfig config, ComponentParams params) throws WTException;

Set getExpandedOids(ComponentConfig config, ComponentParams params) throws WTException; boolean hasChildren(Object node, ComponentResultProcessor resultProcessor,

Presenting Information in the UI

623

TreeDataBuilderAsync builder)

throws Exception;

List<DefaultMutableTreeNode> getDynamicExpandedNodes(ComponentConfig config, ComponentParams params) throws WTException;

Please refer to JavaDoc for details. Concrete implmenetation of TreeExpansionStateManager is provided by DefaultTreeExpansionStateManager. This implementation can be extended to customize the APIs as per requirement or TreeExpansionStateManager can be implemented directly. The concrete implementation can be injected into the builder by using ExpansionStateManager annotation. Example:
@ComponentBuilder ("folderbrowser_tree") @ExpansionStateManager (FolderTreeExpansionStateHandler.class class) // public class FolderTreeBuilder extends AbstractComponentConfigBuilder implements TreeDataBuilderAsync{}

Here FolderTreeExpansionStateHandler implements DefaultTreeExpansionStateManager and is injected into the FolderTreebuilder These APIs are useful for customizing the tree expansion state behavior. E.g. IsExpandNeeded API can be used to override the default logic which decides whether the node should be expanded. Without using DataSource In this case the either setDataSourceMethod should not be called or should set dataSourceMode to DataSourceMode.SYNCHRONOUS. All other configurations are same as explained in the Implementing ComponentConfigBuilder section. Implementing ComponentConfigBuilder Implementing ComponentDataBuilder In this case the databuilder should implement ComponentDataBuilder interface. Example:
@ComponentBuilder(value = "custom.treeExample.seperate", type = ComponentBuilderType.DATA_ONLY) public class TreeExampleComponentDataBuilder implements ComponentDataBuilder { @Override public TreeHandler buildComponentData(ComponentConfig config, ComponentParams params) throws WTException { return new customTreeHandler();// customTreeHandler should implement TreeHandler or extend TreeHandlerAdapter } }

624

Windchill Customization Guide

Single Builder Approach In this case both ComponentConfigBuilder and ComponentDataBuilder are implemented by a single class. Using Asynchronous DataSource Example:
@ComponentBuilder(value = "custom.treeExample") public class TreeExampleBuilder implements TreeDataBuilderAsync, ComponentConfigBuilder,ComponentConfigFactoryAware {....}

Without Using DataSource Example:


@ComponentBuilder(value = "custom.treeExample") public class TreeExampleComponentDataBuilder extends AbstractConfigurableTableBuilder{.}

Defining View setView method on componentConfig enables setting of view for a particular builder The view should be set relative to /WEB-INF/jsp folder. The default view points to uses WEB-INF/jsp/components/tree.jsp The default view can be customized using the custom tag definitions provided in file %WT_HOME%\codebase\WEB-INF\tlds\jcaMvc.tld

Presenting Information in the UI

625

Customization Points
Class Diagram

Customization points for JcaTreeConfig


The following table depicts the customization points available using TreeConfig APIs. Property setting API Description setExpansionLevel Set the the initial expansion level of the tree. setNodeColumn Set the name of the column that will be used to display node labels. setShowTreeLines Set whether tree lines will be displayed to show structure in the tree setDisableAction If set to true, will not show the expand/ collapse norgie in the tree

JcatTableConfig provides an API setFindInTableMode. This API can be used for tree to enable/disable findInTree functionality.

626

Windchill Customization Guide

Configuring Tree Defining Node Column


The id of the column that you want to display node labels (or +/- norgie) should be passed to setNodeColumn method In buildcomponentCOnfig method, builder should call this setter method on TreeConfig Example:
TreeConfig tree = factory.newTreeConfig(); tree.addComponent(factory.newColumnConfig(NAME, true)); tree.addComponent(factory.newColumnConfig(NUMBER, true)); tree.setNodeColumn(NUMBER);

Configuring Tree Control Level of Expansion


When the Tree is populated and presented for the first time, you can control the level to which its expanded. It can be done by one of the following expansion level using setExpansionLevel If the expansion value is none, it will be expanded until root level. For a value of one, it will expand until I level and for a value of full, you get a fully expanded tree.

Example:
TreeConfig tree = factory.newTreeConfig(); treeConfig. setExpansionLevel (TableTreeProperties.FULL_EXPAND);

Configuring Tree Hide Expand/Collapse Expand/Collapse Norgie


Expand/collapse norgie presentation is controlled by setDisableAction method. You can set string value for this attribute. true value will present the expand/ collapse norgie whereas false value will hide them.
TreeConfig tree = factory.newTreeConfig(); treeConfig. setDisableAction(false) //hides the expand/collapse Norgie

Presenting Information in the UI

627

Configuring Tree Enable Tree Lines


You can show tree lines to display the structure in the tree by using calling setShowTreeLines method as following:
TreeConfig tree = factory.newTreeConfig(); treeConfig. setshowTreeLines (false);

Spring MVC Implemented Tree


Migrating JCA tree customization to the MVC implementation customization For customizing JCA trees, various attributes on the tags are specified. All attributes supported on JCA tree tags are supported on the MVC beans. Each JCA tree is represented by interface TableDefinition. The class implementing the TableDefinition would implement methods that can be used to populate the configurable attributes on the beans. So the attributes which were previously configured for the tags should now be populated on corresponding beans mentioned above. For detailed information on defining the TableDefinition refer to Constructing and Rendering a Table Using the JSP Framework on page 579.
Windchill Customization Guide

628

Sample Code
Examples of Usage in Windchill Code Folder Browser table Type Picker Team Tree on Home-> Team Preference Manager Tree Tree Examples under Customization Tab

Presenting Information in the UI

629

Attribute Customization
You want to customize the display of an attribute of a Windchill object. Background Windchill attempts to provide consistent attribute behavior across all client applications. The Windchill Client Infrastructure provides support for rendering attributes of the standard Windchill supported data types (see Windchill Attribute Types on page 633 for more information). This infrastructure includes standard data acquisition, rendering and form processing mechanisms and, re-usable components for rendering the UI elements for attributes. These components honor the meta-data from attribute definition, the configurations defined for that attribute, and the persisted value(s) of the attribute, if any. Windchill provides multiple configurations points for customizing an attributes display and behavior. The Type and Attribute Management utility is the recommended configuration tool. For certain cases, other configuration points may need to be used, such as: Java source files of modeled Windchill classes. See GeneratedProperty in Modeling Columns on page 1300 for more information. Object Initialization Rules Administration. See About Object Initialization Rules for more information. Preference management. See About the Preference Management Utility for more information. Profile administration. See Profiles as a Visibility Control Mechanism for more information. Constraints Properties that can be set on attributes in the Type and Attribute Management utility Default values for attributes Behavior built into the infrastructure to comply with Windchill UI standards DB configurations Attribute validators (see UI Validation on page 718 for more information)

The most common configurations include:

Some of the other factors that implicitly affect the behavior of attributes include:

The framework also provides extension points for customization via the ability to override the standard rendering and data acquisition behavior. See Data Utilities on page 669 for more information.

630

Windchill Customization Guide

Scope of an attribute configuration Windchill offers multiple configuration points for the same configuration as a mechanism to control the scope of the configuration. In general, there are 3 possible scopes for a configuration. Configurations that apply to all attributes of all object types on all screens. This is normally set in the Preference Management Utility. Configurations that apply to a single attribute of a single type on all screens. Attribute Definitions are set in the Type and Attribute Management Utility. Configurations that apply to a single attribute of a single type in a specific UI only. Attribute Layouts are set in the Type and Attribute Management Utility or when defining the component configuration using a java builder.

For certain configurations, more than one configuration point with the same scope is available in order to support backward compatibility. The mechanism used to resolve the values of a configuration set using multiple configuration points varies with each configuration and is detailed in Customization of Common Windchill Business Attributes on page 662. For rules pertaining to overriding attribute constraints, please see administration of Constraints in the Type and Attribute Management utility. Terminology Definition of some commonly used terms Term Attribute Panel Client / Screen Info Page Primary attributes Definition The UI for displaying attributes as name-value pairs according to the Attribute Layout definition. The end user UI in which the attributes will be displayed. Example: Create Wizard Attributes Step.

The attributes panel in the information page that is primarily used for displaying a small set of the attributes. This is normally displayed at the top of the info page. Info Page Full attributes The attribute panel that is primarily used for displaying list a larger set of attributes on an information page. GUI component / UI component Attribute Properties The UI widget (or a composite of UI widgets) displayed on the screen for the user to enter a value for an attribute or to display the value of an attribute. Properties that can be set on attributes either in the Type and Attribute Management utility or using other configuration points to customize the display and data

Presenting Information in the UI

631

Term

Definition acquisition for an attribute.

Windchill Attribute Customization Overview


There are three steps to getting an attribute rendered in the UI. 1. Placing the attribute in the UI 2. Configuring the UI widget for the attribute (optional) 3. Customizing the source of data (optional) Out of these, steps 1 & 2 are the most commonly needed steps. This document primarily deals with these two areas. Placing the attribute in the UI The standard attribute containers supported by Windchill include: Attribute panel. See Attribute Panels on page 365 for more information. Attribute table. See Attribute Tables on page 702 for more information.

Attributes can also be displayed on the UI outside these containers. Configuring the UI widget for the attribute OOTB Windchill automatically determines the UI components to be used for a certain attribute based on the following: Windchill UI standards The data type of attribute The constraints and other configurations defined on the attribute

The Windchill configuration points allow you to alter some of the rendering properties of the widget For some very limited cases, it is possible to specify an alternate widget using a configuration. For all other cases, mapping an alternate widget to an attribute would require writing a custom data utility. See Creating the Data Utility Class on page 669 for more information. Customizing the source of data The source of the data for a given attribute on a given UI can be altered by configuring some of the data acquisition properties, but this should be used only for some very special customization requirements.

632

Windchill Customization Guide

Windchill Attribute Types


Windchill supports five types of attributes: 1. Modeled (see Modeling Columns for more information) 2. Global (see Creating a New Attribute for more information) 3. Standard (see Creating a New Attribute for more information) 4. Alias (see Creating a New Attribute for more information) 5. Calculated (see Creating a New Attribute for more information) Calculated attributes and Alias attributes Calculated attributes and Alias attributes are derived from the values of other attributes. So these attributes should not be used on Create or Edit clients. They can be used on UIs that display persisted values of attributes. For more information on defining these attributes, see Creating a New Attribute.

Windchill Attribute Configurations


Attributes of Windchill objects are rendered in one of the two modes, commonly known as the input mode and the view mode. The input mode is used for allowing the user to set/edit the value of an attribute. The view mode is used for displaying the value of an attribute in an un-editable mode. The following sections identify the default implementation of each of the pieces involved in displaying the input field and/or value field for each data type. String Default behavior and available configurations Input Rendered as: View Rendered as:

UI Configurations: Required Input on page 639 Default Values on page 641 Validating Input Values and Legal Value Lists on page 646

UI Configurations: Visibility (see Visibility and Modifiability on page 643) Multiple Values (Global IBAs Only) on page 654

Presenting Information in the UI

633

Input View Visibility and Modifiability on page Defining Custom Labels on page 643 656 Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656 Controlling the Size of Input Fields for String Attributes on page 653 Create Hyperlinks (see Configuration Points on page 673) Making a String Value All Upper Case or All Lower Case on page 655

Limiting the Length of Values Entered for a String Attribute on page 651 Data Acquisitions Configurations:

Data Acquisitions Configurations: Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information)

Date and Time Date & Time attributes are used to store a date only value (yyyy-mm-dd) or a date and time value (yyyy-mm-dd hh:mm). Default behavior and available configurations Input Rendered as: View Rendered as:

UI Configurations: Required Input on page 639 Default Values on page 641 Validating Input Values and Legal Value Lists on page 646)

UI Configurations: Visibility (see Visibility and Modifiability on page 643) Multiple Values (Global IBAs Only) on page 654) Defining Custom Labels on page 656

Visibility and Modifiability on page 643

634

Windchill Customization Guide

Input

View Date Display Format (see Configuration Points on page 673) Local Time Zone (see Configuration Points on page 673)

Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656 Date Input Field Type (see Configuration Points on page 673)

Local Time Zone (see Configuration Points on page 673) Data Acquisitions Configurations: Data Acquisitions Configurations: Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information) Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Integer Numbers Default behavior and available configurations Input Rendered as: View Rendered as:

Configurations: Required Input on page 639 Default Values on page 641 Validating Input Values and Legal Value Lists on page 646

Configurations: Visibility (see Visibility and Modifiability on page 643) Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656 Percent (see Configuration Points on page 673) Currency (see Configuration Points on page 673)

Visibility and Modifiability on page 643 Multiple Values (Global IBAs Only) on page 654

Defining Custom Labels on page 656 Data Acquisitions Configurations:

Data Acquisitions Configurations:

Presenting Information in the UI

635

Input

View Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information)

Real Numbers A Real Number is stored as a decimal representation (e.g. 1.23). Default behavior and available configurations Input Rendered as: View Rendered as:

Configurations: Required Input on page 639 Default Values on page 641 ) on page 646

Configurations: Visibility (see Visibility and Modifiability on page 643) Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656 Percent (see Configuration Points on page 673)

Visibility and Modifiability on page 643 Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656

Data Acquisitions Configurations:

Currency (see Configuration Points on page 673) Data Acquisitions Configurations: Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information)

Real Numbers with Units Default behavior and available configurations

636

Windchill Customization Guide

Input Rendered as:

View Rendered as:

Configurations: Required Input on page 639) Default Values on page 641 ) on page 646

Configurations: Visibility (see Visibility and Modifiability on page 643) Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656 Percent (see Configuration Points on page 673) Currency (see Configuration Points on page 673)

Visibility and Modifiability on page 643 Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656

Measurement System (see Configu ration Points on page 673)

Data Acquisitions Configurations:

Measurement System (see Configuration Points on page 673) Data Acquisitions Configurations: Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information)

Boolean Default behavior and available configurations Input Rendered as: View Rendered as:

Configurations: Required Input on page 639 Default Values on page 641

Configurations: Visibility (see Visibility and Modifiability on page 643) Defining Custom Labels on page
637

Presenting Information in the UI

Input View 656 Visibility and Modifiability on page 643 Defining Custom Labels on page 656 Data Acquisitions Configurations:

Data Acquisitions Configurations: Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information)

Hyperlink (a.k. (a.k.a. a. URL in the Global Attributes Manager) Hyperlink attributes are used to create a link to a system outside of Windchill. The value of this attribute should be a fully qualified URL.

Example:
Valid value: http://www.ptc.com or www.ptc.com Invalid value: ptc.com Default behavior and available configurations Input Rendered as: View Rendered as:

Configurations: Required Input on page 639) Default Values on page 641 ) on page 646

Configurations: Visibility (see Visibility and Modifiability on page 643) Multiple Values (Global IBAs Only) on page 654 Defining Custom Labels on page 656

Visibility and Modifiability on page 643 Multiple Values (Global IBAs Only) on page 654

Defining Custom Labels on page 656 Data Acquisitions Configurations:

Data Acquisitions Configurations:

638

Windchill Customization Guide

Input

View Configuring the source of data (Customizing Data Acquisition on page 658 for more information) Configuring the data utility (see Data Utilities on page 669 for more information)

Configuring the source of data (Cus- tomizing Data Acquisition on page 658 for more information) Configuring the data utility (see Da- ta Utilities on page 669 for more information)

Object Reference Attributes Limited client infrastructure support is available for Object Reference attributes. Display of object reference type attributes is supported out-of-the-box. Support for input/editing of object reference type attributes is limited to very specific attributes and specific usages only, and is not generally meant for reuse or customization.

Common Attribute Customization Procedures


The following attribute customizations are available: Required Input on page 639 Default Values on page 641 Visibility and Modifiability on page 643 Validating Input Values and Legal Value Lists on page 646 Limiting the Length of Values Entered for a String Attribute on page 651 Controlling the Size of Input Fields for String Attributes on page 653 Multiple Values (Global IBAs Only) on page 654 Making a String Value All Upper Case or All Lower Case on page 655 Automatically Creating Hyperlinks on page 655 Defining Custom Labels on page 656 Customizing Data Acquisition on page 658 Providing Alternate UI Behavior on page 659

Required Input You want to make it compulsory that a value is provided for an attribute. Solution Elements Element Required Constraint
Presenting Information in the UI

Description This configuration will be applied to an

639

Element

Description attribute on all the UIs in which the attribute is displayed. This rule is enforced both in the UI and during persistence in the DB. For exceptions see the javadoc for com.ptc.windchill.annotations.metadata. PropertyConstraints. The constraint can be set using one the following configuration points: For modeled attributes: Required PropertyConstraint annotation (seeModeling Business Objects on page 101 for more information) Required Constraint in the Type and Attribute Management utility (see Constraints Tab for more information)

For global attributes & standard attributes: Required Constraint in the Type and Attribute Management utility (see Constraints Tab for more information) The property Input Required can be set on a modeled, global or standard attribute. Scope: This configuration is applied to this attribute only on the specific attribute panel for which the property is set. This setting is purely a UI only rule and is not enforced during persistence in the DB. The Input Required property cannot be used to disable mandatory input on an attribute that already has a Required constraint.

Input required Property

640

Windchill Customization Guide

Intended Outcome When the attribute is displayed as a Name-Value pair like in an Attribute Panel, the attribute will be marked with an * in front of the label.

A validation message will be thrown when the data is submitted or when the user navigates to another screen. This message is not customizable. Solution The configurations required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Make input required on all UIs in which Use the Required Constraint the attribute is displayed for entry/ editing Make input required when the attribute Use the Required Constraint does not have a UI for entering the value, like import of data, programmatic creation of objects objects/attributes Make input required for the attribute Use the Input Required property only on a specific UI Make input required for the attribute Use the Input Required property only in the UI; do not enforce this outside the UI, like when a value is provided programmatically

Note In tables that allow input of data, the * will not be added to the column headers. This is because if a table displays more than one object type, for any given column, some types might have the attribute configured as required and others may not.

Default Values You want to specify a default values for attributes. Solution Elements Element initialValue

Description A property used to specify default value (s) for an attribute. Applies to modeled attributes only.

Presenting Information in the UI

641

Element

Description See the javadoc for com.ptc.windchill.annotations.metadata. GeneratedProperty and Modeling Business Objects on page 101 for more information. A configuration in the Type and Attribute Management utility. See the Default Values Tab online help topic for more information. See the Object Initialization Rules online help topic for more information. A property used to configure how default values will be displayed in the UI. See Default Value Display Mode in Configuration Points on page 673 for more information.

Default Value

Object Initialization Rule Default Value Display Mode

Intended Outcome Default values are presented in the UI in one of these three modes and/or, default values are persisted automatically: Default value button Pre-populate the field with the default value Do not display default value

Solution You want to specify a default values for attributes. The configurations required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Provide default value(s) for use in create For a modeled attribute, use the initial UI only. value property You do not want this value to be automatically persisted when a value is not provided in the UI. For global and standard attributes, provide the default value in the Type Management utility. See the Default Values Tab online help topic for more information.
642

Windchill Customization Guide

If you want to .. Provide default value(s)s for use in the Create UI and persistence

Configuration Specify the default values using an Object Initialization Rule.

You want this value to be automatically persisted for that attribute when a value is not provided until the point of persistence. Provide default values for attributes that Specify the default values using an Obare not displayed in the Create UI and ject Initialization Rule. use this value for persistence This applies when you want to create an object programmatically (without a UI) or, when some attributes of an object are not added to the Create UI of an attribute. Specify how default values should be Use the Default Value Display Mode presented in the UI property. Limitations The default value specified in an Object Initialization Rule will not be reflected in the Type Management utility. The value set on an attribute during persistence is the value displayed for that attribute in the UI. So when a default value is specified in the Modeled class or the Type and Attribute Management utility, this value will be used only for displaying in the UI. The default value will not be automatically set on an attribute during persistence unless the default value was displayed in the UI as the value of the attribute using one of the methods used for displaying the default value. Only the default values specified using an Object Initialization Rule will be automatically saved with the default value.

Visibility and Modifiability You want to control the visibility and the modifiability of an attribute. Solution Elements Element Immutable constraint

Description A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more

Presenting Information in the UI

643

Element Changeable constraint

Description information. A property constraint. Applies to modeled attributes only.

See the javadoc for com.ptc.windchill. annotations.metadata.PropertyConstraints and Modeling Business Objects on page 101 for more information. Visibility setting in the Type and Attrib- A configuration in the Type and Attribute Management utility ute Management utility. See Visibility Tab for more information. Role-based Attribute Visibility A configuration in the Profiles Management tool. See Managing Profiles for more information. Attribute validator Java classes that can be used to perform attribute validation and filtering. See UI Validation on page 718 for more information Intended Outcome Attributes are displayed as follows for the various configurations: Hidden attribute In a table Outside a table The attribute (both label Column header will be displayed. For & value) is not displayed. those row objects for which the attribute is hidden, the UI displays (Secured Information) Created By (Hidden) Value hidden Read-Only

(When the attribute does not have a value)

When the attribute does not have a value:

(When the attribute has a Created By value) (Unassignable) When the attribute has a value: Created By Read-Write (When the attribute does John Doe When the attribute does not have a
Windchill Customization Guide

644

Outside a table not have a value yet) (When the attribute has value)

In a table value yet: Created By When the attribute has value: Created By John Doe

Solution The configurations required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Always hide an attribute from Simply exclude it from the UI (i.e. do not add it to a specific UI, for all profiles an attribute panel or a table configuration). Hide an attribute from a spe- Use the validation service. cific UI, for all profiles, based on specific business logic Hide an attribute from all Use Role-based Attribute Visibility. UIs, for specific profiles only Limitation: This feature is available only for global attributes. See Creating a New Attribute for more information. Always make an attribute not Use the Immutable constraint / changeable modifiable in any of the UIs constraint. it is displayed on Limitation: If the attribute is immutable on create or edit, do not add it to an area of the UI where fields that will be updated are placed. Control the modifiability Use the visibility settings in the Type Management (hide value, make value edit- utility to control the modifiability of an attribute in able or read-only) of an atthe end user UI. See visibility settings in the Type tribute in a specific UI, for all Manager for more information. profiles Limitations: This feature is limited to Create and Edit UIs only. Also, at this point, the visibility & modifiability settings are honored only for those attributes that have standard attribute behavior (All standard attributes, global IBAs and some modeled attributes). Modeled attributes with special OOTB behavior like Name, Number and Principal may not reflect this configuration.

Presenting Information in the UI

645

If you want to .. Control the modifiability (hide value, make value editable or read-only) of an attribute in all UIs, for specific profiles only

Configuration Use Role-based Attribute Visibility. Limitation: This feature is available only for global attributes. See Creating a New Attribute for more information.

Resolution of Multiple Configurations When a global attribute has visibility configured both in the Profiles Management tool and in the Type and Attribute Management utility, it is resolved as follows: The most restrictive setting of the Type and Attribute Management utility configuration and the result from the Profiles Management tool will be the final visibility setting of the attribute. Example: Visibility settings for the attribute Color in the Profiles Management tool: in the Type and Attribute Management utility, for Create Screen: Resulting visibility setting applied in the Create UI: Value Hidden Read-only

Value-Hidden (this is the most restrictive of the two settings)

Validating Input Values and Legal Value Lists You want to restrict the values allowed for an attribute. Solution Elements Element Legal value list Constraint

Enumerated list Constraint

EnumeratedType in Modeled class definitions Valid Range Constraint

Description A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. See the GenAsEnueratedType columns section in Specialized Persistence Constructs for more information. A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for

646

Windchill Customization Guide

Element upperLimit, lowerLimit Constraints

Wildcard Constraint

Regular expression constraint String format constraint

Selection List Style

Include Blank Option

Description more information. A constraint defined when defining the modeled class. See Modeling Business Objects on page 101 for more information on PropertyConstraints. Same functionality as the range constraint when used with Numeric attributes. A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. A constraint defined in the Type and Attribute Management utility. SeeAttribute Constraint Rules for more information. A property to specify how the legal values should be displayed in the UI. See Select List Style in Configuration Points on page 673 for more information. A property to specify whether to include a blank option in the legal value list . See Include Blank Option in Configuration Points on page 673 for more information.

Intended Outcome You are able to do one or more of the following: Restrict the input by specifying a set of valid values that the user needs to pick from. Example: When Include Blank Option is set to true

When Include Blank Option is set to false

Presenting Information in the UI

647

Restrict user input to be within a certain range and display a validation message when the value is outside the range(s). Ensure that the user input for a String attribute conforms to a given pattern of characters. Display a validation message when the value entered does not conform to the pattern specified in the constraint.

Solution The combinations of the solution elements required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Display a Dropdown list (also configu- For global and standard attributes, use: rable as a group of radio buttons) with Legal value list for non-localized the set of legal values for the attribute; lists do not allow the user to type in a value. Enumerated list for localized lists. For modeled attributes, use: EnumeratedType in Modeled class definitions.

To define a legal value list on an existing modeled attribute without having the need to recompile, use the Legal Value list constraint (localized list) or the Enumerated list constraint(non-localized list) in the Type and Attribute Management utility. Allow the user to type in a value, but re- For modeled attributes, use upper limit, strict the value to be within a given lower limit constraints. range. For standard and global attributes, use Allow the user to type in a value, but define more than one range for validating the value. You want to limit the value entered by the Range constraint. Significant figures constraint This is applicable only to Real Numbers and Real Numbers with Units. Use the wildcard constraint, the regular

648

Windchill Customization Guide

If you want to .. the user to conform to a given pattern. Specify how the legal values should be displayed in the UI Provide a blank option to clear the current value of the attribute, when using legal value lists.

Configuration expression constraint or the string format constraint Use the property Selection List Style. Use the property Include Blank Option.

Combining legal value lists, valid range constraint significant and figures constraint It is possible to have more than one of these configurations defined for an attribute. The following table shows the effect of combining these configurations: Constraints specified in Type and UI behavior Attribute Management utility for an attribute Legal value list(s) + Enumerated list(s) The list displayed will be an intersection + Enumerated type of all the constraints i.e. the list will have entries that are common to all the defined lists. Example: Given the following constraints: 1. Enumeration: COLOR_RED = Red COLOR_BLUE = Blue COLOR_GREEN=Green 2. Non-localized legal value list: COLOR_RED COLOR_BLUE 3. Non-localized legal value list: Red Blue If the user were to apply 1 and 2, the resulting legal values should be: COLOR_RED = Red
Presenting Information in the UI 649

Constraints specified in Type and UI behavior Attribute Management utility for an attribute COLOR_BLUE = Blue If the user were to apply 1 and 3, the result would be an empty set (no legal values). When all the legal value lists specified for an attribute are combined, the resulting list will be an intersection of all the lists (i.e. only those entries that are common to all the lists will be added to the resulting list). So it is possible to end up with an empty legal values list when multiple legal value lists have been defined. When the legal value list is empty, the end-user UI displays an input field. Drop down populated with only those values in the legal value list that satisfy the range constraint. (configurable as a group of radio buttons). No tool-tip message. Drop down populated with only those values in the legal value list that satisfy the range derived from the significant figures constraint. (configurable as a group of radio buttons). No tool-tip message. Input field with tool-tip indicating the valid range(s). Validation message will indicate the valid range(s). The valid range(s) will be the range(s) derived from the intersection of these 2 constraints. Drop down populated with only those values in the discrete set that satisfy both the range(s) of the Range constraint and the range(s) of the
Windchill Customization Guide

Legal value list + Range constraint

Legal value list + Significant figures constraint

Range constraint + Significant figures constraint

Legal value list + Range constraint + Significant figures constraint

650

Constraints specified in Type and UI behavior Attribute Management utility for an attribute Significant figures constraint. No tool-tip message.

Limiting the Length of Values Entered for a String Attribute You want to limit the length of the value entered for a string attribute. Solution Elements Element upperLimit, lowerLimit Constraints

String length Constraint

Character Entry Limit

Description A constraint defined when defining the modeled class. See the information on PropertyConstraint in Modeling Business Objects on page 101 for more information. A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. The property Character Entry Limit can be set on a modeled, global or standard attribute. See Configuration Points on page 673 for more information.

Intended Outcome You are able to restrict the length of string attributes in the UI and/or during persistence and provide feedback to the user when the limit is exceeded. Solution The combinations of the solution elements required to achieve the different kinds of behavior are listed below:

Presenting Information in the UI

651

If you want to .. Configuration Restrict input to a certain number of For modeled attributes, use upper limit, characters on all the UIs in which the at- lower limit constraints. tribute will be displayed for editing. For global and standard attributes, use Also apply this restriction during persis- the String length constraint. tence. This applies when you want to The string length constraint can be used create an object programmatically on modeled attributes also to make con(without a UI) or, when some attributes figurations without requiring Java code of an object are not added to the Create compilation. UI of an attribute. Limitation: The length of the Name attribute conforms to Windchill UI standards and so cannot be overridden using this constraint. Restrict input to a certain number of Use the property Character Entry Limit. characters on a specific UI only. Note: This limit has to be less than the Also, do not apply this restriction during persistence. Byte length The validation in the end-user UI also takes into consideration the number of bytes needed to store the characters entered, to account for variable width encoding and multi-byte databases. Merging multiple constraint definitions When the upperLimit, lowerLimit constraints are specified in the modeled class and one or more String length constraints are specified for the same attribute in the Type and Attribute Management utility, all these constraints are compiled together to provide a range that is common to all of them. So the minimum number of characters that can be entered will be the maximum of all the lower limit values. The maximum number of characters that can be entered will be the minimum of all the lower limit values. Example: Annotated Constraint: Lower limit = 30 Upper limit = 50 Type and Attribute Management utility String Length constraint 1: 20 40 Type and Attribute Management utility String Length constraint 2: 35 - 45 Result of combining all these constraints: 35 - 40 maximum string length.

652

Windchill Customization Guide

Controlling the Size of Input Fields for String Attributes You want to customize the physical width and/or height of the input fields for string attributes. Solution Elements Element String Length Threshold For Multiple Line Input Input Field Type Text Input Rows Text Input Columns

Description Provided as a property or a preference. See String Length Threshold For Multiple Line Input in Configuration Points on page 673 for more information. Provided as a property. See Input Field Type in Configuration Points on page 673 for more information. Provided as a property. See Text Input Rows in Configuration Points on page 673 for more information. Provided as a property. See Text Input Columns in Configuration Points on page 673 for more information.

Intended Outcome You are able customize the physical width and/or height of the input fields for some string attributes. Limitation: The width and height are not configurable for certain special attributes like Name and Number. Solution The combinations of the solution elements required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Customize the height of all input fields Use String Length Threshold For Multiautomatically based on the string length ple Line Input constraint Override the automatic behavior proUse Input Field Type vided by the String Length Threshold For Multiple Line Input for a specific attribute only Always display a certain type of field Use Input Field Type (either single line or multi line) for a specific attribute Specify the actual number of rows visi- Use Text Input Rows. ble without scrolling, in a multi-line text

Presenting Information in the UI

653

If you want to .. input field. Customize the width of the input field

Configuration Use Text Input Columns. Note: For most fields, the width of the field defaults to that specified by Windchill UI standards and the attributes String Length Constraint.

Multiple Values (Global IBAs Only) You want to allow an attribute to be assigned more than one value. Solution Elements Element Single Value Constraint

Delimiter for multi-valued attributes.

Description A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. A preference. See Delimiter for multi-valued attributes in Configuration Points on page 673 for more information.

Intended Outcome You are able to enter multiple values for an attribute edit the values stored for an attribute add / remove values when editing the attribute customize the separator used when displaying multiple values in the UI in the view mode

Solution To configure a global attribute to have multiple values, remove its Single Value constraint. See Attribute Constraint Rules for more information. When multiple values assigned to a global IBA are displayed in the UI in the view mode, they are separated by commas. To customize the separator, use the preference Delimiter for multi-valued attributes . See Delimiter for multi-valued attributes in Configuration Points on page 673 for more information. Limitation: Support for multiple values for Alias attributes and Calculated attributes is not available at this time.
654

Windchill Customization Guide

Making a String Value All Upper Case or All Lower Case You want to automatically make a string value all upper-case or all lower-case without imposing this requirement on the user or any system that provides the value. Solution Elements Element Lower case constraint

Upper case constraint

Description A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information. A constraint defined in the Type and Attribute Management utility. See Attribute Constraint Rules for more information.

Intended Outcome You are able to enter the value of a string in any case (upper, lower or mixedcase) in the Create or Edit UIs and have it automatically stored and displayed as either all upper-case or all lower-case. You are able to programmatically(using java code, import operations etc) set the value of a string attribute in any case (upper, lower or mixed-case) in the Create or Edit UIs and have it automatically stored and displayed as either all upper-case or all lower-case.

Solution ` To configure a string attributes value to be automatically converted to all lowercase, use the Lower case constraint. To configure a string attributes value to be automatically converted to all uppercase, use the Lower case constraint.

Automatically Creating Hyperlinks You want to control the automatic conversion of hyperlink text embedded in a string value to HTML hyperlinks.

Presenting Information in the UI

655

Solution Elements Element Create Hyperlinks preference

Create Hyperlinks property

Description This preference is available in the Attribute Handling category. See Create Hyperlinks in Configuration Points on page 673 for more information. Available in the Type and Attribute Management utility Attribute Definition. See Create Hyperlinks in Configuration Points on page 673 for more information.

Intended Outcome You are able set up a string attribute for the automatic conversion of hyperlink text embedded in a string value to HTML hyperlinks. You are able to prevent the automatic conversion of hyperlink text embedded in a string value to HTML hyperlinks.

Solution To configure this setting for all attributes, use the Create Hyperlinks preference. This preference is available under the Attribute Handling category. To configure this setting for a specific attribute, use the Create Hyperlinks property that can be set on the attribute definition in the Type and Attribute Management utility. Note: Note The value of the property overrides the value of the preference.

Defining Custom Labels You want to customize the label displayed for an attribute. Solution Elements Element Label property

Display Name property

Description A property defined in the Type and Attribute Management utility. See Label in Configuration Points on page 673 for more information. A property defined in the Type and Attribute Management utility Attribute Definition. See the Type and Attribute

656

Windchill Customization Guide

Element

Description Management utility help topic Attribute Information Page for more information. componentRB.rbInfo tableRB.rbInfo com.ptc.core.htmlcomp.jstable. jstableResource com.ptc.core.ui.tableRB wt.enterprise.enterpriseResource (this is also used as the default) wt.identity.identityResource wt.templateutil.table.tableResource com.ptc.windchill.cadx.ws. wsResource

rbInfo files

Intended Outcome Solution The combinations of the solution elements required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Use a custom label on one specific atat- Use the Label property tribute panel only Use a custom column header for an at- If the table is defined using a Java buildtribute on a specific table only er class, set the custom label using the setLabel() method when defining the com.ptc.mvc.components.ComponentConfig for the column representing the attribute. See the JavaDoc for more information. Use the same custom label in all the at- For attributes of TypeManaged objects, tribute panels in which this attribute will use the Display Name property. be displayed Use the same custom column header for If the attribute has an entry on one of an attribute, on all tables in which this the following rbInfo files, modify the attribute will be displayed. rbInfo file entry com.ptc.core.htmlcomp.jstable. jstableResource

Presenting Information in the UI

657

If you want to ..

Configuration com.ptc.core.ui.tableRB wt.enterprise.enterpriseResource (this is also used as the default) wt.identity.identityResource wt.templateutil.table.tableResource com.ptc.windchill.cadx.ws.wsResource For all other attributes, set the Display Name property of the attribute to the custom label using the Type Management utilities Attribute Information Page. Enable the logger com.ptc.core. component.labels

Determine the source of the label of an attribute

Customizing Data Acquisition You want to customize the source of the data of an attribute. Solution Elements Element Data Utility ID

Need property

Target Object property

Description A property defined in the Type and Attribute Management utility or component builder. See Data Utility Id in Configuration Points on page 673 for more information. A property defined in the Type and Attribute Management utility. See Need in Configuration Points on page 673 for more information. A property defined in the Type and Attribute Management utility. See Target object in Configuration Points on page 673 for more information.

Intended Outcome The data for an attribute can be fetched from attributes other than the default. Solution The combinations of the solution elements required to achieve the different kinds of behavior are listed below:
658

Windchill Customization Guide

If you want to . Configuration Specify the source of data for a compo- Example site attribute or a reference attribute The value of the state attribute actually comes from State.state. The attribute that is defined on the type is State. When defining the component configuration, to indicate that the source of data for this attribute is State.state, set the value of the Need property of the State attribute to State.state. Specify a different source of data for a When defining the component configuspecific to the UI only ration, set the value of the Need property of the attribute. Use data from multiple attributes and Wherever possible, define a calculated assemble them using custom logic, to attribute. form the value to be displayed in the UI. If the required calculation is outside the scope of the current support provided for calculated attributes, use a custom data utility. When defining the component configuration, set the value of the Need property of the attribute to the list of attributes that need to be fetched for calculating the value. Example: attributeConfig.setNeed ("name, number, creator");

Providing Alternate UI Behavior You have a need to customize the rendering of a standard attribute like Name that already has a data utility mapped to it, only for a specific case. Since the attribute id is already mapped to a data utility, adding another mapping using the same attribute id will not work as expected. See Data Utilities on page 669 for additional information. Solution Elements Element Data Utility ID

Description A property defined in the Type and Attribute Management utility or

Presenting Information in the UI

659

Element

Need property

Target Object property

Description component builder. See Data Utility Id in Configuration Points on page 673 for more information. A property defined in the Type and Attribute Management utility. See Need in Configuration Points on page 673 for more information. A property defined in the Type and Attribute Management utility. See Target object in Configuration Points on page 673 for more information.

Intended Outcome The data for an attribute can be fetched from attributes other than the default. Solution The combinations of the solution elements required to achieve the different kinds of behavior are listed below: If you want to .. Configuration Use a custom data utility to render Example: an attribute for the scope of a speTo render Number using a custom data utility cific UI only and that attribute alcalled MyNumberDataUtility ready has a data utility mapped to 1. Define your custom data utility it and, the UI is one of the (MyNumberDataUtility) following: an Attribute panel defined us- 2. In an xconf file, map the custom data utility to a custom attribute id(myNumber). ing the Type and Attribute For more information see Map the Data Management utility or a buildUtility to the Attribute ID on page 671. er class an Table defined using the Type and Attribute Management utility or a builder class Use an existing data utility to render an attribute in all the UIs in which the attribute is rendered In a specific UI only, render an attribute using an existing data utility; the existing DU might be already mapped to one or more 3. Set the Data Utility Id property of that attribute to myNumber In an xconf file, map the custom data utility to a custom attribute id(myNumber) To render myNumber using using a custom data utility called MyNumberDataUtility

660

Windchill Customization Guide

If you want to .. attributes

Configuration 1. Define your custom data utility (MyNumberDataUtility) 2. In an xconf file, map the custom data utility to a custom attribute id(myNumber) 3. Set the Data Utility Id property of that attribute to myNumber The column ids must be unique, so you need to use Target Object and Data Utility Id properties to accomplish this. For example, a table could have 3 columns that all render the Name attribute, but from 3 different objects: 1. Add all the three attributes to the attribute panel or table definition 2. For the attributes that belong on objects that are not the backing object, set the value of the property Data Utility Id to name and the Target Object to the attribute that represents the object Example: To display the name attributes of the roleAObject and roleBObject the same way the name attribute of the backing object is displayed, for each of those attributes, set the properties as follows: For roleAName Data Utility Id = name Target Object = roleAObject For roleBName Data Utility Id = name

Rendering the same attribute for multiple objects within the same table

Specifying different renderers for the same attribute id for different object types

Target Object = roleBObject Example: You need to render the render the state attribute of a Document differently than the state attribute of a Part.

Presenting Information in the UI

661

If you want to ..

Configuration Type-based lookup of data utilities is currently not supported by the infrastructure. If this type of behavior is needed, and if your UI displays objects of the same type, then use the Data Utility Id property to accomplish this. On a UI that displays objects of multiple types, like the Folders page, you may use a custom data utility and do the type-based checking within that custom data utility.

Customization of Common Windchill Business Attributes


Some Windchill attributes need to adhere to specific Windchill standards and rules. This behavior is provided OOTB. Some of this behavior is customizable. This section lists some of these standard Windchill attributes and their configuration points. Number Render Number as a link to the object s information page Use case: I want to render the Number attribute as a hyperlink to the objects information page. This behavior can be enabled/disabled by using the Is Info Page Link property. See Configuration Points on page 673 for more information. Making the value of Number server-generated/ server-generated/ server pre-generated/ pre-generated/ immutable The out of the box behavior of Number can be customized using Object Initialization Rules. The combinations of Object Initialization Rules required to achieve the different kinds of behavior for Number are listed below: If you want to .. You will need to The UI the Create configure your OIRs Wizard will look like like this this Always use the server <Value algorithm="com. generated value and, ptc.core.rule.server.impl. GetImmutableConstraint"/ do not want to allow the ><Value algorithm="com. user to enter a value. ptc.core.rule.server.impl.

662

Windchill Customization Guide

If you want to ..

You will need to configure your OIRs like this GetServerAssignedConstraint"/> Always use the pre- gen- <Value algorithm="com. erated value defined in the ptc.core.rule.server.impl. Object Initialization Rules GetImmutableConstraint"/ and, ><Value algorithm="com. ptc.core.rule.server.impl. display this value in the GetServerPreGeneratedUI and, Value"/> do not want to allow the user to modify this value. Use the pre- generated <Value algorithm="com. value defined in the Ob- ptc.core.rule.server.impl. ject Initialization Rules GetServerPreGeneratedand, Value"/> display this value in the UI and, want to allow the user to modify this value. The user to always provide the value

The UI the Create Wizard will look like this

Pre-generated value with no override

Pre-generated value with override.

If there are no other OIR constraints defined for Number, this needs an empty constraints list to work as expected. <AttrConstraint id="number" algorithm="com.ptc.core. rule.server.impl.GatherAttributeConstraints"/> <Value algorithm="com. ptc.core.rule.server.impl. GetServerAssignedConstraint"/>

Allow the user to enter a value and, if a value is not provided by the user, use a servergenerated value.

Presenting Information in the UI

663

Note If the above configurations do not yield the results listed above, check the following values of these other configurations which also affect the editability of Number in a Create or Edit UI: The changeable Property Constraint for a Modeled attribute. See Modeling Business Objects on page 1292 for more information. The Type and Attribute Management utility Visibility settings. See Visibility Tab for more information.

Name Render Name as a link to the object s information page This behavior can be enabled/disabled by using the Is Info Page Link property. See Configuration Points on page 673 for more information. Making the value of Name Server generated

Note This customization has been requested by more than one customer. While there are no supported ways to perform this customization, the following guidance was provided as a workaround. This method involves the use of unsupported APIs. If you choose to use this customization, please note that you may have to make changes to your customization if those APIs change in a future release.
This requires writing a custom data utility and defining the necessary Object Initialization Rules. The steps to do this are listed below, using WTDocument as an example. 1. Ensure your attribute is Rule Configurable. Find your object type in the file: codebase/com/ptc/core/rule/server/delegate/init/ RuleConfigurableTypeAttribute.properties The out-of-the-box entry for WTDocument is:
wt.doc.WTDocument=number,lifeCycle.id,lifeCycle, teamTemplate,teamTemplate.id,folder.id,organization.id

To add Name to this list of attributes, add the following entry to the site.xconf file. Note that the attribute id for the Name attribute (name) is used here.
<Configuration targetFile="codebase/com/ptc/core/rule/server/delegate/init/ RuleConfigurableTypeAttribute.properties"> <Property name="wt.doc.WTDocument" default="name,number,lifeCycle.id, lifeCycle,teamTemplate,teamTemplate.id,folder.id,organization.id"/>

664

Windchill Customization Guide

</Configuration>

2. Add the Object Initialization Rule Using the Object Initialization Rules administrator, add the following rules for WTDocument
<!-- set the name to a generated number --> <AttrValue id="name" algorithm="com.ptc.windchill.enterprise. revisionControlled.server.impl.NumberGenerator"> <Arg>{GEN:wt.enterprise.SequenceGenerator: WTDOCUMENTID_seq:10:0}</Arg> </AttrValue> <AttrConstraint id="name" algorithm="com.ptc.core.rule.server.impl. GatherAttributeConstraints"> <Value algorithm="com.ptc.core.rule.server.impl.GetServerAssignedConstraint"/> <Value algorithm="com.ptc.core.rule.server.impl.GetImmutableConstraint"/> </AttrConstraint>

This example uses the number generator that exists out-of-the-box. You can replace it with a custom number generator, if needed. See About Object Initialization Rules for more information. 3. Create a new Data Utility. This approach reuses the out-of-the-box support provided in the NumberDataUtility for making an attribute server-generated. Create a new data utility that extends the NumberDataUtility. Override the getColumnId() method to return the attribute ID for Name. See Creating a Data Utility on page 669 for more information.
package com.ptc.carambola.customization.examples.wizard; import com.ptc.core.components.descriptor.DescriptorConstants; import com.ptc.core.components.factory.dataUtilities.NumberDataUtility; public class GeneratedNameDataUtility extends NumberDataUtility { @Override protected String getColumnId() { return DescriptorConstants.ColumnIdentifiers. NAME; } }

4. Register the new Data Utility. For this example, this behavior should be applied to Name of WTDocument objects only. Follow the instructions for Providing Alternate UI Behavior on page 659. Use a custom data utility to render an attribute to do this. Making Name Immutable and/or and/or Server Pre-generated Pre-generated The same customization method used for making the value server generated will also enable the name attribute to be customized using the immutable and/or server pre-generated Object Initialization Rules. The combinations of Object

Presenting Information in the UI

665

Initialization Rules required to achieve the different kinds of behavior for Name are the same as those listed in the Making the value of Number server-generated/ server pre-generated/ immutable section in Number on page 662. Location The UI behavior of the Location attribute can be customized using Object Initialization Rules (see About Object Initialization Rules for more information). The combinations of Object Initialization Rules required to achieve the different kinds of behavior for Location are listed below: If you want to .. You will need to The UI the Create configure your OIRs Wizard will look like like this this Always use the server as- <Value algorithm="com. signed folder and, ptc.core.rule.server.impl. GetImmutableConstraint"/ do not want to allow the ><Value algorithm="com. user to specify a folder. ptc.core.rule.server.impl. GetServerAssignedConstraint"/> Always use the pre-gener- <Value algorithm="com. ated folder defined using ptc.core.rule.server.impl. Object Initialization Rules GetImmutableConstraint"/ and, ><Value algorithm="com. ptc.core.rule.server.impl. display this value in the GetServerPreGeneratedUI and, Value"/> do not want to allow the user to modify this value. Allow the user to select a If there are no other OIR folder manually. constraints defined for The field is populated Location, this needs an Also display the launch with the folder from the context folder as the de- empty constraints list to launch context. work as expected. fault value. <AttrConstraint id="folder.id" algorithm="com.ptc.core. rule.server.impl.GatherAttributeConstraints"/> Provide the following op- <Value algorithm="com. tions to the user ptc.core.rule.server.impl.

666

Windchill Customization Guide

If you want to ..

You will need to configure your OIRs like this Use the pre-generated GetServerPreGeneratedValue"/> folder defined using Object Initialization Rules or, Select a folder manually; display the launch context folder as the default value for this.

The UI the Create Wizard will look like this The value of Autoselect Folder is the pre-generated value defined using Object Initialization rules.

And, pre-select the launch context folder as the default option. Provide the following op- <Value algorithm="com. tions to the user ptc.core.rule.server.impl. Use the pre-generated GetServerPreGeneratedfolder defined in Ob- Value"/> ject Initialization Rules or, Select a folder manually. display the launch context folder as the default value for this <Value algorithm="com. ptc.core.rule.server.impl. GetRendererConstraint"> <Arg>SelectGeneratedFolderByDefault</Arg> </Value>

The value of Autoselect Folder is the pre-generated value defined in Object Initialization rules.

And, pre-select the pregenerated folder as the default option. Provide the following op- <Value algorithm="com. tions to the user ptc.core.rule.server.impl. GetServerAssignedCon Use the server asstraint"/> signed folder or, Select a folder manually; display the launch context folder as the default value for this

Presenting Information in the UI

667

If you want to ..

You will need to configure your OIRs like this

The UI the Create Wizard will look like this

And, pre-select the launch context folder as the default option. Provide the following op- <Value algorithm="com. tions to the user ptc.core.rule.server.impl. GetServerAssignedCon Use the server asstraint"/> signed folder or, Select a folder manually; display the launch context folder as the default value for this. <Value algorithm="com. ptc.core.rule.server.impl. GetRendererConstraint"> <Arg>SelectGeneratedFolderByDefault</Arg> </Value>

And, pre-select the serverassigned folder as the default option. Principal Attributes

1. Render Principal as a link to the Principals information page This behavior can be enabled/disabled by using the Is Info Page Linkproperty (see Configuration Points on page 673). Revision The Revision attribute can be configured to distinguish between the checked-out original and the working copy. This can be done by setting the Distinguish WIP Versions property (seeConfiguration Points on page 673). Lifecycle State The Lifecycle State attribute can be configured to render all the lifecycle states instead of just the current state. This can be configured by setting the Is Render All States property (see Configuration Points on page 673).

Note This configuration is applied only when the attribute is displayed on a table or on a component whose com.ptc.core.ui.resources.ComponentType is SIMPLE.

668

Windchill Customization Guide

UI behavior When Is Render All States is set to true:

When Is Render All States is set to false:

Data Utilities
Data utilities are java classes that can be used for customizations that cannot be accomplished using the available configuration points. A data utility is used to get the data and meta-data of an attribute and create the UI component which will be used to render the attribute in the UI. If the data returned by a core API is not sufficient for creating the UI component, data utilities can be used to augment this data with additional information. The additional information can be fetched by an additional query, a call to a service, or whatever else you can get at via Java code. The OOTB implementations of data utilities provide the behavior defined for Windchill OOTB applications in accordance with Windchill UI standards. You can configure a data utility for any attribute id. Creating a Data Utility Creating a new data utility consists of the following steps: Create the data utility (Java) class Map the data utility class to the attribute id in an XCONF file

Creating the Data Utility Class Create your data utility by implementing the com.ptc.core.components.descriptor. DataUtility interface.

Presenting Information in the UI

669

Since data utilities are looked up using application context, your implementation class must be public and must have a public no-arg constructor. It is highly recommended that when you implement a new data utility, you extend the AbstractDataUtility base class. If you have a need to augment the attribute value or change how the attribute is rendered, you should consider extending the existing data utility, if applicable. Use the Available Attributes Report or JcaDebug to find the data utility currently mapped to an attribute. See Available Attributes Report on page 427 and Using jcaDebug on page 442 for more information. 1. Implement the getDataValue() method of the DataUtility interface: The getDataValue() method gets the content that should be placed in the UI for a given attribute. Example: Suppose you want to append the value of a specific string attribute with some extra text. This can be done as follows:
Object getDataValue(String component_id, Object datum, ModelContext mc) throws WTException { .. .. String rawVal = myObject.get(component_id); String displayVal = rawVal + My extra text; TextDisplayComponent gui = new TextDisplayComponent(); gui.setValue(displayVal); return gui; }

Note Avoid making database calls in getDataValue(), because when dealing with tables, the method is called once for every cell in the column. If they must be done, try to do work in setModelData() which is called once per column and cache the results so the database does not have to be called more often than necessary.
2. Implement the setModelData() method of the DataUtility interface: In the interests of performance, we want to process all the objects to be displayed in a single call to setModelData() and to perform the required database queries for all the objects at once, rather than making a separate query for each object. When multiple objects needs to be fetched, as in the case of a table where multiple row objects needs to be fetched, the setModelData() method allows the data utility to prefetch data for all the row objects that will be rendered. The
Windchill Customization Guide

670

method is called before getDataValue() is called for any row/cell, and is supplied a list of all the objects that will be processed. You can take advantage of this call to do some multi-object queries and save the results for later use in the getDataValue() method. If this method is implemented, then you must configure the data utility to be stateful. Map the Data Utility to the Attribute ID Add an application context entry to an xconf file like the following:
<Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.ptc.core.components.factory. dataUtilities.ProjectDataUtility" requestor="java.lang.Object" selector="projectHealthStatus" cardinality="singleton"/> </Service> <Service name="com.ptc.core.components.descriptor.DataUtility"> <Option serviceClass="com.ptc.core.components.factory.dataUtilities. FolderedDataUtility" requestor="java.lang.Object" selector="location" cardinality="duplicate"/> </Service>

A note on cardinality: Your safest bet is to use a "duplicate" cardinality. This will create a new instance of the data utility each time one is requested. Data utility configuration entries can be added to any xconf file that ends up being read in by application context (any "service.properties"-type file). The general convention is to use a file named someprefix.dataUtilities.properties.xconf. When setModelData() is called, the data utility is given a set of objects for which the JCA infrastructure will later request a suitable value to display in the table for each of the objects; the data utility has the opportunity to determine these values and cache them for later retrieval. The JCA infrastructure will later call the getDataValue() method to obtain the specific table cell value for a given object, which the data utility may retrieve from its previously computed cache.

How to Find an Attribute ID


When creating an attribute configuration in your java code you must specify the id of the attribute.

Presenting Information in the UI

671

For Typed and TypeManaged objects, the id should be the Internal Name shown for the attribute in the Type and Attribute Management utility. For other objects, names can be found in the following sources. When using these reports you must type in a fully qualified type name, including the full package for example, wt. part.WTPart. Logical Attributes Report This can be viewed by navigating to Customization -> Tools -> Logical Attributes Report. For TypeManaged classes, this report includes: 1. Alias attributes defined in LogicalAttributes.xml file(s) (Note: This is no longer a recommended practice. Use the Type and Attribute Management utility to define alias attributes instead..) 2. Hard (annotated) attributes, unless overridden by the above. 3. Attributes defined in the Type and Attribute Management utility, unless overridden by an alias attribute.. For non-TypeManaged classes, this report includes: 1. Alias attributes defined in LogicalAttributes.xml file(s) 2. Hard (annotated attributes), unless overridden by an alias attribute. Use the Logical Form of the name from this file as the attribute id in AttributeConfigs and describeProperty tags. Note that not all attributes listed can be used in the UI. A data utility that has the ability to create a gui component for the attribute must be available before it can be displayed. Available Attributes Report This can be viewed by navigating to Customization -> Tools -> Available Attributes Report. This report lists the attributes that can be included in table views. Any attribute in this list could be included in an attribute panel using the name in the JCA ID column. Property Report This can be viewed by navigating to Customization -> Tools -> Property Report. This is a composite report that includes the hard attributes of a type, the logical attributes listed in the Logical Attribute Report, and the table view attributes listed in the Available Attributes Report. You can click on each attribute to display

672

Windchill Customization Guide

additional information about it, including the data utility registered for it, if any. Note that the DefaultDataUtility will handle many attributes for which there is not a specific data utility listed. Not all the attributes in this report are viewable in an attribute panel. In particular, Calculated attributes cannot typically be used in the UI.

Configuration Points
Property Name Applicable DescripDescripattribute tion data types Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 1 attributes, in all clients) PreferPreference Type and Attribute ManageManagement utility Attribute Panel Layout Definition
2

OR CompoComponentConnentConfig
3

Default Val- All data ue Display types Mode

Configures how to populate the default value, if any, in the input field for the attribute. Defaults to Prepopulate. Possible values:

Available as a Site level preference in the Attribute Handling category.

If not specified, the value of the preference Default Value Display Mode will be used.

If not specified, the value of this property from the Attribute Definition will be used, if one has been specified. Otherwise, the value of the preference will be used. OR

Presenting Information in the UI

673

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

None the default value will not be used to populate the input field Pre-Populate the default value, if one is set, will be set in the input field Button A button will be displayed after the input

setDefaultValueDisplayMode()

674

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Selection List UI Style

field, the user can click the button to add the default value to the input field. All attribSpecifies utes that whether the have a Le- legal values gal Value (selection List conlist) for the straint or an attribute Enumerated should be Value List displayed as constraint a dropdefined. down list or as a set of radio-buttons, when the attribute is presented for data entry.

Available as If not specia Site level fied, the valpreference. ue of the preference Note: ApSelection plies to all List Style attributes, except Boo- will be lean attrib- used. utes. AT this level, the style for Boolean attributes is controlled by the preference Boolean Style.

If not specified, the value of this property from the Attribute Definition will be used, if one has been specified. Otherwise, the value of the preference will be used. OR

Presenting Information in the UI

675

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Defaults to Drop Down List. Possible values: Drop Down List the values will be rendered in a drop down list, where the user can select one option Radio Buttons the values will be rendered as a set

setSelectionListStyle()

676

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Boolean Style

Boolean

of radio buttons, where the user can select one option Controls Available as how Booa Site level lean attrib- preference. utes are displayed for input, either as radio buttons or as a dropdown list. Defaults to Radio Buttons. Possible values:

Use the property Selection List Style to override the value of this preference for a specific attribute.

If not specified, the value of the property Selection List Style from the Attribute Definition will be used, if If not speci- one has fied, the val- been specified. Otherue of the preference wise, the value of the Boolean Style will preference will be be used. used. OR

Presenting Information in the UI

677

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Drop Down List the values will be rendered in a drop down list, where the user can select one option Radio Buttons the values will be rendered as a set of radio buttons, where the user can select one

setSelectionListStyle()

678

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

String Length Threshhold For Multiline Input

String

option Specifies Available as the thresh- a Site level old for ren- preference. dering a multi-line input field for a String attribute. The value can be any positive number. If the maximum length of the attribute in characters exceeds this value, a multiline input field will be displayed for data entry. Defaults to 60. Specifies

If not specified, the value of the preference String Length Threshold for Multiline Input will be used.

If not specified, the value of this property from the Attribute Definition will be used, if one has been specified. Otherwise, the value of the preference will be used. setStringLengthThreshholdForMultilineInput()

Input Field

String

Not

If not

If not
679

Presenting Information in the UI

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Type

whether the available at input field this level for the attribute should be single-line or multiline. This directive will override that of the stringLengthThresholdForMultilineInput. Possible values: Single Line a textbox will be rendered for this attribute MultiMultiple

specified, this property is not assigned a default value.

specified, the value of this property from the Attribute Definition will be used, if one has been specified. OR setInputFieldType()

680

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Date Input Field Type

Date

Lines a text area will be rendered for this attribute Specifies Not availwhether the able at this input field level. for a Timestamp attribute is of type dateonly or date & time, so that the UI components can be created accordingly. The default is Date Only. Possible values:

If not specified, the default will be used.

If not specified, the value of this property from the Attribute Definition will be used, if that has been specified. Otherwise the default will be used. OR setDateInputFieldType()

Presenting Information in the UI

681

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Date Only Allow the user to only set the date portion.

Date Date Display Format

Date and Time Allow the user to set both the date and time portion. A date for- Not availmat string able at this (i.e. yyyy- level. mm-dd) to use when displaying the value of this attribute in View

If not specified, the default will be used.

If not specified, the value of this property from the Attribute Definition will be used, if that has

682

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

mode. This does not affect the format used to set the value in input mode. Please refer to the Java class java. text.SimpleDateFormat for the full set of valid characters. If not set, one of the following formats will be used from the rbInfo file componentRB:

been specified. Otherwise the default will be used. OR setDateDisplayFormat ()

Presenting Information in the UI

683

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

STANSTANDARDARD_DAD_DATE_DITE_DISPLASPLAY_FOY_FORMAT if the value of the property Date Input Field Type is set to Date Only, this format will be used. STANSTANDARDARD_DAD_DATE_TITE_TI-

684

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Local Time Date Zone

ME_ME_ZOZONE_NE_DISDISPLAPLAY_FOY_FORMAT if the value of the property Date Input Field Type is not set or is set to Date and Time, this format will be used. Specifies Available as Not availthe time a User level able at this zone to use preference level. for Date attributes that

Not available at this level.

Presenting Information in the UI

685

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

MeasureReal Numment system ber with Units

Create Hyperlinks (in 9.x this was called Ignore URL values in strings)

String

display both the Date and Time portions (i.e. yyyy-MMdd hh:mm zzz). This is only used in view mode; it is not used for input mode. Specifies the measurement system to use for Real Numbers with Units. Specifies whether URL style text embedded in the value of a String attribute should be

Available as Not availa User level able at this preference level.

Not available at this level.

Available as Note: When Not availa Site level upgrading able at this preference from 9.x to level. 10.0, if this property were customized using the file AllClient.

686

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

displayed as a hyperlink in the view mode (example: http://www. ptc.com). Defaults to true.

xml, manual migration is needed. If not specified, the value of the preference Create Hyperlinks will be used. If not specified, the default will be used.

Percent

Numeric

Specifies if Not availa numeric able at this value is to level. be displayed as a percentage or not. This property is only used in view mode. When specified, the notation used will be localespecific.

If not specified, the value of this property from the Attribute Definition will be used, if that has been specified. Otherwise the default will be used. OR setPercent()

Presenting Information in the UI

687

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Currency

Numeric

Defaults to false. Specifies if Not availa numeric able at this value is to level. be displayed as currency value or not. This property is only used in view mode. When specified, the notation used will be localespecific. Defaults to false. Used to Not availmark attrib- able at this utes as Re- level. quired fields even though they may not

If not specified, the default will be used.

If not specified, the value of this property from the Attribute Definition will be used, if that has been specified. Otherwise the default will be used. OR setCurrency ()

Input Required

All

Not available

If not specified, the default will be used. OR

688

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

have a Required constraint. This property is used purely for the UI rendering. Unlike the Required constraint, this will not trigger any server-side validation. Note: If an attribute that has a Required constraint is marked as not required using this property, a server-side exception will be

setInputRequired()

Presenting Information in the UI

689

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

thrown, unless the server-side code takes care of setting the value for the attribute by some other means. The most common usage of this property is to force the user to provide a value for an attribute that does not have a required constraint defined on it. Specifies if Not availthe attribute able at this is to be dis- level. played as a

Is Info Page Name, Link

Not available at this level.

If not specified, the default will be used.

690

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Number and Principal attributes only

hyperlink to the Information Page. In the case of Principal attributes, this will be displayed as a link to the principals info page. When not specified, the following defaults are used: true for Number and Container name false for all other attributes

OR setInfoPageLink()

Presenting Information in the UI

691

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 4 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


5

OR CompoComponentConnentConfig
6

Delimiter for multivalued attributes

Text Input

Specifies the character(s) to use as a separator when displaying the values of an attribute that contain multiple values. This applies only to Global Attributes since they are the only type of attributes that can have multiple values assigned to an attribute. Defaults to a comma followed by a space. An integer

Available as Not availa Site level able at this preference level.

Not available

Not

Not

If not

692

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

Columns

Text Input Rows

value that specifies the width to render the Text Area in create or edit mode. This only applies to String attributes and is only used when the property Input Field Type is set to Multiple Lines An integer value that specifies the height to render the Text Area in create or edit mode. This only applies to

available at this level.

available at this level.

specified, the width defaults to the value specified by Windchill UI standards and the attributes String Length Constraint.

Not available at this level.

Not available at this level.

If not specified, the number of rows is based on the String Length Constraint and the width of the

Presenting Information in the UI

693

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

String attributes and is only used when a multi-line input field is required based on the properties String Length Threshhold For Multiline Input and Input Field Type. Include Blank Option Specifies Not availwhether a able at this blank option level. should be added as the first entry of a dropdown list that displays the legal value list of an Not available at this level.

column. The max number of rows is limited to 3. A scroll bar is added when the input exceeds 3 rows. OR setTextInputRows()

If not specified, the value defaults to true. OR setIncludeBlankOption()

694

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

attribute. When the legal values are displayed as a set of radiobuttons, a button with the label Undefined will be added as the first button in the list. Default to true. Specifies Not availwhether to able at this render all level. the lifecycle states instead of just the current state.

isRenderAllStates

Lifecycle state attributes only

Not available at this level.

If not specified, the value defaults to false. OR setRenderAllStates()

Presenting Information in the UI

695

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

NOTE: This attribute is applicable to components with component type of SIMPLE or TABLE only. Default to false. Distinguish Revision at- Specifies Not availWIP tribute only whether to able at this Versions distinguish level. between the checked-out original and the working copy. Character Entry Limit Species the maximum number of characters that can be entered in Not available at this level.

Not available at this level.

If not specified, the value defaults to false. OR setDistinguishWIPVersions() setCharacterEntryLimit()

Not available at this level.

696

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

Data Utility ID

Need

the UI for a String attribute. The id to use for data utility lookup. When unspecified, the descriptor id is used for the lookup. The logical name of an object attribute needed to create the display value for a column cell. Used by data utilities for retrieving the cell value when the property/column

Not available at this level.

Not available at this level.

setDataUtilityId()

Not available at this level.

Not available at this level.

setNeed()

Presenting Information in the UI

697

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

Target Object

id is not an attribute name defined by introspection or logical attributes. Use a commaseparated list if multiple attributes are needed. The target Not availobject to use able at this for this col- level. umn when it is processed by the Windchill Client Architecture infrastructure. By configuring the targetObject property, the

Not available at this level.

ComponentConfig.setTargetObject()

698

Windchill Customization Guide

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

Label

developer tells the infrastructure to use an alternate row object that is derived from the backing row object returned by the underlying api. Used to set Not availthe label of able at this an attribute level.

Use the dis- setLabel() play name on the attribute definition.

Presenting Information in the UI

699

Property Name

Applicable DescripDescripattribute tion data types

Type and Attribute ManageManage(The ment configuraconfigurautility tion Attribute applies to Definition all 7 attributes, in all clients) PreferPreference

Type and Attribute ManageManagement utility Attribute Panel Layout Definition


8

OR CompoComponentConnentConfig
9

Mode

The mode Not availin which the able at this attribute level. will be displayed. There are 3 modes available: Create, Edit and View

Not available at this level.

setMode()

1. Set using in the Attribute Information Page. (The configuration applies to a specific attributes, in all clients) 2. Set using the Editing Group Attribute Properties window of the attribute in the Type and Attribute Management utility. (Can be used only for attribute panels since the scope is limited to the specific panel) 3. Set using the ComponentConfig builder (Can be used for customizing attributes on attribute panels or tables) (The configuration applies to a specific attribute in a specific UI only)

700

Windchill Customization Guide

Adding Custom Modeled Attributes to all Table Views


This section details the steps required to make custom modeled attributes available in the create table view user interface. Prerequisite: You already have a class with custom modeled attributes. See Attribute Customization on page 630 for more information. 1. Create a site specific file to describe the new class and its attributes. For example codebase\AvailableAttributesSite.xml Create this file and include content in the following format:
<?xml version="1.0" standalone="no"?> <AvailableAttributes> <Class name="<fully qualified class name>"> <Include name="<fully qualified super class name>"/> <Attribute id="<attribute name>"/> </Class> </AvailableAttributes>

Example:
<AvailableAttributes> <Class name="ext.myCompany.MyCompanyChangeIssue"> <Include name="wt.change2.WTChangeIssue"/> <Attribute id="myCompanyString"/> <Attribute id="myCompanyInt"/> <Attribute id="myCompanyTime"/> </Class> </AvailableAttributes>

Any attributes you include in this file will be available in all tables that include that class.

2. Modify site.xconf with the following command to include the new file in the attribute lookup.
xconfmanager -s com.ptc.core.htmlcomp.createtableview.AvailableAttributesDigest er.fileLocation=/com/ptc/core/htmlcomp/createtableview/Availabl eAttributes.xml,AvailableAttributesSite.xml

3. Propogate the xconf changes with the following command


xconfmanager -p

Presenting Information in the UI

701

Attribute Tables
Objective
This documentation provides developers with the information required for implementing the attributes table component for a given business object in information page. The Attribute Table component was developed to give the Windchill products consistency for displaying all necessary attributes of any object in details page. The component should also make developing attributes table much easier. Using this component, a developer only needs to configure attributes tables page only, while the main layout of the page is provided by the component.

Applicability
This documentation should be used by a developer who is responsible for configuring the info page for some object in one of the Windchill products. This design pattern shows how to configured and where the configuration should be done for the attributes table.

Participants
The readers of this documentation should have a basic understanding of JSP, tag libraries and JSTL.

Consequences
By following this documentation the configuration of all attributes table for any business objects should be done in a consistent manner. This will make maintaining these attributes table much easier and more manageable task.

Solution
Overview
The attributes table component was developed using the Windchill Client Architecture. This component provides a common layout for an objects attributes as it is displayed in any of the Windchill products. Using the attributes table component will provide consistency between all objects and Windchill products.

702

Windchill Customization Guide

What is the component


Attributes table Image neededIt is a combination of a JSP, bean, taglib, renderers and service call(s). It displays all the attributes and its value configured for a given object. Not yet implemented: It displays the classification attributes table for WTParts. Follows user interface standards Supports customization requirements

The default attributes table implementation have been added for parts and documents. However both these tables need to be reworked so that necessary or required attributes can be configured. For all the business objects that need to use the attributes table, the developer will need to create a new JSP that is configured for your type. All the details links to attributes table will lead to a servlet which will figure out which page to forward to based on the object type.

Using the component


Create a JSP for your object type Creating a JSP on page 703 Resgistering the JSP on page 704

Creating a JSP Your attributes.JSP will have only the describeAttributesTable tag and list of attribute names as id in describeProperty. Based on the configuration in the describeAttributesTable, the showSoftAttribute.jspf component will render the attributes table panel and its content.

Presenting Information in the UI

703

Here is the example of attributes.jsp for document object.


<jca:describeAttributesTable var="attributesTableDescriptor" mode=VIEW> <jca:describeProperty id="<Logical Form>" /> <jca:describeProperty id="<Logical Form>" /> </jca:describeAttributeTable>

The attribute values are based on logical attribute mapping using the mechanism in place for type instances. For a given object type, you can see what the logical attribute names are by using the LogicalAttributes.jsp. This JSP can be accessed from a running Windchill build; http://<machine>/<Windchill-app-name>/meta/ LogicalAttributeReport.jsp

In the type input field, type the fully qualified class name and click Submit. This should give you a listing of the attributes that can be used for the given object type. Either the logical or the external form can be specified, although the logical form is preferred. Resgistering the JSP For the info page servlet to know which JSP to forward to for your type, an entry for your JSP needs to be specified in a properties file that is used by the type based service. The default properties file for this is typedservices.properties which can be found directly in codebase. The entries should be in the following format:
wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFacto ry/Attributes/wt.doc.WTDocument/0=/netmarkets/jsp/document/attribu tes.jsp wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFacto ry/Attributes/wt.part.WTPart/0=/netmarkets/jsp/part/attributes.jsp

Here is an example of the xcong format:


<!--Info page fragments, Resource is the filepath to a jsp fragment that will configure the info page -->

704

Windchill Customization Guide

<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor="wt.part.WTPart" resource="/netmarkets/jsp/part/attributes.jsp" selector="Attributes"/> <Option requestor="wt.doc.WTDocument" resource="/netmarkets/jsp/document/attributes.jsp" selector="Attributes"/> </Resource>

Windchill/src/typedservices.properties.xconf file is the default xconf file used for type based application context lookups. For your type, you would create your own xconf file within your module that targets typedservices.properties.

Sample Code
Example implementation for the attributesTableComponent
This is an example of how the attributes table could be configured for some object type. However these steps reference to codebase locations only. These steps do not include instructions for source placement or best practices for entering information in xconf files or building of the content or entering in xconf files. This is only to communicate the concepts for getting started. 1. Create a JSP file called attributes.jsp and place it in the following location in your codebase.
codebase/netmarkets/jsp/part/

For now, just add the following content to the page


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <jca:describeAttributesTable var="attributesTableDescriptor" mode="VIEW" id="view.setAttribute" label="Attributes" scope="request"> <jca:describeProperty id="containerName" /> <jca:describeProperty id="name"/> <jca:describeProperty id="number"/> <jca:describeProperty id="creatorName" /> <jca:describeProperty id="currentPrincipal" /> <jca:describeProperty id="cabinet"/> <jca:describeProperty id="cabinetName"/> <jca:describeProperty id="checkoutInfo.state" /> <jca:describeProperty id="comment"/> <jca:describeProperty id="displayIdentifier"/> <jca:describeProperty id="endItem"/>

Presenting Information in the UI

705

<jca:describeProperty id="folderName"/> <jca:describeProperty id="lifeCycleName" /> <jca:describeProperty id="usedBy"/> <jca:describeProperty id="version"/> <jca:describeProperty id="view" /> <jca:describeProperty id="viewName"/> <jca:describeProperty id="owner.id"/> <jca:describeProperty id="ALL_SOFT_SCHEMA_ATTRIBUTES"/>* </jca:describeAttributesTable>

Also, Edit action can be launched with below steps. The step to initially display can be set on request with this form.
startStep=<step id>

* ALL_SOFT_SCHEMA_ATTRIBUTES display all the soft attributes and its value. 2. Register your JSP so the info page servlet will know to forward to it. Add the following entry into codebase/typedservices.properties:
wt.services/rsc/default/com.ptc.netmarkets.util.misc.FilePathFa ctory/Attributes/wt.part.WTPart/0=/netmarkets/jsp/part/attribut es.jsp

3. Test your new jsp. The icons from the Home page or from the Folders page should lead to the new info page servlet. The URL will look something like this:
http://<machine>/<WindchillAppName>/servlet/InfoPage?oid=OR:wt. part.WTPart:62028

The servlet will look up which JSP to forward to in typedservices.properties. You should see the list of attributes name and its value in Third Level Navigation for attributes table.

706

Windchill Customization Guide

Generating the Name Attribute Server


Objective
You want to make the name attribute server generated.

Background
This best practice will describe making the name attribute server generated. This attribute is not server generated out of the box. It will make the name attribute behave exactly as the number attribute. This means the name attribute will also respond to other OIRs that only apply to number out of the box, including ServerPreGenerated and Immutable.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Assume you have a need to have the name attribute be server generated.

Intended Outcome
The name attribute is server generated for all objects that have the ServerAssigned constraint specified in the OIR for name.

Solution
Create your own custom DataUtility for the name attribute and set up the required properties.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Data Utilities GUI Components Object Initialization Rules

Solution Elements
Element Site.xconf Type Configuration Description Contains the configuration information required. Contains the rule configurable attribute lists for each object

RuleConfigurableTypeAttribut Configuration e.properties

Presenting Information in the UI

707

Element

Type

Description type. codebase/com/ptc/core/rule/se rver/delegate/init/RuleConfigu rableTypeAttribute.properties The new Data utility that will be created during this procedure to enable Name to support server generation. An out of the box data utility that knows how to handle server generation for the number attribute. \codebase\netmarkets\jsp\doc ument\createDocumentSetAtt ributesWizStep.jsp

GeneratedNameDataUtility

Java class

NumberDataUtility

Java class

createDocumentSetAttributes WizStep

JSP file

Procedure Make document name attribute server generated


Confirm your attribute is Rule Configurable 1. Look in the file
codebase/com/ptc/core/rule/server/delegate/init/RuleConfigurabl eTypeAttribute.properties

2. Find your object type. For this example we are looking for WTDocument and out of the box we have:
wt.doc.WTDocument=number,lifeCycle.id,lifeCycle,teamTemplate,te amTemplate.id,folder.id,organization.id

3. Notice that name is not an attribute that is available for rules so we need to add it in. In your site.xconf file add the following:
<Configuration targetFile="codebase/com/ptc/core/rule/server/delegate/init/Rul eConfigurableTypeAttribute.properties"> <Property name="wt.doc.WTDocument" default="name,number,lifeCycle.id,lifeCycle,teamTemplate,tea mTemplate.id,folder.id,organization.id"/> </Configuration>

708

Windchill Customization Guide

Load your Object Initialization Rules Using the Object Initialization Rules administrator, add the following rules to the OIR for WTDocument :
<!-- set the name to a generated number --> <AttrValue id="name" algorithm="com.ptc.windchill.enterprise.revisionControlled.server. impl.NumberGenerator"> <Arg>{GEN:wt.enterprise.SequenceGenerator:WTDOCUMENTID_seq:10:0 }</Arg> </AttrValue> <AttrConstraint id="name" algorithm="com.ptc.core.rule.server.impl.GatherAttributeConstraint s"> <Value algorithm="com.ptc.core.rule.server.impl.GetServerAssignedConstrai nt"/> <Value algorithm="com.ptc.core.rule.server.impl.GetImmutableConstraint"/> </AttrConstraint>

Note For this purposes of this demonstration we will reuse the number generator that exists out of the box. You will probably want to replace this with your own custom generator.
See the online help for the Object Initialization Rules Administration for additional information. Create your new Data Utility The simplest way to get a data utility to use the server generation property is to extend the NumberDataUtility. The minimum amount of code you will need to write is to override the getColumnId method to return your column ID. In our case this is name. So we would create the following data utility.
package com.ptc.carambola.customization.examples.wizard; import com.ptc.core.components.descriptor.DescriptorConstants; import com.ptc.core.components.factory.dataUtilities.NumberDataUtility; public class GeneratedNameDataUtility extends NumberDataUtility { @Override protected String getColumnId() { return DescriptorConstants.ColumnIdentifiers.NAME NAME; } }

Presenting Information in the UI

709

Create your new GUI Component By Default, for the wizards, the NumberDataUtility is returning a NumberInputComponent. For the purposes of this example this component is sufficient. If it is not sufficient for your purposes you can create a custom component. Please see Attribute Customization on page 630 for additional information. Register your new Data Utility for your attribute 1. Since for this example we only want the name attribute behavior to be changed for documents we will create a new attribute we will call "documentName" to use. In your site.xconf file add the following:
<Configuration targetFile="codebase/com/ptc/core/components/components.dataUtilities.propert ies"> <Option serviceClass=" com.ptc.carambola.customization.examples.wizard.GeneratedNameDa taUtility" requestor="java.lang.Object" selector="documentName" cardinality="duplicate"/> </Configuration>

2. You will then have to modify the UIs for Document that display this attribute to include documentName instead of name. In the file createDocumentSetAttributesWizStep.jsp change
<jca:describeAttributesTable var="attributesTableDescriptor" ...

<jca:describeProperty id="name" htmlId="NameInputId"/>


... </jca:describeAttributesTable>

To:
<jca:describeAttributesTable var="attributesTableDescriptor" ... <jca:describeProperty id="documentName" htmlId="NameInputId"/> ... </jca:describeAttributesTable>

Modifying the behavior for all object types If you wanted to modify the behavior of the name attribute for all object types you could simply configure the following with out changing any UIs.
<Configuration targetFile="codebase/com/ptc/core/components/components.dataUtilit ies.properties"> <Option serviceClass=" com.ptc.carambola.customization.examples.wizard.GeneratedNameDa

710

Windchill Customization Guide

taUtility" requestor="java.lang.Object" selector=" name" cardinality="duplicate"/> </Configuration>

Customization Points
None.

Limitations
Since Number is a String attribute this quick customization is only relevant for generated attributes of String Type that do not have a discrete set defined.

Sample Code
Examples of Usage in Windchill Code
com.ptc.core.components.factory.dataUtilities.NumberDataUtility.

Packaged Samples
com.ptc.carambola.customization.examples.wizard.GeneratedNameDataUtility

Additional Resources
Related Customization Documentation
Windchill Client Architecture Overview on page 226 Gathering the Data for the UI on page 555 Attribute Customization on page 630

Presenting Information in the UI

711

Icon Delegates
Objective
You want to author an IconDelegate to display icon for a Windchill object type.

Background
The purpose of object icons is to allow the user to readily distinguish between different Windchill business objects in the Windchill UI. Its possible to associate an icon with a Modeled type while modeling the class. This icon will be used when an object of this type is displayed. In case of soft types, the Type and Attribute Management utility allows the user to associate an icon to be used to represent this soft type in the UI. If the icon specified is an invalid or blank, the icon of the parent type is used. This behavior is accomplished using IconDelegates. However, there are cases where the icons are determined dynamically by other factors, such as attributes on the object. The following table shows the OOTB IconDelegates available for some Windchill Types. Windchill Type wt.part.WTPart wt.epm.EPMDocument wt.doc.WTDocument IconDelegate com.ptc.windchill.enterprise.part.comm ands.delegate.WTPartIconDelegate wt.epm.identity. EPMDocumentIconDelegate wt.doc.DocumentIconDelegate

If the user needs different icons on types (other than the OOTB) or for his own modeled/soft types, he needs to author custom IconDelegates for the respective type.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


User is not supposed to author custom IconDelegates for types for which OOTB IconDelegates exists.

Intended Outcome
User able to view the icons defined by his IconDelegate for the respective Windchill type objects.

712

Windchill Customization Guide

Solution
Author custom IconDelegate for Windchill type to specify your icon.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Java Windchill Type Identifiers

Solution Elements
Element Type <custom_IconDelegate>. java java Description Your IcondDelegate Run time Location: Your xconf file xconf <Windchill>\codebase\* Register your IconDelegate Run time Location: <Windchill>\codebase\*

Procedure Authoring Custom IconDelegate


Windchill UI deals with objects either in Persistable form or in TypeInstance form and hence IconDelegates should be able to handle both the forms. The attributes that participate in determining the icon is easily available if you have the object in Persistable form. If the object is in a TypeInstance form and the attributes are not available, then the TypeInstance has to be inflated to get the attributes, which can degrade the performance. If its in a TypeInstance object, the icon and tool tip for the icon are available as an SCA attribute, which is defined in <WT_HOME>/codebase/LogicalAttributes.xml
<Class name="wt.fc.Persistable"> ------<Property> <LogicalForm>objectIcon</LogicalForm> <ExternalForm>SCA|objectIcon</ExternalForm> </Property> <Property> <!-- This attribute is populated by the SCA|objectIcon function --> <LogicalForm>objectTooltip</LogicalForm> <ExternalForm>NPA|objectTooltip</ExternalForm> </Property>

Presenting Information in the UI

713

Authoring the custom IconDelegate 1. You can extend either wt.fc.IconDelegate or an existing subclass of wt.fc.IconDelegate. 2. There are few APIs that you need to over-ride, where you have to put your icon determining logic. a. These two APIs returns an IconSelector object, which holds the information of the icon for the specific Windchill object. API Signature public IconSelector getStandardIconSelector() getStandardIconSelector throws WTException, IllegalAccessException, InvocationTargetException; public IconSelector getOpenIconSelector() getOpenIconSelector throws WTException, IllegalAccessException, InvocationTargetException; b. This API returns the localized tooltip value that need to be shown for the icon. API Signature Description public String getToolTip() The tooltip to be shown with the icon. c. This API is needed to handle TypeInstances. In the method, you have to check whether the available TypeInstance has all the minimum required attribute values to determine icon and tool tip. If not there is a need to inflate the TypeInstance. Description API Signature protected Boolean inflateRequired() Inflate Required, if TypeInstance doesn't have required attributes to calculate the icon/tool tip.
@Override protected boolean inflateRequired() { boolean need = super.inflateRequired(); TypeInstance ti = getTypeInstanceObject(); if(ti != null && !need){ //check you necessary attributes in TypeInstance // to determine to inflate it or not. }

Description Get the standard selector for the icon

Get a selector for when the object is opened (for example when a folder is opened)

714

Windchill Customization Guide

} return need; }

d. This API is needed to handle TypeInstances. In the method, you have to add all the attributes that drive icon/tool tip determination. This will make sure that they are properly populated when you invoke getStandardIconSelector() or getOpenIconSelector(). API Signature protected void initAttributes (Set<AttributeTypeIdentifier> attributes) Description Update <AttributeTypeIdentifier> with attributes that drivedetermining icon/tool tip.

@Override protected void initAttributes(Set<AttributeTypeIdentifier> attributes) { super.initAttributes(attributes); //add your attributes here }

3. IconDelegate defines a static helper method to create AttributeTypeIdentifier and TypeIdentifier objects that your subclass can use. e.g.
AttributeTypeIdentifier NAME_ATI = getIdentifier("name", "wt.part.WTPart"); TypeIdentifier WTPART_TI = getIdentifier("wt.part.WTPart", null);

4. The getObject() API will convert the current TypeInstance to a Persistable, if not available. Hence its usage should be avoided in favor of getObject(false). Coding Pattern Many of the IconDelegate subclasses now use an internal "params" object to encapsulate whether or not they are working with a Persistable or a TypeInstance. The params object has simple properties that the icon resolution logic can use, regardless of whether the properties were populated from a Persistable or TypeInstance.
AttributeTypeIdentifier PERSONAL_CABINET_ATI = getIdentifier("personalCabinet", "wt.folder.Cabinet"); TypeIdentifier CABINET_TID = getIdentifier("wt.folder.Cabinet", null); protected void initAttributes(Set<AttributeTypeIdentifier> attributes) { super.initAttributes(attributes); attributes.add(PERSONAL_CABINET_ATI); }

Presenting Information in the UI

715

private static class ObjectParams { Cabinet cabinet = null; TypeInstance ti = null; ObjectParams(Cabinet cabinet){ if(cabinet != null) this.cabinet = cabinet; } ObjectParams(TypeInstance ti){ if(ti != null) this.ti = ti; } void reSetObject(Cabinet cabinet){ if(cabinet != null) this.cabinet = cabinet; } boolean isPersonalCabinet(){ if(cabinet != null){ return (cabinet.isPersonalCabinet()); }else{ return (Boolean)ti.get(PERSONAL_CABINET_ATI); } } } protected boolean inflateRequired() inflateRequired { boolean need = false; TypeInstance ti = getTypeInstanceObject(); if(ti != null){ need = super.inflateRequired(); if(!need){ if(ti.get(PERSONAL_CABINET_ATI) == null){ // should contain PERSONAL_CABINET_ATI need = true; } } } return need; } private ObjectParams getObjectParams(){ getObjectParams ObjectParams object_params = null; WTObject obj = super.getObject(false); TypeInstance ti = getTypeInstanceObject(); if (obj != null && obj instanceof Cabinet) {//Object is available object_params = new ObjectParams((Cabinet)obj); } else if(ti != null) {//TypeInstance is available if(inflateRequired()){ obj = super.getObject(true); if (obj != null && obj instanceof Cabinet) { object_params = new ObjectParams((Cabinet)obj); }else{ object_params = null; } } else {

716

Windchill Customization Guide

object_params = new ObjectParams(ti); } } return object_params; }

public IconSelector getStandardIconSelector() getStandardIconSelector throws WTException, IllegalAccessException, InvocationTargetException { IconSelector icon = null; ObjectParams object_params = getObjectParams(); if(object_params != null){ boolean is_personal_cabinet = object_params.isPersonalCabinet(); if(is_personal_cabinet) icon = new IconSelector(PERSONAL_ICON); else icon = new IconSelector(SHARED_ICON); } if (icon == null) icon = super.getStandardIconSelector(); return icon; }

Registering the custom IconDelegate You need to register your custom IconDelegate in an xconf file and propagate into the <WT_HOME>/codebase/service.properties file via xconfmanager.
<Service context="default" name="wt.fc.IconDelegate"> <Option cardinality="duplicate" requestor="<your_type>" serviceClass="<your_IconDelegate>"/> </Service>

Presenting Information in the UI

717

UI Validation
Objective
You want to hide an action or attribute in the UI based on some context information. You want to determine whether or not an action selected in the UI should be allowed to proceed based on some context information. You want to determine whether or not a user can proceed to the next step in a wizard or whether the entire wizard may be submitted, based on the data entered by the user in that wizard.

Background
UI Validation is intended to simplify the experience of the Windchill end-user. There are three categories of UI Validation that will each be discussed in further detail in this document. Pre-Validation Post-Select-Validation Post-Submit Validation

Pre-Validation The first category of UI Validation is referred to as Pre-Validation. This is the category of validation that most people will first associate with UI Validation. PreValidation is a term that describes the process of determining whether or not a UI Component should be available in the UI. An example of Pre-Validation would be disabling the check-in action for an object that is not checked-out. Pre-Validation can be applied to both actions and attributes in the UI. Of the three types of UI Validation, this type is the most often-used. Post-Select Validation A second category of UI Validation is Post-Select Validation. Post-Select Validation is the process of determining whether or not an action should be allowed to proceed once it is selected in the UI. An example of post-select validation would be displaying an error message and not allowing the checkout to proceed if a user tries to perform a checkout on an object that is already checked out. Post-Select Validation applies only to actions.

718

Windchill Customization Guide

Post-Submit Validation The final category of UI Validation is Post-Submit Validation. This type of validation is used exclusively in wizards or other forms where users enter data. An example of Post-Submit Validation would be stopping a user from moving to the next step in a wizard because the data theyve entered in the current step is invalid. Post-Submit Validation applies only to wizard steps and wizard submissions.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Pre-Validation - Suppose you want to hide an action in the UI from users who are not members of the current container s team. Post-Select Validation - After a user selects an action, you want to determine whether or not the target object is in a certain lifecycle state before allowing the action to proceed. Post-Submit Validation - After a user enters data in the first step of a wizard and tries to navigate to the next step, you want to determine whether or not the information entered on the first step is valid before allowing them to proceed.

Intended Outcome
Pre-Validation - Before the page is rendered, you are able to determine whether or not the user is a member of the current container s team. If not, the action is not displayed on the page. Post-Select Validation - After the user invokes the action, you are able to check the target objects lifecycle state. If the state is not the state you require, you can display a message to the user, and the action is not performed. Post-Submit Validation - When the user clicks next on the wizard, you get the data entered in the current step and are able to determine whether or not it is adequate to allow the user to proceed to the next step. If the data is inadequate or invalid, you can display a message to the user and not allow them to proceed to the next step.

Solutions
Pre-Validation - Determine whether the business logic is specific to a single action or attribute, or if the same logic could apply to multiple actions or attributes. If the logic is specific to a single UI Component (action or attribute), add the logic to a Validator. If the logic could apply to multiple UI Components, add the logic to a Filter. Finally, associate the Validator or Filter

Presenting Information in the UI

719

with the UI Component to ensure that the business logic is applied to that component. Pre-Validation in a Validator - Implement the performFullPreValidation() and performLimitedPreValidation() methods in a Validator to contain the desired business logic. Pre-Validation in a Filter - Implement the preValidateAction method in a Filter to contain the desired business logic. Post-Select Validation - Implement the validateSelectedAction() and validateSelectedMultiSelectAction() methods in a Validator to define the desired business logic, and associate the Validator with the action. Post-Submit Validation - Implement the validateFormSubmission() method in a Validator to define the desired business logic, and associate the Validator with the wizard step or the entire wizard.

Prerequisite Knowledge
To achieve this objective, you need to have an understanding of the following: The actions framework in the Windchill client architecture. The Application Context or service.properties mechanism for registering delegates. A basic familiarity with the NmCommandBean and its methods will be helpful. The validation service is very generic in nature. It does not provide the APIs youll need in order to determine whether or not something is valid. The service will provide your validators or filters with the context data and form data you need to determine whether or not a UI Component is valid. But you will need to know what to do with that data in order to apply your validation business logic.

The Additional Resources section below includes references to many or all of these subjects.

Solution Elements
In addition to the solution elements involved in UI Validation, this section also contains some definitions of key terms (in bold italic). Element Type StandardUIComponentValidation Java class Service Description Often referred to as the validation service. This is the service class that controls UI Validation. It receives validation

720

Windchill Customization Guide

Element

Type

Description requests from the client infrastructure and delegates to the appropriate validators and filters for validation results. It then passes the validation results back to the client infrastructure. Customizers and application developers should not have to interact directly with this class. Often referred to as a validation key. A UIValidationKey is used to identify the UI Component being validated. You can think of a UIValidationKey as having a one-to-one relationship with an action or attribute. Often referred to as the validation criteria. The UIValidationCriteria is a bean class that contains the context (request, session) data which is passed from the client infrastructure to the validators and filters via the validation service. Most of the content in the UIValidationCriteria is taken directly from the NmCommandBean, although the objects are typically returned as WTReferences, as opposed to NmOids. Often referred to as a validation result. A UIValidationResult represents one unit of validation. In other words, it associates a validation status with a UI Component (action or attribute). In cases

UIValidationKey

Java class

UIValidationCriteria

Java class

UIValidationResult

Java class

Presenting Information in the UI

721

Element

Type

UIValidationResultSet

Java class

Description where validation is being performed for the same action on multiple objects, a UIValidationResult can be associated with each object. Often referred to as a result set. A UIValidationResultSet is just a collection of UIValidationResult objects. The result sets are used in situations where multiple validations are being performed at the same time. For example, if a validator was doing a prevalidation check for the same action on multiple objects, it could aggregate the validation results for each of the objects into a UIValidationResultSet. Often referred to as validation status. This is an enumeration used to determine if or how a UI component should be displayed in the UI. For example, there are values to indicate that an action should be hidden, that an action should be disabled, or that an action should be enabled. Often referred to as a feedback message. This is a message that can be associated with a validation result. It is only used for postselect validation and post-submit validation. Any feedback messages associated with validation results returned by pre-validation will be ignored.

UIValidationStatus

Java class

UIValidationFeedbackMsg

Java class

722

Windchill Customization Guide

Element

Type

Description Feedback messages can have different feedback types (FeedbackType.java) associated with them to indicate whether they are, for example, error messages, warning messages, or info messages. This is the interface that all validator implementations need to implement. However, validators should not directly implement this interface. Rather, they should extend DefaultUIComponentValidator. Each UI component can have zero or one validators associated with it. Typically, a validator will contain logic specific to a single UI component. For more generic validation logic that applies to multiple UI components, a filter is typically used. Validators are called by the validation service to determine the validation status for a specific UI component. Customizers and application developers should not have to interact directly with this class. This is a default implementation of the UIComponentValidator interface. All validator implementations should extend this class. This is the interface that all filter implementations need to implement. However, filters should not implement this interface directly. Rather, they

UIComponentValidator

Java interface

DefaultUIComponentValidator

Java class

ValidationFilter

Java interface

Presenting Information in the UI

723

Element

Type

Description should extend DefaultSimpleValidationFilter or DefaultUniversalValidationFilter. Each UI component can have zero to many filters associated with it. Typically, a filter will contain generic validation logic that could apply to multiple UI components. For validation logic that is specific to a single UI component or a small set of UI components, a validator is typically used. There are two categories of filters: simple filters and universal filters. Simple filters are applied on a component-bycomponent basis. In other words, you have to choose which UI components the logic in a simple filter will apply to. Conversely, universal filters are applied to all UI components, which means you have to choose which UI components the logic in a universal filter does not apply to. Filtersare called by the validation service to determine the validation status for a specific UI component. Customizers and application developers should not have to interact directly with this class. This is the interface that all simple filter implementations need to implement. However, simple filters should not implement this interface directly. Rather, they should extend

SimpleValidationFilter

Java interface

724

Windchill Customization Guide

Element

Type

Description DefaultSimpleValidationFilter. Customizers and application developers should not have to interact directly with this class. This is the interface that all universal filter implementations need to implement. However, universal filters should not implement this interface directly. Rather, they should extend DefaultUniversalValidationFilter. Customizers and application developers should not have to interact directly with this class. This is a default implementation of the SimpleValidationFilter interface. All simple filter implementations should extend this class. This is a default implementation of the UniversalValidationFilter interface. All universal filter implementations should extend this class. This is an interface that all solution group implementations need to implement.

UniversalValidationFilter

Java interface

DefaultSimpleValidationFilter

Java class

DefaultUniversalValidationFilter Java class

UIComponentSolutionGroup

Java interface

*actions.xml

A solution group is a special type of validator that is used for prevalidation based on the installed solutions. For example, if a given action should not be available if Windchill ProjectLink is not installed, that logic should be defined in a solution group. XML file(s) There are multiple satellite versions of actions.xml files (typically one per module), which contain action definitions.

Presenting Information in the UI

725

Element

Type

Description It is also in these files that we configure actions to include simple filters, and exclude universal filters. There are multiple satellite versions of service.properites. xconf files (typically one or more per module), which contain class delegate registry entries. These files are where you register your validators, filters and solution groups so that the validation service knows where to find them.

*service.properties.xconf

XConf file (s)

Pre-Validation Pre-Validation Sequence


The pre-validation sequence begins with the client infrastructure (typically, but not exclusively, the StandardNmActionService) sending a list of UI components to the validation service. The expectation is that for each of those UI components, the validation service will return a validation result indicating the display status for the UI component. Each UI component is represented by a validation key. It is also expected that the Client Infrastructure passes context (session, request, or form) data to the validation service inside of a validation criteria object.

726

Windchill Customization Guide

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). Once the validation service receives the validation request from the client infrastructure, the validation service iterates through each of the validation keys, and performs several tasks to determine the validation status for each of the keys. The first such task that the validation service performs is to see whether or not a given validation key represents a component that should be hidden, based on the PTC solutions that are installed. This is accomplished by referencing a cache of invalid validation keys that is created when the validation service is first started. To create the cache, the validation service simply calls all registered solution groups and asks for a list of invalid validation keys from each of them, based on the installed solutions. If the cache of invalid solution-based keys contains the current validation key, the validation service sets the components status to hidden and does not perform any additional validation on the component. Otherwise, if the cache of invalid solution-based keys does not contain the current validation key, the validation service continues with its pre-validation checks.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. For each validation key, the validation service performs a series of tasks to determine the validation status for that key. The tasks are executed in the

Presenting Information in the UI

727

Key following order: a. Check to see if the validation key is in the list of invalid keys for the installed solution set. The second pre-validation check performed by the validation service is to see whether or not the component is hidden or disabled by the role-based UI service. The role-based UI service was introduced in 8.0 as a way for admin users to configure the display of UI components based on a user s role. With the introduction of the UI Validation Service in 9.0, the role-based UI service has become a special delegate of the UI Validation Service. If the role-based UI service returns a status of hidden or disabled, the validation service sets the components status correspondingly and does not perform any additional validation on the component. Otherwise, if the role-based UI service returns an enabled status, the validation service continues with its prevalidation checks.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. For each validation key, the validation service performs a series of tasks to determine the validation status for that key. The tasks are executed in the following order: a. Check to see if the validation key is in the list of invalid keys for the
Windchill Customization Guide

728

Key installed solution set. b. Check to see if the role-based UI service was configured to disable or hide the component. Assuming the role-based UI service says the component should be enabled, the validation service will next check to see if any filters are associated with the UI component. To determine which filters should be applied to a UI component, the validation service references some additional cached data that is stored when the validation service is first started. The first cache referenced contains a list of all registered universal filters. When a filter is defined and registered as a universal filter, it is automatically applied to all UI components by default. If any universal filters are found in this cache, they are automatically added to the list of filters that will be applied to a given UI component. Although universal filters are applied to all UI components by default, there is support for configuring actions to ignore individual universal filters. (Currently, there is no similar support available for configuring attributes to ignore universal filters, meaning that any universal filter will always be applied to all attributes.) If you want to configure an action to ignore a universal filter, you do so in the actions definition in an actions.xml file. When the validation service is started, a second cache is created containing a map of actions and any universal filters they are configured to ignore. If an entry is found in this cache for a given action, the universal filters that are supposed to be ignored will be removed from the list of filters to be applied to the UI component. Finally, the validation service references a third cache to determine any additional filters that should be applied to a UI component. This third cache is a map that associates actions with simple filters. A filter that is defined and registered as a simple filter must be explicitly associated with an action in order for it to be applied to any actions. (Currently, there is no support for associating a simple filter with an attribute.) If you want to configure an action to use a simple filter, you do so in the actions definition in an actions.xml file. When the validation service is started, this third cache of actions and associated simple filters is created. To summarize, the algorithm used by the validation service to determine which filters should be applied to a given UI component, you could use the following formula: Filters per component = all universal filters ignored universal filters + associated simple filters

Presenting Information in the UI

729

Once the list of filters is established, the validation service calls each of the filters to determine the validation status for the UI component. Please note that the order in which the filters are called can not be guaranteed. If any of the filters return a validation status of hidden or disabled, the validation service sets the components status correspondingly and does not perform any additional validation on the component. Otherwise if all of the filters applied to a given UI component return an enabled status, the validation service continues with its pre-validation checks.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. For each validation key, the validation service performs a series of tasks to determine the validation status for that key. The tasks are executed in the following order: a. Check to see if the validation key is in the list of invalid keys for the installed solution set. b. Check to see if the role-based UI service was configured to disable or hide the component.
Windchill Customization Guide

730

Key c. Check to see if any of the filters associated with the UI component indicate that the component should be disabled or hidden. (See the diagram on the following page for additional details.)If none of the filters indicate that a UI component should be disabled or hidden, the final check performed by the validation service for a given UI component is to check to see if there is a validator associated with the UI component. A validator is associated with a UI component by creating an entry in a service. properties.xconf file that links the action id (for actions) or the descriptor id (for attributes) to the class name of the validator class that should be used for that component. If there is not a validator registered for the UI component, the component is enabled. Otherwise, if there is a validator associated with the UI component, the validation service calls that validator to get a validation status for the UI component.

Presenting Information in the UI

731

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. For each validation key, the validation service performs a series of tasks to determine the validation status for that key. The tasks are executed in the following order: a. Check to see if the validation key is in the list of invalid keys for the installed solution set. b. Check to see if the role-based UI service was configured to disable or hide the component. c. Check to see if any of the filters associated with the UI component indicate that the component should be disabled or hidden. d. Get the validation status from the validator, if there is one associated with the UI component. (See the diagram on the following page for additional details.)At this point, the validation service has completed its validation checks for each UI component. If the client infrastructure passed a single UI component to the validation service to be pre-validated, the validation service will return a single validation result to the caller. If multiple UI components were passed to the validation service for pre-

732

Windchill Customization Guide

validation, the validation service will organize the validation results for each component into a validation result set, which contains one result per UI component. The validation result set is then returned to the caller.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. For each validation key, the validation service performs a series of tasks to determine the validation status for that key. The tasks are executed in the following order: a. Check to see if the validation key is in the list of invalid keys for the installed solution set. b. Check to see if the role-based UI service was configured to disable or hide the component. c. Check to see if any of the filters associated with the UI component indicate that the component should be disabled or hidden. d. Get the validation status from the validator, if there is one associated with

Presenting Information in the UI

733

Key the UI component. 3. Return the validation result or validation result set to the client infrastructure.

Post-Select Post-Select Validation Sequence


Conceptually, post-select validation occurs immediately after a user invokes an action in the UI. In reality, however, post-select validation actually takes place when the target page is being rendered. In other words, there is logic in begin.jspf (code that is included on every JSP page authored in the Windchill Client Architecture) that will call the validation service to determine whether or not the page should be rendered before actually rendering it. Validators are the only accepted locations for post-select validation logic. Unlike pre-validation, there is no interaction with the solution groups, role-based UI service, or filters for post-select validation. Therefore, the sequence for post-select validation is much simpler than for pre-validation. First, the client infrastructure calls the validation service, passing the action corresponding to the page being rendered (this action is represented by a validation key). Along with the action, the client infrastructure passes the context data in the form of a validation criteria instance.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). After receiving a post-select validation request from the client infrastructure, the validation service checks to see if there is a validator associated with the specified action.

734

Windchill Customization Guide

As is the case with pre-validation, a validator is associated with an action by creating an entry in a service.properties.xconf file that links the action id to the class name of the validator class for that action. If there is not a validator registered for the action, the user is permitted to perform the action. Otherwise, if there is a validator associated with the action, the validation service calls that validator to get a validation status for the action.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. The validation service checks to see if there is a validator associated with the action. If so, it calls the validator to get the validation status (permitted or denied) for the action. After the validator returns its validation result, the validation service simply passes along the validation result returned by the validator to the client infrastructure. The client infrastructure will check to see whether that status is permitted or denied. If the status is permitted, the page or wizard is displayed. If the status

Presenting Information in the UI

735

is denied, the user is redirected to the previous page, and if the validator returned a message indicating why the action was denied, that message is displayed to the user.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. The validation service checks to see if there is a validator associated with the action. If so, it calls the validator to get the validation status (permitted or denied) for the action. 3. The validation service passes the validation status (wrapped in a validation result) from the validator to the client infrastructure, which either displays the target page/wizard, or brings the user back to the page where the action was invoked.

Post-Submit Post-Submit Validation Sequence


Post-submit validation occurs when a user navigates from one step to another in a wizard, or when a user submits the entire wizard. Validators are the only accepted locations for post-submit validation logic Unlike pre-validation, there is no interaction with the solution groups, role-based UI service, or filters for post-submit validation. Therefore, the sequence for postsubmit validation is much simpler than for pre-validation. In fact, it is nearly identical to the sequence for post-select validation.
Windchill Customization Guide

736

First, the client infrastructure calls the validation service, passing the id associated with the Next or OK wizard action (this id is represented by a validation key). Along with the validation key, the client infrastructure passes the context data in the form of a validation criteria instance.

Key 1. The Client Infrastructure calls the validation service, passing an id associated with a wizard's "Next" or "OK" action (represented by a validation key), and the context data (represented by a validation criteria instance). After receiving a post-submit validation request from the client infrastructure, the validation service checks to see if there is a validator associated with the wizards Next or OK action. As is the case with pre-validation and post-select validation, a validator is associated with a wizards Next or OK action by creating an entry in a service. properties.xconf file that links the action id to the class name of the validator class for that action.

Presenting Information in the UI

737

If there is not a validator registered for the action, the user is permitted to move to the next step or submit the entire wizard. Otherwise, if there is a validator associated with the Next or OK action, the validation service calls that validator to get a validation status for the action.

Key 1. The Client Infrastructure calls the validation service, passing an id associated with a wizard's next or OK action (represented by a validation key), and the context data (represented by a validation criteria instance). 2. The validation service checks to see if there is a validator associated with the "Next" or "OK" action. If so, it calls the validator to get the validation status (permitted or denied) for the action. After the validator returns its validation result, the validation service simply passes along the validation result returned by the validator to the client infrastructure. The client infrastructure will check to see whether that status is permitted or denied. If the status is permitted, the user is allowed to proceed to the next step in the wizard, or complete the wizard submission. If the status is denied, the user

738

Windchill Customization Guide

restricted from moving to the next wizard step or submitting the wizard, and if the validator returned a message indicating why the action was denied, that message is displayed to the user.

Key 1. The Client Infrastructure calls the validation service, passing an action (represented by a validation key) corresponding to the page being rendered, and the context data (represented by a validation criteria instance). 2. The validation service checks to see if there is a validator associated with the "Next" or "OK" action. If so, it calls the validator to get the validation status (permitted or denied) for the action. 3. The validation service passes the validation status (wrapped in a validation result) from the validator to the client infrastructure, which either allows the user to proceed to the next step in the wizard or submit the entire wizard, or brings the user back to the wizard step where the action was invoked.

Procedure Pre-Validation Pre-Validation


This section describes the steps you should perform for various operations related to pre-validation. This section contains the following procedures: Distinguishing between Pre-Validation Statuses on page 740 Implementing Solution-Based Pre-Validation on page 741

Presenting Information in the UI

739

Implementing Role-Based Pre-Validation on page 744 Implementing Validation Filters on page 745 Implementing Validators for Pre-Validation on page 750

Distinguishing between Pre-Validation Statuses Depending on whether youre validating actions or attributes, the validation statuses youll return from your filters or validators will vary. This section describes some of the rules and best practices for determining which validation statuses to return in certain scenarios. Action Pre-Validation Statuses The validation service and client infrastructure currently support three statuses for pre-validated actions: enabled, disabled, and hidden. As you might suspect, an enabled status means that the action is visible to the user and selectable for the user. The disabled status means that the action is visible to the user, but not selectable (i.e., the action is grayed-out). And the hidden status means that the action is not visible at all to the user. Note that there is currently no support to disable actions rendered as icons (in a table header or table row, for example). If the validation service returns a disabled status for an action icon, the client infrastructure will simply hide the action icon. Whether youre implementing a filter or validator to perform pre-validation logic, youll be expected to return a validation status (either directly or wrapped in a validation result) to the validation service. (If you implement a solution group, the validation service automatically assigns a hidden status to all components deemed invalid by that solution group.) When trying to choose which status to return from your validator or filter, use the following rules of thumb: Always err on the side of enabling. If you cant determine conclusively whether or not an action should be available, give it an enabled status. Chances are there is additional validation that will occur down the line (whether it be another filter, a validator, or post-select validation) when there is more context information available that can disable or deny the user. Youre almost always better off showing a user an action they cant perform than hiding an action that they should be able to perform. When trying to choose between hidden and disabled, ask yourself whether the action could ever be visible to the user in the current context. If the answer is yes, then the status should be disabled. For example, the check-out action is not valid for an object that is currently checked out. But if that same object wasnt checked out, the check-out action would be available to the user. In

740

Windchill Customization Guide

that case, a disabled status is appropriate. However, suppose you had an action that was only available to admin users, and your user is a non-admin. In that case, the action would never be available to that user, so a hidden status would be appropriate. Attribute Pre-Validation Statuses The validation service and client infrastructure currently support four statuses for pre-validated attributes: hidden (ATTR_HIDDEN), hidden value (ATTR_HIDDEN_VALUE), read only (ATTR_READ_ONLY), and visible (ATTR_VISIBLE). The hidden status means that the attributes name nor value is never displayed in the UI. The hidden value status means that the attributes name will be displayed, but not its value. The read only status is used to indicate that an attributes name and value are displayed, but that user may not modify the value. And the visible status is used to indicate that the attributes name and value will be displayed and that the user may modify the value when it is available in a form or wizard. To determine which status applies to your attribute under certain conditions, you should probably seek clarification from the customer, product manager, etc. There arent really any generic rules that can be applied to all attributes. You may recall that a single filter can be applied to multiple actions and attributes. So you may be wondering which status the filter should return in situations where it may be applied to both actions and attributes. In those situations, use the statuses reserved for actions (enabled, disabled, and hidden). The client infrastructure will treat enabled like visible, disabled like read only, and hidden like hidden. When applying a validator to an attribute in a table the validator will be applied to the entire column. The validators for an attribute cannot be applied to a single cell. The entire column will receive the most restrictive state found for any column. For example, if one cell is read only and one is hidden, the entire column will be hidden. Implementing Solution-Based Pre-Validation As indicated in the Pre-Validation Sequence section, the first pre-validation check performed by the validation service is to determine whether or not the UI component should be hidden based on the installed set of Windchill solutions. For example, if Windchill PDMLink is not installed, certain actions should never be available.

Presenting Information in the UI

741

As a rule of thumb, this type of solution-based logic should NEVER be included in your validator or filter classes. You can assume that if your validator or filter has been called, the UI component being validated has already passed any applicable solution-based checks. Solution-based logic should be implemented in a solution group. Implementing a Solution Group Implementing a solution group class is very easy. All you need to do is create a class that implements the UIComponentSolutionGroup Interface, and in your class, implement the getInvalidInstallKeys() method. In that method, you check to see which solutions are installed, and return a list of validation keys representing actions or UI components that should never be available based on the installed solutions. The class on the following page is an simple example of a solution group whose getInvalidInstallKeys() method checks to see if Pro/INTRALINK is installed. If Pro/I is installed, it returns a list of validation keys representing actions or components that should never be available.
package com.ptc.windchill.enterprise.myPackage; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import wt.log4j.LogR; import wt.util.InstalledProperties; public class MySolutionGroup implements UIComponentSolutionGroup { private static UIValidationKey listKey = UIValidationKey.newInstance("list", "change"); private static UIValidationKey crKey = UIValidationKey.newInstance("listChangeRequests", "change"); private static UIValidationKey cnKey = UIValidationKey.newInstance("listChangeNotices", "change"); private static UIValidationKey viewKey = UIValidationKey.newInstance("view", "change"); /* * DEFINE ADDITIONAL ACTIONS AND UI COMPONENTS AS NEEDED */ private static Logger logger = LogR.getLogger(MySolutionGroup.class.getName()); public List getInvalidInstallKeys() { if (logger.isDebugEnabled()){ logger.debug("ENTERING MySolutionGroup.getInvalidKeys"); }

742

Windchill Customization Guide

ArrayList invalidList = new ArrayList(); // if PRO-I is installed, the following UI components are not valid. if (InstalledProperties.isInstalled(InstalledProperties.PRO_I)){ invalidList.add(listKey); invalidList.add(listKey); invalidList.add(cnKey); invalidList.add(viewKey); } /* * ADD ADDITIONAL SOLUTION-BASED CHECKS AS NEEDED */ if (logger.isTraceEnabled()){ logger.trace("RETURNING " + (List)invalidList); } (logger.(trace("RETURNING " + (List)invalidList))){ logger.debug("EXITING MySolutionGroup.getInvalidKeys"); } return invalidList; } }

If youre wondering how to determine which values to include in the validation key factory methods, it depends on whether youre creating a validation key for an action or an attribute. If youre creating a validation key for an action, the first argument represents the action name (from *actions.xml) and the second argument represents the object type (from *actions.xml). For example, to create a validation key to represent the product action below, you would call UIValidationKey. newInstance(product, navigation);
<objecttype name="navigation navigation" class="" resourceBundle="com.ptc.core.ui.navigationRB"> <action name="product product" renderType="GENERAL"> <command class="netmarkets" method="servlet/Navigation?tab=product" windowType="page"/> </action> ...

Constructing the ValidationKey If youre wondering how to determine which values to include in the validation key factory methods, it depends on whether youre creating a validation key for an action, an action model, or an attribute. If you are creating a validation key for an action, the first argument represents the action name (from *actions.xml) and the second argument represents the object type (from *actions.xml). For example, to create a validation key to represent the product action below, you would call UIValidationKey.newInstance(product, navigation);
Presenting Information in the UI 743

<objecttype name="navigation navigation" class="" resourceBundle="com.ptc.core.ui.navigationRB"> <action name="product product" renderType="GENERAL"> <command class="netmarkets" method="servlet/Navigation?tab=product" windowType="page"/> </action> ...

If you are creating a validation key for an action model, the first argument represents the action model name (from *actionModels.xml) and the seconfdargument represents the object type which is always object. For example, to create a validation key to represent the carambola_sub_model below you would call UIValidationKey.newInstance(carambola_sub_model, object);
<model name="carambola_sub_model"> <action name="ripe" type="carambola" /> <action name="grow" type="carambola" /> </model>

If you are creating a validation key for an attribute, simply use the descriptor ID used for that attribute in the Windchill client architecture. For example, to create a validation key for the attribute whose descriptor ID is iteration, you would call UIValidationKey.newInstance(iteration); Registering a Solution Group Once you've created and built your solution group, the only thing left to do is register it. You register a solution group in *service.properties.xconf by creating an entry like this:
<Service context="default" name="com.ptc.core.ui.validation.UIComponentSolutionGroup"> <Option requestor="null" serviceClass="[your fully-qualified SolutionGroup class name]" selector="[any unique key, e.g., "ChangeMgmtSolutionGroup")]" /> </Service>

The propagated entry in *service.properties should look like this:


wt.services/svc/default/com.ptc.core.ui.validation.UIComponentSolu tionGroup/[any unique key, e.g., "MySolutionGroup"]/null/0=[your fully-qualified solution group class name ]

Once your solution group is registered, its logic should be checked any time the validation service is called to perform pre-validation. (Its results are actually cached after the first invocation.) Implementing Role-Based Pre-Validation The second pre-validation check performed by the validation service is to call the role-based UI service to see whether or not an admin user has configured a component to be hidden or disabled for certain users. This check is built into the

744

Windchill Customization Guide

validation service, so there is no work for a customizer to perform. For more information about configuring the role-based UI service as an admin user, please see the Customizing Role-Based UI Function Action Visibility. Implementing Validation Filters Assuming the solution-based and role-based checks pass, the next thing the validation service will do when performing a pre-validation activity is to determine which filters apply to the UI component. As previously mentioned, a typical validation filter will contain pre-validation logic that applies to multiple UI components. So rather than duplicating this logic in multiple validators, a single filter can be created and the logic can be selectively applied to UI components or applied to all UI components. Choose Your Filter Type Simple or Universal The first thing youll need to decide when implementing a filter is whether it should be a simple filter or a universal filter. To do this, ask if your filter logic is more global in nature or if it only applies to a relatively small number of actions. If the logic applies to most actions, you would create a universal filter. In this case, the filter will be applied to all actions, although actions can always be configured to "opt out" of the filter. If your filter logic only applies to a small subset of actions, you would create a simple filter. In this case, you would need to individually configure actions where you want this filter applied. If you're not sure which type of Filter to implement, it's probably easier to start with a simple filter, and convert it to a universal filter later, if necessary. One additional consideration is that there is currently no support for applying a simple filter to attributes, nor is there support for configuring attributes to ignore universal filters. So if you have filtering logic that you want applied to attributes, your only choice is a universal filter. Just be conscious that any universal filter will be applied to all attributes, all the time, no matter what. Implementing a Simple Filter When implementing a simple filter, youll need to create a class that extends com. ptc.core.ui.validation.DefaultSimpleValidationFilter. Then simply override the preValidateAction() method to contain your validation logic and return a validation status. The following class skeleton is an example of a simple filter that would hide an action if the context object is marked for delete.
public class MarkedForDeleteFilter extends DefaultSimpleValidationFilter{

Presenting Information in the UI

745

@Override public UIValidationStatus preValidateAction(UIValidationKey key, UIValidationCriteria criteria){ // ENABLE by default UIValidationStatus status = UIValidationStatus.ENABLED; WTReference contextObj = criteria.getContextObject(); if (/*contextObj.isMarkedForDelete() == */ true){ status = UIValidationStatus.HIDDEN; } return status; ) )

Implementing a Universal Filter You implement a universal filter the exact same way as you would implement a simple filter, with one exception. When implementing a universal filter, you need to extend com.ptc.core.ui.validation.DefaultUniversalValidationFilter. Otherwise, the implementation is exactly the same as a simple filter. Suppose we wanted to implement the filter in the simple filter example as a universal filter instead. Here is what that class skeleton would look like as a universal filter:
public class MarkedForDeleteFilter extends DefaultUniversal ValidationFilter{ @Override public UIValidationStatus preValidateAction(UIValidationKey key, UIValidationCriteria criteria){ // ENABLE by default UIValidationStatus status = UIValidationStatus.ENABLED; WTReference contextObj = criteria.getContextObject(); if (/*contextObj.isMarkedForDelete() == */ true){ status = UIValidationStatus.HIDDEN; } return status; } }

Registering Filters Once you've created a filter, the next step is to register it. Depending on the type of filter you implement (universal or simple), your filter registry will differ. When providing a selector in your registry, the convention is to use the filter class name with replacing the first letter with a lower-case letter, and eliminating the "filter" suffix (e.g., "MarkedForDeleteFilter" would have a selector of "markedForDelete"). The following details should clarify: To register a universal filter, in *service.proeprties.xconf, create an entry like this:
<Service context="default" name="com.ptc.core.ui.validation.UniversalValidationFilter UniversalValidationFilter"> <Option

746

Windchill Customization Guide

serviceClass="com.ptc.windchill.enterprise.markedfordelete.validat ors.MarkedForDeleteFilter" selector="markedForDelete" requestor="null" /> </Service> When registering a simple filter, the only difference is the name attribute of the Service element: <Service context="default" name="com.ptc.core.ui.validation.SimpleValidationFilter SimpleValidationFilter"> <Option serviceClass="com.ptc.windchill.enterprise.somepackage.validators. MarkedForDeleteFilter" selector="markedForDelete" requestor="null" /> </Service>

Associating and Dissociating Actions with a Filter Once you've created and registered your filter, the last thing to do is to associate actions with your Simple Filter, or dissociate actions with your Universal Filter. This is done in *actions.xml. Dissociating Actions from a Universal Filter In cases where you don't want a global filter to be applied to specific actions, you need to find those actions in *acitons.xml that and update them to include an excludeFilter element, as shown below:
<objecttype name="navigation" class="" resourceBundle="com.ptc.core.ui.navigationRB"> <action name="home" renderType="GENERAL"> <command class="netmarkets" method="servlet/Navigation?tab=home" windowType="page"/> <excludeFilter excludeFilter name="markedForDelete" name="markedForDelete /> </action> <action name="program" renderType="GENERAL"> <command class="netmarkets" method="servlet/Navigation?tab=program"windowType="page"/> <excludeFilter excludeFilter name="markedForDelete" name="markedForDelete /> </action> <action name="product" renderType="GENERAL"> <command class="netmarkets" method="servlet/Navigation?tab=product" windowType="page"/> <excludeFilter excludeFilter name="markedForDelete" /> </action> ...

Note The name attribute of the excludeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.

Presenting Information in the UI

747

Associating Actions with a Simple Filter Suppose (hypothetically) you created and registered a simple filter called ProblemReportStatusFilter (and registered it with a selector of "problemReportStatus") that disabled actions if a problem report had a certain status. And suppose you wanted to apply it to a few actions. You would find the actions you want to apply your Filter to in *actions.xml and modify them to include includeFilter elements like this:
<objecttype name="problemReport" class="wt.change2.WTChangeIssue" resourceBundle="com.ptc.windchill.enterprise.change2.changeManagem entActionsRB"> <action name="create" > <command class=/> <includeFilter name="problemReportStatus" /> </action> <action name="edit" > <command class=/> <includeFilter includeFilter name="problemReportStatus" /> </action> <action name="editModifyContentOnly" id="editModifyContentOnly"> <command class="/> <includeFilter includeFilter name="problemReportStatus" /> </action> ...

Note Again, the name attribute of the includeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Multiple Filter Inclusions/Exclusions Inclusions/Exclusions for the Same Action In theory, an action can have any number of universal filters dissociated from it and any number of simple filters associated with it. You would just add as many includeFilter and excludeFilter elements as you need in *actions.xml. For example:
<action name="removeChangeTask" renderType="GENERAL" ajax="row"> <command onClick="removeChangeTask(event)" windowType="no_content" /> <includeFilter name="problemReportStatus /> <excludeFilter name="markedForDelete" /> <includeFilter name="someSimpleFilter" /> <excludeFilter name="someUniversalFilter" /> ... </action>

Note The order of the includeFilter and excludeFilter elements does not matter, nor does it have any bearing on the order in which the filters are called.
Windchill Customization Guide

748

Associating and Dissociating Action Models with a Filter Once you've created and registered your filter, you can also associate action models with your Simple Filter, or dissociate action models with your Universal Filter. This is done in *actionModels.xml. Dissociating Action Models from a Universal Filter In cases where you don't want a global filter to be applied to specific action models, you need to find those action models in *actionModels.xml that and update them to include an excludeFilter element, as shown below:
<model name="CustEx_default_myTab"> <action name="CustEx_simpleTable1" type="object" /> <action name="CustEx_simpleTable2" type="object" /> <action name="CustEx_simpleTable3" type="object" /> <excludeFilter name=" someUniversalFilter " /> </model>

Note The name attribute of the excludeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Associating Action Models with a Simple Filter Suppose (hypothetically) you created and registered a simple filter called ProblemReportStatusFilter (and registered it with a selector of "problemReportStatus") and you wanted to apply it to a few action models. You would find the action models you want to apply your Filter to in *actionModels.xml and modify them to include includeFilter elements like this:
<model name="CustEx_default_myTab"> <action name="CustEx_simpleTable1" type="object" /> <action name="CustEx_simpleTable2" type="object" /> <action name="CustEx_simpleTable3" type="object" /> <includeFilter name="testFilter" /> </model>

Note The name attribute of the includeFilter element should correspond to the selector used to register the filter in *service.properties.xconf.
Multiple Filter Inclusions/Exclusions Inclusions/Exclusions for the Same Action Model In theory, an action can have any number of universal filters dissociated from it and any number of simple filters associated with it. You would just add as many includeFilter and excludeFilter elements as you need in *actionModels.xml.

Presenting Information in the UI

749

For example:
<model name="CustEx_default_myTab"> <action name="CustEx_simpleTable1" type="object" /> <action name="CustEx_simpleTable2" type="object" /> <action name="CustEx_simpleTable3" type="object" /> <includeFilter name="problemReportStatus /> <excludeFilter name="markedForDelete" /> <includeFilter name="someSimpleFilter" /> <excludeFilter name="someUniversalFilter" /> ... </model>

Note The order of the includeFilter and excludeFilterelements does not matter, nor does it have any bearing on the order in which the filters are called.
Implementing Validators for Pre-Validation Assuming the solution-based, role-based, and filter checks pass, the final thing the validation service will do when performing a pre-validation activity is to call the validator associated with a UI component. As previously mentioned, a typical validator will contain pre-validation logic that is unique to a single UI component or a small set of related components. In other words, it is possible to associate a single validator with multiple UI components, if the validation logic is identical for those components. But in that case, you may also want to consider a filter. The advantage of using a filter is that you would always have the option to add a validator at a later time if the logic for one of the components deviates from the others. Limited Pre-Validation vs. Full Pre-Validation There are actually two pre-validation methods defined in a validator one method is for limited pre-validation, and the other is for full pre-validation. The respective methods youll implement are called performLimitedPreValidation() and performFullPreValidation(). The distinction between limited pre-validation and full pre-validation is made for performance considerations. The client infrastructure will ask the validation service to perform limited pre-validation in situations where performance is essential. Currently, the only scenario when limited pre-validation is requested for actions is when the row-level action icons are being pre-validated in a table or tree. For attributes, limited pre-validation is always requested. As a validator developer, you dont need to figure out when limited pre-validation is called vs. when full pre-validation is called. You just implement both methods (performLimitedPreValidation() and performFullPreValidation()) in your validator and assume that the infrastructure will call the appropriate method under the given

750

Windchill Customization Guide

conditions. Its possible and, in many cases, likely that your performLimitedPreValidation() and performFullPreValidation() methods will have the exact same logic. Limited Pre-Validation Pre-Validation Explained Consider a table that has 50 rows, with five row-level action icons in each row. Before the table is rendered, there will be 250 (50 rows x 5 actions) pre-validation checks performed to determine which actions should be available in each row. If each of those validation checks even takes .01 second, that means that 2.5 seconds will be spent on pre-validation alone before the page is even rendered. In this case, we are willing to sacrifice validation accuracy for performance. The client infrastructure will request limited pre-validation from the validation service in this case. The expectation is that your validator will not perform any expensive validation checks when limited pre-validation is invoked, erring on the side of enabling the action. In other words, suppose that you need to check some access permissions in order to really determine whether or not an action should be available to a user, but you know that access permissions are expensive to check. In your validator s performLimitedPreValidation() you would skip the access permission check and assume that the user has the appropriate permissions. The worst case scenario is that the action is displayed and enabled for the user, but once they try to invoke it, post-select validation performs a more complete check and denies the user from performing the action. This is what is meant by sacrificing accuracy for performance in limited pre-validation. Full Pre-Validation Pre-Validation Explained On the other hand, suppose youre pre-validating an action in a drop-down list of actions in a table row, or on an info page. Since were using Ajax to populate these dropdown lists once the user selects them (as opposed to when the page is initially rendered), performance is not as critical. At most, well be validating several actions, but only for a single context object. In this case, it is acceptable to have slower performance in favor of validation accuracy. Considering the same example we described for limited pre-validation, if you need to perform some access permission checking to determine whether or not an action should be available to a user, you can afford to make that check in your validator s performFullPreValidation() method. It may take longer to perform the check, but since the number of validations being performed before the page (or Ajax component) is rendered is manageable, the less-performant check is acceptable.

Presenting Information in the UI

751

Keep in mind that in many situations, your validator s performFullPreValidation() and performLimitedPreValidation() method implementations will be identical. Creating a Validator Creating a validator class should be fairly simple. All you need to do is create a class that extends com.ptc.core.ui.validation.DefaultUIComponentValidator. The class below represents a skeleton for a simple validator class.
package com.ptc.windchill.enterprise.myPackage.validators; import com.ptc.core.ui.validation.DefaultUIComponentValidator; public class MyValidator extends DefaultUIComponentValidator{ //override one or more validation methods from DefaultUIComponentValidator }

Implementing Pre-Validation Methods Once youve created a validator class skeleton, if youre adding pre-validation logic for an attribute, youll want to implement the performLimitedPreValidation() method. If youre adding pre-validation logic for an action, youll want to implement both the performFullPreValidation() and performLimitedPreValidation() methods. As mentioned in the previous sections regarding limited pre-validation and full pre-validation, the implementations of these two methods may be identical, or they may differ. The class on the next page contains some skeleton implementations of these methods.
public class MyValidator extends DefaultUIComponentValidator{ @Override public UIValidationResultSet performFullPreValidation() (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { UIValidationResultSet resultSet = UIValidationResult.newInstance(); // perform your business logic here // if you want to enable the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus.ENABLED)); // if you want to disable the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus.DISABLED)); // if you want to hide the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, UIValidationStatus.HIDDEN));

752

Windchill Customization Guide

return resultSet; } @Override public UIValidationResultSet performLimitedPreValidation() (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { UIValidationResultSet resultSet = UIValidationResultSet.newInstance(); // perform your business logic here // if you want to enable the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus.ENABLED)); // if you want to disable the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus.DISABLED)); // if you want to hide the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, UIValidationStatus.HIDDEN)); return resultSet; } }

Registering Validators Once youve created your validator and implemented the appropriate prevalidation method(s), the only thing left to do is to register it. You need to register your validator to associate it with the action or attribute it is intended to validate. When registering a validator for an action, you may make the association using the action name only, or using a combination of action name and object type. In most cases, using just the action name to identify your validator is sufficient and preferred. When registering a validator for an attribute, you make the association using the attributes descriptor ID. Basic Validator Registration To register your validator (using only the action name for an action), you need to add an entry to *service.properties.xconf like this:
<Service context="default" name="com.ptc.core.ui.validation.UIComponentValidator"> <Option requestor="null" serviceClass="[ your fully-qualified Validator class]" selector="[action name/attribute descriptor ID]" /> </Service>

Presenting Information in the UI

753

Once propagated to *service.properties, it should produce an entry like this:


wt.services/svc/default/com.ptc.core.ui.vali dation.UIComponentValidator/[action name/attribute descriptor ID]/null/0=[your fullyqualified Validator class]/duplicate

Note that in this case, the requestor attribute is null, meaning the actions object type is not used in the lookup.

Type-Based Validator Registration If you feel you have a case where it makes sense to register your validator using an actions object-type in addition to action name, it is very similar to registering a validator using only the action name. The difference lies in the requestor attribute in the properties entry. For validators that do not use an object type, the requestor attribute is set to null. For a validator to be registered using object type, the requestor value will be the fully-qualified class name of the type it is to be registered for. The class name that is used in the requestor attribute corresponds to a class name from actions.xml. For example, consider this fragment of an actions.xml file (NOTE: some text eliminated for readability):
<objecttype name="problemReport problemReport" class="wt.change2.WTChangeIssue wt.change2.WTChangeIssue" ...> <action name="create " > ... </action> ... </objecttype>

In this case, the action we're looking at is called create. Obviously, it's likely that there will be multiple actions defined in the system named create. However, the validation rules for each create action may be different, depending on the type of object being created. Therefore, it might make sense to have separate validators for the create action for, say, a Problem Report and the create action for a Part. Suppose we have a validator defined called com.ptc.windchill.enterprise.change2. validators.ChangeMgmtCreateWizardsValidator that we want to register for create actions, but only if the action is to create a Problem Report. We could look at the actions.xml entry above and see that the create action for a Problem Report is actually defined for an objecttype whose name is problemReport and, more importantly, whose class is wt.change2.WTChangeIssue.

754

Windchill Customization Guide

By using that class value from actions.xml as the requestor attribute in our properties entry, we can tell the validation service that we only want to register our validator (com.ptc.windchill.enterprise.change2.validators. ChangeMgmtCreateWizardsValidator) for create actions whose object type is wt. change2.WTChangeIssue, like this:
<Service context="default" name="com.ptc.core.ui.validation.UIComponentValidator"> <Option serviceClass="com.ptc.windchill.enterprise.change2.validators.Chan geMgmtCreateWizardsValidator" selector="create create" requestor="wt.change2.WTChangeIssue wt.change2.WTChangeIssue" /> </Service>

That's really all there is to it. Basically, if you want to register your validator for an action, but only if that action is associated with a certain object type (in actions. xml), you use the class attribute from actions.xml as the requestor attribute in your properties entry. A few notes: This type-based lookup is currently only available for actions defined in actions.xml. It will not work for attributes or other UI components. For this to work, the class attribute from your actions.xml entry needs to be a concrete class (not an interface - there are many cases where the class attribute is currently set to wt.fc.Persistable). Changing an existing class attribute from an interface to a concrete class is OK in most cases. But you should check with the owner of the actions.xml file you're modifying before doing so.

Verifying Validator Registration There is a command line report you can run to see which validators are registered for a given action or attribute. If your validator is not appearing in this report, that means it is not registered correctly, and will never get called. Examples follow: Finding a single validator (non-type based) Usage example 1 - find the validator registered for the pasteAsCopy action:
Y:\>java java com.ptc.core.ui.validation.UIComponentValidatorFactory pasteAsCopy

Registered validators:
pasteAsCopy ->

Presenting Information in the UI

755

com.ptc.core.foundation.saveas.validators.PasteValidator

Finding multiple validators (non-type based) Usage example 2 - find the validators registered for the setState and pasteAsCopy actions:
Y:\>java java com.ptc.core.ui.validation.UIComponentValidatorFactory setState pasteAsCopy

Registered validators:
setState -> com.ptc.windchill.enterprise.lifecycle.validators.SetStateValid ator pasteAsCopy -> com.ptc.core.foundation.saveas.validators.PasteValidator

Finding a single validator (type-based) Usage example 3 - find the validator registered for the create action whose objecttype name attribute in actions.xml is problemReport. (Note: method server must be running for type-based lookup)
Y:\>java java com.ptc.core.ui.validation.UIComponentValidatorFactory create:problemReport create:problemReport

Registered validators:
create:problemReport(wt.change2.WTChangeIssue) -> com.ptc.windchill.enterprise.change2.validators.ChangeMgmtCreat eWizardsValidator

Finding multiple validators (mix of type-based and non-type based) Usage example 4 - find the validator registered for the pasteAsCopy action and the create action whose objecttype name attribute in actions.xml is problemReport. (Note: method server must be running for type-based lookup)
Y:\>java java com.ptc.core.ui.validation.UIComponentValidatorFactory pasteAsCopy create:problemReport create:problemReport

Registered validators:
pasteAsCopy -> com.ptc.core.foundation.saveas.validators.PasteValidator create:problemReport(wt.change2.WTChangeIssue) -> com.ptc.windchill.enterprise.change2.validators.ChangeMgmtCreat

756

Windchill Customization Guide

eWizardsValidator

Procedures Post-select Post-select Validation


Fortunately, the procedures for implementing post-select validation are much simpler than for pre-validation. There is really only one point where post-select validation can be implemented, and that is within a validator. It should also be noted that post-select validation applies only to actions. There is no concept of post-select validation for attributes or other UI components. Creating a Validator Creating a validator for post-select validation is exactly the same as creating a validator for pre-validation. See Creating a Validator for details. Implementing Post-Select Validation Methods There are two post-select validation methods that can be implemented in a validator one for single-select actions and one for multi-select actions. The respective names of these methods are validateSelectedAction() and validateSelectedMultiSelectAction(). If youre adding validation for an action that could never be a multi-select action, you only need to implement the validateSelectedAction() method. If your action could possibly be a mutli-select action, you should implement both the validateSelectedAction() method and the validateSelectedMultiSelectAction() method. The only real distinction between the two methods is in the method signatures. validateSelectedMultiSelectAction() returns a UIValidationResultSet, whereas validateSelectedAction() returns a single result.
public class MyValidator extends DefaultUIComponentValidator{ @Override public UIValidationResultSet performFullPreValidation() (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { UIValidationResultSet resultSet = UIValidationResult.newInstance); // perform your business logic here // if you want to enable the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey UIValidationStatus.ENABLED)); // if you want to disable the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, UIValidationStatus.DISABLED)); // if you want to hide the action/component, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey UIValidationStatus.HIDDEN)); return resultSet;

Presenting Information in the UI

757

} @Override public UIValidationResultSet validateSelectedMultiSelectAction () (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { UIValidationResultSet resultSet = UIValidationResultSet.newInstance(); // perform your business logic here // if you want to execute the action, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus.PERMITTED)); // // if you want to abort the action, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus.DENIED)); // if you want to prompt the user for confirmation, do this: // resultSet.addResult(UIValidationResult.newInstance(validationKey, // UIValidationStatus. PROMPT_FOR_CONFIRMATION)); return resultSet; } }

How to Handle UIValidationStatus.PROMPT_FOR_CONFIRMATION If your validator retuns PROMPT_FOR_CONFIRMATION status, it need to be configured special way by using PTC.validation. AJAXPostSelectValidation JavaScript function.
<action name="myAction" > <command class="com.ptc.xxx" method="function" onClick=" PTC.validation.AJAXPostSelectValidation(event, validationKey)"/> </action>

In this case, once you have made a/few selections and click myAction: PTC.validation.AJAXPostSelectValidation function based on the provided validationKey executes post-select functions on the mapped validator. If the status is PROMPT_FOR_CONFIRMATION, confirmation pop-up will be shown and based on your selection further processing will happen. If you opt for yes for the confirmation or the status was PERMITTED, another request will be send to the server to do the operation. There is inbuilt intelligence not to invoke your validator again for this request.

758

Windchill Customization Guide

Procedures Post-Submit Post-Submit Validation


The procedures for implementing post-submit validation is much simpler than for pre-validation and similar to post-select validation. There is really only one point where post-submit validation can be implemented, and that is within a validator. It should also be noted that post-submit validation applies only to wizard steps and wizard submissions. Creating a Validator Creating a validator for post-submit validation is exactly the same as creating a validator for pre-validation. See Creating a Validator for details. Implementing Post-Submit Validation Methods There is only one post-submit validation method that can be implemented in a validator The respective name of the method is validateFormSubmission(). This method is intended to be called after a wizard "next" or "finish" action is invoked, to determine whether or not the user-entered data is valid.
public class MyValidator extends DefaultUIComponentValidator{ @Override public UIValidationResult validateFormSubmission (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { UIValidationResult result = UIValidationResult.newInstance(validationKey, UIValidationStatus.NOT_VALIDATED); // perform your business logic here // if you want to execute the action, do this: // result = UIValidationResult.newInstance(validationKey, UIValidationStatus.PERMITTED); // if you want to abort the action, do this: // result = UIValidationResult.newInstance(validationKey, UIValidationStatus.DENIED); // if you want to prompt the user for confirmation, do this: // result = UIValidationResult.newInstance(validationKey, // UIValidationStatus.PROMPT_FOR_CONFIRMATION); return result; } }

Presenting Information in the UI

759

How to Handle UIValidationStatus.PROMPT_FOR_CONFIRMATION If your validator retuns PROMPT_FOR_CONFIRMATION status, it needs to be specially configured. Option 1: Use your own custom ok/apply wizard button by using PTC. validation.AJAXValidateFormSubmission JavaScript function.
<action name="myOkButton" id="PJL_wizard_ok" > <command class="" method="" windowType="page" url=" javascript:PTC. validation.AJAXValidateFormAndSubmit(validationKey)"/> </action>

In this case, once you click myOkButton: PTC.validation.AJAXValidateFormAndSubmit function based on the provided validationKey executes post-submit functions on the mapped validator. If the status is PROMPT_FOR_CONFIRMATION, confirmation pop-up will be shown and based on your selection further processing will happen. If you opt for yes for the confirmation or the status was PERMITTED, the form will be submitted. There is inbuilt intelligence not to invoke your validator again for this request. Option 2: Add your own user submit function in your jsp (invoked when the form is submitted) by using PTC.validation.AJAXValidateFormSubmission JavaScript function.
<script type="text/javascript"> setUserSubmitFunction (function () {return PTC.validation. AJAXValidateFormSubmission(validationKey);}); </script>

In this case, once you have ok/finish wizard button : PTC.validation.AJAXValidateFormSubmission function based on the provided validationKey executes post-submit functions on the mapped validator. If the status is PROMPT_FOR_CONFIRMATION, confirmation pop-up will be shown and based on your selection further processing will happen. If you opt for yes for the confirmation or the status was PERMITTED, the ok/finish wizard button submits the form. There is inbuilt intelligence not to invoke your validator again for this request.

760

Windchill Customization Guide

Miscellaneous Tips, Tricks, and Things to Avoid


This section contains the following topics: Working with Access Permissions on page 761 Rule of Thumb: One Validator per Action/Attribute/Component on page 762 Do Not Inflate WTReferences on page 763 Handle Null Values on page 764 Use the @Override Annotation on page 765 UIValidationCriteria.toString() on page 765

Working with Access Permissions There is an attribute on UIValidationCriteria that can be used to store access permissions retrieved by one validator or filter, to be used by a subsequent validator or filter. For example, suppose actionA, actionB, and actionC are all in the same action model, and all need to know whether or not the user has modify permissions in the current container. If the validator or filter for actionA is invoked first, it can query the AccessControlManager for the permissions and then store them in the UIValidationCriteria, so that the validators or filters for actionB and actionC do not need to perform the same query again. In general, if you need to check access permissions in a validator or filter, you should do the following: Check to see if the permissions are already stored in the UIValidationCriteria by calling the new UIValidationCriteria.getCachedAccessPermissions() method. If getCachedAccessPermissions() returns a non-null value, you can use those permissions for your validation checks If getCachedAccessPermissions() returns null, then you can query the AccessControlManager to get the permissions you need, and then store them in the UIValidationCriteria for subsequent validators by calling the setCachedAccessPermissions() method.

The intent of the cachedAccessPermissions attribute in UIValidationCriteira is that it store the result of AccessControlManager.getPermissions(). So in other words, you should write your validator or filter code to look like this:
// check to see if the access permissions have already been calculated... WTKeyedHashMap accessPermissions = criteria.getCachedAccessPermissions(); // if the access permissions have not been calculated yet, get the permissions and cache them for other // validators to use

Presenting Information in the UI

761

if (accessPermissions == null){ accessPermissions = AccessControlManager.getPermissions(...); criteria.setCachedAccessPermissions(accessPermissions); }

Additional notes regarding access permissions: wt.access.AccessControlManager has the following APIs available in singleand multi-object variants: hasAccess - returns true if the principal has the given access permission, otherwise returns false checkAccess - throws a NotAuthorizedException and emits an event for auditing purposes if the principal does not have the given access permission getPermissions - returns the set of permissions (AccessPermissionSet) granted to a principal Use hasAccess or getPermissions to evaluate a users rights and continue (e.g., UI action validation code disables action based on the user s rights) One way of checking to see if a user has access is to use one of the hasAccess APIs. Another way would be to have anyone that needs to check permissions for an object (or objects) call one of the two getPermissions APIs, and store the result in the UIValidationCriteria, for use by other validators that also need to check permissions for the same object(s) (assuming the domain, type & state of the object and the current principal remain the same), rather than calling hasAccess to evaluate access rights for each permission check. Even if the result was not stored, the getPermissions API would be useful for any validator that needs to check multiple permissions. AccessPermissionSet is a collection, and has a method to check if a specified permission is in the set:
boolean includes(AccessPermission permission) // Returns true if permissions in this set include rights for the specified permission.

The checkAccess APIs should NOT be used to see if the user has a specified permission, unless the intent is that an exception is to be propagated to the end user. If the NotAuthorizedException is caught and does not result in a user's action failing due to the lack of access rights, auditing of the exception should be disabled. See the Javadoc for more information.

Rule of Thumb: One Validator per Action/Attribute/Component Dont fall into the trap of having one validator registered for multiple unrelated actions. The result is lots of if/else branching and some very large methods. This can make maintenance difficult, and makes it much easier to introduce regressions.

762

Windchill Customization Guide

In general, the only times where you would use a single validator for multiple actions/components would be if those components share the exact same validation logic, or if you have an either/or scenario. What we mean by an either-or scenario is that in a given action menu, either actionA or actionB should appear, but never both. For all other cases, the best practice is to register one validator per action/ component. Do Not Inflate WTReferences You may be tempted to write validation code like this. Don't do it.
@Override public UIValidationResultSet performFullPreValidation (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { Persistable contextObject = validationCriteria.getContextObject validationCriteria.getContextObject(). ().getObject getObject(); (); WTContainer container = validationCriteria.getParentContainer validationCriteria.getParentContainer(). ().getReferencedContainer getReferencedContainer(); (); if (!contextObject instanceof WTPart){ ... } if (!container instanceof PDMLinkProduct){ ... } }

The code above in bold is performing a relatively costly operation of inflating the WTReferences held in the UIValidationCriteria to Persistables. There may be cases where inflating those objects is not avoidable, but there are also many cases where it can be avoided. If all you really need to know is if the context object or parent container is an instance of some class, you can use the isAssignableFrom() method instead, like this:
@Override public UIValidationResultSet performFullPreValidation (UIValidationKey validationKey, UIValidationCriteria validationCriteria, Locale locale) throws WTException { WTReference contextObjectRef = validationCriteria.getContextObject(); WTContainerRef containerRef = validationCriteria.getParentContainer(); if (!WTPart.class.isAssignableFrom(contextObjectRef.getReferencedClas s())){ ... }

Presenting Information in the UI

763

if (!PDMLinkProduct.class.isAssignableFrom(containerRef.getReferenced Class())){ ... } }

Handle Null Values There may be cases where you are writing a validator or filter for a specific action on a specific page in a product where you need one of the attributes from UIValidationCriteria to perform your business logic. For example, suppose you're working on a 3rd level table on an info page, and in that table's toolbar, you don't want an action to appear if you're on an info page for a Generic Part. So you do the following (do not duplicate this code, but for the sake of an example...):
if (((WTPart)validationCriteria.getContextObject().getObject()).getGe nericType() .equals(GenericType.GENERIC)){ ...

And that may work fine in your test cases where you're only testing an action on part details pages. But what if that action also appears in the toolbar of one of the tables on the home page, or on the products list page? Then the code above will throw a NullPointerException from those pages, since validationCriteria. getContextObject() will (correctly) return null. There are a few things you can do to avoid this scenario. The first is to check and make sure that the values you're getting from UIValidationCriteria are not null. If a value is null, log a warning, and call super.[whatever method you're implementing] (key, criteria, locale);. The other thing you can do is when performing comparisons, use the .equals operation on the "expected" value. For example:
if (ComponentType.WIZARD.equals(validationCriteria.getComponentType() )

NOT
if (validationCriteria.getComponentType().equals(ComponentType.WIZARD ))

In general, just because a null value doesn't allow validation to proceed in your use case, that doesn't mean it should be a showstopper in every use case.

764

Windchill Customization Guide

Use the @Override Annotation Its highly encouraged to use the Override annotation, whenever you over-ride methods of the ootb delivered classes. UIValidationCriteria.toString() UIValidationCriteria, the toString() is not over-ridden to give information of its content. You can use the following method for logging.
public String toString_heavy(Logger logger, Level level)

If the Level of the Logger matches with the Level provided, the method will return the information. Since the method performs some costly calculations, its suggested to use this it wisely.

Presenting Information in the UI

765

Customizing the Find Number Field


Outof-the-box, the Find Number Field of the Edit Structure Window in the Product Structure browser will not accept values which contain spaces. However, the Find Number field can be customized to accept values that include spaces, including leading or trailing spaces.

Caution If you perform this customization you must maintain and carry-forward this customization when you move to a later release of Windchill. Note If you want to allow leading or trailing spaces, perform steps 1 and 3 below; otherwise step 2 is sufficient.
1. The entry "wt.load.preserveSpace=true" has to be added to the file Windchill \codebase\wt.properties to allow for leading/trailing spaces. 2. To customize the logic in this field, perform the following steps: a. Implement the interface "ValidateFindNumberDelegate.java" b. Override the 'validateFindNumbers (String[])' method as described in the sample code provided below. c. Ensure that the implementation throws a WTPropertyVetoException (as in the example) if any of the contraints are violated. d. Register this new delegate in Windchill\codebase\service.properties.xconf: There is a section with the following entry in this file:
<!-The wt.part.ValidateFindNumbersDelegate service. Delegate validation for Find Numbers on WTPartUsageLink objects subclasses thereof --> <Service context="default" name="wt.part.ValidateFindNumbersDelegate"> <Option cardinality="duplicate" requestor="java.lang.Object" serviceClass="wt.part.DefaultValidateFindNumbersDelegate"/> </Service>

Replace wt.part.DefaultValidateFindNumbersDelegate with the full path and name of the new delegate that was just created. e. Run "xconfmanager -Fpv" to propagate the changes. f. Create an rbinfo entry with the message you want to display when an error occurs. 3. If the customization rules pertaining to leading/trailing spaces have to be obeyed while loading data from a load file as well, then the following code

766

Windchill Customization Guide

samples provide an example of how to do this in the method "getValue(String, Hashtable, HashTable, boolean)". OOTB Implementation
protected static String getValue( String name, Hashtable nv, Hashtable cmd_line, boolean required ) throws WTException { String value = LoadServerHelper.getValue(name,nv,cmd_line,required?LoadServerH elper.REQUIRED:LoadServerHelper.NOT_REQUIRED); if (value != null) { value = value.trim(); if (value.equals("")) { value = null; } } return value; }

Customized implementation allowing leading and trailing spaces while loading from a file:
protected static String getValue( String name, Hashtable nv, Hashtable cmd_line, boolean required ) throws WTException { String value = LoadServerHelper.getValue(name,nv,cmd_line,required?LoadServerH elper.REQUIRED:LoadServerHelper.NOT_REQUIRED); // Don't trim leading/trailing spaces if reading Find Number field. if(!name.equalsIgnoreCase("findNumber")) { if (value != null) { value = value.trim(); if (value.equals("")) { value = null; } } } return value; }

Sample Code
// Generated DefaultValidateFindNumbersDelegate%43C7A40F0161: Fri 03/07/08 10:41:32 /* bcwti * * Copyright (c) 2007 Parametric Technology Corporation (PTC). All Rights * Reserved. * * This software is the confidential and proprietary information of PTC * and is subject to the terms of a software license agreement. You shall

Presenting Information in the UI

767

* not disclose such confidential information and shall use it only in acco rdance * with the terms of the license agreement. * * ecwti */ package wt.part; import import import import java.lang.String; wt.part.ValidateFindNumbersDelegate; wt.part.WTPartUsageLink; wt.util.WTException;

//##begin user.imports preserve=yes import wt.util.WTPropertyVetoException; //##end user.imports

// Preserved unmodeled dependency

//##begin DefaultValidateFindNumbersDelegate%43C7A40F0161.doc preserve=no /** * Standard delegate to handle validation of Find Numbers, i.e., OOTB behavior, * which is doing nothing. * * <BR><BR><B>Supported API: </B>true * <BR><BR><B>Extendable: </B>true * * @version 1.0 **/ //##end DefaultValidateFindNumbersDelegate%43C7A40F0161.doc public class DefaultValidateFindNumbersDelegate implements ValidateFindNumbersDelegate {

// --- Attribute Section ---

private static final String RESOURCE = "wt.part.partResource"; private static final String CLASSNAME = DefaultValidateFindNumbersDelegate.class.getName(); //##begin user.attributes preserve=yes //##end user.attributes //##begin static.initialization preserve=yes private static final String SPACE = " "; private static final String HYPHEN = "-"; //##end static.initialization

// --- Operation Section --//##begin validateFindNumbers%43C6C7F300E8.doc preserve=no /** * * <BR><BR><B>Supported API: </B>false

768

Windchill Customization Guide

* * @param partUsageLinks * @exception wt.util.WTException **/ //##end validateFindNumbers%43C6C7F300E8.doc public void validateFindNumbers( WTPartUsageLink[] partUsageLinks ) throws WTException { //##begin validateFindNumbers%43C6C7F300E8.body preserve=yes //##end validateFindNumbers%43C6C7F300E8.body } //##begin validateFindNumbers%45A68DEC00D9.doc preserve=no /** * * <BR><BR><B>Supported API: </B>false * * @param findNumbers * @exception wt.util.WTException **/ //##end validateFindNumbers%45A68DEC00D9.doc public void validateFindNumbers( String[] findNumbers ) throws WTException { //##begin validateFindNumbers%45A68DEC00D9.body preserve=yes try { doValidation(findNumbers); } catch (WTPropertyVetoException wtpe) { throw new WTException (wtpe); } //##end validateFindNumbers%45A68DEC00D9.body } //##begin user.operations preserve=yes /** * Method to validate if the format of the "Find Number" field is correct or not. * The default logic allows only alphanumeric entries for this field. * A WTPropertyVetoException is thrown if the format of the string in this field does not * match the constraints imposed. The consequence of this Exception is that an error dialog * will be displayed with a message as defined in the rbinfo file. * This method can be customized to incorporate any constraint that the user might wish * to impose on this field. * @param findNumbersArray The value being entered (and validated) for the "Find Number" field * @throws WTPropertyVetoException */

Presenting Information in the UI

769

private void doValidation(String[] findNumbersArray) throws WTPropertyVetoException { for(int j = 0; j < findNumbersArray.length; j++) { String a_FindNumber = findNumbersArray[j]; // Find Number can only be alphanumeric with the exception that the "Find Number" // string can contain a space (" ") or a hyphen ("-") as part of it. The string can // start or end with a space, but cannot start or end with an hyphen. // SPR 1457664 if (a_FindNumber != null) { for (int i = 0; i < a_FindNumber.length(); i++) { if(a_FindNumber.startsWith(HYPHEN) || (a_FindNumber.endsWith(HYPHEN))) { Object[] args = {a_FindNumber}; throw new WTPropertyVetoException( RESOURCE, wt.part.partResource.FIND_NUMBER_NOT_ALPHANUMERICAL_ERROR, args, new java.beans.PropertyChangeEvent( this, "findNumber", a_FindNumber, a_FindNumber )); } if (!Character.isLetterOrDigit(a_FindNumber.charAt(i))) { if((a_FindNumber.substring(i, i + 1)).equals(SPACE) || (a_FindNumber.substring(i, i + 1)).equals(HYPHEN)) { // We have already checked that the first and/or last character is not an hyphen // in the if-condition above. So, if the code gets into this block, we can be sure // that the hyphen is in the middle of the string and not at the beginning or end. // Also, if the character is a space, we are allowing it, so we can continue. continue; } else { Object[] args = {a_FindNumber}; throw new WTPropertyVetoException( RESOURCE, wt.part.partResource.FIND_NUMBER_NOT_ALPHANUMERICAL_ERROR, args, new java.beans.PropertyChangeEvent( this, "findNumber", a_FindNumber, a_FindNumber )); } } } } } } //##emd user.operations }

770

Windchill Customization Guide

Inline Messaging
You can develop inline message to capture success or failure of certain user actions. You can also use this to display warning or any informational message. However, this cannot be used for any kind of message that requires user input. Background This topic details the information to needed to develop inline messages using outof-the-box components as building blocks. Intended Outcome An inline message is displayed in the browser to the end user with the intended message(s).

Solution
Use common JavaScript and java class components to display inline message that gives user feedback about success or failure or warning message(s) for their actions. Prerequisite Knowledge To apply this process, you need to have an understanding of the following: Java programming Basic web development using JavaScript, JSPs , custom tags, and HTML forms

Solution Elements Element Java Method getSuccessFeedbackMessage()

Description This method is called by setResultNextAction() of DefaultObjectFormProcessor and is called when FormResult is SUCCESS. This constructs the FeedbackMessage with the message title, additional messages and the info page link for the object(s) that was created. If the object has no identity then only Object icon and Object Type will show up as info page link. This is then

Presenting Information in the UI

771

Element

Description displayed in UI as Inline Success message informing user that object was created successfully. This method may be overridden by subclasses desiring different behavior. See the JavaDoc for more details. A javascript method that renders the inline message in the main window. It takes the array of message JSON objects as an argument. Each message JSON object must have MessageTitle, an array of messages and the type of Message. Valid Message Types are: SUCCESS, FAILURE, WARNING, FATAL, INFO. This should NOT be used for any confirmational kind of messages. See the JavaDoc for more details. Location: <WT_HOME>/codebase/ netmarkets/javascript/util

Javascript PTC.messaging.showInlineMessage()

Customization Points
The out-of-the-box JCA framework has Inline Success message displayed in UI for successful object creation. This inline message is shown for single object creation:

772

Windchill Customization Guide

For Multi-object creation below inline message is shown in the UI:

How to customize the message title for successful object create? In the above screen shot message title is CONFIRMATION: Create successful . If an application needs to override the message title then in their object form processor they need to override public WTMessage getSuccessMessageTitle() method and provide their own localized message title. How to customize the message body for successful object create? In the above screen shot of single object create, message body is The object was
created successfully.

If an application needs to override the message body for single object creation then in their object form processor they need to override public WTMessage getSuccessMessageBody() method and provide your own localized message body. For multiple objects creation the method to override the message body is public WTMessage getSuccessMessageBodyForMulti() in the form processor.

Sample Code
The sample code for showing inline message for message type SUCCESS using JavaScript function:
PTC.messaging.showInlineMessage( [{ MessageType:'SUCCESS', MessageTitle:'Confirmation: Create successful', Messages:["Object created successfully."], OidIdentity: [{oid: "OR:wt.part.WTPart:11021", icon: "wtcore/images/part.gif", objType: "Part"}] }]);

Additional Resources
The following customization topics contain related information:

Presenting Information in the UI

773

Windchill Client Architecture Overview on page 226 Adding Custom Code to all Windchill Client Architecture Pages on page 248 Javascript Functions Overview on page 242 Customizing the UI with Ajax on page 312 Constructing Wizards on page 775 Constructing and Rendering a Table Using the JSP Framework on page 579

774

Windchill Customization Guide

16
Constructing Wizards
Windchill Client Architecture Wizard .......................................................................... 776 Wizard Processing................................................................................................... 802 Building Wizards to Create a Single Object ................................................................ 823 Building Wizards to Edit a Single Object .................................................................... 846 Customizing Reusable Wizard Steps......................................................................... 860

This chapter describes how to construct wizards.

775

Windchill Client Architecture Wizard


Objective
You want to create or perform an operation on object(s) by collecting information step by step.

Background
Wizards are popup windows that are used to guide you step by step through the process of creating an object, or performing an operation on an object. A wizard is a user interface consisting of a sequence of steps that lead the user through a specific task one step at a time, the user clicks next to move through the steps. It might not be necessary to complete all the steps present in a wizard. Once the required information is provided, you can click FINISH / OK button to submit the data to the server. A wizard can consist of one or many steps which must be completed in a certain order.

776

Windchill Customization Guide

A clerk is a user interface consisting of a tab control that has two or more tabs. Data can be entered and the user can complete tabs in any order. A user may freely move from one tab to another, even if the current tab is not complete. A clerk is not meant to guide users sequentially through a task, and is typically used for frequent and easily accomplished tasks.

Constructing Wizards

777

The layout for single step wizards and multi step wizards will be different. The single step wizard will not have Step icons, Step links and Back / Next navigation buttons.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


A wizard should be used when you need to create / edit object(s) by performing any operations on it after collecting required information in a specific systematic manner. A table rendered within a wizard is JCA table and table rendered inside a picker is a JSCA table. For the most part, clerks are implemented in the same fashion as that of wizards and the instructions in this document are applicable to both. Any differences are noted. Otherwise, the term "wizard" should be interpreted as either a wizard or a clerk and "wizard step" should be interpreted as either a wizard step or a clerk tab.

Solution
Use a Wizard or Clerk component.

778

Windchill Customization Guide

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development, which involves HTML, JSP, Java, JavaScript and Custom taglibs. Overview of Windchill Client Architecture tags. The actions framework in the Windchill client architecture. Action validation framework.

Solution Elements
Element components.tld Type tld Description Tag Library Descriptor (TLD) file, which contains Wizard Tag and Wizard-Step Tag definition Run time Location: <Windchill>\codebase\WEB-INF\tlds \ Contains all the necessary logic of how to move from one step to another and how to call methods defined for each of the steps. Run time Location: <Windchill>\codebase\netmarkets\tlds \javascript\compon ents The jsp file in which your wizard implementation is defined. The jsp file, which contains contents of

wizard.js

Js

<your_wizard_ page>.jsp

jsp

<your_wizard_ step>.jsp

jsp

Constructing Wizards

779

Element <*-actions>.xml

Type xml

actionmodels.xml

xml

<resourceBundle>.rbInfo

rbInfo

formProcessorController

java

wizard

Tag

Description the wizard step. The actions for the wizard as well as each wizard step are defined in this XML file. The models for the list of buttons, to be displayed at the bottom of the wizard (i. e. the navigation area) are defined in this XML file. This is another option where you can specify locale specific Strings and properties for wizard step and wizard actions. The java class, which will be executed after the wizard, is submitted. The wizard framework will pass on the data / information to this java class. For more information see Building Wizards to Create a Single Object on page 823 and Building Wizards to Edit a Single Object on page 846. Specifies the action pointing to the main JSP for the wizard and defines the steps contained in
Windchill Customization Guide

780

Element

Type

wizardStep

Tag

Description the wizard. Tag handler: com/ptc/core/ components/tags/ components/ WizardTag Specifies the action pointing to the main JSP for the step.

Procedure Configuring Wizard Component


Create actions for Wizard as well as Wizard steps Each step of the wizard and the wizard itself needs an action declaration for the associated page. Actions are grouped together using object types. These object types are declared inside of the <listofactions> tag contained in any one of the *actions.xml files. For more details on how actions work please see the Action Framework documentation. Windchill will expect all jsp pages related to this object type to be located in <Windchill>\codebase\netmarkets\jsp\<objecttype>. For the below specified example the location will be <Windchill>\codebase\netmarkets\jsp\changeTask\. The create action is defined for the wizard page. By default, the name attribute of the action points to the main jsp page for your wizard relative to codebase/ netmarkets/jsp, unless a url attribute is specified on the command tag. Therefore, for the action below Windchill will now expect create.jsp to be located in <Windchill>\codebase\netmarkets\jsp\changeTask\ folder. Since this action is for the wizard, it is necessary to specify windowType as popup inside the <command> tag. See Windchill Client Architecture Action Framework Overview on page 486 for more details on the windowType attribute. The affectedAndResultingItemsStep action is defined for the wizard step. The corresponding jsp should be located at <Windchill>\codebase\netmarkets\jsp \changeTask\ affectedAndResultingItemsStep.jsp. Since this action is for the wizard step, it is necessary to specify windowType as wizard_step.
<objecttype name="changeTask" class="wt.change2.WTChangeActivity2"> <action name="create"> <command class=<path to form processsor>" </action> <action name="affectedAndResultingItemsStep"> <command windowType="wizard_step" /> </action>

windowType="popup"/>

Constructing Wizards

781

</objecttype>

The command class is the java class that should be called to process the wizard data. Typically, this will extend CreateObjectFormProcessor. Note that it is not necessary to specify a method attribute in the command tag if the form processor class extends DefaultObjectFormProcessor or CreateObjectFormProcessor. Note that the windowType attribute of the command subtag for steps should always be set to wizard_step. Optional action tag attributes are shown in the table below. Action tag attribute ajax Default value None Possible Values Description page component row Specifies what portion of the parent page should be refreshed when the wizard processing completes. The value page refreshes the entire page (equivalent to not using ajax). The value component refreshes the table from which the wizard was launched. The value row refreshes one or more table rows. To use the value row your form processor must tell the system which rows (objects) need to be added. References an entry in roleaccessprefs.xml (uic name) used to

UIComponent

None

782

Windchill Customization Guide

Action tag attribute

Default value

Possible Values Description specify role-based access to the wizard action.

Here is an example action for launching a creation wizard for MyPart objects:
<objecttype name="myPart" class="ext.part.MyPart" <action name="create" uicomponent="CREATE_MYPART" ajax="row"> <command class="com.ptc.windchill.enterprise.part.forms.CreateMyPartFormProcessor" onClick="validateCreateLocation(event)" windowType="popup"/> </action>

The validateCreateLocation() javascript method shown in the action above is applicable to create wizards that can be launched from a folder browser. See Solution Elements in Solution on page 778 for more information. Refer to Adding Actions and Hooking Them Up in the UI on page 485 for more information on actions and the command tag attributes. In addition to creating the wizard action, you will need to create text for the action name, wizard window title, action tooltip, etc. This is described in Adding Actions and Hooking Them Up in the UI on page 485. Create the Wizard page Create a new jsp page inside <Windchill>\codebase\netmarkets\jsp\ folder and name it as create.jsp. Wizard steps that are not preloaded should include the following directives at the top of the jsp page:
<%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%>

Most wizard steps will also use tags in the components.tld tag library and so will also need to include that as follows:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>

Define the wizard using the <wizard> tag. All the steps for this wizard will be defined inside <wizard> tag using <wizardStep> tag. If a step is preloaded, none of these are required, but it is safe to include them. A non-preloaded-step:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components" %> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <jca:wizard > <jca:wizardStep action="defineItemWizStep" type="object"/> <jca:wizardStep action="setAttributesWizStep" type="object" />

Constructing Wizards

783

<jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" /> </jca:wizard> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Define a Clerk Defining a clerk is exactly same as defining a wizard, the only difference in the case of a clerk is that you define the type as "clerk".
<jca:wizard type="clerk clerk"> <jca:wizardStep action="defineItemWizStep" type="object"/> <jca:wizardStep action="setAttributesWizStep" type="object" /> <jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" /> </jca:wizard>

After defining the wizard type as "clerk", the wizard will be displayed as per the Clerk UI standards. Step indicators will not appear and step titles will be displayed as tabs. The Next and Previous buttons will not be displayed for Clerk. The user can navigate from any step to any step without entering the required fields. The validation for required fields will be done when the user clicks on the "OK" button. The user will be shown a message about required fields and will be taken to the appropriate steps, where required fields are not populated. The Clerk Component has a provision through which application developers can call their specific validation logic. For example: An application developer can write following code in jsp file to call javascript() on OK Button.
<script> Event.observe($("PJL_wizard_ok"), 'click', userdefinedjavascriptFunction ); </script>

Specify localized Strings / properties for wizard step and wizard actions You can specify localized strings / properties in a <resourceBundle>.rbInfo file. The format of each entry should be <objectType>.<action>.<property>.<type> = <value>. For example, you can specify the height and width of the popup window in which the wizard will be displayed, using the following property: changeTask. create.moreurlinfo.value=width=800,height=700
changeTask.create.description.value=New Change Task changeTask.create.description.comment=Used as the label for the create action changeTask.create.title.value=New Change Task changeTask.create.title.comment=Used as the title for the create action changeTask.create.tooltip.value=New Change Taskchange Task.create.tooltip.comment=Used as the tooltip for the create action changeTask.create.icon.value=../../wtcore/images/task_create.gif changeTask.create.icon.comment=DO NOT TRANSLATE changeTask.create.icon.pseudo=false

784

Windchill Customization Guide

changeTask.create.moreurlinfo.value=width=800,height=700 changeTask.create.moreurlinfo.pseudo=false

Create the wizard step page This can be any JSP page, and can contain any other component(s) as well as plain HTML contents. You do not have to create new steps if already existing steps will work. See Customizing Reusable Wizard Steps on page 860 for steps available to reuse.

Customization Points
This section contains the following topics: <action>.xml attributes on page 785 <wizard> tag attributes on page 787 <wizardStep> tag attributes on page 788 Providing user defined buttons to Wizard on page 789 Providing user defined form processor controller on page 790 Providing server side validation before / after processing a wizard step on page 790 Loading the wizard step content when it is visited on page 791 Marking a wizard step as required on page 791 Hiding a wizard step on page 792 Displaying the hidden / dynamic step at runtime on page 793 Providing user defined SUBMIT function on page 793 Providing client side validations before a wizard step is displayed on page 794 Providing client side validations after a wizard step is finished on page 794

<action>.xml <action>.xml attributes


Parameter name Default Value None Possible Values Any string Req? Description Yes The name of the action. Used as the name attribute on wizard step tags. Overrides the id of the wizard step (default is type.action). Used to

id

<type>. Any String <action>

No

Constructing Wizards

785

Parameter

Default Value

Possible Values

Req? Description identify the step in certain javascript functions. If not specified the id <action type>.<action name> will be used. Specify the javascript function name to invoke client side validation for a wizard step when step is finished and the user clicks Next or OK on the wizard step. Can be used to do client-side validation of the form data.. Specify the javascript function name to invoke client side validation for a wizard step when step is loaded. Specify the server validator name to invoke server side validation for a wizard step when step is loaded when the user navigates to the step using the Previous or Next button... Specify the server validator name to invoke server side validation for a wizard step to be called after the user clicks Next or Finish on the step. Can be used to do server-side validation of the form data. Specifies that wizard step is to be downloaded when wizard is launched rather than when the user

afterJS

Any String

No

beforeJS

Any String

No

beforeVK

Any String

No

afterVK

Any String

No

preloadWizar true dPage

false / true

No

786

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req? Description navigates to the step. Preloading wizard steps will make it faster to move to the next step. However, do not preload wizard steps that are dependent on information gathered in previous steps.. Specifies that wizard step is to be hidden at first, or for the action to be rendered as nonclickable. Specifies that wizard step is required.

hidden

false

false / true

No

required

false

false / true

No

<wizard> tag attributes


Parameter buttonList Default Possible Values Value Default Any String WizardBu ttons Req? Description No The action model containing the list of buttons to display in the wizard. The default set is the DefaultWizardButtons action model. Another commonly used set isNoStepsWizardButtons (for single-step wizards) Additional buttons sets are available in actions. xml and custom button sets can be defined The FormProcessorController class that should be used to process the wizard when it is submitted.

formProcesso DefaultF Any String rController ormProce ssorContr oller

No

Constructing Wizards

787

Parameter

Default Value

Possible Values

Req? Description If not specified, DefaultFormProcessorCo ntroller will be used. The overriding title to display instead of the default title in the rbInfo file or action.properties file. This title will not be localized / internationalized by default. You need to take care of passing a localized title. The selector key to identify help file from services.properties file. Identifies whether wizard is of type clerk or not. If "clerk" is specified, the wizard will be displayed as per clerk UI. This allows for text to be displayed above the progress bar using the UI standard.

title

Any String

No

helpSelectorK ey type

Any String

No

wizard

Wizard/clerk/dialog

No

progressMess age

Any String

No

<wizardStep> tag attributes


Parameter action Default Value Possible Values Any String Req? Description Yes The name of the action to include in the wizard parent tag. The type of the action to include in the wizard parent tag. The object handle to identify which object this step corresponds to.

type

Any String

Yes

objectHandle -

Any String

No

788

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req? Description Only required if the wizard needs to create multiple objects. By default, no object handle is needed. The label for the step. Note: Actions should already have labels. Only set this attribute if you want to override the action's label. A small text help button to be displayed on top of the wizard step content. Optional.

label

Any String

No

embeddedHel p

Any String

No

Providing user defined buttons to Wizard


You can change / specify different types of buttons that are present at the bottom of the wizard (i.e. the navigation area). The Wizard framework provides a default button model, which consists of buttons like NEXT, PREVIOUS, OK, APPLY and CANCEL. However, the Wizard framework also provides you the ability to specify your own set of buttons with user-defined functionality. In <your_wizard_page>.jsp
<jca:wizard buttonList="PreferenceWizardButtons PreferenceWizardButtons" > ... ... </jca:wizard>

You need to provide corresponding entry in actionmodels.xml file:


<actionmodels> <model name="PreferenceWizardButtons PreferenceWizardButtons"> <action name="revertButton" type="object"/> <action name="okButton" type="object"/> <action name="cancelButton" type="object"/> </model> </actionmodels>

Constructing Wizards

789

Every button in the actionmodel should have a corresponding entry for its action in actions.xml file. If there is a separate java class written to render that particular button, than you can specify the name of that class and its method (which contains the rendering code) using the class and method attributes of <command> tag. For example:
<action name="revertButton" id="PJL_wizard_revert_to_default"> <command class="" method="" windowType="page" url="javascript:revertToDefault()"/> </action>

Note For a clerk, only the OK and Cancel buttons are displayed by default. If new buttons are to be configured, the appropriate button model should be configured.

Providing user defined form processor controller


You can specify a form processor controller, which would be executed when the wizard is completed and the user clicks on OK, FINISH or APPLY button to submit it. The form processor controller gets the data specified in all the wizard steps, from Wizard framework, and processes it. After processing the data, a form processor controller returns an object of FormResult, along with the status. Based on the status (SUCCESS / FAILURE), which is returned, the wizard framework will decide further action. For example: In <your_wizard_page>.jsp
<jca:wizard formProcessorController = "com.mycompany.MyUniqueFormProcessorController">y ... </jca:wizard>

Note For more information see the Wizard Processing on page 802 section.

Providing server side validation before / after processing a wizard step


You can implement server side validations using specific java classes and configuring the wizard to execute them before / after processing a wizard step. You can achieve this by using beforeVK and afterVK attributes of <action> tag. You need to provide a key as the value for these attributes. The corresponding key should be declared in any <*-service>.properties file specifying the java class which will perform the validations and return the result. For example:
<action name="setAttributesWizStepForCreateMultiPart" beforeVK = "nameNumberValidation nameNumberValidation">

790

Windchill Customization Guide

<command windowType="wizard_step"/> </action>

OR
<action name="setAttributesWizStepForCreateMultiPart" afterVK = "nameNumberValidation nameNumberValidation"> <command windowType="wizard_step"/> </action> <Service context="default" name="com.ptc.core.ui.validation.UIComponentValidator"> <Option requestor="null" selector="nameNumberValidation nameNumberValidation" serviceClass="com.ptc.windchill.enterprise.part.validator.CreateMul tiPartNameNumberValidator" /> </Service>

Loading the wizard step content when it is visited


By default, all of the wizard steps are downloaded at wizard execution time. You can configure the wizard such that the content of any wizard step is not loaded when the wizard is first initialized and loaded. You can load the contents of a wizard step when you try to visit that step. You may need this feature when the step is dependant on information gathered from a previous step. You can use preloadWizardPage attribute of <action> tag to achieve this. By default, the value of this attribute is true. For example:.
<action name="setClassificationAttributesWizStep " preloadWizardPage="false"> preloadWizardPage="false" <command windowType="wizard_step"/> </action>

Note In the case of a clerk, all the steps will be loaded by default. The clerk does not have conditional display of steps (i.e. hidden steps), so all the steps would be preloaded.

Marking a wizard step as required


You can mark a wizard step as required. By doing so, the wizard cannot be submitted unless and until this required step is visited at least once. So the submit buttons (like OK, FINISH or APPLY) would be enabled only after all the required steps are completed / visited at least once. For example:
<action name="setClassificationAttributesWizStep" required="true"> required="true <command windowType="wizard_step"/> </action>

Constructing Wizards

791

You can also mark a wizard step as required at runtime. You need to use a javascript function called setStepRequired which is defined in main.js file. You need to pass the id of the step. The default id of the step is in the format <type>. <action>. Use the value of the id attribute if it is defined explicitly while defining wizard step action. For example:
<table border="0"> <tr> <td align="left" valign="top" NOWRAP> <w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>" value="<%=NmObjectHelper.CB_COPY%>" checked="true" onclick="setStepRequired setStepRequired(<type>.<action >);"/> </td> </tr> </table>

Hiding a wizard step


There are two ways to hide a wizard step. First, you can hide a wizard step initially when the wizard is launched. Secondly, you can hide the wizard step at run time depending on certain criteria or certain user actions. In both the cases, it is mandatory to register the wizard step while defining the wizard. In <your_wizard_page>.jsp
<jca:wizard > <jca:wizardStep action="defineItemWizStep" type="object"/> <jca:wizardStep action=" setClassificationAttributesWizStep " type="object" /> <jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" /> </jca:wizard>

To implement first way of hiding a step, you can make use of the hidden attribute of <action> tag. For example: In <*-actions>.xml
<action name="setClassificationAttributesWizStep setClassificationAttributesWizStep" hidden="true"> hidden="true" <command windowType="wizard_step"/> </action>

To hide a wizard step at runtime, you need to use a javascript function called removeStep which is defined in main.js file. You need to pass the id of the step that needs to be removed. The default id of the step is in the format <type>. <action>. Use the value of the id attribute if it is defined explicitly while defining wizard step action. For example: In <your_wizardstep_page>.jsp
<table border="0"> <tr> <td align="left" valign="top" NOWRAP> <w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>" value="<%=NmObjectHelper.CB_COPY%>" checked="true" onclick="removeStep removeStep(<type>.<action >);"/>

792

Windchill Customization Guide

</td> </tr> </table>

Note Clerk does not use the of conditional display of steps (i.e. hidden steps), so all the steps will be preloaded and displayed to the user.

Displaying the hidden / dynamic step at runtime


You can show up the hidden wizard step at runtime using the javascript function called insertStep which is defined in main.js file. You need to pass the id of the step that needs to be inserted. The default id of the step is in the format <type>. <action>. Use the value of the id attribute if it is defined explicitly while defining wizard step action. It is mandatory to register the wizard step while defining the wizard. For example: In <your_wizard_page>.jsp
<jca:wizard > <jca:wizardStep action="defineItemWizStep" id= defineItemWizStep type="object"/> <jca:wizardStep action=" setClassificationAttributesWizStep " type="object" /> <jca:wizardStep action="affectedAndResultingItemsStep" type="changeTask" /> </jca:wizard>

In <*-actions>.xml
<action name="setClassificationAttributesWizStep setClassificationAttributesWizStep" hidden="true"> hidden="true" <command windowType="wizard_step"/> </action>

In <your_wizardstep_page>.jsp
<table border="0"> <tr> <td align="left" valign="top" NOWRAP> <w:radioButton id="copy" name="<%=NmObjectHelper.CHOICE%>" value="<%=NmObjectHelper.CB_COPY%>" checked="true" onclick="insertStep insertStep(<type>.<action>);"/> </td> </tr> </table>

Providing user defined SUBMIT function


You can configure a user-defined javascript function, which will be called when the wizard is submitted. You need to write you own submit functionality in some javascript function and than pass the name of that function as an argument to setUserSubmitFunction (provided by wizard framework). By doing so, you are

Constructing Wizards

793

preventing the wizard framework to call the default submit function. Based on the return value (true / false), the wizard framework will decide further action. For example:
<script type="text/javascript"> function user_validate() { ... ... return true; } setUserSubmitFunction(user_validate); </script>

Providing client side validations before a wizard step is displayed


You can configure a user-defined javascript function, which will be called when a wizard step is loaded but before it is displayed. You need to write you own functionality in some javascript function and specify the name of function as the value for the attribute "beforeJS" while defining the action for that particular step. This particular step will only be displayed if the specified function returns "true", else the wizard will move to the previous step. For example: In <*-actions>.xml
<action name="setClassificationAttributesWizStep" beforeJS =" validatePreviousStep"> <command windowType="wizard_step"/> </action>

In any JSP page or Javascript file accessible to wizard


<script type="text/javascript"> function validatePreviousStep() { ... ... return true; } </script>

Providing client side validations after a wizard step is finished


You can configure a user-defined javascript function, which will be called when a wizard step is completed but before next step is loaded. You need to write you own functionality in some javascript function and specify the name of function as the value for the attribute "afterJS" while defining the action for that particular step. The next step will only be displayed if the specified function returns "true". For example:

794

Windchill Customization Guide

In <*-actions>.xml
<action name="setClassificationAttributesWizStep" afterJS =" validateStep"> <command windowType="wizard_step"/> </action>

In any JSP page or Javascript file accessible to wizard


<script type="text/javascript"> function validateStep() { ... ... return true; } </script>

Configuring Wizard - Suppressing enter key


You can suppress form submission on enter key.
<script type="text/javascript"> // Supress form submission twice due to hiting enter function wizardKeyUpListener(event) { var target = Event.element(event); if (event.keyCode == Event.KEY_RETURN || event.which == Event.KEY_RETURN) { if (target != null && (target.tagName == "SELECT" || target.tagName == "TEXTAREA" || target.tagName == "INPUT")) { Event.stop(event); return false; } } }

Configuring Wizard - Changing the Default Focus Element


You can change the default focus element in the wizard. Generally the infrastructure will try to make the default focus element the first required field that is editable (input, select, or textarea tag). This is very tricky and so the infrastructure may not get it right in all cases. If a different element is desired for the first focused element, or this behavior is not working properly in your wizard then you can create some javascript code to get your desired behavior. In a .js file included only by this wizard: //First, Remove the current focus listener to avoid any race conditions. For Example:
PTC.un('ready', PTC.wizard.focusOnReadyFunc); //Create the new focus listener to select your desired component function customFocusFunc {} { // Focus on a specific ID when it becomes available

Constructing Wizards

795

} //Register your new listener on the page. PTC.onReady( customFocusFunc );

Creating Data Validators for Your Steps


Validation of the data entered by users is done after each step and in some cases after each input field is completed.. . It may be done on the client via javascript and/or on the MethodServer via a Java class that extends UIComponentValidator. The system automatically validates that all required attribute values are provided if the input fields are generated by the standard renderers. The renderers add a class="required" attribute to the input field and the wizard javascript checks to make sure that each field with such an attribute has a value. You can do other client validation in a javascript method by specifying the method as the value of the afterJS attribute of the step action. See Adding Custom Code to all Windchill Client Architecture Pages on page 248 for information on how to package your custom javascript. Validation of data values against constraints defined for the attributes in the Type and Attribute Management utility must be done in the MethodServer. This is done by implementing the validateFormSubmission() method on a subclass of DefaultUIComponentValidator. You then specify the name of the selector key for a service.properties entry pointing to your DefaultUIComponentValidator in the afterVK attribute of your step action. The validateFormSubmission() method of your validator class will be automatically called by the framework when the user clicks the Next or OK button on a step. It is also called when the value of any attribute in the driver attributes panel is changed. Default server-side validators are available for the Set Context, driver attributes table, and Set Attributes wizard steps. The selector keys and validator class paths are specified in the following entries in components.service.properties.xconf:
<Service context="default" name="com.ptc.core.ui.validation.UIComponentValidator"> <Option serviceClass="com.ptc.core.components.validators. com.ptc.core.components.validators. ContextWizardStepValidator" ContextWizardStepValidator requestor="null" selector= "setContextWizStep setContextWizStep"/> <Option requestor="null" serviceClass="com.ptc.core.components.validators. com.ptc.core.components.validators. DefineObjectStepValidator" DefineObjectStepValidator selector="defineItem defineItem" /> <Option serviceClass="com.ptc.core.components.validators. com.ptc.core.components.validators. SetAttributesStepValidator" SetAttributesStepValidator requestor="null" selector=" setAttributesWizStep "/> </Service>

If the out-of-the-box validator classes meet your needs you can use them by specifying the selector strings shown in the entries above as the values of the afterVK attributes of your wizard step actions. If you need to do additional validation, you can write your own validators, typically subclassing the standard validators. Note that all the form data can be accessed from the
796

Windchill Customization Guide

UIValidationCriteria parameter passed to the validator by calling UIValidationCriteria.getFormData(). The validateFormSubmission() method should return a UIValidationResult with a status of UIValidationStatus. PERMITTED if all the form data is valid or a status of UIValidationStatus. DENIED if one or more attribute values are not valid. In the latter case, the user will be returned to the wizard step just completed to correct the invalid values. Feedback messages to be displayed to the user should be added to the UIValidationResult using the UIValidationResult.addFeedbackMsg() method.

Limitations
Windchill Wizard framework takes help from Windchill Action framework to pick up the localized wizard title either from the related .rbInfo file or from a action_<locale>.properties file. It uses the <objectType> and <action> to fetch the required value. The problem arises when you try to use url attribute of command tag (while defining the wizard action). If the value of the url attribute points to a jsp page whose name matches with some another action, the wizard framework will receive localized title corresponding to that action. Consider the following scenario:
<action name="createPartWizard createPartWizard"> <command class="com.ptc.windchill.enterprise.part.forms.CreatePartFormProcessor" method="execute" onClick="validateCreateLocation(event)" windowType="popup"/> </action> <action name="createMultiPart" > <command class = "com.ptc.windchill.enterprise.part.forms.CreateMultiPartFormProcessor" method="execute" onClick="validateCreateLocation(event)" windowType="popup" url="/netmarkets/jsp/part/createPartWizard createPartWizard.jsp?wizardType=multiPart" /> </action>

In the above specified case, the wizard title for the action createMultiPart will be picked up from the property part.createPartWizard.title.value and not from the property part. CreateMultiPart.title.value. The workaround for this scenario is to use the title attribute of the wizard tag. If this attribute is specified, the wizard framework will not try to look in to any rbInfo or properties file. However, be sure that you provide a localized string as a title to wizard tag. For example:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%> <fmt:setBundle basename="com.ptc.windchill.enterprise.part.partResource"/> <fmt:message var="createMultiplePartWizardTitle" key = "part.createMultiPart.WIZARD_LABEL" />

Constructing Wizards

797

<jca:wizard helpSelectorKey="PartMultipleCreate" title="${createMultiplePartWizardTitle}"> title="${createMultiplePartWizardTitle}" ... ... </jca:wizard>

Limitations for Clerks


Clerks will execute only required fields validation for all the clerk steps. All the other validations mentioned below should be provided by the respective clerk developers: Valid Characters - Validate that the user has not entered any illegal characters for a given field (e.g. alpha characters in a numeric field). Format - Validate that the user has entered values in an expected and understandable format. Note that the UI should do as much as possible to prevent the user from entering invalid formats in the first place (e.g. clearly indicating what format is expected, allowing different formats to be entered). See the Form Standard for more information. Length - Validate that the user has entered a value which is neither too long nor too short for a given field. Uniqueness - Validate that data entered is unique with respect to existing data in the system. For example, verifying that a given part number does not already exist in the system.

In case of clerk, while navigating between steps any java code such as a validator may not get the required fields so developers need to take care and apply logic accordingly.( E.g. While creating a new document first step has required field type (means type of document), since in clerk user is free to navigate between other tabs while clicking on other tabs,user might not have selected required filed type in first step. In that case server validator cant get value of type attribute.)

Sample Code
Examples of Usage in Windchill Code
Create Part wizard:
<Windchill>\codebase\netmarkets\jsp\part\createPartWizard.jsp

Create Folder wizard:


<Windchill>\codebase\netmarkets\jsp\folder\create.jsp

798

Windchill Customization Guide

Create Document wizard:


<Windchill>\codebase\netmarkets\jsp\document\create.jsp

Create Multiple Documents wizard:


<Windchill>\codebase\netmarkets\jsp\document\createMulti.jsp

Packaged Samples
Wizard Example One on page 799 Wizard Example Two on page 800 Clerk Example One on page 801

Packaged Samples
Wizard Example One
Description This is an example of a wizard with three steps. The second and third steps are conditionally displayed based on the content of the first step. The first step also includes before and after JavaScript method. Location of Example To navigate to this example in the produce go to Customization >> Component Catalog >> Wizard Component >> In the example section select the first New Wizard Description. Actions for this Example newWizardExampleOne setFirstWizStep setThirdWizStep setSecondWizStep

Action Models for this Example None

Files Used in This Example \netmarkets\jsp\carambola\customization\examples\wizard \newWizardExampleOne.jsp \netmarkets\jsp\carambola\customization\examples\wizard\setFirstWizStep.jsp

Constructing Wizards

799

\netmarkets\jsp\carambola\customization\examples\wizard\setSecondWizStep. jsp \netmarkets\jsp\carambola\customization\examples\wizard\setThirdWizStep.jsp

Wizard Example Two


Description This is an example of a wizard with three steps. The second and third steps are conditionally displayed based on the content of the first step. The first step also includes before and after JavaScript method. The steps in this wizard contain a table and a tree and illustrate how those components can be included in a wizard step. Location of Example To navigate to this example in the produce go to Customization >> Component Catalog >> Wizard Component >> In the example section select the second New Wizard Description. Actions for this Example newWizardExampleTwo setFourthWizStep setFifthWizStep setSixthWizStep

Action Models for this Example None

Files Used in This Example \netmarkets\jsp\carambola\customization\examples\wizard \wizardExampleTwo.jsp \netmarkets\jsp\carambola\customization\examples\wizard\setFourthWizStep. jsp \netmarkets\jsp\carambola\customization\examples\wizard\setFifthWizStep.jsp \netmarkets\jsp\carambola\customization\examples\wizard\setSixthWizStep.jsp

800

Windchill Customization Guide

Clerk Example One


Description This is an example of a clerk with three steps. The second and third steps are conditionally displayed based on the content of the first step. Location of Example To navigate to this example in the produce go to Customization >> Component Catalog >> Wizard Component >> In the example section select New Clerk Description. Actions for this Example clerkExampleOne setFirstClerkStep setSecondClerkStep setThirdClerkStep

Action Models for this Example None

Files Used in This Example \netmarkets\jsp\carambola\customization\examples\wizard\clerkExampleOne. jsp \netmarkets\jsp\carambola\customization\examples\wizard\setFirstClerkStep. jsp \netmarkets\jsp\carambola\customization\examples\wizard \setSecondClerkStep.jsp \netmarkets\jsp\carambola\customization\examples\wizard\setThirdClerkStep. jsp

Constructing Wizards

801

Wizard Processing
Objective
You have created a JSP wizard to gather information from a user about one or more object(s). You now need to create the code to process that information and perform a database operation(s) on the object(s).

Background
If your wizard uses one of the built-in button sets, when a user clicks the Finish, Apply, Save, or Check In button to submit the form, a javascript function is called that invokes the doPost() method of the WizardServlet. The WizardServlet loads the HTTP form data and other wizard context information, such as where the wizard was launched, into a NmCommandBean. It then passes the NmCommandBean to the FormDispatcher class. The FormDispatcher performs an RMI call to a FormProcessorController class in the MethodServer. The FormProcessorController partitions the form data into ObjectBeans. One ObjectBean is created for each target object of the wizard. It contains all the form data specific to that object and any form data that is common to all objects. The FormProcessorController then passes the ObjectBeans to classes called ObjectFormProcessors that perform the tasks appropriate to the wizard for example, creating a new object in the database, updating an object in the database, or checking in an object. ObjectFormProcessors, in turn, can call classes called ObjectFormProcessorDelegates to perform one or more subtasks. If your wizard is performing an operation on a single object you may need to create your own ObjectFormProcessor and/or ObjectFormProcessorDelegates to perform the tasks specific to your wizard. However, if your wizard is creating or editing an object, you may be able to take advantage of some processors that are delivered with the product for those purposes. See Building Wizards to Create a Single Object on page 823 and Building Wizards to Edit a Single Object on page 846 for more information. If your wizard has multiple target objects you may or may not also need to create your own FormProcessorController to control the order in which objects are processed.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Assumes that you have already created the necessary JSPs, data utilities, GUI components, and renderers to display your wizard.

802

Windchill Customization Guide

Also assumes that you have created the necessary actions to hook up your wizard to the UI.

Intended Outcome
Perform a database operation(s) related to one or more Windchill object.

Solution
Use the JSP client architecture framework and common components to process wizard form data and perform the appropriate database tasks for one or more object (s).

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Java programming Basic web development using HTML forms Familiarity with the Windchill service APIs or other APIs necessary to perform the tasks appropriate to the wizard

Definition of terms used in this section: Term Definition target object Object(s) for which you are gathering data in your wizard. Some operation(s) will typically be performed on these objects in your wizard processing.

Solution Elements
Element WizardServlet Type Java class; runs in the servlet container Description This is the class to which wizard form data gets posted and which sends the response page sent back to the browser after processing completes.

FormProcessor Controller

Runtime location: <WT_HOME>/srclib/ CommonComponents-web.jar Java interface; imple- Classes implementing this interface mentations run in the instantiate and call ObjectFormProMethod Server cessor(s) to execute wizard tasks.

Constructing Wizards

803

Element

Type

Description Runtime location: <WT_HOME>/srclib/ CommonComponents.jar A default implementation of FormProcessorController that should be sufficient for all single-object wizards. This controller partitions the HTML form data into ObjectBeans and passes those beans to ObjectFormProcessors. Wizards with multiple target objects may need to extend this class to control the order in which objects are processed.

DefaultForm ProcessorController

Java class; runs in the Method Server

ObjectForm Processor

Runtime location: <WT_HOME>/srclib/ CommonComponents.jar Java interface; imple- Classes implementing this interface mentations run in the perform the database and related Method Server tasks appropriate to the wizard using the form data. Each wizard will have only one ObjectFormProcessor class but multi-object wizards may have multiple instances of that class. ObjectFormProcessors may call ObjectFormProcessor Delegates to perform subtasks. Runtime location: <WT_HOME>/srclib/ CommonComponents.jar A default implementation of ObjectFormProcessor that contains the logic to execute ObjectFormProcessorDel egates and perform several other common tasks. This is the base class that should be extended by wizard-specific processors.

DefaultObject FormProcessor

Java class; runs in the Method Server

804

Windchill Customization Guide

Element

Type

Description

ObjectForm ProcessrDelegate

Runtime location: <WT_HOME>/srclib/ CommonComponents.jar Java interface; imple- Classes implementing this interface mentations run in the are called by ObjectFormProcessors Method Server to perform processing subtasks. Multiple ObjectFormProcessorDel egates may be called by one processor and the same delegate may be used by multiple processors to handle a task common to multiple wizards. These are optional. Runtime location: <WT_HOME>/srclib/ CommonComponents.jar A default implementation of ObjectFormProcessorDelegate. This provides no-op behavior for methods a subclass may not need to implement. This is the base class that should be extended by task-specific delegates. Runtime location: <WT_HOME>/srclib/ CommonComponents.jar A container for the form data specific to a specific target object and the data common to all objects. Provides methods to retrieve the form data for a given object. Runtime location: <WT_HOME>/srclib/ CommonComponents.jar A container for ObjectBeans that knows which ObjectBeans should be processed by the same processor instance and the order in which they should be processed.

DefaultObject FormProcessor Delegate

Java class; runs in the Method Server

ObjectBean

Java class; runs in the Method Server

ProcessorBean

Java class; runs in the Method Server

Constructing Wizards

805

Element

Type

Description Runtime location: <WT_HOME>/srclib/ CommonComponents.jar A class used to pass method results between server methods and from the server to the WizardServet. Runtime location: <WT_HOME>/srclib/ CommonComponents.jar

FormResult

Java class; runs in the Method Server and client

The relationship between the main Java classes in the wizard processing framework is shown in the UML diagram below.

Form Processing Task Flow


Frequently, multiple tasks are performed on wizard target object(s) when processing the form data. These typically follow the following sequence: 1. Preprocessing During this phase the setup for the database operation is done. For example: for an object creation wizard, instances of the object(s) are created and their attributes set from values in the form data for an object edit wizard, the object(s) are retrieved from the database and their attributes are modified per the values in the form data

2. Start a database transaction block

806

Windchill Customization Guide

3. Do the database operation. For example: for an object creation wizard, the object(s) would be stored in the database for an object edit wizard, the object(s) would be updated in the database

4. Postprocessing Do database or other tasks that need to be done after the main database operation but within the same transaction block so that the database operation will be rolled back if these task fail. These tasks typically require that the target object(s) be persisted beforehand. For example: share the object(s) to another container submit the object(s) to a workflow

5. End the database transaction block 6. Post-transaction processing Do tasks that need to be done after the transaction block is closed so that the entire database transaction will not be rolled back if the tasks fail. For example: check out an object Additional database operations may be performed in this phase if desired. The tasks in each processing phase are performed by ObjectFormProcessors and ObjectFormProcessorDelegates. Every wizard must have an ObjectFormProcessor which should extend the DefaultObjectFormProcessor. This is the primary class that controls and performs the processing tasks appropriate to the wizard. Wizards may or may not have one or more ObjectFormProcessorDelegates that are called by the ObjectFormProcessor (via the DefaultObjectFormProcessor) to perform processing subtasks. ObjectFormProcessorDelegates should extend the DefaultObjectFormProcessorDelegate class. See Create any necessary ObjectFormProcessorDelegate classes for your wizard on page 820 for more information about ObjectFormProcessorDelegates. Both ObjectFormProcessor and ObjectFormProcessorDelegate classes have preProcess(), doOperation(), postProcess(), and postTransactionProcess() methods for carrying out tasks during each processing phase. Not every wizard will have tasks in every phase, so it is not necessary that every processor and every delegate implement all of these methods, if they extend from the default classes DefaultObjectFormProcessor and DefaultObjectFormProcessorDelegate, respectively. Those parent classes provide default implementations of each method. If an ObjectFormProcessor does implement one of these methods, it should call the super() method of the DefaultObjectFormProcessor, which will handle the calling of ObjectFormProcessorDelegates.

Constructing Wizards

807

The HTML form data will be passed to ObjectFormProcessors and ObjectFormProcessorDelegates in a list of ObjectBeans. An ObjectBean contains the data specific to one target object and the data common to all the target objects. For wizards with a single target object the list will contain only one ObjectBean. For wizards with multiple target objects the list will contain one ObjectBean for each target object and the ObjectBeans may be organized into a tree structure representative of the relationship between the objects and the order in which they should be processed. The creation of ObjectBeans is handled by the FormProcessorController. The FormProcessorController also handles the opening, closing, and, if necessary, rollback of the database transaction and the calling of the ObjectFormProcessors. For the latter, the DefaultFormProcessorController uses objects called ProcessorBeans. Target objects with the same parent object, which are of the same type, and which have the same ObjectFormProcessorDelegates are placed into the same ProcessorBean. Each ProcessorBean also will have it's own instances of the ObjectFormProcessor and ObjectFormProcessorDelegates for the ObjectBeans it contains. ProcessorBeans may be organized into a tree structure to control the order in which objects are processed. (Wizards with a single target object will have only one ProcessorBean. ) The task flow of the DefaultFormProcessorController is as follows: 1. Call the preProcess() method of ObjectFormProcessor for the root ProcessorBean, passing it the ObjectBeans in the ProcessorBean. Then call the preProcess() method of the processors for the children of the root ProcessorBean, in the order in which they appear in the child list. Then call the preProcess() method for the children of the children, and so forth. 2. Do Transaction.start() 3. Call the doOperation() method of the ObjectFormProcessor for the root ProcessorBean and its children in the same way as preProcess(). 4. Call the postProcess() method of the ObjectFormProcessor for the root ProcessorBean and its children in the same way as preProcess(). 5. If steps 1-4 are successful, do Transaction.commit() 6. Call the postTransactionProcess() method of the ObjectFormProcessor for the root ProcessorBean and its children in the same way as preProcess(). If any method returns a status of FormProcessingStatus.FAILURE, the controller will call the setResultNextAction() method of the ObjectFormProcessor that failed so it can set information needed for the HTML response page.

Note ObjectFormProcessors should not open/commit additional transaction blocks in steps 3 or 4 as nesting of transactions is not recommended.
Windchill Customization Guide

808

Wizards with Multiple Target Objects


Two types of multiple-object wizards are supported: wizards with multiple unrelated target objects Example: create multiple parts wizards with a tree of related target objects Example: create a change notice and related change tasks The data specific to a given object should be contained either in a table row specific to that object or in a wizard step specific to that object. An example table where each row represents a part being created and each column is an attribute of the part is shown below.

Each wizard step must display one of these types of data: data in tabular format where each row represents a different object data that is specific to one and only one of the objects created data that is common to all objects created

A step cannot contain object-specific data for multiple objects unless it is in tabular format. In multiple-object wizards, the object to which an input field applies is identified by an "objectHandle" embedded in the name attribute of the HTML input field. For example:
<input id="null1188140328133" name="<someFieldIdString>!~objectHandle~430512131997223~! <someAdditionalText>" value="" size="60" maxlength="60" type="text">

In the example above, "430512131997223" is the object handle, "! ~objectHandle~" is the required prefix, and "~!" is the required suffix. The HTML name attribute in which the object handle is embedded can be any string and the object handle may appear anywhere within the string.

Constructing Wizards

809

When the DefaultFormProcessorController loads the form data in to ObjectBeans, it will strip off the object handle (including the required prefix and suffix) from the name attribute and use the resulting string as the key for the value in the form data parameter maps. For example, to retrieve the form value for the input field above you would call ObjectBean.getTextParameter() with the following key:
<someFieldIdString><someAdditionalText>

The framework generates object handles on name attributes for you in one of two ways: If data for the objects is being captured in tabular format, where each row represents an object and each column an attribute of the object, the handle will be dynamically generated for you if you put a "rowBasedObjectHandles" attribute on the renderTable tag:
<jca:renderTable model="<your model name>" rowBasedObjectHandles="true" />

The dynamically generated object handle will represent the time in nanoseconds when the row was created. Where all the data on a given wizard step is for the same object, you specify the object handle for that object on the wizard step action:
<jca:wizardStep action="setContextWizStep" type="object" objectHandle="<your object handle string>"

If data on the wizard step is common to all objects created, no object handle is needed on the input fields. The object handle associated to the data in an ObjectBean can be accessed by the ObjectBean.getObjectHandle() method. The FormProcessorController controls the order in which processors are called to process the ObjectBeans, as described in the sections below. Note that in the illustrations below, circles are used to represent ObjectBeans. Circles representing objects of the same type will have the same shading. Multiple unrelated target objects Typically, when a wizard has multiple unrelated target objects, the objects are the same type:

An example of such a wizard is that in which you can create multiple parts. This wizard has three steps: 1. Define Part

810

Windchill Customization Guide

User enters the type of parts to be created and other attributes common to all the parts being created. 2. Set Attributes User enters the name and number of each part to be created in tabular format. This table is dynamic in that the user can enter any number of parts. 3. Set Additional Attributes User enters some additional attributes common to all of the parts. If the user enters data for five parts, the DefaultObjectFormProcessorController will create five ObjectBeans. Each ObjectBean will contain the data from step 2 specific to the part it represents and the data from steps 1 and 3. Because there is no relationship between the parts and they can be created independently, none of the ObjectBeans will have parents or children. Since the same ObjectFormProcessor and ObjectFormProcessorDelegates will be used to process all the ObjectBeans and all the objects are of the same type, they will all be placed in the same ProcessorBean. Multiple related target objects Other wizards may have multiple related target objects. For example, you might have a wizard that creates a change notice and the change tasks related to that change notice. To create the associations between the change notice and the change tasks, the processor for the change notice will need to know how the objects relate to each other.

The change notice ObjectBean has three child ObjectBeans. The change task ObjectBeans have a parent ObjectBean and no children. In this case, you would need to write your own FormProcessorController to create the structure of ObjectBeans. This can be a subclass of the DefaultFormProcessorController. The default controller will create the ObjectBeans for you. You would override it's createObjectBeanStructure() method, which is given a flat list of all the ObjectBeans. In that method you would set the parents and children of the
Constructing Wizards

811

ObjectBeans. You pass back a list of all the root ObjectBeans. After you have created the ObjectBean structure, the DefaultFormProcessorController will call the ProcessorBean.newCollection() method which will group the ObjectBeans into ProcessorBeans as follows:

In the diagram above the circles represent the ObjectBeans and the solid lines the relationships between them. The rectangles represent the two ProcessorBeans and the dotted line the relationship between them. Each ProcessorBean will have its own instances of the ObjectFormProcessor and the ObjectFormProcessorDelegates needed for the objects in it. If the processor for the root ProcessorBean is called "ProcessorInstance1" and the processor for the child ProcessorBean is called "ProcessorInstance2", the processor methods would be called as follows: Method Task Performed 1 ProcessorInstance1.preProcess create an instance of a (ObjectBean in Processor Bean 1) WTChangeOrder2 and store it in the "object" attribute of the bean 2 ProcessorInstance2.preProcess create three instances of (ObjectBeans in Processor Bean 2) WTChangeActivity2 and store them in the "object" attributes of the beans 3 ProcessorInstance1.doOperation persist the WTChangeOrder2 (ObjectBean in Processor Bean 1) 4 ProcessorInstance2.doOperation persist the WTChangeActivity2 (ObjectBeans in Processor Bean 2) instances 5 ProcessorInstance1.postProcess create the associations between the (ObjectBean in Processor Bean 1) change notice and the change tasks none 6 ProcessorInstance2.postProcess (ObjectBeans in Processor Bean 2)
Windchill Customization Guide

812

Method ProcessorInstance1. postTransactionProcess (ObjectBean in Processor Bean 1) ProcessorInstance2. postTransactionProcess (ObjectBeans in Processor Bean 2)

Task Performed none

none

The tasks could be arranged differently. For example, you could create the associations in method 6 instead of method 5 with the same effect. Or, you could create an ObjectFormProcessorDelegate to create the associations in its postProcess() method. The framework offers the flexibility to modularize your code as best fits your wizard. Just be sure to arrange your tasks correctly relative to the start and end of the main transaction. Your structure of ObjectBeans could be more complex. For example:

As you can see from the diagram above, ObjectBeans will be placed in different ProcessorBeans if any of the following is true: the object in the ObjectBeans are different types the ObjectBeans have a different ObjectFormProcessor

Constructing Wizards

813

(Note: at this time all the ObjectBeans in the wizard must have the same ObjectFormProcessor.) the ObjectBeans have a different list of ObjectFormProcessorDelegates the ObjectBeans have a different parent ObjectBean

The DefaultFormProcessorController will call the processors associated with each ProcessorBean starting at the root ProcessorBean and proceeding down the tree to the leaf ProcessorBeans.

Procedure - Creating Your Wizard Processing Code


You have two options in creating your wizard processing code: Wizards with a Single Target Object on page 814 Wizards with Multiple Target Objects on page 820

Wizards with a Single Target Object This process consists of the following steps: Create your processor class on page 814 Specify the processor class for the wizard on the wizard action on page 817 Create any necessary ObjectFormProcessorDelegate classes for your wizard on page 818 Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard on page 819

Create your processor class Three processors for handling object creation and editing wizards are delivered with the product: com.ptc.core.components.forms.CreateObjectFormProcessor com.ptc.core.components.forms.DefaultEditFormProcessor com.ptc.core.components.forms.EditWorkableFormProcessor

These processors may be used as is or extended for your own purposes. If your wizard is not an object creation or editing wizard you will need to create your own ObjectFormProcessor. ObjectFormProcessors should extend the DefaultObjectFormProcessor class. You should place your form processing logic into the preProcess(), doOperation(), postProcess(), and postTransactionProcess() methods of the processor, as appropriate. Your methods should call the corresponding super method of the DefaultObjectFormProcessor, which will handle the calling of
Windchill Customization Guide

814

ObjectFormProcessorDelegates. These methods will be passed a single ObjectBean, which will contain all the form data from the wizard. The form data can be accessed using the getter methods of that object. The following getter methods are commonly used:
public public public public public public public public public public Map<String,List<String>> getChangedComboBox() Map<String,String> getChangedRadio() Map<String,String> getChangedText() Map<String,String> getChangedTextArea() Map<String,List<String>> getChecked() Map<String,List<String>> getUnChecked() List getRemovedItemsByName(String paramName) List getAddedItemsByName(String paramName) String getTextParameter(String key) String[] getTextParameterValues String key)

See the javadoc for more information. The "object" attribute of the ObjectBean represents an instance of the target object . Where appropriate, it should be set by one of your processor methods (most likely preProcess()) for use by downstream methods. Other information can be passed from one method to another using processor instance variables. The NmCommandBean object passed to these methods contains information about the page from which the wizard was launched and the object selected on the parent page when the wizard was launched. It also contains all the HTML form data but you should use the methods on the ObjectBean rather than the NmCommandBean to access that data. See the javadoc for NmCommandBean for more information. You pass the outcome of the preProcess(), doOperation(), postProcess(), and postTransactionProcess() methods back to the DefaultFormProcessorController using the com.ptc.core.component.FormResult object. Before returning, each of these methods should call FormResult.setStatus() to return the processing status. Three options are available: FormProcessingStatus.SUCCESS - if the method executed without error FormProcessingStatus.FAILURE - if the method encountered a fatal errors FormProcessingStatus.NON_FATAL_ERROR - if the method succeeded but encountered one or more problems that should be reported to the user.

The DefaultFormProcessorController passes the returned FormResult to its continueExecuting() method to determine whether processing should continue to the next phase or be aborted. By default, it will abort only if the status is FormProcessingStatus.FAILURE. If processing is to be aborted or after all processing competes successfully, the controller will call the setResultNextAction() method of the ObjectFormProcessor to set information in the FormResult needed to construct the response page sent back to the browser.

Constructing Wizards

815

This method should convey the following information: Whether the wizard window should be closed. Determined from the status and nextAction variables. Whether the window from which the wizard was launched should be refreshed. Determined from the nextAction variable. The javascript you would like executed in the response, if any. Determined from the nextAction and javascript variables. Whether a new URL should be loaded into the launch window and, if so, what that URL should be loaded. Determined from the nextAction and URL variables. What feedback messages should be displayed to the user, if any. Determined from the feedbackMessages and exceptions variables. Feedback messages, if any, are displayed before executing any window operations or provided javascript. Exception messages are only displayed if status is FormProcessingStatus. FAILURE or FormProcessingStatus.NON_FATAL_ERROR. See the javadoc for the FormResult, FormProcessingStatus, and FormResultAction classes for more information. It is also possible for your ObjectFormProcessor's preProcess(), doOperation(), postProcess(), and postTransactionProcess() methods to throw exceptions. In that case, control will be returned to the WizardServlet which will set the variables of the FormResult as follows: status - FormProcessingStatus.FAILURE nextAction - FormResultAction.NONE exceptions - the thrown Exception

This will cause the response page to display the exception message in an alert window and then close the wizard window. How to get selected object(s) in form processor using NmCommandBean There are four different form processing scenarios and to get the selected oid in each scenario there is different API on NmCommandBean that can be used. See the picture below for more details.

816

Windchill Customization Guide

Specify the processor class for the wizard on the wizard action You specify the ObjectFormProcessor class in the <command> subtag of the <action> tag for the wizard. Your action tag will be contained in a *actions.xml file. Here is an example of how you would specify the CreateDocFormProcessor class as your processor.
<action name="create"> <command class="com.ptc.core.components.forms.CreateObjectFormProcessor" windowType="popup" /> </action>

Constructing Wizards

817

Create any necessary ObjectFormProcessorDelegate classes for your wizard ObjectFormProcessorDelegates may be used to carry out one or more subtasks in your wizard processing. Because the same delegate class may be called by multiple ObjectFormProcessors, they are typically used for tasks that are needed by multiple wizards. Here are some examples of how ObjectFormProcessorDelegates are used in the delivered product: Several object creation wizards have a checkbox named "Keep checked out after checkin." The ObjectFormProcessors for all these wizards call the same ObjectFormProcessorDelegate class to handle this checkbox and checkout the object after it is created if the box is checked. Wizards to create objects that are ContentHolders typically have a Set Attachments step to specific the documents that should be attached to the object. All these wizards call the same ObjectFormProcessorDelegate class to handle the persistence of the attachments. Many object creation wizards have an input field for a Location attribute to specify the object's folder. Because the processing of this input field is complex all these wizards call the same ObjectFormProcessorDelegate to set the folder on the object being created.

As shown in the examples above, a ObjectFormProcessorDelegate can handle the processing of one or many input fields. If your wizard does not have any HTML elements that are used in multiple wizards you may not need any delegates. However, they can be useful for modularizing your processing code also. ObjectFormProcessorDelegates should extend the class DefaultObjectFormProcessorDelegate. ObjectFormProcessorDelegates are instantiated by the DefaultFormProcessorController and passed to the ObjectFormProcessor. ObjectFormProcessorDelegates have preProcess(), doOperation(), postProcess(), and postTransactionProcess() methods just like ObjectFormProcessors. The delegates registered for the wizard will be called by the DefaultObjectFormProcessor during the different processing phases. The outcome of an ObjectFormProcessorDelegate method is passed back to the ObjectFormProcessor using a FormResult, just as the ObjectFormProcessor methods pass back their results to the FormProcessorController. Typically, a delegate will only pass back a status and, possibly, feedback messages in the FormResult. The ObjectFormProcessor will set and pass back the nextAction in the FormResult it sends to the FormProcessorController since it knows the launch context of the specific wizard in which the delegate is being used.

818

Windchill Customization Guide

Like ObjectFormProcessor methods, ObjectFormProcessorDelegate methods can throw exceptions. How these are handled depends on the ObjectFormProcessor calling it. Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard The names of the ObjectFormProcessorDelegate classes to be instantiated by the DefaultObjectFormProcessor, if any, are communicated in hidden input fields as follows:
<input name="FormProcessorDelegate" value="com.ptc.core.components.forms.NumberPropertyProcessor" type="hidden">

These hidden input fields can be created in several ways: If you have a delegate associated with a specific wizard step, the delegate can be specified in the command subtag of in the wizard step action. For example:
<action name="attachmentsWizStep" postloadJS="preAttachmentsStep" preloadWizardPage="false" <command class="com.ptc. class="com.ptc.windchill. windchill.enterprise. enterprise.attachments. attachments.forms. forms.Second Second aryAttachmentsSubFormProcessor" aryAttachmentsSubFormProcessor windowType="wizard_step"/> </action>

The wizard framework will then generate a hidden FormProcessorDelegate field in the wizard for any wizard using this step. If you have specified an object handle on the wizard step action, the name attribute of the hidden field will include the object handle so that the delegate will be called only for the target object associated with the step. If you have a specific input field that requires a delegate you can generate the hidden field in the data utility that creates the GUI component for the input field. It is recommended that the data utility return a subclass of AbstractGuiComponent to take advantage of the addHiddenField() method and the AbstractRenderer. After creating the GUI component in the data utility, call the method addHiddenField() in the AbstractGuiComponent class. For example:
LocationInputGuiComponent guiComponent = new LocationInputComponent(); guiComponent.addHiddenField (CreateAndEditWizBean.FORM_PROCESSOR_DELEGATE, "com. ptc.windchill.enterprise.folder.LocationPropertyProcess or");

The hidden input field will be generated for you by the AbstractRenderer automatically. If the field is associated with a step or table row that has an object handle, that object handle will be embedded in the HTML name

Constructing Wizards

819

attribute of the hidden field. If you choose to return a GUI component that does not extend Abstract GuiComponent, your GUI component and renderer would have to know how to render the necessary hidden field. You can include a hidden field for your delegate directly in your jsp file. However, one of the first two methods is preferred because it encapsulates the hidden field with its associated HTML input fields.

Wizards with Multiple Target Objects This process consists of the following steps: Create your processor class on page 814 Specify the processor class for the wizard on the wizard action on page 820 Create any necessary ObjectFormProcessorDelegate classes for your wizard on page 818 Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard on page 819 Create a FormProcessorController, if needed on page 821 Specify the FormProcessorController to be used in your wizard, if needed on page 821

Create your processor class The same as for a wizard with a single target object. See Create your processor class on page 814. Specify the processor class for the wizard on the wizard action The same as for a wizard with a single target object. See Specify the processor class for the wizard on the wizard action on page 817. Create any necessary ObjectFormProcessorDelegate classes for your wizard The same as for a wizard with a single target object. See Create any necessary ObjectFormProcessorDelegate classes for your wizard on page 818. Specify the ObjectFormProcessorDelegate(s) to be used in your wizard The same as for a wizard with a single target object. See Specifying the ObjectFormProcessorDelegate(s) to be used in your wizard on page 819. Remember that an object handle must be embedded in the name attributes of the hidden fields specifying the delegates if you want the delegate to be used only for a given object.

820

Windchill Customization Guide

Create a FormProcessorController, if needed If the target objects of your wizard form a structure of related objects, you will need to create your own FormProcessorController to create a structure of the ObjectBeans. You should subclass the DefaultFormProcessorController to leverage its ability to partition the form data into ObjectBeans and ProcessorBeans and call the form processors. Typically, the only method you will need to override is the createObjectBeanStructure() method. Specify the FormProcessorController to be used in your wizard, if needed If you have created your own FormProcessorController, you should specify the controller to be used for your wizard on the wizard tag in your main JSP file for the wizard. For example:
<jca:wizard helpSelectorKey="change_createProblemReport" buttonList="DefaultWizardButtonsWithSubmitPrompt" formProcessorController="com.ptc. formProcessorController="com.ptc.windchill. windchill.enterprise. enterprise.change2. change2.forms. forms. controllers.ChangeItemFormProcessorController"> controllers.ChangeItemFormProcessorController">

Limitations
Only one ObjectFormProcessor class per wizard is supported at this time The framework does not support having data for multiple objects in the same wizard step unless it is in tabular format. It also does not support having data common to all the objects on the same step as object-specific data.

Additional Resouces
Related Package/Class Package/Class Javadoc
com.ptc.core.components.forms.FormDispatcher com.ptc.core.components.forms.FormProcessorController com.ptc.core.components.forms.DefaultFormProcessorController com.ptc.core.components.forms.ObjectFormProcessor com.ptc.core.components.forms.DefaultObjectFormProcessor com.ptc.core.components.forms.CreateObjectFormProcessor com.ptc.core.components.forms.DefaultEditFormProcessor com.ptc.core.components.forms.EditWorkableFormProcessor com.ptc.core.components.forms.ObjectFormProcessorDelegate com.ptc.core.components.forms.DefaultObjectFormProcessorDelegate com.ptc.core.components.forms.FormResult

Constructing Wizards

821

com.ptc.core.components.forms.FormResultNextAction com.ptc.core.components.forms.DynamicRefreshInfo com.ptc.core.components.forms.FormProcessingStatus com.ptc.core.components.util.FeedbackMessage com.ptc.core.ui.resources.FeedbackType

822

Windchill Customization Guide

Building Wizards to Create a Single Object


Objective
You need to develop a wizard to capture user input and from that input create a Windchill business object in the database.

Background
Windchill provides a framework for creating wizards and navigating between wizard steps. It also provides data utilities, GUI components, renderers, and validators for creating input elements in your wizard JSPs. Finally, it provides a framework for processing the data sent to the server when the wizard form is submitted. These frameworks and components are described in other documents listed in Prerequisite Knowledge on page 825. This document builds upon that information to describe how to develop and process wizards designed specifically to create Windchill objects. It will tell you how to use out-of-the-box components as building blocks to create your own wizards. Components you will typically make use of are: action definitions for wizard steps that are common to multiple wizards jsp and jspf files for wizard steps that are common to multiple wizards custom tags for managing wizard data and displaying elements on the page Java classes for processing the wizard data after the user submits the wizard

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Assume you have created a custom Windchill business object class or soft type and you want to develop a wizard that will allow users to create one instance of that object type in the database. The object to be created should be a Persistable. It may or may not implement the Typed, Foldered, and/or Iterated interfaces. Where this document makes reference to attributes that are not applicable to your object type it is correct to ignore those implementation details. This document describes the creation of a very basic wizard to create objects. There are many reusable steps available to you out of the box. For more details on adding these steps to a wizard see Customizing Reusable Wizard Steps on page 860.

Constructing Wizards

823

Be aware that it may not be necessary to develop your own custom wizard to create instances of a custom type. If your type is a Windchill business class for which a wizard with a type picker is already available, it may be possible to use the out-of-the-box wizard for the type. The out-of-the-box wizards will automatically find subclasses and soft types of a given base type such as WTPart or WTDocument and display those subtypes in the type picker so that a user can create instances of them. For example, if you have created a soft subtype of WTPart called PBPart, it will be displayed in the New Part wizard as follows:

You need to specify any non association attributes you have defined for your sub type in the Type and Attribute Management utility Layout for them to appear as Input fields in the non driver attributes table. Attributes will be displayed in the UI exactly as you specify them in the Type and Attribute Management utility. If you want to order the attributes on this step differently, you will need to create a new jsp for this step specifically for your subtype but you can still use the New Part wizard. However, if you need to associate other objects to your new object or require additional wizard steps, you will likely need to develop a custom wizard. This document describes the process of developing a wizard that creates a single object. See Building Wizards to Edit a Single Object on page 846 for information on constructing a wizard to edit an object.

824

Windchill Customization Guide

Intended Outcome
Add a single- or multi-step HTML wizard to the product that allows a user to create a business object in the database. The arrangement of steps and presentation of attributes within the wizard should be similar to that of other Windchill wizards to provide a consistent user experience.

Solution
Use common jsp, tag, JavaScript, and Java class components built on top of the jsp wizard framework to create a wizard for capturing user input and for processing that input and creating the object in the database.

Prerequisite Knowledge
To apply this process, you need to have an understanding of the following: Java programming Basic web development using JSPs , custom tags, and HTML forms How to create hard or soft Windchill business object types. See the following chapters for more information on creating your business object classes: Getting Started With Windchill Customization on page 43 System Generation See the Type and Attribute Management utility chapter of the Windchill Business Administrator's Guide for more information on creating soft types and attributes. The use of actions to launch jsp pages and wizards. See Adding Actions and Hooking Them Up in the UI on page 485 for information on how to create actions. The Windchill framework for creating wizards and processing wizard data. See Constructing Wizards on page 775 for more information on this topic. The use of tables and property panels to present information in the UI and how to acquire the data for these components. For more information see Customizing HTML Clients Using the Windchill JSP Framework on page 309 Gathering the Data for the UI on page 555 Presenting Information in the UI on page 573

Constructing Wizards

825

The use of data utilities, gui components, and renderers to create HTML elements for presenting and editing object attributes within tables and property panels. See Presenting Information in the UI on page 573 for more information. The use of the UI Validation Service for validating the user s ability to perform actions and for validating the data entered in wizards. See Adding Validation Logic for Actions and Properties on page 452 for more information. The Windchill service APIs or other APIs necessary to perform the data processing tasks appropriate to the wizard Attribute Layout See Attribute Customization on page 630 for more information. This document will build on this knowledge and provide additional information on the components available to help you create and process wizards for the specific purpose of creating a Windchill business object in the database.

Definition of Terms Used in This Section


Term base type Definition A hard or soft type class that is the root type of the wizard's type picker. If the wizard does not have a type picker, this is the type of object that will be created. The base type is used to look up the correct JSPs for wizard steps that have different jsp variants for different subtypes until a specific type is selected by the user. An attribute whose value and/or display characteristics are wholly or partially determined by the value of another attribute (called the "driver attribute") via an object initialization rule (OIR), access control policy, or other mechanism. An attribute whose value drives the value and/or display characteristics of another attribute (called a "dependent" attribute) via an object initialization rule (OIR), access control policy, or other mechanism. An object attribute defined in a Java class. An object type defined in a Java class. Hard types are typically created in java classes using annotations and may extend out-of-the-box Windchill business object classes.

dependent attribute

driver attribute

hard attribute hard type

826

Windchill Customization Guide

Term object type

soft attribute

soft type

target object

Definition A Java class or soft type defining the attributes and behavior of the business object(s) you want to create. An attribute of the object defined in the Windchill Type and Attribute Management client. These attributes are not defined in the Java business object class and are stored in database tables separate from the table for the business class. An object type defined using the Type and Attribute Management utility rather than in a Java class. Soft types may extend other soft types but all have a hard type as their root type. The object you are creating in your wizard.

Solution Elements
Element JSPs Type Description

The following jsp and jspf files can be used to create and display components common to many create wizards. Unless otherwise noted, they are located in the <WT_HOME>/codebase/netmar kets/jsp/object and <WT_HOME>/codebase/ netmar kets/jsp/components directories. createEditUIText jsp file Contains some UI text common to create and edit wizards. includeWizBean jsp file Defines the CreateAndEditWizBean called during the generation of jsp pages to access wizard data. Beans CreateAndEditWizBean Java class This bean is available to your jsps if you include the includeWizBean jspf file. It has getter methods for wizard data set by the initializeItem tag such as the operation, default container, the base type, and so forth. Javascript validateCreateLocation A javascript method you can specify on the onClick parameter of the wizard action for

Constructing Wizards

827

Element

Type

Description wizards that can be launched from a folder browser toolbar. This checks to make sure that the user does not have more than one folder checked and that the user has not checked an object that is not a folder. If either is the case, a popup error message is displayed. Location: <WT_HOME>/codebase/netmar kets/javascript/util

Java Classes You can use the classes below to help create and process your wizard. They are located in the <WT_HOME>/codebase/WEB- INF/lib/wncWeb.jar file. CreateAndEditModelGetter Java class A class that may be called via a getModel tag to generate the data for property panels and attributes tables in create wizards. CreateObjectFormProcessor Java class A class that may be used or extended to process your wizard form data. Extends DefaultObjectFormProcessor. DefaultObjectFormProcessorDe- Java class A class that may be extended to legate implement various processing subtasks. ObjectBean Java class A container for the form data specific to one target object and for the data common to all objects. Provides methods to retrieve the form data for the associated object. A wizard creating only one object will have only one ObjectBean. FormResult Java class; A class used to pass method reruns in the sults between server processor Method Serv- methods and from the server to er and client the WizardServlet.

828

Windchill Customization Guide

Procedure Creating Your Wizard


You will need to perform the following tasks to create your wizard: Create an Action for the wizard on page 829 Create a main jsp file for your wizard on page 829 Create your first custom step on page 830 Select Reusable Steps on page 831

Create an Action for the wizard You will need an action to launch your new wizard. For more details on the options available for this action see the Wizard Processing on page 802. A simple action could look like this:
<objecttype name="Novel"> <action name="create"> <command class="com.ptc.core.components.forms.CreateObjectFormProcessor" method="execute" url="netmarkets/jsp/carambola/customization/examples/wizard/ wizardExampleTwo.jsp" windowType="popup"/> </action> </objecttype>

Note If you follow the standard naming convention for actions and place your jsp in the <objecttype>\<actionname>.jsp location you do not need the url parameter. The pretend object types for the examples do not follow that in order to avoid cluttering your system.
We recommend that you name your action (and main wizard jsp file) create. If you will have more than one create action for your objecttype based on launch point or other criteria, you can add a suffix to the action name to qualify it, as shown below: createFrom<launch point> Example: createFromWorkspace create<type of object> Example: createSharedDocument Add this action to an action model so that you can access it on your system. Create a main jsp file for your wizard You will need to create a jsp which describes your create wizard. To start with we will put in just the wizard tag. This does not specify enough information for the wizard to work but at this point you can click the action and see the wizard open.
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%>

Constructing Wizards

829

<%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <jca:wizard title="Create Literature"> </jca:wizard> <%@include file="/netmarkets/jsp/util/end.jspf"%>

At this point, if you launch your wizard, you should see the message No Valid Actions to Display as we have not yet defined any steps. For additional information on the customizations you can make to your main wizard jsp see the Wizard Processing on page 802 and Sample Code on page 843. Create your first custom step A custom wizard step is also made up of an action and a jsp. Action:
<action name="createNovelStep"> <label>Welcome to your Create Novel Wizard</label> <command url="netmarkets/jsp/carambola/customization/examples/ wizard/createNovelStep.jsp" windowType="wizard_step"/> </action>

Initial JSP content: Hello World. Update the WizardTag to include your step:
<jca:wizard title="Create Literature"> <jca:wizardStep action="createLiteratureStep" type="fakeLiterature"/> </jca:wizard>

830

Windchill Customization Guide

At this point you have created a simple wizard and when you launch it you should see:

You can now develop your own jsp files for your unique steps using the same table, property panel, and javascript components used in the jsp files for common steps. Select Reusable Steps When you are unable to use one of the out of the box wizards for you object type, you can still reuse some of the out of the box steps. For this example, we will add the defineItemAttributesWizStep and the attachments step. For full details on all the options available for these steps see Attachments on page 355 and Customizing Reusable Wizard Steps on page 860. Update the create.jsp to include these steps:
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <jca:initializeItem operation="${createBean.create}" baseTypeName= "wt.doc.WTDocument|org.example.FakeLiterature"/> <jca:wizard buttonList="DefaultWizardButtons" helpSelectorKey="AssignView_help" title="Create Literature"> <jca:wizardStep action="createLiteratureStep" type="fakeLiterature"/> <jca:wizardStep action="defineItemAttributesWizStep" type="object"/> <jca:wizardStep action="attachments_step" type="attachments" /> </jca:wizard>

Constructing Wizards

831

<%@include file="/netmarkets/jsp/util/end.jspf"%>

Note For the defineItemAttributesWizStep we also had to include the initializeItem tag to setup the type we are creating. For more details on this tag and on the other options available when using this step see Customizing Reusable Wizard Steps on page 860.
At this point your wizard can create FakeLiterature objects. There are many variations on this basic setup. For more information see the customizations below, the sample code below, the Wizard Processing on page 802 and Customizing Reusable Wizard Steps on page 860.

Customization Points
Creating Your Form Processor and Form Processor Delegates
This section assumes you are familiar with the standard wizard processing framework described in the Wizard Processing on page 802.

832

Windchill Customization Guide

The class com.ptc.core.components.forms. CreateObjectFormProcessor is available as a default form processor for wizards creating Persistable objects. This class may be extended as necessary to meet your purposes.

The CreateObjectFormProcessor does the following:

Constructing Wizards

833

preprocess() method extracts all of the ObjectBean form data that has a special name attribute as described in Attribute Tables on page 702. creates a TypeInstance for the new object and applies the attribute values from the form to it, validating the values against any constraints defined for the attributes in the Type and Attribute Management utility converts the TypeInstance into a Persistable and sets it as the object attribute on the ObjectBean calls super.preProcess() to call the preprocess() methods of any FormProcessorDelegates registered for the wizard calls super.doOperation() to call the doOperation() methods of any FormProcessorDelegates registered for the wizard calls PersistenceHelper.manager.store() to store the Persistable in the database if the status of the FormResult is SUCCESS or NON_FATAL_ERROR, sets the nextAction on the FormResult to FormResultAction.REFRESH_OPENER; if the wizard was launched from a folder browser it also sets the refreshInfo attribute of the FormResult as follows: action = NmCommandBean.DYNAMIC_ADD oid = newly created object location = folder of new object As a result, if launched from a folder browser, the wizard will be closed and the new object will be dynamically added to the folder in the right pane of the browser without refreshing the entire launch page; if not launched from a folder browser, the entire launch page will be refreshed. Any feedback messages put in the FormResult will be displayed to the user. Note that the ajax attribute on the wizard action must be set to row for dynamic row refresh to occur; if not set the entire launch page will be refreshed regardless of the values in the dynamicRefresh attribute. If the status set on the FormResult is FAILURE, sets the nextAction to FormResultAction.NONE. This will return the user to the wizard page on which OK was clicked. getSuccessFeedbackMessage() method (called by setResultNextAction())

doOperation() method

setResultNextAction() method (called by the DefaultFormProcessorController)

834

Windchill Customization Guide

This method is called when FormResult is SUCCESS.This constructs the FeedbackMessage see Inline Messaging for more information on configuring message content. In the UI this inline message is shown as below for single object creation:

For Multi-object create the UI as shown below:

Note the CreateObjectFormProcessor does not implement postProcess() or postTransactionProcess() methods so these are inherited from the DefaultObjectFormProcessor. See the javadoc for more information. If you are extending an existing Windchill business class, there may be a processor specific to that class that you should use or extend instead of CreateObjectFormProcessor. These are shown in the table below. Consult the javadoc for these classes for more information on their behavior. If your class extends: WTPart Use processor class: If creating a wizard to be launched from a workspace: com.ptc.windchill.enterprise.part.forms.CreatePartFromW orkspaceFormProcessor If creating a wizard to be launched from the Edit Structure client: com.ptc.windchill.enterprise.part.forms.CreatePartFromTa bularInputProcessor All other single-object creation wizards: com.ptc.windchill.enterprise.part.forms.CreatePartFormPro cessor

Constructing Wizards

835

If your class extends: WTDocument

Use processor class: For creating a document from a template: com.ptc.windchill.enterprise.doc.forms.CreateDocFromTe mplateFormProcessor For creating a document template: com.ptc.windchill.enterprise.doc.forms.CreateDocTemplat eFormProcessor For all other single-object create wizards:

com.ptc.core.windchill.enterprise.doc.forms.CreateDocFor mProcessor WTChangeIssues com.ptc.windchill.enterprise.change2.forms.processors.Cre ateProblemReportFormProcessor WTChangeRequest2 com.ptc.windchill.enterprise.change2.forms.processors.Cre ateChangeRequestFormProcessor WTChangeOrder2 com.ptc.windchill.enterprise.change2.forms.processors.Cre ateChangeNoticeFormProcessor WTChangeActivity2 com.ptc.windchill.enterprise.change2.forms.processors.Cre ateChangeTaskFormProcessor WTVariance com.ptc.windchill.enterprise.change2.forms.processors.Cre ateVarianceFormProcessor. If the behavior of one of the provided form processors meets your needs, you do not need to write your own processor, just specify that processor as the value of the class attribute of the command subtag of your wizard action. If it does not meet your needs, you should write a subclass of it to process the wizard form data. Note that you do not need to create your own processor if you only want to provide special code for setting an attribute. In that case, you need only to write a FormProcessorDelegate to handle this task. Remember to register the FormProcessorDelegate in a hidden form field and make sure that the attribute input field does NOT have a special name attribute that will be recognized by the CreateObjectFormProcessor. See Attribute Tables on page 702 for more information. Note that you do not need to create your own processor if you only want to provide special code for setting an attribute. In that case, you need only to write a FormProcessorDelegate to handle this task. Remember to register the FormProcessorDelegate in a hidden form field and make sure that the attribute input field does NOT have a special name attribute that will be recognized by the CreateObjectFormProcessor.

836

Windchill Customization Guide

The FormProcessorDelegate should extend from DefaultObjectFormProcessorDelegate. NumberPropertyProcessor and KeepCheckedOutDelegate are examples of custom FormProcessorDelegates available out of the box. The class structure for FormProcessorDelegates is shown below.

If you create your own processor, be aware that its preProcess() method will be called by the standard validator classes after each wizard step. Make sure you do not modify the database in this method. Here are some of the more common cases where you may need to write your own ObjectFormProcessor class and the methods you would override to handle them: Case 1: You need to perform a different action when the wizard closes. For example, perhaps you want to load a new page when the wizard closes instead of refreshing the launch page. Or, perhaps your wizard can be launched from multiple points and you want refresh the launch page in one case and load a new page in another case.

Solution: Subclass the out-of-the-box processor and override the setResultNextAction method. From the NmCommand.getCompContext() method you can obtain information about the launch context of the wizard. Here is an example of how this is done for the create baseline client:
String compContext = cb.getCompContext(); if (compContext != null) { try { NmContext compContextObj = NmContext.fromString(compContext);

Constructing Wizards

837

Stack<NmContextItem> contextItems = compContextObj.getContextItems(); for (NmContextItem contextItem : contextItems) { String action = contextItem.getAction(); if ("addToBaseline".equals(action) || "addToBaselineSingle".equals(action) || "addToBaselineStep".equals(action)) { < set some next action > } } . . .

Note that if your wizard is launched from a table and you have specified ajax=row on the wizard action, you must set the refreshInfo attribute on the FormResult to tell the system what rows to refresh. Typically, the attributes of the DynamicRefreshInfo object will be as follows: action = NmCommandBean.DYNAMIC_ADD oid = the NmOid of the object that was created location = the NmOid of the table object containing the new row. Typically, this will be a folder. If you have used an ajax attribute of page or component you do not need to set the refreshInfo attribute. See the Customizing the UI with Ajax on page 312 section in the Customizing HTML Clients Using the Windchill JSP Framework on page 309 chapter and the javadoc for the FormResult, FormProcessingStatus, and FormResultAction classes for more information. Case 2: You need to do some post processing after the object is persisted. For example, change object wizards have a dialog to allow the user to submit the object to workflow immediately after creation. For this, they need to perform another operation after the object is created. In some cases, this kind of requirement can be handled by creating an ObjectFormProcessorDelegate for the input field and implementing a postProcess() or postTransactionProcess() method on it that will be called automatically by the infrastructure. However, in other cases you may prefer for your form processor to handle this. For example, you cannot control the order in which FormProcessorDelegates are called so if operation ordering is a requirement you would need to do the operations in the form processor.

Solution: Subclass the CreateObjectFormProcessor and override the postProcess() or postTransactionProcess() method (which are inherited from DefaultObjectFormProcessor) to perform your operation.
Windchill Customization Guide

838

(Note that if you put a Keep checked out checkbox in your wizard by including the keepCheckedOutCheckbox.jspf file, this will be processed automatically by the KeepCheckedOutDelegate. You do not need to handle this). Case 3: You need to use a special API to persist the object. For example, change objects are persisted using the StandardChangeService2 class, which handles some life cycle and foldering tasks in addition to persisting the object.

Solution: Subclass the out-of-the-box processor and override the doOperation() method. In your method you cant call the super method, but you should still make sure the doOperation() method of any registered FormProcessorDelegates are called. You can accomplish that by calling the processDelegates() method inherited from DefaultObjectFormProcessor. For example:
FormResult doOperationResult = new FormResult(); doOperationResult.setStatus(FormProcessingStatus.SUCCESS); doOperationResult = processDelegates (DO_OPERATION, clientData, objectBeanList); if (!continueProcessing(doOperationResult)) { return doOperationResult; } try { < persist the object > } catch(WTException e) { < do error handling > } return doOperationResult;

Note that delegates are called after form processor tasks in most processing phases, but in the doOperation phase they should be called before the form processor does its tasks. This is to allow delegates to perform operations after all attributes have been set but before the object is persisted. Case 4: You need to set attributes on the new object programmatically You may have attributes that you need to set on the object before it is persisted which are not exposed in the UI.

Solution: There are alternate ways to handle this.


Create a FormProcessorDelegate and implement its preProcess() method. In that method, set the attribute values on the object in the ObjectBean. Add a hidden form field to your wizard jsp specifying the name of your delegate, which will be automatically instantiated by the framework. For example:
<input type="hidden" name="

Constructing Wizards

839

${createBean.formProcessorDelegateConstant}" value=" <path name of your delegate> delegate ">

Subclass the out-of-the-box processor and override the preProcess() method. You can call the createItemInstance() method of the superclass to create the Persistable for you and then set the attributes you desire on the Persistable. For example:
FormResult preProcessResult = new FormResult(FormProcessingStatus.SUCCESS); for (ObjectBean objBean: objectBeans) { FormResult objectResult = new FormResult(FormProcessingStatus.SUCCESS); objBean.setObject(createItemInstance(clientData, objBean, objectResult)); preProcessResult = mergeIntermediateResult(phaseResult, objectResult); if (!continueProcessing(preProcessResult)) { return preProcessResult; } Object newObj = objBean.getObject(); < set additional attributes on the new object here> } // Call processDelegates() which will call registered processor delegates delegatesResult = processDelegates(DO_OPERATION, clientData, objectBeanList); preProcessResult = mergeIntermediateResult(preProcessResult, delegatesResult); if (!continueProcessing(preProcessResult)) { return preProcessResult; }

Note that the above example is written so that the processor could be used for wizards creating more than one object. In general, it is probably preferable to use the delegate approach for setting your attributes rather than the subclass approach as it will insulate you from any modifications that might be made to the CreateObjectFormProcessor preprocess() method in the future.

840

Windchill Customization Guide

Limitations
When laying out the steps and attributes of a Windchill object creation wizard, it is important to keep in mind the interdependencies between the object type, container context, organization context, folder location, default life cycle, and, possibly, other attributes of your new object. These interdependencies can result from: type definitions object initialization rules (OIRs) access control policies (ACLs)

Type Definitions Many wizards allow a user to create one of several object subtypes derived from a given base type. You can define soft subtypes and soft attributes in the Attribute and Type and Attribute Management utility at the organization or site level. This means that the organization container of the object must be known before the list of available object types is displayed and the input fields for soft attributes are rendered. Also, the default type for some Windchill business types is determined by preferences which can be set at the container, organization, and site levels so these must also be known Access Control Policies The object types which a given user has permission to create are defined by the access control policies for the administrative domain to which the object belongs and by ad hoc rules. Administrative domain is typically, although not always, determined by the objects folder. In addition, access rules can be further refined based on the initial state of the default life cycle for the object type. Object Initialization Rules Object initialization rules are defined by object type at the site, org, and/or container levels. Such rules can dictate whether or not the server assigns an attributes value or it is entered by the user; what the default value of an attribute is, if any; whether the value is editable; and other display characteristics of an attribute. Attributes for which OIRs are defined in the out-of-the-box product include: Organization Number Name (variant parts only) Folder location Life cycle template

Constructing Wizards

841

Team template1 Versioning scheme

These OIRs may be modified or deleted by customizers and additional OIRs for other attributes may be written by customizers. These actual and potential interrelationships between properties are illustrated in the following diagram, where the shaded boxes represent wizard elements.

As you can see from this diagram, the relationships between various object properties can become complex and circular. For example, to display an input field for folder location you must know the default folder set by the OIR, which requires knowledge of the type of object being created. However, to display a picker with the available object types you must know the administrative domain, which is determined by the folder. This document will refer to attributes whose values affect the values of other attributes as driver attributes. The affected attributes will be called dependent attributes. Driver attribute values must be determined upstream of any attribute values dependent on them. By upstream we mean either from the wizard launch context, entered by the user on a previous wizard step, or, in some cases, entered by the user in a table or panel on the same step but above that of dependent attributes. Any time a driver attribute value is changed the downstream parts of the wizard must be refreshed if they contain dependent attributes and have been preloaded. (see Loading the wizard step content when it is visited on page 791 for information on preloaded and non-preloaded steps.) The exact nature of the interrelationships between attributes depends on how a site defines its OIRs and access control policies. The wizards delivered by PTC are set up to gather attribute information in an order consistent with the access control
Windchill Customization Guide

842

rules and OIRs defined out-of-the-box and with anticipated common customizations. They make certain assumptions about how a customer site has set up its OIRs and ACLs. These include the following: A site has OIRs defining the default life cycle for different object types OIRs are only defined for base types such as WTPart or WTDocument and not defined differently for subtypes of the base types

If these assumptions do not hold or your site introduces additional attribute dependencies via its OIRs or access control policies, the layout of wizard steps and attributes may need to be customized to ensure that driver attributes are always upstream of their dependent attributes.

Sample Code
Main JSP for the New Baseline Wizard
Filename: /codebase/netmarkets/jsp/baseline/createBaseline.jsp This is a one-step wizard so it uses the NoStepsWizardButtons actionmodel defined in codebase/actionmodels.xml.
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <script src='netmarkets/javascript/baseline/baseline.js'></script> <jca:initializeItem operation="${createBean.create}" baseTypeName="wt.vc.baseline.ManagedBaseline"/> <jca:wizard buttonList="NoStepsWizardButtons" helpSelectorKey="baseline.createHelp"> <jca:wizardStep action="setBaselineAttributesStep" type="baseline" /> </jca:wizard> %@include file="/netmarkets/jsp/util/end.jspf"%

Main JSP for the New Product Wizard


Filename: /codebase/netmarkets/jsp/baseline/create.jsp
<%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%> <%@ page import="com.ptc.windchill.enterprise.part.PartConstants"

Constructing Wizards

843

%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <fmt:setBundle basename="com.ptc.windchill.enterprise.product.productResourceClie nt"/> <jca:initializeItem operation="${createBean.create}" baseTypeName="wt.pdmlink.PDMLinkProduct" <jca:wizard helpSelectorKey="PDMAdminProdCreate_Help" buttonList="DefaultWizardButtonsNoApply"> <jca:wizardStep action="defineItemWizStep" type="object" /> <jca:wizardStep action="setAttributesWizStep" type="object" /> </jca:wizard> <SCRIPT language="javascript"> . . . </SCRIPT> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Packaged Samples
Many out of the box Windchill wizards make use of these steps and can be referenced as examples.

Basic Create Wizard


This is a simple example create wizard that creates an object of the Literature type. The Literature Type is a Softtype of WTDocument which can be loaded automatically. You will be prompted to load the type anytime you attempt to access an Example that relies on the type. There are very few customizations in this example but it does show how you can customize the type picker. The attributes being displayed on the attributes step are loaded for you when you load the type and can be configured through the Type and Attribute Management utility. Location of Example To navigate to this example in the produce go to Customization Component Catalog Wizard Component Examples Basic Create Wizard .

844

Windchill Customization Guide

Actions for this Example create, fakeLiterature setContexWizStep, object defineItemAttributesWizStep, object

Action Models for this Example None

Files Used in This Example \netmarkets\jsp\carambola\customization\examples\wizard\createLiterature.jsp /config/actions/Carambola-actions.xml

Constructing Wizards

845

Building Wizards to Edit a Single Object


Objective
You need to develop a wizard to allow a user to edit the attributes of a Windchill business object and update the object in the database.

Background
Object edit wizards are typically launched by an action labeled Edit or Check Out and Edit. Developing a wizard to edit a business object is very similar to developing a wizard to create that business object. Many of the components you will use are the same. However, there are a few differences between create and edit wizards and some of these require different components or different component configuration. These differences include the following: Edit wizards do not allow users to change the container context, owning organization, folder location, or type of an object Some edit wizards do not allow the user to change the identity attributes on the master of an object (for example: name and/or number). Such changes must be made via a Rename or Edit Common Attributes client. Other master attributes may not be editable also. If the object being edited is a Workable and it is not checked out by the user when the edit wizard is launched, the wizard should check out the object automatically. The attribute input fields in edit wizards are pre-populated with the values that exist in the database for the object rather than the default values defined in the Java class or Attribute and Type and Attribute Management utility. Edit wizards for Workables have different navigation buttons. Instead of an OK button they have Save and Check In buttons. The former saves the changes to the working copy of the object without checking in or iterating it. The second creates and checks in a new iteration of the object. Also, the Cancel button pops up a message reminding the user that the object will remain checked out. jsp and jspf files for wizard steps that are common to multiple wizards custom HTML tags for managing wizard data and displaying elements on the page Java classes for processing the wizard data after the user submits the wizard

Components available specifically for editing include:

846

Windchill Customization Guide

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This section assume you have created a custom Persistable business object class or soft type and you want to develop a wizard that will allow users to edit the attributes of one instance of that object type. The information in this document is applicable to editing both Workable and nonWorkable objects and both Typed and non-Typed objects. This document describes the reusable common components upon which most Windchill edit wizards are based. If your custom type extends an existing Windchill business class, such as WTPart, WTDocument, or WTChangeIssue, there may be components more specific to those classes that could or should be used instead of the components described herein. These class-specific components are built on top of the common components described in this document. A discussion of those class-specific components is beyond the scope of this document. Be aware that you do not necessarily need to develop your own wizard to edit instances of a custom type. If your type is a modeled or soft subtype of a Windchill business class such as WTPart, WTDocument, or Problem Report (WTChangeIssue) , you may be able to use the out-of-the-box edit wizard for your purposes. The out-of-the-box wizards will automatically display input fields for hard and soft attributes of custom subtypes on the Set Attributes step. Attributes in the table will be ordered as follows: Out-of-the-box attributes, ordered as listed in the JSP file Custom modeled attributes, ordered alphabetically by display name Custom soft attributes, ordered alphabetically by display name

If you want to order the attributes on this step differently or require additional fields on this step, you will need to create a new jsp for this step specifically for your subtype. However, you can still use the Edit Part wizard. If you want to add additional steps to an existing wizard , you will need to develop a custom wizard , but may be able reuse many of the steps/components of the existing wizard.

Intended Outcome
Add a single- or multi-step HTML wizard to the product that allows a user to update a business object in the database. The arrangement of steps and presentation of attributes within the wizard should be similar to that of other Windchill wizards to provide a consistent user experience.

Constructing Wizards

847

Solution
Use common jsp, tag, JavaScript, and Java class components built on top of the jsp wizard framework to create a wizard for capturing user input and for processing that input and creating the object in the database.

Prerequisite knowledge
To achieve this objective, you need to be familiar with theBuilding Wizards to Create a Single Object on page 823 topic, especially . on page 825

Solution Elements
Element Tags Type Description

Note All of the tags in the Solution Elements on page 827 section of the Building Wizards to Create a Single Object on page 823 topic are also applicable to edit wizards. This tag is in addition to those. See Building Wizards to Create a Single Object on page 823 for more information. (The Solution Elements on page 827 section.) Tag autoCheckOutItem Checks out the object to the current user if it is not already checked out. Adds an object reference to the working copy as an attribute of the current HTTPRequest, as a parameter in HTTPRequestData parameter map of the NmCommandBean, and as a hidden field in the DOM. The key to the working copy value is CreateAndEditWizBean.WORKING_COP Y_REF_PARAMETER_NAME.
This tag should be put in the main JSP for the wizard immediately below the initializeItem tag. Tag library: <WT_HOME>/codebase/ WEB-INF/tlds/wo rkinprogress.tld Tag handler: com.ptc.windchill.enterprise. wip.tags.Auto CheckOutObjectTag Beans CreateAndEditWizBean Java class This bean is available to your jsps if you include the includeWizBean jspf file. It has getter methods for wizard data such as the
Windchill Customization Guide

848

Element

Description operation (create or edit) and working copy object reference. Java Classes You can use the classes below to help create and process your wizard. They are located in the <WT_HOME>/codebase/WEB-INF/ lib/wnc Web.jar file. CreateAndEditModelGet Java class A class that may be called via a getModel ter tag to generate the data for property panels and attributes tables in edit wizards. DefaultEditFormProcess Java class A class that may be used or extended to or process wizard form data for nonWorkable objects. Extends DefaultObjectFormProcessor. EditWorkableFormProc Java class A class that may be used or extended to essor process wizard form data for Workable objects. Extends DefaultObjectFormProcessor.

Type

Procedure Creating an Edit Wizard


The following tasks need to be performed to create the wizard: Create an Action for the Wizard on page 849 Create a Main jsp for Your Wizard on page 850 Create Custom Steps as Needed on page 851 Select Reusable Steps on page 851

The tasks shown in bold are always required. The other tasks may or may not be needed, depending on the requirements of the wizard. If there are attributes in your wizard that cannot be displayed by the standard Windchill dataUtilties, gui components, and renderers you also may need to write Java classes for those functions. Create an Action for the Wizard An action is needed to launch your wizard. This task is very similar to creating an action for a create wizard. The only difference is that your form processor, specified on the class attribute of the command tag, will typically be one of the processors listed in Solution Elements on page 848 or a subclass of one of those classes.

Constructing Wizards

849

For more details on the options available for this action see <action>.xml attributes on page 785. A simple action could look like this:
<objecttype name="FakeLiterature"> <action name="editLiterature"> <command class="com.ptc.core.components.forms.EditWorkableFormProcessor" method="execute" url="netmarkets/jsp/carambola/customization/examples/ wizard/exampleLiteratureEdit.jsp" windowType="popup"/> </action> </objecttype>

It is recommended that the action (and main wizard jsp file) be named edit. If there will be more than one edit action for the objecttype based on launch point or other criteria, add a suffix to the action name to qualify it, as shown below: editFrom<launch page or table> edit<name for a subset of attributes being edited> Ex: editFromAttributesTable Ex: editAnnotations

Add this action to an action model so that it can be accessed it on the Windchill system. Create a Main jsp for Your Wizard Next, create a jsp which describes the edit wizard. At a minimum it is generally necessary to put in just one step for editing attributes. For more details on advanced configuration of the edit attributes step see Customizing Reusable Wizard Steps on page 860.

<%-- This wizard is an example of using a read-only attributes panel in an Edit wizard. --%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <%@ taglib prefix="wip" uri="http://www.ptc.com/windchill/taglib/workinprogress"%> <%-- This tag checks out the document and sets magical form inputs and data on the command bean. This makes sure that the command bean's get oid methods return the oid of the working copy. --%> <wip:autoCheckOutItem /> <jca:initializeItem operation="${createBean.edit}"/> <jca:wizard buttonList="EditWizardButtons" helpSelectorKey="DocMgmtDocEdit" title="Example Literature Edit with Attribute Panels"> <jca:wizardStep action="editAttributesWizStep" type="object" embeddedHelp="This is an example of a simple Edit wizard. This wizard demonstrates how to change the attributes in the read only attribute panel."/> </jca:wizard> <%@include file="/netmarkets/jsp/util/end.jspf"%>

850

Windchill Customization Guide

AutoCheckOutItem Tag If your target object is a Workable and your wizard can be launched for an object that is not already checked out via a Check Out and Edit or other action, you should include an autoCheckOutItem tag in your main jsp immediately below the initializeItemTag.
<%@ taglib prefix="wip" uri="http://www.ptc.com/windchill/taglib/workinprogress"%> ... <wip:autoCheckOutItem/>

This tag will check out the object to the current user before opening the wizard. Button Set Typically, wizards for editing Workable objects will use one of the following two button sets: EditWizardButtons (multiple-step wizards) NoStepsEditWizardButtons (single step wizards)

These include Save and Check In buttons. For editing nonWorkable objects one of the following is usually used: DefaultWizardButtonsNoApply (multiple-step wizards) NoStepsWizardButtons (single step wizards)

These are all defined in <WT_HOME>/codebase/config/actions/actionmodels.xml. Create Custom Steps as Needed Custom steps can also be created for edit wizards using the same techniques that are described in Wizard Processing on page 802 and Building Wizards to Create a Single Object on page 823. Select Reusable Steps In Create a Main jsp for Your Wizard on page 850 we already selected the reusable step to edit object attributes. For more details on customizing this step and for information on additional reusable steps available see Customizing Reusable Wizard Steps on page 860.

Constructing Wizards

851

Customization Points
Creating Your Form Processor and Form Processor Delegates
Two form processor classes are available for edit wizards:
com.ptc.core.components.forms.DefaultEditFormProcessor for nonWorkable objects com.ptc.core.components.forms.EditWorkableFormProcessor- for Workable objects

These classes may be extended as necessary to meet your purposes.

Both of these processors do the following:

852

Windchill Customization Guide

preProcess() method same as the preprocess() method of the CreateObjectFormProcessor except that it creates a TypeInstance for a persisted object calls super.doOperation() to call the doOperation() methods of any FormProcessorDelegates registered for the wizard calls PersistenceHelper.manager.save() to store the Persistable in the database

doOperation() method

The setResultNextAction() method varies as follows: DefaultEditFormProcessor.setResultNextAction() (called by the DefaultFormProcessorController) If the status of the FormResult is SUCCESS or NON_FATAL_ERROR, sets the next action to FormResultAction.REFRESH_OPENER; it also sets the refreshInfo attribute of the FormResult as follows: action = NmCommandBean.DYNAMIC_UPDATE oid = object that was edited location = object that was edited As a result, if the edited object is displayed in a table row of the launch page and the ajax action on the wizard action was set to row, only the table row will be refreshed. If the ajax action was set to page or was not specified, the entire launch page will be refreshed. If the ajax action was set to component and the wizard was launched from a table toolbar, only that table will be refreshed. If the status set on the FormResult is FAILURE, sets the nextAction to FormResultAction.NONE. This will return the user to the wizard page on which OK was clicked.

EditWorkableFormProcessor.setResultNextAction() (called by the DefaultFormProcessorController) If the status of the FormResult is SUCCESS or NON_FATAL_ERROR and the Check In button was clicked Sets the next action to FormResultAction.JAVASCRIPT and adds javascript to launch the check in action. If the edit action was launched from a table row, the table row will be refreshed when the checkin completes. If the edit action was launched from an info page, the info page of the new iteration will be displayed when the check in completes.

Constructing Wizards

853

and the Save button was clicked If the wizard was launched from the folder browser, sets the next action to FormResultAction.REFRESH_OPENER and adds dynamic refresh attributes to refresh the table row of the edited object If not launched from the folder browser, sets the next action to FormResultAction.LOAD_OPENER_URL and loads the url for the info page of the working copy If the status of the FormResult is FAILURE sets the next action to FormResultAction.NONE If you are extending an existing Windchill business class, there may be a processor specific to that class that you should use or extend instead of the DefaultEditFormProcessor or EditWorkableFormProcessor. These are shown in the table below. Consult the javadoc for these classes for more information on their behavior. Use processor class If your class extents WTChangeIssue com.ptc.windchill.enterprise.change2.forms.processors.Ed itProblemReportFormProcessor WTChangeRequest2 com.ptc.windchill.enterprise.change2.forms.processors.Ed itChangeRequestFormProcessor WTChangeOrder2 com.ptc.windchill.enterprise.change2.forms.processors.Ed itChangeNoticeFormProcessor WTChangeActivity2 com.ptc.windchill.enterprise.change2.forms.processors.Ed itChangeTaskFormProcessor WTVariance com.ptc.windchill.enterprise.change2.forms.processors.Ed itVarianceFormProcessor If one of the provided form processors meets your needs, you do not need to write your own processor just specify that processor as the value of the class attribute of the command subtag of your wizard action. If they do not meet your needs, you should write a subclass of one of them to process the wizard form data. See Creating Your Form Processor and Form Processor Delegates on page 832 for examples of cases where you may need to implement your own processor. netmarkets/jsp/components/beginWizard.jspf If you create your own processor, be aware that its preProcess() method will be called by the standard validator classes after each wizard step. Make sure you do not modify the database in this method.

854

Windchill Customization Guide

Sample Code
Main JSP for the Edit Product Wizard
Filename: <WT_HOME>/codebase/netmarkets/jsp/product/editProductWizard.jsp Notes: This is a one-step wizard
<%@ page import="com.ptc.windchill.enterprise.product.ProductClientRB" %> <%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%> <%--> Get resource bundle. <--%> <fmt:setLocale value="${localeBean.locale}"/> <fmt:setBundle basename="com.ptc.windchill.enterprise.product.productResource Client" /> <fmt:message var="attributeStepLabel" key="product.editProductAttributesWizStep.title" /> <jca:initializeItem operation="${createBean.edit}"/> <jca:wizard buttonList="NoStepsWizardButtons" helpSelectorKey="PDMAdminProdEdit_help"> <%--> This step uses the common action definition. The JSP file for the step is, however, product-specific and hooked up using PartManagement-typedservices-properties.xconf <--%> <jca:wizardStep action="editAttributesWizStep" type="object" label="${attributeStepLabel}"/> </jca:wizard>

%@include file="/netmarkets/jsp/util/end.jspf"%

Main JSP for the Edit Part Wizard


Filename: <WT_HOME>/codebase/netmarkets/jsp/part/edit.jsp

Constructing Wizards

855

Notes: This can be a single- or multi-step wizard, depending on the product modules installed Illustrates how to include the Set Classification Attributes and Attachments steps. This page calls the js function onloadEditPart when the page loads. This function calls loadClassificationStep to load the classification step if the part is classified and may perform some other UI configurations depending on the wizard launch point.
<%@ taglib prefix="jca" uri="http://www.ptc.com/windchill/taglib/components"%> <%@ taglib prefix="wip" uri="http://www.ptc.com/windchill/taglib/workinprogress"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/attachments" prefix="attachments" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ include file="/netmarkets/jsp/components/includeWizBean.jspf"%> <%@ include file="/netmarkets/jsp/components/createEditUIText.jspf"%> <%--> PartHelper.js contains the onloadEditPartWizard method <--%> <script language="JavaScript" src="netmarkets/javascript/part/PartHelper.js"></script> <% if(InstalledProperties.isInstalled(InstalledProperties.SCMI)) { %> <attachments:fileSelectionAndUploadApplet forceApplet='${param.addAttachments != null }'/> <% } %>

<%--> The onload javascript method dynamically loads the classification step if the part is classified. It also disables the check in button when the wizard is launched from a workspace. <--%> <script language="Javascript"> Event.observe(window, 'load', onloadEditPartWizard); </script>

856

Windchill Customization Guide

<fmt:setBundle basename="com.ptc.windchill.enterprise.part.partResource"/>

<%--> Reuse the same labels as for create part <--%> <fmt:message var="editAttributesWizStepLabel" key="part.createPartWizard.SET_ATTRIBUTES_WIZ_STEP_LABEL" /> <fmt:message var="attachmentsWizStepLabel" key="part.createPartWizard.ATTACHMENTS_WIZ_STEP_LABEL" />

<jca:initializeItem operation="${createBean.edit}"/>

<% if (request.getParameter("newInWorkspace") == null) { %> <%--> The part is not new in workspace. Do autoCheckout <--%> <wip:autoCheckOutItem/> <% } %>

<% if ((request.getParameter("newInWorkspace") != null) || (request.getParameter("checkedOutInWorkspace") != null)) { %> <script language="Javascript">newOrCheckedOutInWorkspace=true</script> <% } %>

<%--Only if SCMI or PartsLink is installed do we use a multi-step wizard<--%> <% if (InstalledProperties.isInstalled(InstalledProperties.SCMI) ||

InstalledProperties.isInstalled(InstalledProperties.PARTSLINK)) { %> <c:set var="buttonSet" value="EditWizardButtons"/> <% } else { %> <c:set var="buttonSet" value="NoStepsEditWizardButtons"/> <% } %>

Constructing Wizards

857

<jca:wizard buttonList="${buttonSet}" helpSelectorKey="PartEdit_help">

<%--> The Set Attributes step uses the common action definition. The JSP file for the step is, however, part specific and hooked up using PartManagement-typedservices-properties.xconf <--%> <jca:wizardStep action="editAttributesWizStep" label="${editAttributesWizStepLabel}" type="object"/>

<jca:wizardStep action="setClassificationAttributesWizStep" type="part"/> <%--> The attachments step will get enabled or disabled based on the AttachmentsStepAction Validator hooked up to it <--%> <jca:wizardStep action="attachments_step" label="${attachmentsWizStepLabel}" type="attachments" />

</jca:wizard>

<%@include file="/netmarkets/jsp/util/end.jspf"%>

Additional Resources
Related Package/Class Package/Class Javadoc
com.ptc.core.components.forms.DefaultEditFormProcessor com.ptc.core.components.forms.EditWorkableFormProcessor Also see the Sample Code on page 843 section in Building Wizards to Create a Single Object on page 823.

858

Windchill Customization Guide

Packaged Samples
Basic Edit Wizard
This is an example of a simple edit wizard. It does not contain many customizations. It demonstrates how the builder can be used to control the set of attributes displayed in the read only attributes panel. The editable attributes displayed are controlled by the Type and Attribute Management utility. For more information on laying out the editable attribute see Editing Attribute Layouts. Location of Example This example can be viewed in the Windchill product by navigating to Customization -> Component Catalog -> Wizard -> Examples section -> Basic Edit Wizard Actions for this Example editLiterature, fakeLiterature editAttributesWizStep, object

Action Models for this Example None

Files Used in This Example /netmarkets/jsp/carambola/customization/examples/wizard/ exampleLiteratureEdit.jsp com.ptc.mvc.builders.carambola.wizard.LiteratureEditDetailsWizStepBuilder. java /config/actions/Carambola-actions.xml

Constructing Wizards

859

Customizing Reusable Wizard Steps


Overview
You need to develop a wizard to capture user input and from that input create or edit a Windchill business object in the database. The wizard will have common steps that already exist in other wizards and should not be duplicated. Background Windchill provides many reusable wizard steps that can be configured and added to a custom wizard. In many cases reusing a wizard step is as simple as adding the correct wizard step tag specifying the wizard step action to your wizard tag. This document is not intended to cover this simplest case. In some cases there can be additional information required by a step or additional customizations you may want to do on a step. This document describes a few available reusable steps that have some additional required information or customization options. This section details when and how to use these steps. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions Assume you have created a custom Windchill business object class or soft type and you want to develop a wizard that will allow users to create or edit one instance of that object type in the database. This document describes common wizard steps that are available for reuse. Additionally, if your custom type extends an existing Windchill business class, such as WTPart, WTDocument, or WTChangeIssue, there may be components more specific to those classes that could or should be used instead of the components described herein. These class-specific components are built on top of the common components described in this document. A discussion of those classspecific components is beyond the scope of this document. Intended Outcome Add a preexisting step to the new wizard and configure the step. Prerequisite Knowledge To apply this best practice, you need to have an understanding of the following: The Windchill framework for creating wizards, creating custom wizard steps, and processing wizard data. For more information see: Building Wizards to Create a Single Object on page 823

860

Windchill Customization Guide

Building Wizards to Edit a Single Object on page 846 These topics have multiple prerequisites of their own which you should also study. This document will build on this knowledge and provide additional information on the components available to help you create and process wizards for the specific purpose of creating a Windchill business object in the database. Definition of Terms Used Term base type

classification attribute

Context

dependent attribute

driver attribute

hard attribute hard type

Definition A hard or soft type class that is the root type of the wizard's type picker. If the wizard does not have a type picker, this is the type of object that will be created. The base type is used to look up the correct JSPs for wizard steps that have different jsp variants for different subtypes until a specific type is selected by the user. An attribute associated with a classification node that has been assigned to a part. Classification Attributes are generally specified and edited on a separate step from hard and soft attributes. The container (Product, Library, Project, etc.) in which the object(s) are being created. An attribute whose value and/or display characteristics are wholly or partially determined by the value of another attribute (called the "driver attribute") via an object initialization rule (OIR), access control policy, or other mechanism. An attribute whose value drives the value and/or display characteristics of another attribute (called a "dependent" attribute) via an object initialization rule (OIR), access control policy, or other mechanism. An object attribute defined in a Java class. An object type defined in a Java class. Hard types are typically created in java

Constructing Wizards

861

Term

object type

soft attribute

soft type

Definition classes using annotations and may extend out-of-the-box Windchill business object classes. A Java class or soft type defining the attributes and behavior of the business object(s) being created. An attribute of the object defined in the Windchill Type and Attribute Management utility. These attributes are not defined in the Java business object class and are stored in database tables separate from the table for the business class. An object type defined using the Type and Attribute Management utility rather than in a Java class. Soft types may extend other soft types but all have a hard type as their root type. The Literature object created for the examples at the end of this document is an example of a soft type.

Reusable Wizard Steps


The following reusable wizard steps are available: defineItemAttributesWizStep on page 862 editAttributesWizStep on page 876 SetContextWizStep on page 879 setClassificationAttributesWizStep on page 881 attachments_step on page 882 setAccessControlWizStep on page 883

defineItemAttributesWizStep
The body of this step typically contains four sections: a read-only context property panel, a type picker, and a driver attributes property panel and the editable attributes panel. It is configured using MVC framework and jsps. An MVC builder defines the content of and configures the (non-driver) attributes panel in the step.
Windchill Customization Guide

862

The context panel, type picker, driver attributes panel, primary content panel (if any), and other components are configured via jsps. Only the type picker is required.

Context panel Read-only information about the object being created that is derived from the launch context or entered on previous wizard steps. If the object is WTContained this typically displays the container for the new object

Driver attributes This property panel displays input fields for attributes that can drive the values of and/or constraints on other attributes to be entered by the user. If a value in this panel is changed, all subsequent wizard steps are automatically refreshed based on the new attribute value(s). Therefore it is important to place all driver attributes in this section. If the preference Display Expose Organization is set to true and the object is OrganizationOwned, this panel should include a picker for the organization attribute of the object. Although organization id does not drive the

Constructing Wizards

863

value of other attributes out-of-the-box, customers often want to set up such dependencies. The object type indicates which other attributes should be included, if any. See How to create a step with additional driver attributes on page 876 for more information. Editable Attributes Panel Typically contains all the soft and hard attributes for the object type that were not entered on previously, except for part classification attributes, which are entered on a following step. Note that one of the attributes typically presented in this list is folder location. Folder location drives administrative domain which, in turn, drives access control policies which, in turn, drives the list of object types available for creation by the user. The list of types presented in the type picker is based on a default folder derived from the launch context. The user could potentially select a different folder location for which the access control policies vary. Thus it is possible the user could select a folder for which they do not have permission to create the selected type. If this happens, an error message will be displayed when the user clicks OK. Checkboxes This section contains checkboxes to provide processing instructions for the new object. These include: Checkbox label Keep checked out Applicability Used for new RevisionControlled objects Description If checked, the system checks out the object after creation If checked, the new document is checked out and downloaded If checked, the new template is immediately available for use

Checkout and download Used for creating documents from templates Enabled Used for creating document templates

Solution Add the defineItemAttributesWizStep to the new wizard and correctly configure the step. When to use this step This step is intended for use for creating Typed objects. For Edit Wizards see editAttributesWizStep.

864

Windchill Customization Guide

Solution Elements Action The action for this step is:


<action name="defineItemAttributesWizStep" afterVK="setAttributesWizStep" id="defineItemAttributesWizStep " preloadWizardPage="false" required="true" resourceBundle="com.ptc.core.ui.componentRB"> <component name=" defineItemAttributesWizStep" typeBased="true" indowType="wizard_step"/> </action>

Action file: <WT_HOME>/codebase/actions.xml

Note The action for this step has a component attribute instead of a command attribute because it is created using a MVC builder Java class.
JSPs View jsp page: <WT_HOME>/codebase/WEB-INF/jsp/netmarkets/object/ defineItemAttributesWizStep.jsp This is the default JSP that defines the view for this step. This view includes a read-only property panel for the context name, a type picker, the driver attributes panel and the editable attributes panel for entering attribute values. The OOTB view jsp includes other jsps that do some of the work. The table below describes these sub-jsps JSP defineItemAttributesWizStep.jsp Description The view jsp for the Set Attributes step; includes configureTypePicker tag for presenting & configuring the type picker, the driver attribures panel, Primary Content Panel (if any), the attribute table and check boxes(if applicable). defineItemReadOnlyPropertyPanel.jspf Contains the describePropertyPanel tag for the read-only panel defineItemReadOnlyProperties.jspf Contains describeProperty tags for the attributes in the read-only panel defineItem.jspf Looks up the JSP for the driver attributes panel and gets the data for and renders all the page elements. Contains a renderPropertyPanel tag that contains the read-only subpanel, type picker, and

Constructing Wizards

865

JSP

driverAttributesSetup.jspf

Description driver attributes subpanel;. The type picker is configured to call a js function that will refresh the driver attributes panel, editable attributes panel, and downstream non-preloaded steps any time the type value is changed. Makes an ajax call to the TypeBasedIncludeServlet to get the JSP containing the describePropertyPanel, getModel, and renderPropertyPanel tags for the driver attributes panel. Unless overridden by a service.properties entry for a specific type, one of the following JSPs will be used: <WT_HOME>/codebase/netmarkets/jsp/object/defineItemAttributesPanel.jsp (for OrganizationOwned objects) This contains a component for input of the owning organization. Note this is only displayed if the preference Display -> Expose Organization is set to true. <WT_HOME>/codebase/netmarkets/jsp/object/defineItemAttributesPanelEmpty.jsp (for all other objects)

defineItemStepContextPanel.jspf

Empty Contains the getModel and renderPropertyPanel tags for the read-only attributes subpanel

Validator The SetAttributesStepValidator is available to validate the data in the set attirbutes wizard step.

866

Windchill Customization Guide

This class will validate whether or not alla the input attributes in the set attributes step have valid values by checking constraints. This class does not do the "required" attribute validation. That is done on the client with javascript. Tags All the tags below are defined in the <WT_HOME>/codebase/WEB-INF/tlds/components.tld file. See the javadoc for the Windchill Client Architecture Common Components tag library and the javadoc for the tag handlers listed below for more information on the tags and their attributes. Element initializeItem Description Initializes some data for the object being created using attribute values passed on the tag and the launch context of the wizard. This data is stored as hidden fields in the HTML form data and in the HTTPRequestData parameter map of the NmCommandBean. Tag handler: com/ptc/core/components/ tags/components/InitializeItemTag Builds an attribute layout of object attributes used for entering attribute values. The layout contains a group of name value pairs and is controlled by Type and Attribute Management utility. This tag only renders the attributes after validation of the driver attributes and if the driver attributes are valid. WEB-INF\tags\mvc\attributesTableWizComponent.tag Configures the type picker table for more details see Configure the Type Picker on page 870. Tag handler: com/ptc/core/components/ tags/components/ ConfigureTypePickerTag

attributesTableWizComponent

configureTypePicker

Constructing Wizards

867

Other Java Classes These additional java classes are also involved in the creation of this step and available for advanced customization. DefineItemAttributesWizStepBuilder : MVC Builder for the Set Attributes step which includes the driver attributes and the attributes table. TypedAttributesPanelBuilder : MVC Builder for the attributes panel.

Procedure Configure the Step Add the action to the wizard tag To add this step to the wizard, use: <jca:wizardStep action="defineItemAttributesWizStep" type="object"/> Add the initializeItemTag The InitializeItem tag initializes some data for the object being created from the launch context of the wizard and the attributes passed to the tag. This information includes: type of operation (create or edit) the base type of the object being created default container initial value for the type picker type instance identifier for the object being created AttributePopulator class, if any

See Default view JSP for the Set Attributes Step on page 883 for the attributes of this tag. The only required attribute is operation. <jca:initializeItem operation="${createBean.create}" baseTypeName="wt.doc.WTDocument|org.rnd. FakeLiterature"/> Layout the attributes The attributes displayed on this step are controlled in the Type and Attribute Management utility. For details on laying out the attributes on this step see Attribute Panels on page 365.

868

Windchill Customization Guide

Customizations If the Set Attributes step is the first step in the wizard or nothing in this step is affected by data on prior steps then it can be preloaded. Otherwise, specify it to not be preloaded in the step action. If the wizard has a Set Context step and a type picker, it should not be preloaded as the context will affect the content of the type picker. The sections below describe how to perform common customizations of this step.

Note Please remember that you should always place your custom jsp and jspf files in a directory under wtSafeArea, as described in Managing Customizations on page 112.
<initializeItem> Tag Parameters See the javadoc for com.ptc.core.components.tags.InitializeItemTag and the Common Components tag library for the most up-to-date information on tag parameters. Parameter operation Default Value None Possible Values CreateAndEditWizBean. CREATE CreateAndEditWizBean. EDIT objectHandle Req? Yes Description Indicates whether the object is being created or edited. Not used for single-object creation wizards The string form of the Windchill type identifier for the class of object to create. For example, "wt.part. WTPart" or "wt.part. WTPart|

baseTypeName the type asso- any Windchill ciated with the type identifier wizard action string

No

Constructing Wizards

869

Parameter

Default Value

Possible Values

Req?

Description MySoftPart". This class will be the root type in the wizard's type picker. It is also used to look up the correct jsps for wizard steps that have different variants for different subclasses until a specific type is selected in the type picker. Optional. If not specified, the type associated with the wizard action will be used.

Configure the Type Picker The base type for the wizard is derived from an attribute on the InitializeItem tag or, if none, from the object type associated with the wizard action. (More about the InitializeItem tag later.) If you want to allow users to create either the base type or a subtype of the base type you would include a type picker in your wizard. The list of types available in the type picker is typically determined as follows: 1. Compute the list of hard and soft subtypes of the base type. Soft subtypes are the instantiable soft types defined for the base type in the given organization container. 2. Determine the default life cycle and initial life cycle state for the base type and each subtype based on the composite object initialization rules for the type in the given container.

870

Windchill Customization Guide

3. Determine a default folder location context for the new object. This is done as follows: 4. If the renderer constraint SelectGeneratedFolderByDefault is defined in the composite OIRs for the base type or the user is creating a shared object from the shared-to container s folder browser Use the folder defined by the OIRs for the base type in the target container If no OIR folder is defined, use the default cabinet for the target container Use the folder selected in the launch context. This could be the folder checked in the folder browser table, the folder highlighted in the left pane of the folder browser, or the folder associated with the business object from whose info page the create action was launched. If no folder can be determined from the launch context, determine the folder as shown under item i. above

5. If no renderer constraint is defined and it is not a shared-to object

6. Based on the default initial life cycle state and the administrative domain of the folder location, determine whether the user has create permission for each type. If not, filter that type from the list. 7. Display the remaining types in the picker. The default value for the type picker is determined from a preference for some base types, as follows: Base Type WTPart Preference Create and Edit -> Part Create Default Type WTDocument Create and Edit -> Document Create Default Type WTChangeIssue (ProblemReport) Create and Edit -> Problem Report Create Default Type WTChangeRequest2 (Change Request) Create and Edit -> Change Request Create Defaualt Type WTChangeOrder2 (Change Notice) Create and Edit -> Change Notice Create Default Type WTChangeActivity2 (Change Task) Create and Edit -> Change Task Create Default Type WTVariance (Variance) Create and Edit -> Variance Create Default Type

For all other wizards, the base type is used as the default type.

Constructing Wizards

871

When the user selects a type in the type picker, javascript is executed that refreshes the driver attributes panel below it and all following wizard steps. This is necessary because object type can affect which jsps are used for subsequent steps as well as the attribute input fields displayed. How to reconfigure the type picker The type picker can be modified to filter certain types from the list, specify a different default value, etc. The configuration parameters are described in the javadoc for the ConfigureTypePicker tag. To specify different picker parameters you will need to: 1. In your wizard jsp,add the following line to the top of the file:
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%>

2. Add the configureTypePickerTag 3. Add pickerParam subtags to the configureTypePicker tag as shown in the javadoc for the ConfigureTypePickerTag. See Create Wizard Using Keep Checked Out Checkbox on page 887 for an example. <configureTypePicker> Tag Parameters Parameters to this tag are in the form of pickerParam subtags. All of these parameters are optional. Example syntax:
<jca:configureTypePicker> <p:pickerParam name="seedType" value="wt.part.WTPart|org.r_and_d. SoftPartType1/> <p:pickerParam name="filterType" value="wt.part.WTPart|org.r_and_d.SoftPartType1|org.r_and_d. SoftPartType1B"/> <p:pickerParam name="showRoot" value="false"/> </jca:configureTypePicker>

Parameter seedType

Default Value None

defaultType

Description The top-level type that should be used to generate the list of types. For example, "wt.part. WTPart". May include more than one of these parameters. May be taken from any Windchill type The type that a preference (see identifier string should be selected
Windchill Customization Guide

Possible Values any Windchill type identifier string (logical or external)

872

Parameter

Default Value table above)

filterType

displayHierarchy

showRoot

Possible Values Description (logical or by default. For exexternal) ample, "wt.part. For all other wizWTPart." May be a ards, the base type string, such as "Seis used. lect a Type" rather than a type name. None any Windchill type A type that should identifier string be excluded from (logical or the type list. For external) example, "SoftPartType1". The descendants of the filter type are also excluded. May include more than one of these parameters. false true (to display Indicates whether hierarchy) the type list should be displayed as a false (to display flat list or in hierflat list) archical form. true true (to display Whether the seedseed types) Types should not be displayed. false (to not dis-

play seed types) adminDomainRef- The domain associ- any administrative String representaString ated with the dedomain reference tion of the adminisfault folder string trative domain location (see Overreference that view on page 860 should be used for access-control filtering of the type list. For example, "wt.admin.AdministrativeDomain:7" Type BOTH ROOT_TYPES Indicates the kind (only seedTypes of types to be diswill be displayed) played. Value should be one of

Constructing Wizards

873

Parameter

Default Value

Possible Values Description the enum constants SOFT_TYPES defined in com.ptc. (only soft types will be displayed) windchill.enterprise.picker.type. MODELED_server. TYPES (only mod- TypePickerTypes. eled types will be displayed BOTH (both modeled and soft types will be displayed)

How to add components to the step To add components to the step (for example, additional checkboxes at the bottom) do the following: 1. Create a new main jsp file for the step 2. Copy the contents of the file <WT_HOME>/netmarkets/jsp/object/ defineItemWizStep.jsp into the new file. 3. Add the desired components to the page as follows:
<div id='driverAttributesPane'> ... </div> Add components here if you want them to appear below the drive attributes panel <div id='setAttributesTablePane'></div> Add components here if you want them to appear below the attributes panel

4. Create a new builder class for the step, overriding the getView() method to specify the view jsp for the step. The suggested Name for the builder class for this step is <object type> DefineItemAttributesWizStepBuilder.java The suggested name for view JSP for this step is: defineItemAttributesWizStep.jsp or defineItemAttributesWizStep For<object type>.jsp (if there is more than one in the directory)

874

Windchill Customization Guide

If the object is RevisionControlled one example of additional information to include is a Keep checked out checkbox, include the following jsp in the view jsp to display it: /netmarkets/jsp/components/ keepCheckedOutCheckbox.jspf See Default view JSP for the Set Attributes Step for WTPart on page 884 and Create Wizard Using Keep Checked Out Checkbox on page 887 for examples. How to remove components from the step 1. Create a new main jsp file for the step 2. Copy the contents of the file <WT_HOME>/netmarkets/jsp/object/ defineItemWizStep.jsp into the new file. 3. One component that one may want to remove is the read-only property panel. To do this delete the following line from the file:
<%@ include file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.jspf"%>

How to modify the contents of the read-only property panel in the step 1. Create a new main jsp file for the step. 2. Copy the contents of the file <WT_HOME>/netmarkets/jsp/object/ defineItemWizStep.jsp into the new main jsp file. 3. Delete the following line and replace it with your custom describePropertyPanel tag that includes the attributes you want to display:
<%@ include file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.jspf"%>

Be sure to set the following attributes on your describePropertyPanel tag: Attribute var id scope mode Value defineItemStepContextPanelDescriptor defineItemStepContextPanelDescriptor request VIEW

Alternatively, you could include a new jspf file that contains your describePropertyPanel tag instead of placing it in-line. See JSP for the Defining the Define Item Panel for WTPart on page 884 for an example. How to create a step with no driver attributes For this you do not need to create a new wizard step JSP.

Constructing Wizards

875

Create an entry in a type-based service properties xconf file pointing to the jsp file defineItemAttributesPanelEmpty, as follows:
<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor="<object object type to be created>" created resource=/netmarkets/jsp/object/defineItemAttributesPanelEmpty.jsp selector="defineItemAttributesPanel"/> </Resource>

How to create a step with additional driver attributes For this you do not need to create a new wizard step JSP, just a new sub-JSP file for the driver attributes, as follows. 1. Create a new JSP file containing describePropertyPanel, getModel, and renderPropertyPanel tags for your driver attributes. (Note this must be a .jsp file and not a .jspf file.) Use the file <WT_HOME>/codebase/netmarkets/jsp/ object/defineItemAttributesPanel.jsp as an example and list the attributes you want to display in the describePropertyPanel tag. Because the output of this jsp is parsed and inserted dynamically inserted into the page, it must not contain any display text or HTML besides the three tags listed above. 2. Create an entry in a type-based service properties xconf file pointing to your new jsp file as follows:
<Resource context="default" name="com.ptc.netmarkets.util.misc.FilePathFactory"> <Option requestor="<object object type to be created>" created resource=<path path to your jsp page > selector="defineItemAttributesPanel"/> </Resource>

editAttributesWizStep
This step is common to almost all edit wizards and is where the user edits most of the objects attributes. It generally contains a read-only context property panel and an attribute input panel. By default there are no read only attributes. The desired attributes vary by object type. An MVC builder is used to configure the set of read only attributes to be displayed foa given type when it is desired. Some typical attributes displayed in the read only are are: the object type the container name (If the object is WTContained) the organization id (If the new object is OrganizationOwned and the preference Display -> Expose Organization is set to true)

876

Windchill Customization Guide

You will need to decide what, if any, information needs to be displayed in this panel for your object type. The attribute input panel typically contains input fields for all the editable soft and hard attributes for the object type, it does not contain input fields for part classification attributes. These are entered on a following step. The set of attributes displayed in this panel is controlled by the Type and Attribute Management utility. Solution Add the editAttributesWizStep to your new wizard and configure the step. When to use this step This step is intended for use for editing objects. For Creating objects see defineItemAttributesWizStep on page 862. Solution Elements Action
<action name="editAttributesWizStep" id="editAttributesWizStep" preloadWizardPage="false" required="true" afterVK="editAttributes" resourceBundle= "com.ptc.core.ui.componentRB"> <component name="editAttributesWizStep" typeBased="true" windowType="wizard_step"/> </action>

Action file: <WT_HOME>/codebase/actions.xml Note that the editAttributesWizStep action specifies the page as non-preloaded in case in is not the first step in the wizard and is dependent on an earlier step. However, if it is the first step, the framework will preload it regardless of how it is specified on the action. JSP View JSP Page: <WT_HOME>/codebase/netmarkets/jsp/object/ propertyAttributesWizStep.jsp Validator The EditAttributesStepValidator is available to validate the data entered in this step. This class will validate whether or not all the input attributes in the edit attributes step have valid values by checking constraints. The "required" attribute validation will be done on the client with javascript.

Constructing Wizards

877

Other Java Classes These additional java classes are also involved in the creation of this step and available for advanced customization. DefaultEditAttributesWizStepBuilder : MVC Builder for the Set Attributes step which includes an empty read only attributes area and the editable attributes panel. Extend this class to define a non empty set of read only attributes. TypedAttributesPanelBuilder : MVC Builder for the attributes panel.

Procedure Configure the Step Add the Action to Your Wizard Tag To add this step to your wizard you can use: <jca:wizardStep action="editAttributesWizStep" type="object"/> Add the initalizeItem Tag Like the defineItemAttributesWizStep, editAttributesWizStep requires an initializeItem tag. Instead of setting the operation attribute of this tag to ${createBean.create}, you should set it to ${createBean.edit}. The following tag attributes are not applicable to edit wizards: objectHandle, baseTypeName. Layout the Attributes The attributes displayed on this step are controlled in the Type and Attribute Management utility. For details on laying out the attributes on this step see Attribute Panels on page 365. Customization How to Modify the Conents of the Read-Only Property Panel in the Step To modify the read only attribute panel to have it contain some attribute, write an EditAttributesWizStepBuilder. The new builder should extend from DefaultEditAttributesWizStepBuilder and implement the buildReadOnlyAttributePanelConfig method. In this method, create an AttributePanelConfig containing the desired attributes. Use the TypeBased annotation to specify the type the builder applies to. An Example builder can be found in the Basic Edit Wizard example in Building Wizards to Edit a Single Object on page 846. A basic builder might look like the following:
@TypeBased(value = "FakeLiterature") public class LiteratureEditDetailsWizStepBuilder extends DefaultEditAttributesWizStepBuilder {

878

Windchill Customization Guide

@Override protected AttributePanelConfig buildReadOnlyAttributePanelConfig (ComponentParams params) throws WTException { ComponentConfigFactory factory = getComponentConfigFactory(); AttributePanelConfig attrPanel = factory.newAttributePanelConfig(); attrPanel.addComponent(getContainerAttributeConfig(params)); attrPanel.addComponent(factory.newAttributeConfig(DescriptorConstants. ColumnIdentifiers.TYPE)); return attrPanel; } }

SetContextWizStep
This step typically has only one input field, which is a picker for the owning container of the object being created. The selected container will be used to select the appropriate OIRs for other attributes. In many cases, the container is determined from the launch context of the wizard and this step is not needed. For example, if the wizard is launched from the folders page of a product, the container is assumed to be that product. Solution Add the SetContextWizStep to your new wizard and configure the step. When to use this step This step is for WTContained objects only. This step contains a context (container) picker and should be included in a create wizard for a WTContained object if the container cannot be determined from the launch context and/or you want to allow the user to choose a container. Solution Elements Action
<action name="setContextWizStep" id="setContextWizStep" preloadWizardPage="true" required="true" afterVK="setContextWizStep"> <command windowType="wizard_step"/> </action>

Action file: <WT_HOME>/codebase/config/actions/actions.xml

Constructing Wizards

879

JSP View jsp page: <WT_HOME>/codebase/WEB-INF/jsp/netmarkets/object/ setContextWizStep.jsp Validator The ContextWizardStepValidator is available to validate the data in the set context wizard step. The ContextWizardStepValidator just validates that the form data contains a valid container object reference. This validator also determines if the step should be displayed in the wizard. If the context has been determined from the launch point the step will be skipped even though it is included in the wizard. Procedure Configure the Step Add the Action to Your Wizard Tag To add this step to your wizard you can use: <jca:wizardStep action="setContextWizStep" type="object"/> When you are using this step it is recommended that this be the first step in your wizard. Customizations Creating a Custom Set Context Step JSP Page If a custom wizard has a Set Context step, the out-of-the-box step jsp listed above will usually suffice. The only time it might be necessary to develop a custom step jsp is if there is a need to capture additional attribute values before the display attributes are presented on the Define Object step. For example, assume that: The wizard launch point has no folder context There are not any OIRs that set a default folder location for new objects There are defined access control policies denying users create permission for certain object subtypes. These policies are based on the administrative domain associated with the folder in which the new object is located.

In this case, the object container will have no effect on folder selection and you may want the user to select a folder location so the list of types available to him/her can be accurately determined. In this case you may want to put a folder input field

880

Windchill Customization Guide

on a step prior to the Define Object step. You could either add this input field to the Set Context step or add additional step to the wizard to capture folder location either before or after the Set Context step. (Either way, you will also need your own JSP for the Define Object step so you set the administrative domain parameter on the type picker based on the user s folder selection in the Set Context step.) If a custom Set Context jsp is needed and it needs to have a container picker, it is recommended that the out-of-the-box jsp is included in it rather than copying the contents of the out-of-the-box jsp. This will ensure the custom page will continue to behave correctly even if the context picker is modified in a future release.

setClassificationAttributesWizStep
Solution Add the setClassificationAttributesWizStep to your new wizard and configure the step. When to use this step This step only applies to WTParts and subtypes thereof when PartsLink is installed. It is a dynamic step that only appears if the part is classified. It allows the user to modify the classification attributes of the part. It displays the classification of the part in view mode at the top and then includes a table of input fields for classification attributes. This step can be used for both creating and editing objects. Note that the Set Classification Attributes step is marked as hidden. It is dynamically inserted into the wizard if the user clicks the Choose Classifications radio button on the Set Attributes step. It is dynamically removed if the user clicks the Do Not Classify radio button to unclassify the part. Solution Elements Action
<action name="setClassificationAttributesWizStep" id="setClassificationAttributesWizStep" hidden="true" required="true" preloadWizardPage="false"> <command windowType="wizard_step"/> </action>

Action file: <WT_HOME>/codebase/ config/actions/PartManagementactions.xml

Constructing Wizards

881

JSP View JSP Page: <WT_HOME>/codebase/netmarkets/jsp/part/ setClassificationAttributesWizStep.jsp Validator The Set Classification Attributes step uses the same validator as the Set Attributes step. Procedure Configure the Step To add this step to your wizard you can use: <jca:wizardStep action=" setClassificationAttributesWizStep" type="part"/> Add the Action to Your Wizard Step Customizations Using the Step in an Edit Wizard When building an edit wizard that contains the Set Classification Attributes step you will need to dynamically load that step if the part being edited is classified. The js function loadClassificationStep() in <WT_HOME>/codebase/netmarkets/ javascript/part/PartHelper.js is available to do that. In most cases this should be called indirectly by calling the onloadEditPartWizard() function when the wizard loads your main wizard jsp, as follows:
<script language="JavaScript" src="netmarkets/javascript/part/PartHelper.js"> </script> ... full jsp contents, the following javascript should be the last thing in the file... <script language="Javascript"> PTC.onReady(onloadEditPartWizard); </script>

The onloadEditPartWizard() function calls loadClassificationStep() and also does some additional configuration for wizards launched from a workspace. You can use it regardless of whether your wizard can be launched from a workspace.

attachments_step
This step is typically included when creating or editing objects that are ContentHolders. It allows the user to attach documents, links, and other content to the new object. See Attachments on page 355for information on the elements that must be included to incorporate this step.
Windchill Customization Guide

882

No validator is provided or needed for the attachments step.

setAccessControlWizStep
This step is typically included when you want to allow the user to make modifications to the access permissions for the object. See Component Access Control on page 350 for information on the elements that must be included to incorporate this step.

Sample Code
Default view JSP for the Set Attributes Step
This jsp is the MVC view for the defineItemAttributesWizStep action for objecttype=object in <WT_HOME>/codebase/configs/actions.xml. The MVC builder for the Set Attributes Step for any object is DefineItemAttributesWizStepBuilder. The MVC view for the builder is defined in WEB_INF/jsp/object/ defineItemAttributesWizStep.jsp The next section Default view JSP for the Set Attributes Step for WTPart on page 884 illustrates having own view jsp for object type WTPart as WTPart need to include a customized type picker and ReadOnlyPropertyPanel.
<%@ <%@ <%@ <%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%> include file="/netmarkets/jsp/components/beginWizard.jspf"%> include file="/netmarkets/jsp/components/createEditUIText.jspf"%> include file="/netmarkets/jsp/components/includeWizBean.jspf"%Ok. W>

//The driver attribute panel that defines the top section that includes the read only property panel for context, type picker and driver attributes <div id='driverAttributesPane'> <%@ include file="/netmarkets/jsp/components/defineItemReadOnlyPropertyPanel.jspf"%> <jca:configureTypePicker/> <%@ include file="/netmarkets/jsp/components/defineItem.jspf"%> </div> //Include Attribute Panel defining the non driver attributes <mvc:attributesTableWizComponent/> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

Constructing Wizards

883

Default view JSP for the Set Attributes Step for WTPart
WTPart need to include a customized type picker, ReadOnlyPropertyPanel, and custom information related to the CreateCadDocStep option. Hence we need to define a builder for WTPart(PartDefineItemAttributesWizStepBuilder) to set the view for the Set Attributes step (WEB_INF/jsp/part/ defineItemAttributesWizStep. jsp). The only difference from the Generic one is that the jsps to render the driver attributes is different.
<%@ <%@ <%@ <%@ <%@ <%@ taglib uri="http://www.ptc.com/windchill/taglib/jcaMvc" prefix="mvc"%> taglib uri="http://www.ptc.com/windchill/taglib/mvc" prefix="mvc1"%> include file="/netmarkets/jsp/components/beginWizard.jspf"%> include file="/netmarkets/jsp/components/createEditUIText.jspf"%> include file="/netmarkets/jsp/components/includeWizBean.jspf"%> taglib uri="http://www.ptc.com/windchill/taglib/wrappers" prefix="wrap"%>

<%@ page import="com.ptc.windchill.enterprise.part.partResource" %> <fmt:setBundle basename="com.ptc.windchill.enterprise.part.partResource"/> <fmt:message var="createCADDocument" key="<%= partResource.CREATE_CAD_DOC_ FROM_NEW_PART_LABEL %>" /> <div id='${createBean.currentObjectHandle}driverAttributesPane'> <%@ %@ include file="/netmarkets/jsp/part/defineItem.jspf"%> file="/netmarkets/jsp/part/defineItem.jspf"% </div> <mvc:attributesTableWizComponent attributesTableWizComponent/> <c:if <c:if test='${param.showNewCADDocStep test='${param.showNewCADDocStep == "true"}'> <wrap:checkBox <wrap:checkBox name="createCADDocForPart" id="createCADDocForPart" label="${createCADDocument}" renderLabel="true" renderLabelOnRight="true" checked="false" onclick="toggleCreateCADDocStep('part. onclick="toggleCreateCADDocStep('part.defineItemAttributesWizStepForCADDoc! defineItemAttributesWizStepForCADDoc!~ ~ objectHandle~caddocHandle~!');" /> </c:if> </c:if> <br> <c:if test='${param.invokedfrom != "workspace"}'> <%@ %@ include file="/netmarkets/jsp/components/keepCheckedOutCheckbox.jspf"%> file="/netmarkets/jsp/components/keepCheckedOutCheckbox.jspf"% </c:if> <input id="selectedClfNodes" type="hidden" name="selectedClfNodes" > <input id="selectedClfNodesDisplayName" type="hidden" name="selectedClfNodesDisplayName" > <%@ include file="/netmarkets/jsp/util/end.jspf"%>

JSP for the Defining the Define Item Panel for WTPart
Filename: <WT_HOME>/codebase/ netmarkets/jsp/part/defineItem.jspf This example illustrates how to override the read-only context panel and to reconfigure the type picker.
Windchill Customization Guide

884

<%@ page import="com.ptc.windchill.enterprise.part.PartConstants" %> <%@ page import="com.ptc.core.ui.componentRB" %> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ %@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%> prefix="p"% <%@ taglib uri="http://www.ptc.com/windchill/taglib/partcomponents" prefix="partcomp"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/fmt" prefix="fmt"%> <jca:describePropertyPanel <jca:describePropertyPanel var="defineItemStepContextPanelDescriptor" id="defineItemStepContextPanelDescriptor" scope="request" mode="VIEW" type="wt.part. type="wt.part.WTPart"> WTPart"> <jca:describeProperty <jca:describeProperty id="containerName" label="${createBean.containerLabel}"/ label="${createBean.containerLabel}"/> > </jca:describePropertyPanel> </jca:describePropertyPanel> <%-- Get the part types to filter from type picker selection list --%> <partcomp:PartCreateHelper var="partTypesToFilter" method="getPartTypesToFilter"/> <c:choose> <c:when test='${param.invokedfrom == "tabular_input"}' > <!-- If New Part client is invoked from Edit Structure, association constraints need to be enforced. (Please see the Javadoc for DefaultAssociationConstraintIT for more details). The list of creatable types needs to be filtered out to inlcude only the types allowed by association constrains. This is achieved by finding the list of valid (allowable) types using the getSeedPartTypes below and then setting the type picker's 'type' parameter to 'ROOT_TYPES' --> <!-- Get the seed part types. Usually, it is wt.part.WTPart but it can be a bunch of types if association contraints are in place --> <partcomp:PartCreateHelper var="seedPartTypes" method="getSeedPartTypes"/> <jca:configureTypePicker> <jca:configureTypePicker> < %-Type Picker picks up the default from Preferences. It does not have be set here. --%> --%> <c:forEach <c:forEach var="item" items="${seedPartTypes}"> <p:pickerParam <p:pickerParam name="seedType" value="${item}"/> value="${item}"/> </c:forEach> </c:forEach> <c:forEach <c:forEach var="item" items="${partTypesToFilter}"> <p:pickerParam <p:pickerParam name="filterType" value="${item}"/> value="${item}"/> </c:forEach> </c:forEach> <p:pickerParam <p:pickerParam name="type" value="ROOT_TYPES"/> value="ROOT_TYPES"/> </jca:configureTypePicker> </jca:configureTypePicker> </c:when> <c:when test='${param.invokedfrom == "config_link_table"}' > <!-- The part types in the type picker must come from the association constraints on the configurable link. --> <clui:getRoleBTypesForNewAction var="roleBObjectTypes" roleBBaseType="wt.part.WTPart"/>

Constructing Wizards

885

<jca:configureTypePicker> <c:forEach var="item" items="${roleBObjectTypes}"> <p:pickerParam name="seedType" value="${item}"/> </c:forEach> <c:forEach var="item" items="${partTypesToFilter}"> <p:pickerParam name="filterType" value="${item}"/> </c:forEach> <p:pickerParam name="type" value="ROOT_TYPES"/> </jca:configureTypePicker> </c:when> <c:otherwise> <jca:configureTypePicker> <%-Type Picker picks up the default from Preferences. It does not have be set here. --%> <c:forEach var="item" items="${partTypesToFilter}"> <p:pickerParam name="filterType" value="${item}"/> </c:forEach> </jca:configureTypePicker> </c:otherwise> </c:choose> <%@ include file="/netmarkets/jsp/components/defineItem.jspf"%>

Additional Resources
Related Customization Documentation
Windchill Client Architecture Wizard on page 776 Wizard Processing on page 802 Configuring a Context Picker on page 933 Configuring a Type Picker on page 960 Configuring an Organization Picker on page 952 Configuring a User Picker on page 975 Configuring an Item Picker on page 943 Building Wizards to Create a Single Object on page 823

886

Windchill Customization Guide

Building Wizards to Edit a Single Object on page 846 Attachments on page 355 Component Access Control on page 350 Attribute Customization on page 630

Related Package/Class Package/Class Javadoc


com.ptc.core.components.tags.components..InitializeItemTag com.ptc.core.components.tags.components.ConfigureTypePickerTag Common Components Tag Lib Javadoc

Packaged Samples
Many out of the box Windchill wizards make use of these steps and can be referenced as examples.

Create Wizard Using Keep Checked Out Checkbox


Description : This is an example of a wizard to create an object of the Literature type which includes the Keep Checkedout Checkbox. The Literature Type is a Softtype of WTDocument which can be loaded automatically. You will be prompted to load the type anytime you attempt to access an Example that relies on the type. This Example Illustrates a very basic create. It includes an example of creating an MVC Builder and a custom view for the defineItemAttributesWizardStep. The attributes being displayed on the attributes step are loaded automatically when the type is loaded through the UI and can be configured through the Type and Attribute Management utility. Location of Example : To navigate to this example in the produce go to Customization >> Component Catalog >> Wizard Component >> In the example section select Create Wizard using Keep Checked Out Checkbox Actions for this Example: createLitCheckBox, fakeLiterature setContexWizStep, object defineItemAttributesWizStep, object
Constructing Wizards 887

Action Models for this Example : None Files Used in This Example /netmarkets/jsp/carambola/customization/examples/wizard/ CreateLitCheckbox.jsp /netmarkets/jsp/components/keepCheckedOutCheckbox.jspf /netmarkets/jsp/carambola/attributePanel/ fakePoemDefineItemAttributesWizStep.jsp com.ptc.mvc.builders.carambola.wizard. FakePoemDefineItemAttributesWizStepBuilder /config/actions/Carambola-actions.xml

Create Wizard Using Common Steps


Description : This is an example of a wizard to create an object of the Literature type which includes some of the available out of the box steps. The attributes being displayed on the attributes step are loaded for you when you load the type and can be configured through the Type and Attribute Management utility. The context picker step is included and will display when the context cannot be determined. The attachments component is included for adding attachments to the Literature object. A custom Step is also included to demonstrate how to add any custom step jsp to a wizard. Location of Example : To navigate to this example in the produce go to Customization >> Component Catalog >> Wizard Component >> In the example section select Create Wizard using Common Steps Actions for this Example : createLitCheckBox, fakeLiterature setContexWizStep, object defineItemAttributesWizStep, object attachements_step, attachments setClassificationAttributesWizStep, part createLitCustomWizStep, fakeLiterature Action Models for this Example : None Files Used in This Example :

888

Windchill Customization Guide

/netmarkets/jsp/carambola/customization/examples/wizard/ CreateLitOOTBSteps.jsp /netmarkets/jsp/carambola/customization/examples/wizard/ CreateLitCustomWizStep.jsp /config/actions/Carambola-actions.xml

Constructing Wizards

889

17
Information Pages
Customizing Information Page Components .............................................................. 892

This chapter describes how to customize information pages.

891

Customizing Information Page Components


You want to create or modify an information page for a Windchill business object. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This information should be applied by a developer or customizer who is responsible for creating a information page for a new Windchill business object. This documentation assumes that: You are familiar with the use of Java builder classes used to acquire the data from the server as described in MVC Components on page 251. In prior releases the information was retrieved using the InfoPageBean Java class. This is not the recommended approach any longer.

Intended Outcome An Information Page.

The information page is made up of the following pieces, many of which are configurable. Title bar area: Go to latest link (only appears on info pages for non-latest versions) Actions Menu Commonspace/Workspace toggle Object Type icon Item Identification Status Glyphs (checkout, share, pending changes, etc)

892

Windchill Customization Guide

State of item (only appears for LifeCycleManaged items) Help icon

Tab Set

Out of the box tabs and tabs configured by administrators are displayed at the top + tab that allows the user to add custom tabs

Table of Contents Menu

Information tab table of contents links to drag n drop for rearranging the content of the tab:

Visualization and Attributes Panel This panel is intended to have a small subset of attributes.

Information Pages

893

Attributes The attributes option is intended to have the full set of attributes displayed as panels or in a table

894

Windchill Customization Guide

Solution
Create a builder Java class, which extends DefaultInfoComponentBuilder, that will define the elements to be rendered on the information page for a specific business object type. The layout of the attributes is controlled by the attribute layout manager in the Type and Attribute Management utility. Prerequisite Knowledge To apply this information you need to have an understanding of the following: The MVC framework for creating the Java builder class (see MVC Components on page 251) JSP-based client architecture framework in Windchill (see Windchill Client Architecture Overview on page 226) The actions framework in the Windchill client architecture (see Windchill Client Architecture Action Framework Overview on page 486) How to manage attribute layouts using the Type and Attribute Management utility (see Type and Attribute Management utility)

Solution Elements Using this component, a developer will need to create a builder by extending DefaultInfoComponentBuilder. Element DefaultInfoComponent Builder.java Type Description Java class The default builder that all other information page builders should extend from. The builder is responsible for gathering the required data from the server.

The core elements used to generate the information page are shown below. These are not expected to be overridden by a developer. The builder is where a developer can control which items are displayed on the information page for a business object and the Type and Attribute Management utility can be used to control the layout of attributes. Element Type Description infoPage.jsp JSP The JSP that all information page actions should invoke. It calls begin.jspf/end.jspf and calls the infoPage tag in the MVC taglib. infoPage.tag Tag , defined in Sets up the JSP context and crethe MVC taglib ates the info page ComponentDefinition object. It calls the

Information Pages

895

Element

Type

RenderInfoPageModel Tag.java

infoPage.jsfrag

myTab.jsfrag

Description renderInfoPageModel tag in the components taglib and calls the JavaScript renderer to generate the HTML for the information page. Java tag, defined It constructs a JSON object (a.k. a. InfoModel) from the data in in the components taglib the builder and writes out the JSON object to its print stream. JavaScript JavaScript renderer that takes in fragment the JSON InfoModel object. It generates the HTML for the information page JavaScript Renders the top-level tabs and fragment provides the ability to move items around in the tab content area.

Supporting Elements Element attributePanel.jsp Type JSP Description JSP to invoke to render an Attributes Panel. The Attribute Panel component is used to display the Attributes and Visualization and Attributes widgets. The layout of the attributes in an Attribute Panel is controlled by the attribute layout manager in the Type and Attribute Management utility. See Attribute Panels on page 365 for more information. Sets up the JSP context and creates the Attribute Panel ComponentDefinition object. It calls the renderAttributePanel tag in the components taglib and calls the JavaScript renderer to generate the HTML for the attribute panel. It constructs a JSON object (a.k.

attributePanel.tag

Tag , defined in the MVC taglib

RenderAttributePanel

Java tag, defined

896

Windchill Customization Guide

Element Tag.java

attributePanel.jsfrag

Type Description in the a. InfoModel) from the data in components taglib the builder and writes out the JSON object to its print stream. JavaScript JavaScript render that takes in the fragment JSON InfoModel object. It generates the HTML for the attribute panel.

Information Page Process Flow The builder is called first to collect the necessary data from the server. The builder forwards the request to the view (i.e. infoPage.jsp). The default view, infoPage.jsp, includes the infoPage tag. The tag creates a JSON object, known as the infoModel object, from the data it collected from the builder. The infoModel is serialized (by writing it out as JSON string to the JSP writer) and passed to the JavaScript render which ultimately generates the HTML. Here is the process sequence for rendering the info page:

Information Pages

897

Information Page Builder Designer When creating an information page for a new business object type, a developer will have to create a builder that extends the DefaultInfoComponentBuilder. The builder class needs to include the following Java annotations so the correct builder gets called for that business object type:
@ComponentBuilder(value = ComponentId.INFOPAGE_ID) @TypeBased(value = "wt.part.WTPart") public class PartInfoBuilder extends DefaultInfoComponentBuilder { .

The annotation for the builder ID is specificed in the super class DefaultInfoComponentBuilder. Annotations are inherited, so when extending this class, the ComponentBuilder annotation is not required. It will not hurt anything if it is there and if you are not extending this class be sure to include it. See MVC Components on page 251 for details on how to register your builder class or package. The only method that needs to be overridden is the buildInfoConfig() method. This method is where you would set which elements you would like to have displayed on the information page for that business object type and calls the necessary service APIs to collect the data for those elements. SeeCustomization Options in Info Page Builder on page 900 for more information about those elements. The annotation for the builder can contain a hard type or a soft type:
@TypeBased(value = "wt.part.WTPart") @TypeBased(value = " com.company.SoftType")

See TypeBased on page 259 in MVC Components Overview on page 252 for more information.

898

Windchill Customization Guide

Information Pages

899

Customization Points
The default information page will just have a details tab and a + new tab option. The details tab is set up to show just the More Attributes panel. That attributes panel layout will come from the layout definition in the Type and Attribute Management utility. For details on customizing attribute layouts see Layouts Tab. When you create a new tab only 2 options would be available in the Customize menu on that tab. More Attributes and Visualization and Attributes. (or if your object type does not have a visualization delegate registered youd just get More Attributes and Attributes) To customize what is displayed in the info page youll need to create a builder as defined above in the Information Page Builder Designer section of Solution on page 895. Then, the instructions below describe how to customize various aspects of the Info Page by overriding the buildInfoConfig() API in your custom builder. Customization Options in Info Page Builder You can control what elements appear on the information page in your builder class. For more information about the builder class, see Information Page Builder Designer section in Solution on page 895.. The following options can be set on the InfoConfig object: Information Page Item Method to invoke on Builder InfoConfig setTabSet() Default Value Description

Tab Level Set

"defaultInfoPageTabSet"

Name of the action model to be used for the top-level tabs. Please refer toCustomization Options in Info Page Builder on page 900 for more information about configuring the tab set Please refer to Configure the Table of Contents on page

900

Windchill Customization Guide

Information Page Item

Method to invoke on Builder InfoConfig

Default Value

Description

Tab set saving

setTabSetKey()

905 section for more information about configuring the default tables on a specific tab. The hard type of This tabSetKey the business object will be used for is used. For exam- saving tab order, ple wt.part. tab content and the WTPart last active tab. If no tabSetKey is specified by the builder the hard type of the business object will be used as the tabSetKey. For example, part info page will end up using a tab set key of "wt.part. WTPart". Some info pages change this tabSetKey to share behavior across types. For example, the caddoc and saved caddoc info pages will both have tabSetKey of "wt.epm. EPMDocument". Other info pages change this tabSetKey to get different behavior for the

Information Pages

901

Information Page Item

Method to invoke on Builder InfoConfig

Default Value

Description

same type. For example, the 'Clash Job Definition' info page will have a different tabSetKey so that tabs/tables added to that page are not added to the WTDocument info page. Recommended tab set keys would be: wt.part. WTPart" WCTYPE| wt.part. WTPart| com.acme. SoftPart

Action menu

setActionListName Defined in an ac() tions model with the menufor attribute set

Be careful with these keys from release to release. Since they are persisted to the database a migrator will be needed if the key needs to change. Name of the action model to be used for the Actions Menu. See Windchill Client Architecture Action Framework Overview on page 486 or Defining Menus

902

Windchill Customization Guide

Information Page Item

Method to invoke on Builder InfoConfig

Default Value

Description

Table of Contents (TOC) menu

on page 540 to define the action model. If no action menu is desired pass an empty string () to this method. Name of the action model to be used for the Customize Menu on a tab. This is the same action model that was used to render the third-level action bar in prior releases. Please refer to Configure the Table of Contents on page 905 for more information about configuring the default tables on a specific tab

See Windchill Client Architecture Action Framework Overview on page 486 or Defining Menus on page 540 to define the action model.
903

Information Pages

Information Page Item

Method to invoke on Builder InfoConfig Add a status glyph addComponent()

Default Value

Description

Help Button

setHelpContext()

Workspace Toggle Not defined in the builder, see deButton scription for more details

Adds a status glyph to the top of the info page. See Adding a Status Glyph on page 306 for more information about adding status glyphs in the builder. Sets the help context to a specific help page. Set of buttons that appear to the right of the Actions menu. This is configured in javascript and added to the infoModel JSON object via the info page beforerender event. SeeAdding a Status Glyph on page 906 for more information.

Configure a Top-Level Top-Level Tab Set If you would like to specify a top-level tab set for your information page, create an action model and set the action model in the info page builder. For example, you could define the following action model for a tab set:
<model name=partInfoPageTabSet resource=com.ptc.core.ui.navigationRB> <action name=productStructureGWT type=psb/> <submodel name=partInfoDefaultDetails type=object/> </model>

Then, you would specify the tab set on the builder as follows:
InfoComponentConfigFactory f =

904

Windchill Customization Guide

(InfoComponentConfigFactory)getComponentConfigFactory(); InfoConfig result = f.newInfoConfig(); result.setTabSet(partInfoPageTabSet );

For more information on configuring the tabs, and how to specify the content (tables) for a particular tab, please refer to Tab Customizations on page 910. For more details about defining tabs please refer to Client Tabs on page 332. Configure the Table of Contents The table of contents (TOC) is comprised of two items, the menu and the links. They are shown below, circled in red.

TOC Menu The TOC menu allows an end user to add or remove items from the tab. It will only appear on tabs that the user has access to modify. For more information about when tab contents can be modified, seeClient Tabs on page 332. To specify the action model to use as the Table of Contents (TOC) menu, set the action model in your info page builder, like the following (highlighted below):
public InfoConfig buildInfoConfig(ComponentParams params) throws WTException { InfoComponentConfigFactory factory = getComponentConfigFactory(); InfoConfig infoConfig = factory.newInfoConfig(); // sets the action model for the TOC menu on the Tabs of the info page infoConfig.setNavBarName infoConfig.setNavBarName("third ("third level nav package"); ... return infoConfig; }

The action model for the TOC menu should contain the complete set of items that can be added to any of the top level tabs.

Information Pages

905

The TOC menu is a replacement of the Third Level navigation toolbar items found in prior releases:

TOC Links The order of content items in a tab can be modified by dragging and dropping the links in the TOC if the user has the permission to modify the tab contents. See Client Tabs on page 332 for more information. Adding a Status Glyph

You can add a status glyph to the information page for a particular business object type. SeeAdding a Status Glyph on page 906 for more information, Workspace / Common Space Toggle Buttons Currently, the CAD Document info pages show Workspace and Common Space toggle buttons between the Actions menu and the Got to Latest link

If you would like to have the info page show the Workspace or Common space toggle buttons (or any other set of buttons) for a another object type, youll need to set the attribute toggleButtonConfigs on the infoModel object. The attribute toggleButtonConfigs takes an array of button configs. Example JavaScript Button Definition:
// add the buttons to the information page via the beforerender event PTC.infoPage.on("beforerender", addToggleButtons);

// function that adds the buttons to the infoModel object function addToggleButtons(infoModel) { var cs_button = { id: 'commonspace_button',

906

Windchill Customization Guide

icon: 'com/ptc/windchill/uwgm/cadx/images/csUnHilite.gif', handler: function() { var params = { typeIdForTypeLookup: 'com.ptc.carambola.customization.examples. infoPage.Carambola', oid: extractParamValue(getWindow().location.href, 'oid') }; PTC.infoPage.goTo('', params); }, tooltip: 'toggle to commonspace' }; var ws_button = { id: 'workspace_button', icon: 'com/ptc/windchill/uwgm/cadx/images/wsHilite.gif', handler: function() { var params = { typeIdForTypeLookup: 'com.ptc.carambola.customization.examples. infoPage.Carambola', oid: extractParamValue(getWindow().location.href, 'oid'), csName: 'Carambola Example', }; PTC.infoPage.goTo('', params); }, tooltip: 'toggle to workspace' }; infoModel.toggleButtonConfigs = [cs_button, ws_button]; }

Help Button

The help button will appear in the upper right corner of the info page if you set a help context in your info builder:
// sets the help topic to use from the Windchill Help Center infoConfig.setHelpContext infoConfig.setHelpContext("InfoPageHelpTopic"); ("InfoPageHelpTopic");

See Linking to Help Topics on page 1013 for more information. Configuration Options via the Type and Attribute Management Utility The attribute layout for the Attributes panel as well as for the Visualization and Attributes component is controlled via the layout manager in the Type and Attribute Management utility.

Information Pages

907

The layout More attributes layout corresponds to the Attributes action on the information page. Likewise, the layout info page layout for primary attributes corresponds to the Visualization and Attributes action on the information page. Attribute Customizations Attributes v.s. Visualization and Attributes There is a validator attached to the Attributes and Visualization and Attributes TOC options. That validator will hide one or the other based on the visualization delegate that is found for the object type. So even if both actions are specified in your TOC action model you would only see one in the UI:
<model name="defaultTOC"> <action name="primaryAttributes" type="object"/> <action name="visualizationAndAttributes" type="object"/> </model>

Having both actions in the TOC model allows visualization to be hidden/shown for a parent and sub types as needed at runtime. You will not typically need to write a builder class for the Attributes panel, the Visualization and Attributes component, or the More Attributes panel. You configure the attributes panels using the Type and Attribute Management utility, as described in n . They are displayed by the PrimaryAttributeBuilder and VisualizationAttributesBuilder, and TypedAttributesPanelBuilder classes, respectively.

908

Windchill Customization Guide

You can customize the visualization component of the Visualiation and Attributes panel by writing a custom visualization delegate. See the next section Configuring the Visualization Component on page 909 for details of how to register a visualization delegate. Configuring the Visualization Component

Out of the box there should be a visualization component shown for Representations, Representables, and Viewables. But there are a couple things that need to be configured correctly for it to show up. First, make sure youve defined your TOC in the info builder:
infoConfig.setNavBarName(defaultTOC)

Second, make sure youve included the Visualization and Attributes option in your TOC action model:
<model name="defaultTOC"> <action name="primaryAttributes" type="object"/> <action name="visualizationAndAttributes" type="object"/> </model>

You can make a custom visualization delegate if your object type doesnt have visualization out of the box, or if you would like to define different visualization for your object type. First define a custom visualization delegate with the desired html:
import com.ptc.core.components.rendering.guicomponents.VisualizationComponent; import com.ptc.core.components.visualization.VisualizationDelegate; public class CarambolaVisualizationDelegate extends AbstractVisualizationDelegate { public VisualizationComponent getVisualizationComponent(Object datum, ServletRequest request) { String html = "<div id=wvs_pview_div class=vizComponent><IMG src='netmarkets/ images/demodata/carambola.jpg'/></div>"; return new VisualizationComponent(html); } }

The html could include javascript if needed. See the VisualizationComponent javadoc for more details. Second, register the custom visualization delegate with an typed services xconf entry:
<Service context="default" name="com.ptc.core.components.visualization.

Information Pages

909

VisualizationDelegate"> <Option serviceClass="com.ptc.carambola.customization.examples.infoPage. CarambolaVisualizationDelegate" requestor="com.ptc.carambola.customization.examples.infoPage. Carambola" selector="visualization" cardinality="singleton"/> </Service>

Your html should appear in the visualization section. Note, currently the visualization html is put into a panel with a hard coded width and height of 298x202. There are some cases where visualization is shown for a parent type but needs to be hidden for a sub type. For example, visualization is shown for EPMDocuments but is hidden Notes which are a soft type of EPMDocument. In this case the visualization component can be hidden for the sub type by registering the DefaultVisualizationDelegate for that sub type. This will hide the visualizationAndAttributes action from the TOC so you should make sure the TOC action model for the sub type includes the primaryAttributes action:
<model name="defaultTOC"> <action name="primaryAttributes" type="object"/> <action name="visualizationAndAttributes" type="object"/> </model>

To see some logging about which delegate is found and when actions are hidden/ shown by that delegate you can enable a log4j logger named com.ptc.core. components.validators.VisualizationAndAttributesFilter. Tab Customizations Configure a Tab with a Default Set of Tables You can specify a tab to have a set of tables shown by default. To do this, you will create an action model that contains the actions for the desired default tables. For example, the Details tab on the part information page may define the following default tables:
<model name="partInfoDefaultDetails" resourceBundle="com.ptc.core.ui.navigationRB"> <action name="visualizationAndAttributes" type="object"/> <action name="whereUsed" type="object"/> </model>

The tables wont show up unless they are in the Table of Contents (TOC) action model. See the Configure the Table of Contents on page 905 for more details. Please Client Tabs on page 332 or Defining Menus on page 540 for more information about defining the action model.

910

Windchill Customization Guide

Hide/Show Hide/Show Tab Content with Validators Validators can be used to hide/show tabs or to hide/show tables/panels within the tabs. Each tab is an action or action model. Each table or panel is an action. See the validation documentation for details on how to hook up a validator to an action/ action model. Load a specific tab or a particular table on a tab Sometimes its necessary to have a specific tab loaded or to bring a user to a particular table on a tab. Both of these scenarios can be achieved by adding request parameters to the information page URL. Load a Specific Tab To have a particular tab selected when the user navigates to the information page, set the following URL parameters (both need to be set): URL Parameter tabAction Description Specifies the name of the submodel or action element in the tab set (action model) Specifies the object type of the submodel or action. Submodel: If the tab is defined as a submodel in the actionModels.xml file, set the value of this parameter to object. Actions: If the tab is defined as an action in the actionModels.xml file, set the value of this parameter to the actions type. For example, the value for the action below would be part:
<objecttype name="part" class= "wt.part.WTPart"> <action name="createPart"> .... </action> ... <objecttype>

tabType

Information Pages

911

Load a Specific Table To bring the user to a specific table (on a certain tab) when the user navigates to the information page, set the following URL parameters (both need to be set): URL Parameters tlnAction tlnType Description Specifies the action name that corresponds to that item on the tab Specifies the object type of the action. For example, the value for the action below would be part:
<objecttype name="part" class= "wt.part.WTPart"> <action name="createPart"> .... </action> ... <objecttype>

Supported Combinations of Tab and Table URL Parameters Here are the supported combinations of the URL parameters listed in the previous sections. Tab Parameters on URL Tab Parameters not on URL Table Parameters on User is brought to the 1. If the table is found on URL specified tab and the page a tab (any tab), the is scrolled to the given user is brought to that table tab and the page is scrolled to the specified table 2. If the table is not currently on a tab, a new tab is created and the table is added to that tab 3. If the table does not exist, an error message is displayed Table Parameters not on User is brought to the URL specified tab 1. User is brought back to the tab that they recently visited 2. Default to the left
Windchill Customization Guide

912

most tab if the user has not visited the information page within the current browser session. Configuring tabs through the Windchill UI The following information gives a high-level overview of how user and administrator-created tabs can be configured. Please seeClient Tabs on page 332 for more information. Adding additional tabs for users Tabs on the information page can be configured by site and organization administrators, per object type. Site administrators can create tabs that will be visible for all users, per object type. Organization adminsitrators can create tabs that will be visible for all members of that organization, per object type. For example, a site administrator can add a tab called "Site Tab" by navigating to the information page of any part, and clicking the "+" tab to add a tab. The administrator may further customize the tab by adding content to the tab, via the customize link. Any user within this site will now see this "Site Tab" for every part information page, with the content defined by the administrator. Users will not be able to modify the tab or its contents, or close the tab An organization administrator may configure tabs for all members of their organization in the same way. Non-administrator users may also create and configure their own tabs, per object type. These tabs will not be available to other users. Default Tab Set for End Users The tabs that a user sees on an information page will be a combination of tabs defined by the action model for that information page, any tabs configured by the site administrator, any tabs defined by the organization administrator, and finally any tabs defined by the user. All tab sets will be specific to an object type The algorithm for retrieving the tabs for a given information page for a user is as follows: Retrieve the tabs defined by the action model. Retrieve the tabs defined by the site administrator for the object type

Information Pages

913

Retrieve the tabs defined by user s organization administrator for the object type Retrieve the tabs defined by user for the object type.

Specifying a Tab Renderer You will not need to specify a tab renderer for your info page to work, but here are some details of how the contents of the action model get rendered. Each tab (action) will render its contents (the items on the tab) by calling a JavaScript renderer. The default tab renderer will return a simple Ext.Panel. This renderer will request the URL of the tab (action), when the tab is activated. The response (HTML) from the URL will be added to the Ext.Panel. All actions in the tab set (such as productStructureGWT from the example above) are rendered with this default tab renderer. The default renderer for submodels will return a more complex Ext.Panel object This renderer will display each of the items (actions) in the submodel as drag-ndroppable items on the tab. All submodels in the tab set (such as partInfoDefaultDetails from the example above) are rendered with this default submodel renderer. Object Type Icon Customizations

The object type icon is controlled outside of the Information Page component. It is configurable. For information on configuring the icon see Icon Delegates on page 712. Item Identifications Customization The item identification information is controlled outside of the Information Page component. It is configurable. Item Identification is controlled by the DisplayIdentification service and its delegates. To configure different identification information you can create your own DisplayIdentification delegate that implements the wt.identity.DisplayIdentification interface. For more details on working with these services see (customizing service properties).

914

Windchill Customization Guide

Information Page Stickiness Details The information page stores its state both on the client (the user s web browser) and on the server. It uses client-side stickiness to maintain the currently active tab and uses server-side stickiness to preserve the order of the top-level tabs. Tabs created dynamically on the information page (by clicking the + tab) are stored in the database (these may be defined for an entire site, an organization, or per user).

Client Side Stickiness The currently active (i.e., selected) tab on the information page is stored on the client, using client-side stickiness, per object type (unless overridden, see Overriding Stickiness Key on page 916). For example, if a user has Tab A selected on a document information page, then navigates to the folder browser, the next time the user goes back to any document information page, Tab A will be the initially active tab. The active tab will typically be stored for the length of the browser session, or until the user clears their browser cache. When there is no active tab stored on the client for a given object type, the left-most tab on the information page will become the active tab. Client-side stickiness uses the browser s offline storage mechanism, and as such, behavior may vary across different browsers. For more information on client-side stickiness, please see Overriding Stickiness Key on page 916. Server Side Stickiness Much like the client side stickiness, server side stickiness is stored per business object type (unless overridden, see the see the Overriding Stickiness Key section). That is, the tab order on the information page tabs for Documents is stored in a different key than the tab order on the page for Parts. As tabs are reordered on each page, the ordering of the tabs is stored on the server via User Preferences. It will be stored in a separate key for each user. Since the keys are stored in user preferences on the server, the order of tabs on the page will be maintained across browser sessions. If a user changes the tab ordering on a Document information page, those changes will not affect the information for a Part. However, if a user changes the tab order for Document1, then navigates to the information page for Document2, the tab order will be the same as Document1. The server side stickiness can be reset (i.e. cleared) by the end user by navigating to http://<machine_name>/<Windchill> app/#ptc1/user/

Information Pages

915

utilitiesList and clicking the link to reset the server side stickiness. For more information about server-side stickiness, please see Overriding Stickiness Key on page 916. User Created Tabs The contents of a user defined tab are stored per object type (unless overridden, see Overriding Stickiness Key on page 916). Therefore, a new tab on a Document information page, New Tab 1, could contain different items than a tab on a Part information page named New Tab 1. As items on a tab are added, removed, and re-ordered, the ordering of the items are stored on the server in the ClientTab database table. Each tab will be stored in a separate row for each user. Since tabs are stored in the database, the items contained on the tab will be maintained across browser sessions. For more information about how user-created tabs are persisted, see Client Tabs on page 332. Overriding Stickiness Key The stickiness key (or 'tabSetKey') will be used for saving tab order, tab content and the last active tab. If no tabSetKey is specified by the builder the hard type of the business object will be used as the tabSetKey. For example, part info page will end up using a tab set key of "wt.part.WTPart". Some info pages change this tabSetKey to share behavior across types. For example, the caddoc and saved caddoc info pages will both have tabSetKey of "wt. epm.EPMDocument". Other info pages change this tabSetKey to get different behavior for the same type. For example, the 'Clash Job Definition' info page will have a different tabSetKey so that tabs/tables added to that page are not added to the WTDocument info page. Be careful with these keys from release to release. Since they are persisted to the database a migrator will be needed if the key needs to change.

Sample Code
Example implementation for the InfoPageComponent
This example can be viewed in the Windchill product by navigating to Customization -> Example Information Page. The Customization tab is hidden outof-the-box but can be enabled via the Client Customization preference available in Site->Utilities->Preferences Manager.

916

Windchill Customization Guide

This example shows an info page for an object of the new type Carambola.. The Carambola object type is a simple Java class with an icon and various attributes. The example illustrates how to: create a set of tabs define a tab customization menu (tab actions) define an action dropdown menu display status glyphs next to the object name add a help topic construct a custom VisualizationDelegate use a custom view jsp that adds toggle buttons for commonspace/ workspace and a Go to Latest link.

Two of the tabs displayed on the info page illustrate what happens when the server encounters errors when producing a page. The tab Error Page With Generic Exception shows how exception messages are displayed when java or scriplet code executed on a jsp page throws an exception. The tab 404 error shows how a HTTP 404 response code is displayed when the jsp page specified in an action could not be found. The action Action Has Invalid Onclick in the Actions menu illustrates the message that is provided when the javascript provided in the onclick attribute of an action command subtag is invalid. The action Action Has Complex Onclick illustrates another action with an invalid onclick attribute. Onclick attributes should contain a single javascript function call. In this case, the onclick attribute has multiple function calls. The action framework wraps the multiple statements in one function call to prevent the page display from aborting. The panels and tables available for display on the info page tabs via the Customize link are ones created for other examples in the Customization tab, such as the Attribute Panel, Property Panel, and Table examples.

Files Used in this Example


Action Models Used in this Example Action Model File Name: CarambolaactionModels.xml Codebase path: codebase/config/actions Action Model Names CustEx_infoPage_tabset carambola_details CustEx_default_myTab CustEx_error_on_page CustEx_error_404

Information Pages

917

CustEx_infoPage_third_level _navigation CustEx_submodel_simpleTable CustEx_submodel_advancedTable CustEx_InfoPage_attributes carambola_info_page carambola_sub_model Actions Used in this Example Action File Name: Carambola-actions.xml Codebase path: codebase/config/actions Action Names CustEx_simpleTable1 CustEx_simpleTable2 CustEx_simpleTable3 CustEx_advancedTable1 CustEx_advancedTable_custom _oid_actions CustEx_error_on_page CustEx_error_404 propertyPanel attributePanel visualizationAndAttributes primaryAttributes onclickIsInvalid onclickToBeWrapped Files Used in this Example File Carambola.jar Description Carambola object class

Source code examples are located in the Carambola-java.jar file in the <WT_HOME>\Windchill \srclib\wnc diretory. CarambolaVisualizationDelegate that creates the content for the Delegate.java VisualizationComponent on the page
Windchill Customization Guide

918

Source code examples are located in the Carambola-java.jar file in the <WT_HOME>\Windchill \srclib\wnc diretory. CarambolaInfoBuilder. Info page builder class for object type java Carambola Source code examples are located in the Carambola-java.jar file in the <WT_HOME>\Windchill \srclib\wnc diretory. CarambolaVizAndAttrBuilder for the Visualization and Attributes Builder.java penel. You do not typically need to write a Source code examples are located in builder for this panel. Such a builder was the Carambola-java.jar file in required for this example only because the Carambola object type is not a type the <WT_HOME>\Windchill exposed in the Type Manager. \srclib\wnc diretory. carambolaInfoPage.jsp View (jsp) for the page with javascript to Source code examples are located in produce toggle buttons and Go to Latest the Carambola-java.jar file in link. the <WT_HOME>\Windchill \srclib\wnc diretory. <WT_HOME>\Windchill VisualizationDelegate service property \codebase\com\ptc \carambola\carambola. service.properties.xconf

Updating Legacy information Pages


If you have an info page jsp using describeInfoPage and infoPage.jspf here are the steps to convert to the new design: 1. Create an InfoBuilder. a. Many of the attributes on the describeInfoPage tag should have a corresponding setter on the InfoConfig. i. id, helpContext, actionListName, navBarName, b. The propertyPanel, moreAttributesActionName, moreAttributesActionType attributes (and the addPropertyPanel tag) are obsolete. See step 4 for how to create your attribute layouts.

Information Pages

919

c. The describeStatusGlyph tags will become properties on the InfoConfig. (see Adding a Status Glyph on page 906) 2. Configure the Help Button if necessary (see Help Button on page 907) 3. Configure Visualization if necessary (see Configuring the Visualization Component on page 909) 4. Create an attribute layout for your object type using one of these 3 options: a. Through the Type and Attribute Management utility. (see Type and Attribute Management) b. With a load file. c. With a custom attribute panel builder. See the Packaged Samples. 5. Delete the xconf entry for your info page jsp a. If there is an xconf entry for your object type, that will be used instead of the InfoPageBuilder. 6. Delete the describeInfoPage tag and infoPage.jspf include from your info.jsp 7. If there is something left in your jsp that you want displayed on the info page (some tables or property panels), move those tables/property panels into the third level nav bar (which becomes the Table of Contents). This way the tables/ panels shown can be configured by admins and the end user. a. Create a separate action for each table/panel. See the Actions Framework documentation for more info on actions/action models. i. Preferred create a builder for each table/panel. See the MVC table documentation. The resulting actions.xml entry will be something like:
<action name="myTable"> <component name="myTable" typeBased="true" windowType="page"/> </action>

ii. Legacy way create a separate jsp for each table/panel. The resulting actions.xml entry will be something like:
<action name="myTable"> <command windowType="page"/> </action>

b. Add those actions to your navBarName action model. Make sure you have set that navBarName in the InfoBuilder. (see the Configure the Table of Contents on page 905 for more details. ) c. Configure which tables/panels are shown out of the box on the Details tab. See Tab Customizations on page 910 for more information.

920

Windchill Customization Guide

Debugging
Add jcaDebug=true to the URL to see some debug info displayed on the info page. http://<hostName>/<webApp>/app/#ptc1/tcomp/ infoPage?typeIdForTypeLookup=com.ptc.carambola. customization.examples.infoPage.Carambola&jcaDebug=true In particular, at the top of the page jcaDebugdisplays whether a ComponentConfigBuilder or a jsp produced the page. Also available are which action models were used for the Actions menu, the top tab set and the Customize option that lets you add tables to the tabs. See the jcaDebug documentation for more details about what is displayed and where to find it. Log4J The following log4J loggers are available to provide you more information when debugging your Information Page implementation: Logger com.ptc.core.components. validators. VisualizationAndAttributesFilter Description Logs information related to the hiding and showing of the primaryAttributes or visualizationAndAttributes components. See Attributes v.s. Visualization and Attributes Logs information related to finding the context object for the information page. Logs information related to the view chosen for the information page. This may be useful if you are trying to set a custom view. Logs information related to determining whether the requested information page is being rendered with a legacy jsp or an MVC builder.

com.ptc.jca.mvc.components. AbstractInfoComponentBuilder com.ptc.mvc.components. AbstractInfoConfigBuilder

com.ptc.jca.mvc.controllers. TypeBasedIncludeController

Log4javascript Log4javascript is also available for debugging within the browser. You can turn this on by adding a parameter to the end of the url. &jsLog=PTC. This will turn on all the JavaScript logging. You will then see the logging information in the FF/ Chrome console or in a separate console which opens when you add the parameter in IE browsers. The following loggers can also be turned on individually by setting jsLog=<loggername>.

Information Pages

921

Logger PTC.infoPage

PTC.infoPage.ActiveTab

PTC.jca.state.ClientStateStore

PTC.infoPageTableMgr

PTC.jca.manager

Description Logs information about errors encountered when rendering an info page as well as, information related to refreshing the top area of the page. Logs information related to selecting the active tab based on defaults, stickiness and potential overrides. Logs information related to the stickiness information being stored and retrieved for client side stickiness. Logs information about the adding and removing of tables from the tabs on an information page. Logs information about the adding and removing of tables from the tabs on an information page and about the adding and removing of tabs.

922

Windchill Customization Guide

18
Incorporating Pickers in JSP Clients
Configuring Pickers ................................................................................................. 924 Configuring a Context Picker .................................................................................... 933 Configuring an Item Picker ....................................................................................... 943 Configuring an Organization Picker ........................................................................... 952 Configuring a Type Picker ........................................................................................ 960 Configuring a User Picker......................................................................................... 975 Configuring a Participant Picker ................................................................................ 982

This chapter describes how to customize and configure pickers.

923

Configuring Pickers
Solution
Write a custom JSP page and use the Item Picker tag to display the picker. Configure the search criteria fields to be included in the picker using the PickerAttributes.xml file. Configure the object types and containers to be searched using parameters on the itemPicker tag. Prerequisite knowledge To achieve this objective, you need to have an understanding of the following: Basic development involving HTML forms, JSP, XML. Picker common components Table common component View creation

Solution Elements Element pickerAttributes.xml

Type XML

SearchResultsTable .properties.xconf

Xconf

Description Runtime location: <WT_HOME>\codebase\picker Attributes.xml Runtime location: <WT_HOME> \codebase\com \ptc\netmarkets\search\ SearchResultsTable. properties.xconf This file can be used to configure table view definition.

924

Windchill Customization Guide

Procedure - Launching the picker and defining the object types to be searched
The picker can be launched from your JSP by calling the itemPicker tag:
<wctags:itemPicker id="customized_item_picker" objectType="WCTYPE| wt.part.WTPart|org.r_and_d.mypart" componentId="customizedItemPicker ForSoftPart "/>

The objectType parameter indicates that the search should be limited to objects of type org.r_and_d_mypart. The value of the id parameter should be an identifier that is unique for the given page. The value of the componentId parameter is a key that will be used to look up the search criteria to be presented in the picker. This is described in the next section.

Procedure - Customizing the Picker Search Criteria


The search criteria for a picker can be customized using the file pickerAttributes.xml. First define a new component id for the picker using the componentID parameter on the picker tag, as shown above, and then define the object attributes to be used as search criteria in the xml file as shown below.
<ComponentID id="customizedItemPickerForSoftPart"> <ObjectType id="WCTYPE|wt.part.WTPart|org.r_and_d.mypart"> <SearchCriteriaAttributes> <Attributes> <Name>name</Name> <DisplayName>NAME_LABEL</DisplayName> <IsSearchable>true</IsSearchable> </Attributes> </SearchCriteriaAttributes> </ObjectType> </ComponentID>

If the componentID attribute is not specified or if you do not define search criteria in pickerAttributes.xml, by default pickerSearch componentId is used to display the search criteria. The pickerAttributes.xml files can be modified by customers and is the only file to be modified in this regard. This file contains only search criteria and not the object types. Prefix WCTYPE is allowed in this xml file. It is required in case of soft types. For hard types only object type is required. In this example, the component id is the component id defined for our picker on the picker tag (see Procedure - Launching the picker and defining the object types to be searched on page 925). We have defined a single attribute to be searchable, which is the attribute nameon the object type org.r_and_d.mypart.
Incorporating Pickers in JSP Clients

925

${domain} is specific to EPM document. It is generic and not internal to developers. This xml file contains search criteria input fields and not types. If you were searching for more than one object type, you will have to add entries for other object types after first object type under same component id. In case of multiple type searches, generic (persistable object type) criteria will be displayed. Common Customization Points are listed in following tables: Parameter Id Default Value Possible Values Anything thats unique in a page Req? Yes Description An ID is associated with every picker in Scope of the calling application. This ID has to be unique for all pickers, irrespective of type on one page. The id should not contain "." (Dot) in the name. componentId determines the attributes that should appear in search criteria panel for the given picker. Name of the customized callback javascript function that a user would have to implement. Its recommended that you should specify pickerCallback function in custom.js file Default value for textbox rendered by the picker.
Windchill Customization Guide

componentId

pickerSearch

Any valid component id specified in pickerAttrib utes.xml

No

pickerCallback Generated at Name of the runtime if user callback has not speci- function fied this parameter

No

defaultValue

(blank)

Any values

No

926

Parameter Label displayAttribute

Default Possible Values Value Context Picker Any value Name Any attribute

Req? No No

Description Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the item picker. Value of the containerRef in which a user wants to restrict the search. Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will get ANDed with the internal where clause. Default value of the hidden textbox associated with the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. This attribute defines whether you want to have find icon along with the textbox. This attribute defines whether the
927

containerRef

(blank)

Any container No

baseWhere Clause

(blank)

Any valid I*E No where clause query

pickerTitle

Contexts

Any value

No

pickedData Fetcher

<WebApp>/ URL location netmarkets/jsp/ of the fetcher search/picked file Data.jsp

No

Editable

True

true/false

No

readOnlyPic kerTextBox

False

true/false

No

Incorporating Pickers in JSP Clients

Parameter

Default Value

Possible Values

Req?

Description picker text box should be editable or not. You should specify this parameter with value as true when you want to launch picker as a table level action or inline. This parameter contains a comma separated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. This parameter defines the picker type i.e. search picker or picker picker. In search picker, you will see search criteria in the picker and then you have to click the search button to see the results however in case of picker picker you will directly see the results table without any search criteria. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for

Inline

False

true/false

No

pickedAtt ributes

Name

Any comma separated list of valid attributes

No

pickerType

search

search/picker

No

pickerText BoxLength searchResults ViewId

25

Any numeric value

No

(blank)

Any valid view No id

928

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req?

Description the picker search results table.

Incorporating Pickers in JSP Clients

929

Procedure - Defining the containers to be searched


To confine the search to objects in certain containers, use the containerRefparameter on the picker tag. The value of this parameter should be a comma-separated list of one or more WTContainerRef objects, in string format, for the containers you want to search. The WTContainerRefs for the containers can be fetched by querying for the containers and getting the WTContainerRef for each from the WTContainer object. If no containerRef parameter is provided, all containers will be searched.
<wctags: itemPicker id=" customized_item_picker objectType="WCTYPE|wt.part.WTPart|org.r_and_d.mypart" containerRef=" OR: wt.pdmlink.PDMLinkProduct:33707 componentId="customizedItemPickerForSoftPart" />

Procedure - Customizing the search result table view


Search result tables use the table common component and hence the column display can be configured by creating a new table view. You will first need to create a new JCAConfigurableTable Java class defining your table view. Then create a service property entry in a *.properties.xconf file that can be used to look up your table view class based on an identifier you choose called the selector. For example, if your table view class was CustomizedPartView, your service property entry might look like this:
<Service context="default" name="com.ptc.core.htmlcomp.tableview.ConfigurableTable"> <Option serviceClass="com.ptc.netmarkets.search.views.CustomizedPartView" requestor="java.lang.Object" selector="wt.part.WTPart.customizedSearchView "/> </Service>

Finally, pass the selector as below to the picker tag, as shown below, and the search results table will be rendered with this view.
<wctags: itemPicker id=" customized_item_picker" objectType="WCTYPE|wt.part.WTPart|org.r_and_d.mypart" containerRef="<OR: wt.pdmlink.PDMLinkProduct:33707 componentId="customizedItemPickerForSoftPart" searchResultsViewId="wt.part.WTPart.customizedSearchView"/>

930

Windchill Customization Guide

Sample Code
<html> <body> <table> <tr> <%-launching user picker--%> <wctags:userPicker id="testUserPicker" label="MyUserPicker" readOnlyPickerTextBox="false" editable="true" showSuggestion="true" suggestMinChars="5" /> </tr> <tr> <%-launching organization picker--%> <wctags: organizationPicker id="orgPicker" label="MyOrgPicker" readOnlyPickerTextBox="false" editable="true" showSuggestion="true" suggestMinChars="3"/> </tr> <tr> <%-launching context picker--%> <wctags: contextPicker id="contextPicker" label="MyContextPicker" pickerTitle="ContextPicker" /> </tr> <tr> <%-launching Item picker--%> <wctags:itemPicker id="itemPicker" label="MyItemPicker" pickerTitle="ItemPicker"/> </tr>

<tr> <%-launching Item picker with exclude sub types and access controller --%> <wctags:itemPicker id="CustomizedItemPicker" label="CustomizedItemPicker" pickerTitle="CustomizedItemPicker"excludeSubTypes="WCTYPE|wt.doc.WTDocument| org.rnd.Minutes,WCTYPE|wt.doc.WTDocument|org.rnd.General" customAccessController="com.ptc.windchill. enterprise.search.server.LatestVersionAccessController"/> </tr> <tr> <%-launching Item Masterpicker--%> <wctags:itemMasterPicker id="itemMasterPicker" label="MyItemMasterPicker"/> </tr> <tr> <%-launching Item Masterpicker--%> <wctags:genericPicker id="genericPicker"objectType="wt.part.WTPart"label ="Part Picker using generic" /> </tr> <tr>

Incorporating Pickers in JSP Clients

931

launching Item Masterpicker--%> <wctags:genericPicker id="viewPicker" objectType="wt.vc.views.View" label=" View Picker using generic" pickerType="tree" /> </tr> <tr> <%-launching Recently Visited Context Picker- Single Select--%> <wctags:contextPicker id="containerTypeListSingleSelect" label=" Recently Visited Context PickerSingle Select" pickerTitle="ContextPicker" showRecentlyUsed="true" displayAttribute="containerInfo.name"/> </tr> <tr> <%-launching Recently Visited Context Picker- Multi Select--%> <wctags:contextPicker id="containerTypeListMultiSelect" label="Recently Visited Context Picker- Multi Select" pickerTitle="ContextPicker" showRecentlyUsed="true" displayAttribute="containerInfo.name" showMultiSelectRecentlyUsed="true"/> </tr> </table> </body> </html>

<%--

932

Windchill Customization Guide

Configuring a Context Picker


Objective
You want to add a context picker to a custom UI and need to configure the picker to: Search only for objects of certain type(s) Search only for objects in certain container(s) Display certain search criteria input fields Display certain attributes of the objects in the search results table

Background
The context picker is used when you have a requirement to perform an operation that is based on certain context.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


It is assumed that your <MyPage>.jsp file in which you are putting tag includes /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf files.

Intended Outcome
You should see a text box and Find icon along with the specified label after using the tags for context picker. After clicking Find icon , the context picker will be launched.

Incorporating Pickers in JSP Clients

933

On clicking Find icon you should see a Context Picker for Project as follows:

Solution
Use the Context Picker Common Component in your JSP file to include Context Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving JSP, JavaScript, Custom taglibs The management of resource bundle file customizations Windchill xconfmanager concepts

Solution Elements Element PickerAttributes.xml

Type XML

Description You should use this file to customize the search criteria attributes for an object type for your picker.

searchClientResource.java

Runtime location: <WT_HOME>\codebase\ pickerAttributes.xml Resource bundle file You should use this file to localize the contents of the pickers.

934

Windchill Customization Guide

Element contextPicker.tag

Type Custom JSP tag file

Description This file contains the information about the supported parameters for this tag.

SearchableTypes.properties .Xconf

Runtime location: <WT_HOME>\codebase\ WEB-INF\tags\Context Picker.tag xconf Properties file You should specify component Id and corresponding object types in this file and then run xconfmanager. Runtime location: <WT_HOME>\codebase\ com\ptc\windchill\enterprise \ search\server\Searchable Types.properties.xconf You should specify custom pickerCallback function for picker in this file. Runtime location: <WT_HOME>\codebase\ netmarkets\jsp\search\ custom.js

custom.js

JavaScript file

Note You want to disable the type picker in the Context Picker.

Procedure Including a Context Picker in a jsp page


The context picker can be launched from your JSP by calling the contextPicker tag:
<tr> <wctags:contextPicker id="contextPickerId" /> </tr>

Incorporating Pickers in JSP Clients

935

Customization Points
Customization Points are listed in following tables: Parameter Id Default Value Possible Req? Values Anything False thats unique in a page Description An ID is associated with every picker in the calling application. This ID has to be unique for all pickers, whether of different types or same type, in one page. The id should not contain "." (dot) in the name. componentId determines the attributes that should appear in search criteria panel of the given picker. Name of the customized callback function that a user would have to implement. Its recommended that you specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected
Windchill Customization Guide

componentId

No Any valid component id specified in picker Attributes.xml No pickerCallback Generated at Name of the runtime if user callback has not speci- function fied this parameter pickerSearch

defaultValue

(blank)

Any values

No

defaultHidden (blank) Value

Any values

No

pickedData Fetcher

<WebApp>/ URL location netmarkets/ of the fetcher jsp/search/ file pickedData.jsp

No

936

Parameter

Default Value

Possible Values

Req? No No

Description results. Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the context picker Value of the containerRef in which a user wants to restrict the search. Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. Title of the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. This attribute defines whether you want to have Find icon along with the textbox or not. This attribute defines whether the picker text box should be editable or not. This parameter is

Label displayAttribute

Context Picker Any value Name Any attribute

containerRef

(blank)

Any container No

baseWhere Clause

(blank)

Any valid I*E where clause query

No

pickerTitle pickedData Fetcher

Contexts <WebApp>/ netmarkets /jsp/search/ pickedData.jsp

Any value URL location of the fetcher file

No No

Editable

True

true/false

No

readOnlyPick- False er TextBox

true/false

No

typeComp

Foundation.

Any valid

No

Incorporating Pickers in JSP Clients

937

Parameter onentId

Default Value contextPicker

Inline

False

Possible Values componentId specified in Searchable Types.properties file true/false

Req?

Description passed to define set of types that can be shown in Type Picker

No

pickedAttributes

Name

Any comma separated list of valid attributes

No

showTypePicker

true

true/false

No

pickerType

search

search/picker

No

pickerTextBox 25

Any numeric

No

You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a comma separated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. This parameter should be used to enable type picker in the picker. This parameter defines the picker type i.e. search picker or picker picker. In search picker, you will see search criteria in the picker and then you have to hit the search button to see the results however in case of picker picker you will directly see the results table without any search criteria. This parameter
Windchill Customization Guide

938

Parameter Length searchResults ViewId

Default Value

Possible Values value

Req?

Description defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to define your own custom access controller. This parameter would accept the complete class name as the value. To specify multiple customAccess Controller you can pass on comma (,) separated list of the class names. This parameter is used to exclude sub types from the search. This parameter is used to specify the extra attributes that are to be used for auto-suggest This property is used to enable autosuggest to the picker. This parameter is used to specify the min. character on which auto-suggest initiates if enabled Key for selecting

(blank)

Any valid view No id

customAccess (blank) Controller

Any valid name

No

excludeSub Types

(blank)

Any valid subtypes

No

extraSuggest Attribute

emailId

Any field user False wants to search on

showSuggestion

false

True/false

False

suggestMin Chars

integer

False

suggestService Picker specific userPicker,

False

Incorporating Pickers in JSP Clients

939

Parameter Key

Default Value

Possible Req? Values partPicker etc.

Description suggestable class (e. g. ContextService PickerSuggestable) which in turn call query service.Key needs to be present in search-service. properties.xconf file. The passed container types will be merged in recently visited combo box though they are not part of recently visited list. This property must be used only for search page for pickers do not use this property. This depends on showRecently Used=true. User can provide the custom onchange function for recently used combo. The two checkboxes 'I am member of' and 'In my organization' will be shown if this property is made true. If this property is made true multi select recently used context picker will be shown. In this case you need to modify your callback function and
Windchill Customization Guide

mergeContainer Types

False

onChangeFor RecentlyUsed

False

showMember false OfCheckBoxes

True/false

False

showMulti false SelectRecently Used

True/false

False

940

Parameter

Default Value

Possible Values

Req?

Description onchange function. Default value is false. Implemented for search page only.

Configuring Context Picker without type picker


<wctags:contextPicker id="contextPickerId" showTypePicker="false"/>

Configuring Context Picker with multi select option in results table


<wctags:contextPicker id="contextPickerId" multiSelect="true" />

Configuring Context Picker with your own typeComponentId in the type picker
<wctags:contextPicker id="contextPickerId" typeComponentId=" Foundation.myContextPickerComponentId" />

where Foundation.myPickerComponentId is available in SearchableTypes.properties file.

Configuring baseWhereClause in Context picker


<wctags:contextPicker id="contextPickerId" baseWhereClause="(name=demo*)" />

Incorporating Pickers in JSP Clients

941

Configuring pickerCallback function in Context picker


<wctags:contextPicker id="contextPickerId" pickerCallback="myPickerCallback" />

myPickerCallback function can be like:


function myPickerCallback(objects, pickerID) { var updateHiddenField = document.getElementById(pickerID); var updateDisplayField = document.getElementById(pickerID + "$label$"); var myJSONObjects = objects.pickedObject; for(var i=0; i< myJSONObjects.length;i++) { var oid = myJSONObjects[i].oid; // Here name is the displayAttribute requested var displayAttr = eval("myJSONObjects[i].name"); updateHiddenField.value=oid; updateDisplayField.value=displayAttr; } }

942

Windchill Customization Guide

Configuring an Item Picker


Objective
You want to pick instance(s) of Windchill business objects.

Background
The item picker is used when you have a requirement to select specific business object(s) depending upon certain criteria and use them in your application.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


It is assumed that your <MyPage>.jsp file in which you are putting tag includes /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf files.

Intended Outcome
You should see a text box and Find Button along with the specified label after using the tags for item picker. After clicking the Find button, the item picker will be launched.

Incorporating Pickers in JSP Clients

943

On clicking the Find button you should an Item Picker as:

Solution
Use the Item Picker Common Component in your JSP file to include Item Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving JSP, JavaScript, Custom taglibs The management of resource bundle file customizations Windchill xconfmanager concepts

Solution Elements
Element pickerAttributes.xml Type XML file Description You should use this file to customize the search criteria attributes for an object type for your picker.

searchClient

Runtime location: <WT_HOME>\codebase\picker Attributes.xml Resource bundle You should use this file to localize

944

Windchill Customization Guide

Element Resource.java itemPicker.tag

Type file Custom JSP tag file

Description the contents of the pickers. This file contains information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\WEB-INF \ tags\itemPicker.tag You should specify component Id and corresponding object types in this file and then run xconfmanager. Runtime location: <WT_HOME>\codebase\com\ptc\ windchill\enterprise\search\server\ SearchableTypes.properties.xconf You should specify custom pickerCallback function for picker in this file. Runtime location: <WT_HOME>\codebase\netmarkets \ jsp\search\custom.js

SearchableTypes.properties.xconf

xconf Properties file

custom.js

JavaScript file

Note You want to disable the type picker in the Item Picker.

Procedure Including an Item Picker in a jsp page


Configure basic item picker:
<tr> <wctags:itemPicker id="itemPickerId" /> </tr>

Customization Points
Parameter Id Default Value Anything thats unique in a page Possible Values Req? Yes Description An ID is associated with every picker in the calling application.

Incorporating Pickers in JSP Clients

945

Parameter

Default Value

Possible Values

Req?

Description This ID has to be unique for all pickers, whether of different types or same type, in one page. The id should not contain "." (dot) in the name. componentId determines the attributes that should appear in search criteria panel of the given picker. Name of the customized callback function that a user would have to implement. Its recommended that you specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. Label of the picker. Name of the attribute that should be displayed in the picker textbox after selecting result from the item picker Value of the containerRef in which a user wants to restrict the search. Additional where clause if you want to

No Any valid component id specified in picker Attributes.xml No pickerCallback Generated at Name of the runtime if user callback has not speci- function fied this parameter componentId pickerSearch

defaultValue

(blank)

Any values

No

defaultHidden (blank) Value Label displayAttribute Item Picker Name

Any values

No

Any value Any attribute

No No

containerRef

(blank)

Any container No

baseWhere Clause

(blank)

Any valid I*E No where clause

946

Windchill Customization Guide

Parameter

Default Value

Possible Values query

Req?

Description filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. Title of the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. This attribute defines whether you want to have Find icon along with the textbox or not. This attribute defines whether the picker text box should be editable or not. This parameter is passed to define set of types that can be shown in Type Picker

pickerTitle pickedData Fetcher

Item <WebApp>/ netmarkets/ jsp/search/ pickedData.jsp True

Any value URL location of the fetcher file

No No

Editable

true/false

No

readOnly False PickerTextBox

true/false

No

typeCompon entId

Foundation. contextPicker

Inline

False

Any valid componentId specified in Searchable Types. properties file true/false

No

No

picked Attributes

Name

Any comma separated list of valid attributes

No

You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a comma separated list of the attributes that a user wants a picker to fetch. This is

Incorporating Pickers in JSP Clients

947

Parameter

Default Value

Possible Values

Req?

Description applicable only if inline is true. This parameter should be used to enable type picker in the picker. This parameter defines the picker type i.e. search picker or picker picker. In search picker, you will see search criteria in the picker and then you have to hit the search button to see the results however in case of picker picker you will directly see the results table without any search criteria. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to define your own custom access controller. This parameter would accept the complete class name as the value. To specify multiple customAccess Controller you can pass on comma (,) separated list of the class names. Name of object type that should be present
Windchill Customization Guide

showType Picker pickerType

True

true/false

No

search

search/picker

No

pickerText BoxLength searchResults ViewId

25

Any numeric value

No

(blank)

Any valid view No id

customAccess (blank) Controller

Any valid name

No

objectType

wt.fc. Persistable

wt.part. WTPart

No

948

Parameter

Default Value

Possible Values

Req?

Description as the default object type This parameter is used to exclude sub types from the search. Value of iteration field that should be set. Default value is ALL Value of revision field that should be set. Default value is ALL Format of type picker. Value should one of *dropdown*, *table*, *tree* This parameter is used for setting type picker for single or multi select This parameter is used to for setting list of object type based on certain relation in type picker This parameter is used for setting default selected type in type picker This parameter is used for showing or hiding subtypes.Possible values are ROOT_TYPES (only seedTypes will be displayed), SOFT_TYPES (only SOFT Types will be displayed), BOTH (MODELED & SOFT

excludeSub Types

(blank)

Any valid subtypes ALL

No

defaultIteration ALL Value defaultVersion ALL Value typePicker Format

No

ALL

No

No

singleSelect TypePicker

No

typePicker ObjectList

No

typePicker DefaultType

No

typePicker SubTypeDisplay

No

Incorporating Pickers in JSP Clients

949

Parameter

Default Value

Possible Values

Req?

Description Types will be displayed) This parameter is used for setting Shows the seedTypes as I level elements This parameter is used for showing All Applicable Object Type in type picker This parameter is used to specify comma separated list object ref to be excluded from search results.

typePicker ShowRoot

No

showAll ObjectTypes

No

excludeRef

A Comma sep- No arated list of object refs to be excluded from search

Configuring Item Picker without type picker


<wctags:itemPicker id="itemPicker" showTypePicker="false"/>

Configuring Item Picker with default object type


<wctags:itemPicker id="itemPicker" objectType="wt.part.WTPart" />

Configuring Item Picker with multi select option in results table


<wctags:itemPicker id="itemPicker" multiSelect="true" />

Configuring Item Picker with your own typeComponentId in the type picker
<wctags:itemPicker id="itemPicker" typeComponentId=" Foundation.myPickerComponentId" />

where Foundation.myPickerComponentId is available in SearchableTypes.properties file.

Configuring baseWhereClause in Item picker


<wctags:itemPicker id="itemPicker" baseWhereClause="(name=demo*)" />

950

Windchill Customization Guide

Configuring pickerCallback function in Item picker


<wctags:itemPicker id="itemPicker" pickerCallback="myPickerCallback" />

myPickerCallback function can be like:


function myPickerCallback(objects, pickerID) { var updateHiddenField = document.getElementById(pickerID); var updateDisplayField = document.getElementById(pickerID + "$label$"); var myJSONObjects = objects.pickedObject; for(var i=0; i< myJSONObjects.length;i++) { var oid = myJSONObjects[i].oid; // Here name is the displayAttribute requested var displayAttr = eval("myJSONObjects[i].name"); updateHiddenField.value=oid; updateDisplayField.value=displayAttr; } }

Incorporating Pickers in JSP Clients

951

Configuring an Organization Picker


Objective
Problem: You want to add an organization picker to a custom UI and need to configure the picker to: Search only for objects of certain type(s) Search only for objects in certain container(s) Display certain search criteria input fields Display certain attributes of the objects in the search results table

Background
The organization picker is used when you have a requirement to select specific organization(s) depending upon certain criteria and use them in your application. Typical use case could be that you may want to find parts that are available in particular organization. In this case, you can have a organization picker and then through this you can select the organization and pass it on to the search criteria to perform search for parts.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


It is assumed that your <MyPage>.jsp file in which you are putting tag includes /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf files. Intended Outcome You should see a text box and a Find button along with the specified label after using the tags for organization picker. After clicking the Find button, the organization picker will be launched.

952

Windchill Customization Guide

On clicking Find button you should see an organization picker.

Solution
Use the Organization Picker Common Component in your JSP file to include Organization Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving JSP, JavaScript, Custom taglibs The management of resource bundle file customizations Windchill xconfmanager concepts

Solution Elements
Element PickerAttributes.xml Type XML Description pickerAttributes.xml XML file You should use this file to customize the search criteria attributes for an object type for your picker. Runtime location:

Incorporating Pickers in JSP Clients

953

Element

Type

searchClientResource.java Resource bundle file

organizationPicker.tag

Custom JSP tag file

Description <WT_HOME>\codebase\ pickerAttributes.xml You should use this file to localize the contents of the pickers. This file is contains the information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\ WEB-INF\tags\ ContextPicker.tag You should specify component Id and corresponding object types in this file and then run xconfmanager. Runtime location: <WT_HOME>\codebase\ com\ptc\windchill\ enterprise\search\ server\Searchable Types.properties.xconf You should specify custom pickerCallback function for picker in this file. Runtime location: <WT_HOME>\codebase\ netmarkets\jsp\search\ custom.js

SearchableTypes.proper ties.Xconf

xconf Properties file

custom.js

JavaScript file

Note You want to disable the type picker in the Context Picker.

954

Windchill Customization Guide

Procedure Including an Organization Picker in a jsp page


The organization picker can be launched from your JSP by calling the organizationPicker tag:
<tr> <wctags:organizationPicker id="organizationPickerId" /> </tr>

Customization Points
Parameter Id Default Value Possible Values Anything that is unique in a page Req? False Description An ID is associated with every picker in the calling application. This ID has to be unique for all pickers, whether of different types or same type, in one page. The id should not contain "." (dot) in the name. componentId determines the attributes that should appear in search criteria panel of the given picker. Name of the customized callback function that a user would have to implement. Its recommended that you should specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the

componentId

pickerSearch

pickerCallback Generated at the runtime if user has not specified this parameter

Any valid component id specified in pickerAttrib utes.xml Name of the callback function

No

No

defaultValue

(blank)

Any values

No

defaultHidden (blank) Value

Any values

No

Incorporating Pickers in JSP Clients

955

Parameter

Default Value

Possible Values

Req?

Description picker. Label of the picker. Name of the attribute that should be displayed in the picker textbox after selecting result from the organization picker Value of the containerRef in which a user wants to restrict the search. Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. The title of the picker. URL of the data fetcher file that will be used by the AJAX call to process the selected results. This attribute defines whether you want to have Find icon along with the textbox or not. This attribute defines whether the picker text box should be editable or not.
Windchill Customization Guide

Label display Attribute

Context Picker Any value Name Any attribute

No No

containerRef

(blank)

Any container No

baseWhere Clause

(blank)

Any valid I*E where clause query

No

pickerTitle pickedData Fetcher

Contexts

Any value

No No

<WebApp>/ URL location netmarkets/ of the fetcher jsp/search/ file pickedData.jsp

Editable

True

true/false

No

readOnly False PickerTextBox

true/false

No

956

Parameter Inline

Default Value False

Possible Values true/false

Req? No

Description You should specify this parameter with value as true when you want to launch picker from a table level action or inline. This parameter contains a comma separated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. This parameter defines the picker type i.e. search picker or picker picker. In search picker, you will see search criteria in the picker and then you have to hit the search button to see the results however in case of picker picker you will directly see the results table without any search criteria. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to specify the

picked Attributes

Name

Any comma separated list of valid attributes

No

pickerType

search

search/picker

No

pickerText BoxLength searchResults ViewId

25

Any numeric value

No

(blank)

Any valid view No id

extraSuggest Attributes

emaild

Any field user False wants to search

Incorporating Pickers in JSP Clients

957

Parameter

Default Value

Possible Values on

Req?

Description extra attributes that are to be used for auto-suggest If this property is made true multi select recently used context picker will be shown. In this case you need to modify your callback function and onchange function. Default value is false. Implemented for search page only. This property is used to enable auto-suggest to the picker. This parameter is used to specify the min. character on which auto-suggest initiates if enabled Key for selecting suggestable class (e. g. ContextService Picker Suggestable) which in turn call query service.Key needs to be present in searchservice. properties.xconf file.

show Suggestion

false

True/false

False

suggest MinChars

Integer values

False

suggest ServiceKey

Picker specific userPicker, False partPicker etc.

Configuring Organization Picker with multi select option in results table


<wctags:organizationPicker id="orgPickerId" multiSelect="true" />

958

Windchill Customization Guide

Configuring baseWhereClause in Organization picker


<wctags:organizationPicker id="orgPickerId" baseWhereClause="(name=myOrg*)" />

Configuring pickerCallback function in Organization picker


<wctags:organizationPicker id="orgPickerId" pickerCallback="myPickerCallback" /> myPickerCallback function can be like: function myPickerCallback(objects, pickerID) { var updateHiddenField = document.getElementById(pickerID); var updateDisplayField = document.getElementById(pickerID + "$label$"); var myJSONObjects = objects.pickedObject; for(var i=0; i< myJSONObjects.length;i++) { var oid = myJSONObjects[i].oid; // Here name is the displayAttribute requested var displayAttr = eval("myJSONObjects[i].name"); updateHiddenField.value=oid; updateDisplayField.value=displayAttr; } }

Incorporating Pickers in JSP Clients

959

Configuring a Type Picker


You want to create a Type Picker either for the display or for the assignment of type-able items. Background Type Picker Common Component is to be used either for display or for assignment of type-able items. For example in a search application to select the type of objects that you are interested to do a search on or in a create application to create an item of a specific type. It can be used to display the type in case of edit or view applications. The component can be used in the context/mode of CREATE, EDIT, SEARCH or VIEW. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions If the Type Picker behavior is to be driven by site/organization preferences viz. display (list or tree), default type, filter criteria etc, its assumed that you will extract the relevant information and pass them to the component. The component will apply access control policies except for SEARCH mode. It is assumed that your <MyPage>.jsp file in which you are implementing this common component includes /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf files.

Intended Outcome Depending upon the format, you will get either a dropdown or table or a tree: Type Picker in DropDown Format

Type Picker in Table Format

960

Windchill Customization Guide

Type Picker in Tree Format

Incorporating Pickers in JSP Clients

961

Solution
Use Type Picker Common Component to display or for the assignment of type -able items. Prerequisite knowledge To understand this documentation, you need to have an understanding of the following: Basic development involving JSP, JavaScript and Custom taglibs The management of resource bundle files customizations Windchill xconfmanager concepts Windchill Type Identifiers

Solution Elements Element picker.tld

Type tld

Description Tag Library Descriptor (TLD) file, which contains Type Picker Tag definition Run time Location:

962

Windchill Customization Guide

Element

Type

Description <Windchill> \codebase\WEB-INF\ tlds\ You should use this file to localize the contents of the Type Picker pop up. Your TypePicker Common Component implementation containing jsp file. You can define wt.typepicker exclude property here Run time Location: <Windchill>\codebase \wt.properties

typePickerResource.java

Java

<your_page>.jsp

jsp

wt.properties

properties

The solution is also addressed to these variations: 1. You want to specify that a container will display a particular subset of all types in a Type hierarchy. 2. You want to specify filtering criteria on the types shown, including criteria on custom subclasses. 3. You want to specify the root/base types (OOTB or custom) to be used. 4. You want to include a type picker that will be launched as a dropdown or table/ tree popup menu. 5. You want to specify whether or not non-instantiable types are to be presented for picking Procedure Configuring Type Picker Common Component 1. Include necessary artifacts. You should include the necessary artifacts in your configuring jsp file e.g. /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf file. You also need to declare picker taglib directive. (uri=http://www.ptc.com/windchill/ taglib/picker) 2. Configure Type Picker.
<%@ taglib uri="http://www.ptc.com/windchill/taglib/picker" prefix="p"%> <%@ include file="/netmarkets/jsp/util/begin.jspf"%> ----

Incorporating Pickers in JSP Clients

963

---<!-- TYPE PICKER CONFIGURE START --> < p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <p:pickerParam name="seedType" value="wt.epm.EPMDocument" /> <p:pickerParam name="type" value="BOTH" /> <pr:pickerParam name="displayHierarchy" value="false" /> <p:pickerParam name="showRoot" value="true" /> </p:typePicker> <!-- TYPE PICKER CONFIGURE END --> ------<%@ include file="/netmarkets/jsp/util/end.jspf"%>

Customization Points
typePicker tag attributes Parameter id Default Value Possible values Any value Req? Yes Description Used to distinguish between the multiple TypePicker usages in a page. The id value should not contain "." (dot). Used as the Picker label Defines in which mode the Type Picker is going to be used and it should be one of the value defined in com.ptc. core.ui. resources. ComponentMode Target Element is the one in which the selected elements attributes will be populated. It should be a subclass of com. ptc.core. components. rendering. AbstractGui Component Currently support TextBox and ComboBox
Windchill Customization Guide

label mode

SEARCH

Any value -

No No

field

No

964

Parameter

Default Value renderContext -

Possible values -

Req? No

Description Object should be an instance of com.ptc. core. components. rendering. RenderingContext. If not supplied the component will create one for the user. This is the object type in which the picker action is specified in *actions.xml . <Windchill>\ codebase\ config\actions\ EnterpriseUIactions.xml This is the action name that is specified in *actions.xml for the picker action

objectType

typepicker

No

actionName

typePicker

No

pickerParam tag attributes Parameter adminDomain Ref Default Value Possible values Req? No Description String representation of the administrative domain reference (wt.admin.Admin DomainRef). Used to check access control rights. String representation of the container reference (wt.inf.container. WTContainerRef) and is used to populate types specified for this

containerRef

No

Incorporating Pickers in JSP Clients

965

Parameter

Default Value

Possible values

Req?

Description container. If adminDomainRef is provided, containerRef is calculated from that even if user has supplied it. If adminDomainRef is NOT provided, component uses the default AdminDomain for the supplied containerRef or if containerRef is not provided, component uses default WTContainer (Exchange container). String representation of State (wt.lifecycle.State) and is used while checking access control rights. Accepts valid logical or external representation of Windchill Type Identifiers. Multiple values supported and its required for mode = CREATE/EDIT/VIEW Accepts valid logical or external representation of Windchill Type Identifiers. Multiple values supported. The type and its descendants are filtered out from the picker element Accepts valid logical or external representation of Windchill Type Identifiers. For single select,
Windchill Customization Guide

lifeCycleState

No

seedType

No

filterType

No

defaultType

No

966

Parameter

Default Value

Possible values

Req?

Description it should be only one value. Multiple values are supported and its required for mode = EDIT/VIEW. It can support blank, "Select a Type" etc values also. Localized Display name and value separated by a "$" delimiter and multiple values are supported. It should be one of the enum constant value defined in com.ptc. windchill. enterprise.picker. type.server. TypePickerFormat. The possible values are dropdown, table, tree Possible values are single and multi. It should be one of the enum constant value defined in com.ptc. windchill. enterprise.picker .type.server. TypePickerTypes. Possible values are ROOT_TYPES (only seedTypes will be displayed), SOFT_TYPES (only SOFT Types will be displayed), BOTH (MODELED & SOFT Types will be displayed) Accepts String representation of Boolean value. This is valid only for

appOption

No

format

dropdown

No

select type

single BOTH

No No

display Hierarchy

false

false/true

No

Incorporating Pickers in JSP Clients

967

Parameter

Default Value

Possible values

Req?

Description dropdown format for which it presents picker elements in hierarchy. Accepts String representation of Boolean value. If true - only instantiables will be displayed and for false both instantiables and non-instantiables will be displayed Accepts String representation of Boolean value. If true shows the seedTypes as I level elements. componentId is defined as 'APP_ID+.+ COMPONENT_NAME'. Valid APP_IDs are ProjectLink, Foundation, or PDMLink. This is used for mode = "SEARCH" to find the I level types from <Windchill>\codebase\ com\ptc\windchill\ enterprise\search\ server\Searchable Types.properties. Passing null will default to the Default A javaScript function that will be invoked to populate the selected element attributes in the target element. This is not applicable for dropdown.

showInstan tiable

false

false/true

No

showRoot

true

false/true

No

componentId

Foundation. allSearch

No

pickerCallBack

typePicker Populate Target Element

No

968

Windchill Customization Guide

Parameter pickedData Fetcher

Default Possible values Value netmarkets/ jsp/ typepicker/ type Picker_data Fetcher.jsp

Req? No

Description A jsp file which is invoked in the AJAX call to fetch attributes of the picked elements. The file should be located in the <Windchill>/codebase and relative path is the value to be provided. Its not applicable for dropdown.

Configuring Type Picker that will be launched as a dropdown or table/ tree popup menu Type Picker in Drop Down forma
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <p:pickerParam name="format" value="dropdown" /> </p:typePicker>

Type Picker in table format


< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <p:pickerParam name="format" value="table" /> </pr:typePicker>

Type Picker in tree format


< p:typePicker id="typePickerTest" label="Type : " <p:pickerParam name="format" value="tree" /> </p:typePicker> mode="SEARCH" >

Configuring Type Picker with your filter criteria Filtering via filterType parameter
< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <p:pickerParam name="seedType" value="wt.doc.WTDocument" /> <p:pickerParam name="filterType" value="com.ptc.ReferenceDocument" /> </p:typePicker>

Filtering via properties defined in wt.properties. The properties are to be defined in <Windchill>/codebase/wt.properties.xconf and propagated to wt.properties file via xconfmanager. Property wt.typepicker excludede Description wt.typepicker excludedelimiter Example wt.typepicker exclude

Incorporating Pickers in JSP Clients

969

Property limiter

Description =<delimiter string> This defines the delimiter to be used for wt. typepicker exclude property and the default value is , wt.typepicker exclude/<mode>/ <root type>=< delimited list of external string representation of type identifier> mode should be one of the value defined in com.ptc. core .ui.resources. ComponentMode If no mode identifier is specified, then its assumed that the property is applicable to all mode. Multiple values are to be separated by wt.typepicker excludede limiterproperty

Example delimiter=;

wt.typepicker exclude/<mode>/ <root type>

wt.typepicker exclude/CREATE/ wt.doc. WTDocument= WCTYPE|wt. doc.WTDocument |org.r_and_ d.Agenda wt.typepicker exclude/wt.doc .WTDocument =WCTYPE|wt.doc. WTDocument|org .r_and_d. Meeting

wt.typepicker exclude/<mode>/

Excludes the listed types and all their modeled and soft subtypes from the Type Picker if the root type matches the provided seedType. wt.typepicker wt.typepicker exclude/<mode> exclude/CREATE/

970

Windchill Customization Guide

Property <container type>

Description /<container type> =<delimited list of external string representation of type identifier> mode should be one of the value defined in com.ptc. core. ui.resources .ComponentMode

Example wt.pdmlink. PDMLinkProduct =WCTYPE|wt. doc.WTDocument| org.r_ and_d.Agenda

wt.typepicker exclude/wt. pdmlink.PDMLink Product =WCTYPE| wt.doc. If no mode identiWTDocument fier is specified, then |org.r_and_d its assumed that the .General property is applicable to all mode. Multiple values are to be separated by wt.typepicker excludede limiter property Excludes the listed types and all their modeled and soft subtypes from the Type Picker if the container type matches the provided containerRef. The exclusion types extracted from the properties would be aggregated. The result of above illustrated examples would mean that Agenda, Plan and General and their sub types would be filtered out when the rootType is WTDocument and container being PDMLinkProduct and the operation is CREATE. For all other operations, only Meeting and General and their sub types would be filtered out. Configuring Type Picker with your root/base root/base types
< p:typePicker id="typePickerTest" label="Type : " mode="CREATE" > <p:pickerParam name="seedType" value="wt.part.WTPart" /> </picker:typePicker>

Incorporating Pickers in JSP Clients

971

Configuring Type Picker with or without non-instantiable non-instantiable


< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <p:pickerParam name="seedType" value="wt.part.WTPart" /> <p:pickerParam name="showInstantiable" value="true" /> </p:typePicker>

Configuring Type Picker with your picker call back function


< p:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <p:pickerParam name="seedType" value="wt.part.WTPart" /> <p:pickerParam name="pickerCallBack" value="myCallBack" /> </p:typePicker>

Points to be taken care while authoring your pickerCallBack This javaScript function will be invoked to populate the selected element attributes in the target element. User supplied function should be available in the page where Type Picker is inserted. pickerCallBack function signature is "call_back_function(JSON_Object, Picker_Id, Field_Id)" e.g
function mycallBack(JSONObjects, pickerId, targetId) { var elements = JSONObjects.pickedObjects; var targetElement = document.getElementById(targetId); //update Target Element if ((targetElement.type == "text") || (targetElement.type == "hidden")) { -------}else { -------} //update hidden field var valueElement = document.getElementById(pickerId); ----return true; }

Configuring Type Picker with your picker data fetcher


< picker:typePicker id="typePickerTest" label="Type : " mode="SEARCH" > <picker:pickerParam name="seedType" value="wt.part.WTPart" /> <picker:pickerParam name="pickedDataFetcher" value="myfolder/myDataFetcher.jsp" /> </picker:typePicker>

972

Windchill Customization Guide

Points to be taken care while authoring your pickedDataFetcher The response of the pickedDataFetcher should contain <DIV> tag with id same as the Type-Picker id. The content inside the <DIV> tag is extracted and evaluated to create JSON objects. An example of a typical response will be
<DIV id=Type_Picker_Id > {"pickedObjects": [ {"type" : "Part" , "theType" : "wt.part.WTPart "}, {"type" : "Document" , "theType" : "wt.doc.WTDocument} ] } </DIV>

Accessing the Selected/Populated Selected/Populated Information from Type Picker If you supply GUIComponent (via field) and RenderingContext (via renderContext) for Target Element and If GUIComponent Id is not set; Type Picker CC will set it to Type Picker Id If RenderingContexts ContextString not set, Type Picker wont set it. You supply GUIComponent and NO RenderingContext for Target Element Type-Picker uses a default RenderingContext, whos ContextString wont be set. You supply NO GUIComponent and NO RenderingContext for Target Element Type-Picker creates appropriate GUIComponent and will set Type Picker s Id to it. DropDown format If you want to access the selected value in the page (after submitting the page), the
HTML_NAME_OF_TARGET_ELEMENT = RenderingContext.getContextString ()+"___" + GUIComponent.getId() + GuiComponentUtil.COMBO_BOX;

If you want to access the selected value in the Command, you can get a hold of it through the NmCommandBean
HashMap comboBox_hmap = commandBean.getChangedComboBox(); Object comboBox = comboBox_hmap.get(GUIComponent_Id);

Table/Tree Popup Format If you want to access the target element (TextBox or ComboBox) in the page, the TEXTBOX
HTML_NAME_OF_TARGET_ELEMENT = RenderingContext.getContextString

Incorporating Pickers in JSP Clients

973

()+"___" + GUIComponent.getId() + GuiComponentUtil.TEXT_BOX;

COMBOBOX
HTML_NAME_OF_TARGET_ELEMENT = RenderingContext.getContextString ()+"___" + GUIComponent.getId() + GuiComponentUtil.COMBO_BOX;

The selected values are stored in an input hidden element in the page, with the selections separated by a delimiter (,) If you want to access the selected value in the Command, you can get a hold of it through the NmCommandBean.
String selected_value = cb.getTextParameter(Type_Picker_Id);

974

Windchill Customization Guide

Configuring a User Picker


Objective
You want to add a user picker to a custom UI and need to configure the picker to: search only for objects of certain type(s) search only for objects in certain container(s) display certain search critieria input fields display certain attributes of the objects in the search results table

Background
The user picker is used when you have a requirement to select specific user(s) depending upon certain criteria and use them in your application. Typical use case could be that you may want to find parts which are created by certain user. In this case you can have a user picker and then through this you can select the user and pass it on to the search criteria to perform search for parts.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


It is assumed that your <MyPage>.jsp file in which you are putting tag includes /netmarkets/jsp/begin.jspf or /netmarkets/jsp/beginPopuf.jspf file and /netmarkets/jsp/end.jspf files.

Intended Outcome
You should see a text box and Find icon along with the specified label after using the tag for user picker. After clicking the Find icon, a user picker will be launched.

Incorporating Pickers in JSP Clients

975

On clicking the Find button you should see a user picker.

Solution
Use the User Picker Common Component in your JSP file to include User Picker in your application.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Basic development involving JSP, JavaScript, Custom taglibs The management of resource file customizations. Windchill xconfmanager concepts

Solution Elements
Element PickerAttributes.xml Type XML Description pickerAttributes.xml XML file You should use this file to customize the search criteria attributes for an object type for your picker. Runtime location: <WT_HOME>\codebase\

976

Windchill Customization Guide

Element

Type

Description pickerAttributes.xml

searchClientResource .java userPicker.tag

Resource bundle You should use this file to localize the file contents of the pickers. Custom JSP tag This file is contains the information about the supported parameters for this tag. Runtime location: <WT_HOME>\codebase\ WEBINF\tags\ userPicker.tag xconf properties You should specify component Id and file corresponding object types in this file and then run xconfmanager. Runtime location: <WT_HOME>\codebase\ com\ptc\windchill\ enterprise\search\ server\Searchable Types.properties.xconf You should specify custom pickerCallback function for picker in this file. Runtime location: <WT_HOME>\codebase\ netmarkets\jsp\search \custom.js

SearchableTypes .properties.Xconf

custom.js

JavaScript file

Procedure Including a User Picker in a jsp page


Configure basic user picker:
<tr> <wctags:userPicker id="userPickerId" /> </tr>

Incorporating Pickers in JSP Clients

977

Customization Points
Customization Points are listed in following tables: Parameter Default Value Id Possible values Anything that is unique in a page Req? Description No An ID is associated with every picker in the calling application. This ID has to be unique for all pickers, whether of different types or same type, in one page.The id should not contain "." (dot) in the name. componentId determines the attributes that should appear in search criteria panel of the given picker. Name of the customized callback function that a user would have to implement. Its recommended that you specify pickerCallback function in custom.js file Default value for textbox rendered by the picker. Default value of the hidden textbox associated with the picker. This attribute defines whether you want to have Find icon along with the textbox or not. This attribute defines whether the picker text box should be editable or not. You should specify this parameter with value as true when you want to launch picker from a table level action or inline.

componentId picker Search

Generated at runtime if user has not specified this parameter defaultValue (blank) defaultHidd enValue Editable (blank)

pickerCall back

No Any valid component id specified in picker Attributes.xml No Name of the callback function

Any values Any values

No No

True

true/false

No

readOnly PickerText Box Inline

False

true/false

No

False

true/false

No

978

Windchill Customization Guide

Parameter Default Value picked Attributes Name

Possible values Any comma separated list of valid attributes Any value Any attribute

Req? Description No This parameter contains a comma separated list of the attributes that a user wants a picker to fetch. This is applicable only if inline is true. Label of the picker. Name of the attribute that should be the displayed in the picker textbox after selecting result from the user picker Value of the containerRef in which a user wants to restrict the search. Additional where clause if you want to filter search results on some specific criteria regardless of user input. This where clause will just get ANDed with the internal where clause. Title of the window in which the picker is launched. URL of the data fetcher file that will be used by the AJAX call to process the selected results.

Label display Attribute

Context Picker Name

No No

containerRef (blank)

Any container No

baseWhere Clause

(blank)

Any valid I*E where clause query

No

pickerTitle

Contexts

Any value

No

pickedData Fetcher

pickerType

<WebApp>/ netmarkets/ jsp/search/ pickedData .jsp search

URL location of the fetcher file

No

search/picker

No

This parameter defines the picker type i.e. search picker or picker picker. In search picker, you will see search criteria in the picker and then you have to hit the search button to see the results however in case of

Incorporating Pickers in JSP Clients

979

Parameter Default Value

Possible values

Req? Description picker picker you will directly see the results table without any searchcriteria. This parameter defines the length of the picker text box. This parameter allows user to define custom view id for the picker search results table. This parameter is used to restrict the user search to active/deleted/active and deleted users only. This parameter is used to enable role drop down in user picker. If you want to use this parameter then you should specify the containerRef parameter from where the roles have to be fetched. This parameter is used to specify the extra attributes that are to be used for autosuggest. This parameter is used to enable auto suggest for the picker. This parameter is used to specify the min. character on which auto-suggest initiates if enabled Key for selecting suggestable class (e.g. ContextService PickerSuggestable) which in turn call query service.Key needs to be present in
Windchill Customization Guide

pickerText BoxLength searchResults ViewId showUser Type

25

Any numeric value

No

(blank)

Any valid view No id

ActiveOnly ActiveOnly DeletedOnly ActiveAndDel Etc true/false

No

showRoles

False

No

extraSuggest emaild Attributes

Any field user No wants to search on True/false No

showS uggestion suggestMin Chars

False

Integer values

No

suggest ServiceKey

Picker specific

No userPicker, partPicker etc.

980

Parameter Default Value

Possible values

Req? Description search-service.properties .xconf file.

Configuring User Picker with multi select option in results table


<wctags:userPicker id="userPickerId" multiSelect="true" />

Configuring baseWhereClause in User picker


<wctags:userPicker id="userPickerId" baseWhereClause="(name=demo*)" />

Configuring pickerCallback function in User picker


<wctags:userPicker id="userPickerId" pickerCallback="myPickerCallback" />

An exsmple of the myPickerCallback function:


function myPickerCallback(objects, pickerID) { var updateHiddenField = document.getElementById(pickerID); var updateDisplayField = document.getElementById(pickerID + "$label$"); var myJSONObjects = objects.pickedObject; for(var i=0; i< myJSONObjects.length;i++) { var oid = myJSONObjects[i].oid; // Here fullName is the displayAttribute requested var displayAttr = eval("myJSONObjects[i].fullName"); updateHiddenField.value=oid; updateDisplayField.value=displayAttr; } }

Incorporating Pickers in JSP Clients

981

Configuring a Participant Picker


Objective
Participant Picker gives you the ability to search for participants using a variety of search criteria and gives the ability to pick selective participants.

Background
The current way of picking of participants is limited to Users, Groups, and is not consistent across Windchill. The new Participant Picker Common Component gives consistent behavior across Windchill. Participant Picker gives you the ability to search Participants of type User, Group, and Organization. It provides a wide variety of search scope criteria using which you can narrow down the search.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Using in Windchill Client Architecture table: You should define a Windchill Client Architecture action, and point the action to a JSP page that has participant picker tag. Provide the required attributes action Class and action Method to the participant picker tag. Add the Windchill Client Architecture action you created to the desired Windchill Client Architecture table. When you click the action, it will launch the Participant Picker Wizard. Select desired participant and click OK. The Picker will invoke the action Method of the action Class that you have provided. In that method, you will consume or process the selected participant in a desired way. Using Participant Picker in combination with Property Picker: The assumption is that you know how to use the Property Picker. The action attribute of your Property Picker should point to the JSP page that has participant picker tag. The required attribute action Class should (empty) and action Method should be JavaScript:${pickerCallback}(). ${pickerCallback} is the pickerCallback JavaScript function that you supplied to Property Picker. After you select the desired participants and click OK in the wizard, your pickerCallback JavaScript function will be invoked with JSON object containing the picked participants.

Intended Outcome
The selected participants are either populated in Windchill Client Architecture table, or a populated in text box of Property Picker.

982

Windchill Customization Guide

Solution
Use the Participant Picker to search for participants, and add the selected participants to a Windchill Client Architecture table or text box in a Property Picker.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: How to add Windchill Client Architecture actions to a Windchill Client Architecture table, how to dynamically update the table with selected participants. How to configure a Property Picker, how to author JavaScript picker Callback functions.

Solution Elements
Element actionClass Type Tag Attribute Description Name of the action class that needs to be invoked for processing the selected Participants. Name of the action method that needs to be invoked for processing the selected Participants. This will determine whether the picker allows multiple selections ("multi"), or just a single select ("single"). Use this to set the default to any Participant type. The class com. ptc.core.components.beans. PrincipalBean has four string constants defined, which one can be pass to this attribute. The constants are ALL_PARTICIPANT, USER, GROUP and ORG. Use this to set the default Participant type specified in the tag attribute participantType as the only supported type. This takes value true/false. When set to true, it will restrict to single type specified as

actionMethod

Tag Attribute

select

Tag Attribute

participantType

Tag Attribute

singleParticipantType

Tag Attribute

Incorporating Pickers in JSP Clients

983

Element

Type

Description in the attribute participantType. When set to false or left unspecified, the picker supports participant types ALL_PARTICIPANT, USER, GROUP, ORG. This map contains key, value pairs of association to be displayed in association drop down list. Keys are Java String literals that are returned to the user upon selection of any association. Value is a localized string that is displayed in association drop down list. The association you desire to be pre selected in the dropdown should be passed in this attribute. The localized string for Display Label of the association. Set this to "true" to get email Textbox rendered. You can type any comma or space separated emails that you desire to invite. The List of Context in which you wants to perform Search In. This map contains key, value pairs of contexts to be displayed in Search In drop down list. Keys are Java String literals that represent oid of the Windchill object. Value is a localized string that is displayed in Search In drop down list. If this attribute is set to true when searching for users, only users with email addresses are returned. Default is false. Set this to false to prevent the recent participants TextBox from being rendered. Default is true. If this attribute is set to true when searching for users, only
Windchill Customization Guide

associationMap

Tag Attribute

defaultAssociation

Tag Attribute

associationLabel emailAllowed

Tag Attribute Tag Attribute

contextMap

Tag Attribute

filterEmail

Tag Attribute

recentAllowed

Tag Attribute

applicationContext Search

Tag Attribute

984

Element

Type

Description users within a specified application context will be returned. Default is false. The context you desire to be pre selected in the dropdown should be passed in this attribute. LDAP server's list is passed, to perform search. Default this attribute is not supplied. This map contains key, value pairs of contexts to be displayed in Service drop down list. Keys are Java String literals that represent the LDAP Server. Value is a localized string that is displayed in Service drop down list. Set this to true to search for internal groups. Default is false. Set this to true to bypass the restricted search scope set on the organization. Default is false. Set this to true to force the restricted search scope, despite how it is set on the organization. Default is false. Set this to true to add a filter on search to restrict search scope to the selected role. This option will only display when the type option is User. When true, this will provide a dropdown list of available roles in the search criteria. The roles will come from the passed in context.

defaultContext

Tag Attribute

serviceMap

Tag Attribute

includeInternal disableRestricted SearchScope enforceRestricted SearchScope

Tag Attribute Tag Attribute

Tag Attribute

showRoles

Tag Attribute

resourcePool

Tag Attribute

Default is false. This will provide the pool of principals to search. All access control rules will still apply.

Incorporating Pickers in JSP Clients

985

Element searchProfileGroups

Type Tag Attribute

Description Set this to true to search only profile groups in the system. Default is false. Set this to PrincipalBean.LDAP to search only disconnected principals in LDAP. Set this to PrincipalBean.DB to search only disconnected principals in the DB.

searchDisconnected Principals

Tag Attribute

title

Tag Attribute

Default is false. This will provide the title for the participant picker window. Default is Find Participant. This will determine whether or not the "Search In:" field shows up in the participant picker. Default is "true" to preserve existing functionality. This will set the help link for the picker, if nothing is provided it will default to the service.properties value for ParticipantPickerHelp This will filter the search results to only return objects that the current user has MODIFY permission on.

showSearchIn

Tag Attribute

helpSelectorKey

Tag Attribute

enforceModify Permission

Tag Attribute

986

Windchill Customization Guide

Procedure Making Association available in Participant Picker


You want to include association in the Participant Picker. You will need to supply the tag attributes associationMap, defaultAssociation and associationLabel to the Participant Picker tag. The second example in Sample Code on page 989 below describes code sample of how association can be added to the Participant Picker.

Procedure Participant Picker with Search in Context


You want to narrow down the search to different contexts. You will need to supply the tag attributes contextMap and defaultContext to the Participant Picker tag. The contexts can be Organization, Site, Product, Project, and Library.

Procedure Search for Participants in different LDAP


You want to search for Participants in a different LDAP. You will need to supply the tag attribute serviceMap. Configure your Windchill to support multiple LDAP servers. Each LDAP server will be identified by a name. The name of LDAP server has to be supplied as key, and a localized display label as value. When you supply the serviceMap, you will see a dropdown in the Participant Picker with label Service. The selected key is sent as service parameter to the Info*Engine tasks by the Participant Picker.

Procedure Making Email invitation available in Participant Picker


You want to add email invitation text box to the Participant Picker. You will need to set the tag attribute emailAllowed="true". The third example in the Sample Code on page 989 section below describes code sample of how get email invitation textbox in the Participant Picker.

Procedure Single select Participant Picker


You want to select only participant at a time. You will need to set the tag attribute select=single. This will render the Participant selection list as text box that can hold one value at a time.

Procedure Restrict to single Participant type search


You want to restrict the type of Participants to be searched to one. You will need to set the tag attribute singleParticipantType="true".

Incorporating Pickers in JSP Clients

987

988

Windchill Customization Guide

Sample Code
Sample JSP that contains a Participant Picker tag
After making entry for action to launch the Participant Picker, write a JSP with the same name as in action tag (e.g. participantPickerSample.jsp).
<%@ page import="com.ptc.windchill.enterprise.picker.principal.PrincipalBean"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <jca:participantPicker actionClass="com.ptc.netmarkets.principal.CustomPrincipalCommands" actionMethod="addPrincipal" participantType="<%= PrincipalBean.GROUP %>"> > </jca:participantPicker> -

This will render a basic participant picker as show below.

Incorporating Pickers in JSP Clients

989

You perform a search based on search criteria. Move desired participants to Participant List and click OK. The component invokes actionClass and actionMethod provided as attributes to the participant picker tag. You need to write actionMethod in the actionClass. Example code is given below.
public class CustomPrincipalCommands { public static FormResult addPrincipal(NmCommandBean cb) throws WTException { FormResult result = new FormResult(FormProcessingStatus.SUCCESS); result.setNextAction(FormResultAction.REFRESH_OPENER); String principals = cb.getTextParameter(PrincipalBean.PARAM_SELECTED_PRINCIPALS); if (principals == null) { result.setStatus(FormProcessingStatus.FAILURE); return result; } ArrayList<String> selectedPrincipals = new ArrayList<String>(); int start = 0; int pos = principals.indexOf("#", start); while (pos != -1) { String principal = principals.substring(start, pos); selectedPrincipals.add(principal); start = pos + 1; pos = principals.indexOf("#", start); } // Now process selectedPrincipals return result; } }

You should write a static method as actionMethod. It will take only one argument i. e., NmCommandBean. The selected participants are sent to this method as text parameters. With in the component these values are stored in hidden variable. The name of the hidden variable is defined as a static String in com.ptc.windchill. enterprise.picker.principal.PrincipalBean. To extract selected participants use PrincipalBean.PARAM_SELECTED_PRINCIPALS. This will return # separated DN (Distinguished Name).

990

Windchill Customization Guide

Adding Association
To add association in the Participant picker, you need to provide three attributes as highlighted in the following sample. The attribute associationMap takes LinkedHashMap. You supply the key, value pairs to this map. Keys are the java String literals. When user selects an association, this key String literal is passed back to the actionMethod as text Parameter. Values are localized string displayed in the dropdown list. Component uses LinkedHashMap to retain the order in which the key value pairs are added while displaying in the dropdown list.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ page import="java.util.LinkedHashMap"%> <%@ page import = "com.ptc.windchill.enterprise.picker.principal. PrincipalBean" %> <% LinkedHashMap associationMap = new LinkedHashMap(); associationMap.put("GUEST", "Guest"); associationMap.put("MEMBERS", "Members"); associationMap.put("PROJECT MANAGER", "Project Manager"); %> <c:set var="associationMap" value="<%= associationMap %>"/> <c:set var="participantType" value="<%= PrincipalBean.USER %>"/> <jca:participantPicker actionClass="com.ptc.netmarkets.principal.CustomPrincipalCommands" actionMethod="addPrincipal" participantType="${participantType}" emailAllowed="true" defaultAssociation="GUEST" associationMap="${associationMap}" associationLabel="Add to Role" > </jca:participantPicker>

The above code will render association dropdown as shown in the following figure.

In the above example, you are trying to add a role to the participant. You move the desired participants to Participants List, select a role from the association list and click OK. The actionMethod code will now look like this.
public class CustomPrincipalCommands { public static FormResult addPrincipal(NmCommandBean cb) throws WTException { FormResult result = new FormResult(FormProcessingStatus.SUCCESS);

Incorporating Pickers in JSP Clients

991

result.setNextAction(FormResultAction.REFRESH_OPENER); String principals = cb.getTextParameter(PrincipalBean.PARAM_SELECTED _PRINCIPALS); if (principals == null) { result.setStatus(FormProcessingStatus.FAILURE); return result; } ArrayList<String> selectedPrincipals = new ArrayList<String>(); int start = 0; int pos = principals.indexOf("#", start); while (pos != -1) { String principal = principals.substring(start, pos); selectedPrincipals.add(principal); start = pos + 1; pos = principals.indexOf("#", start); } String role = cb.getTextParameter(PrincipalBean.PARAM_ASSOCIATION); ArrayList result = NmRoleHelper.service.addUsersToRole(cb, role, selectedPrincipals); return result; } }

992

Windchill Customization Guide

You can extract the selected association from text parameter as highlighted in the above code.

Incorporating Pickers in JSP Clients

993

Adding Email subscription


The tag to get email subscription the code will look like this.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/components" prefix="jca"%> <%@ page import="java.util.LinkedHashMap"%> <%@ page import = "com.ptc.windchill.enterprise.picker.principal. PrincipalBean" %> <% LinkedHashMap associationMap = new LinkedHashMap(); associationMap.put("GUEST", "Guest"); associationMap.put("MEMBERS", "Members"); associationMap.put("PROJECT MANAGER", "Project Manager"); %> <c:set var="associationMap" value="<%= associationMap %>"/> <c:set var="participantType" value="<%= PrincipalBean.USER %>"/> <jca:participantPicker actionClass="com.ptc.netmarkets.principal.CustomPrincipalCommands" actionMethod="addPrincipal" participantType="${participantType}" emailAllowed="true" defaultAssociation="GUEST" associationMap="${associationMap}" associationLabel="Add to Role" > </jca:participantPicker>

The above code will render the email subscription field as shown in the following figure.

994

Windchill Customization Guide

Sample JSP to launch the Picker and send back the picker values to a Textbox.
You can use Property Picker tag to render a Textbox and Find button to launch Participant Picker. The Find button has to declared in actions.xml as described in the above sections. The Property Picker by default provides a JavaScript call back function that will be invoked by the picker to send back the picked values from any picker. Property Picker also has an ability to define custom JavaScript function that can be invoked by pickers. For example:
<p:propertyPicker label="${label}" field="${textbox}" action="participantPickerSample2" type="participantpicker"> <p:populate from="${displayAttribute}" to="${displayFieldId}"/> <p:populate from="oid" to="${id}" /> <p:pickerParam name="pickerId" value="${id}" /> <p:pickerParam name="objectType" value="wt.org.WTGroup"/> <p:pickerParam name="componentId" value="${componentId}"/> <p:pickerParam name="pickedDataFetcher" value="${pickedDataFetcher}" /> <p:pickerParam name="pickerCallback" value="${pickerCallBack}" /> <p:pickerParam name="containerRef" value="${containerRef}"/> <p:pickerParam name="baseWhereClause" value="${baseWhereClause}" /> <p:pickerParam name="pickerTitle" value="${pickerTitle}"/> <p:pickerParam name="multiSelect" value="${multiSelect}"/> </p:propertyPicker>

Coming back to the Participant Picker, one can get the callback JavaScript function name as request parameter, when Participant Picker is launched from Property Picker.
<c:set var="pickerCallback" value="<%=request.getParameter("pickerCallback")%>"/> <jca:participantPicker actionClass="" actionMethod="JavaScript:${pickerCallback}()" participantType="<%= PrincipalBean.GROUP %>" <jca:participantPicker>

We pass a blank string to the actionClass attribute of Participant Picker. The JavaScript call back function name that we got from the request parameter is appended to the string JavaScript: and passed as value to actionMethod. This string JavaScript: is used internally in the picker to identify, as PickerCallBack mechanism is needed. When user selects the desired participants and clicks OK, the values are sent back to the JavaScript function as JSON object (as defined in Property Picker). Examples of Usage in Windchill Code All locations are within \Windchill\codebase\netmarkets\jsp: \roleAccess\profile_addMembers.jsp \subscription\subscrPrincipalPicker.jsp \team\addUsersToRole.jsp

Incorporating Pickers in JSP Clients

995

\object\findParticipant.jsp \work\addUsersToRole.jsp (resourcePool) \principal\find_disconnected.jsp (searchDisconnectedPrincipals) \group\addProfileToList.jsp (enforceModifyPermission & searchProfileGroups) \user\addToAdmin.jsp (enforceRestrictedSearchScope) \agreements\findParticipant.jsp (disableRestrictedSearchScope)

996

Windchill Customization Guide

19
Configurable Links
Configurable Link Tables .......................................................................................... 998

997

Configurable Link Tables


Special link types, known as configurable links, are provided which can be used to configure and display additional relationship tables on document and part information pages. JSP files have been provided to allow sites to implement and display these configurable link tables. The tables then display in the navigation link menus on the information page. For more information, see the Type and Attribute Management chapter of the Windchill Business Administrator's Guide.

Configurable Links Example


An example has been provided out-of-the-box for each of the configurable link types, including tables for both the parent type and child type information pages. The following files are delivered for the example: %WT_HOME%/loadfiles/configurableLinks/ ConfigurableLinkExamples.xml

Note The load file loads both the link types and the association constraints.
%WT_HOME%/codebase/config/actions/ ConfigurableLinkExamples-actionmodels.xml %WT_HOME%/codebase/config/actions/ ConfigurableLinkExamples-actions.xml %WT_HOME%/codebase/com/ptc/windchill/enterprise/ object/configurableLinkExamplesResource.class

The file ties the registry of the Customize menu on information pages to the link type that is implemented for the table, the table header, and the action title. %WT_HOME%/codebase/com/ptc/windchill/enterprise/ ConfigurableLinkExamples.xconf %WT_HOME%/codebase/com/ptc/windchill/enterprise/ ConfigurableLinkExamples-wt.properties.xconf %WT_HOME%/codebase/com/ptc/windchill/enterprise/ ConfigurableLinkExamples-service.properties.xconf

998

Windchill Customization Guide

Caution It is recommended that you install this example on a test machine. Uninstalling the example requires manually deleting entries from some files. See Uninstalling the Configurable Links Example on page 999 for more information.

Installing the Configurable Links Example


Use the following procedure to install the configurable links example. 1. Open a windchill shell. 2. Enter the following command:
xconfmanager -i %WT_HOME%/codebase/com/ptc/windchill/enterprise/ConfigurableLinkExamples.xconf -p

3. Restart your method server. 4. Load the loadfile:


windchill wt.load.LoadFromFile -d %WT_HOME%/loadfiles/configurableLinks/ConfigurableLinkExamples.xml

Note The actionmodels.xml file overrides the Customize menu on information pages with the Configurable Link Examples menu on the end. If you have customized your third-level navigation menus, then these lists must match or your customizations will be overridden. As an alternative, you could add the Configurable Link third-level navigation to the actions entry for your info pages.

Uninstalling the Configurable Links Example


Use the following procedure to uninstall the configurable links example. This procedure involves manually editing the files that were loaded when the example was installed. 1. Open the %WT_HOME%/declarations.xconf file. 2. Remove the entry containing the string: "ConfigurableLinkExamples. xconf" 3. Save and close the %WT_HOME%/declarations.xconf file. 4. Open the %WT_HOME%/codebase/wt.properties file. 5. Remove the following entries from the file: config/actions/ConfigurableLinkExamples-actions. xml config/actions/ConfigurableLinkExamplesactionmodels.xml

Configurable Links

999

6. Save and close the %WT_HOME%/codebase/wt.properties file. 7. Restart the method server. The example has been uninstalled and the third-level navigation Configurable Link Examples will no longer display.

Customizing Configurable Link Tables


This section describes each of the components that went in to creating a Configurable Link Table and displaying it in the OOTB example. Customizing the configurable link tables are also covered here. Customization is described using the OOTB example as a reference. An important point to note is that the file extensions (Ex: .xml, .xconf) and the format within the files must be maintained. 1. Define Configurable Link types and valid relationships. The first step to customizing configurable link tables is to define the configurable link soft types and the relationship constraints for each link type. This is done in the ConfigurableLinkExamples.xml file. This file contains two sections: Configurable Link Soft Types: The first part defines the Configurable Link Soft Types. The name and description for each link type must be defined here. The name field defined on BeginTypeDefView is the Configurable Link Type and is what will be used to tie-in the registration of the display location of the table, the table header and the action title associated with the link type (see Creating labels for the table header and action title on page 1871). The BeginTypeDefView name, the PropertyValue description and a displayName must be defined with meaningful customized names to define a new Configurable Link Type. Configurable Link Valid Relationships: The second part of this file contains the relationship constraints for the configurable link soft types that have been defined - these are the valid relationships for each defined link type. Each constraint specifies the Role A and Role B objects to be associated with a specific link type. "Role A" is the object that constitutes the lefthand-side of the link, and "Role B" is the object that constitutes the righthand-side. The linkType is the BeginTypeDefView that is defined in the Configurable Link Soft Type definition. The roleAType and roleBType are the objects that take on the respective roles for the specific linkType.

2. Define Action Names for the Relationship Tables.

1000

Windchill Customization Guide

The next step is to set up a mechanism to display the relationship table corresponding to a configurable link. This is done by defining actions for each configurable link table. The file ConfigurableLinkExamplesactions.xml does this in the example provided. This file contains the action definitions for all configurable links in the OOTB example. In the UI, the table names (i.e., actions) are displayed in a sub-menu in the Customize menu on information pages. Clicking on an action will display a table that shows the relationship contained by that configurable link. The table can display the relationship either from the Role A side or from the Role B side, depending on how the action is set up. To display the relationship from the Role A side, the URL associated with the action must point to: /netmarkets/jsp/object/configurableLinkRoleATable. jsp To display the relationship from the Role B side, the URL associated with the action must point to: /netmarkets/jsp/object/configurableLinkRoleBTable. jsp

To define a new action, follow the syntax within the <action /action> fragment. The name field for the action can be set to any meaningful name. The value used for this field will be used as the key to provide the display name for this action in the rbinfo file (see Creating labels for the table header and action title on page 1871). After setting the name of this action, follow the rules above to define if this specific action will display the relationship table from the Role A or the Role B side. 3. Determining the location to display the actions. The actions created in step 2 above need to be defined in the appropriate area in order to display them. An action-model is used to provide this definition. In the OOTB example, the file ConfigurableLinkExamples-actionmodels.xml handles this aspect.

Configurable Links

1001

The relationship tables for configurable links should be defined in the in the
Customize menu on information pages. steps 3a and 3b describe how to create a model, and then display it. The end result is that the Customize menu on

information pages will have a new menu option. The menu option will be the actions that display the relationship tables for configurable links. a. Defining a model i. First, define the action model by giving it a name "configLinkExamples" in the OOTB example. The resourceBundle definition after the name is the location of the java file using annotations that contains the display names (see Creating labels for the table header and action title on page 1871). ii. Now that the name has been defined, a brief description can be provided. iii. Next, define all the actions (i.e., relationship tables) that are intedned to be displayed under this action model. In the example, all actions defined in step 2 are under this model. iv. Finally, the model as a whole needs to be placed in the in the Customize menu on information pages of objects that intend to display it. In this example, it is intended to be displayed from the part and document info pages. That is done by overriding the pre-existing definition for the Customize menu on information pages for these 2 objects, and this is described below. b. Displaying the model The model "third_level_nav_part" contains the list of Customize menu on information pages that is available for parts. OOTB, this model is defined in PartClient-actionmodels.xml, and the menu options are "general", "relatedItems", "changes", "history", and "collaboration". In order to add the newly created configLinkExamples model to the info page of a part, the "third_level_nav_part" definition has been overridden to include this new model as well. An important point to keep in mind is that performing this step will override any previous customizations to "third_level_nav_part". In order to retain any previous customizations, copy the definition of the model being overridden ("third_level_nav_part" in this case) as it exists on the system into the newly created actionmodels file ("ConfigurableLinkExamples-actionmodels.xml" in this case). Then add the newly defined model ("configLinkExamples" in this case) to the overridden model ("third_level_nav_part") using the "submodel" tag.

1002

Windchill Customization Guide

The same steps in step 3b would have to be followed to display the new menu option for configurable link tables in the in the Customize menu on information pages of any other object (Document is also provided in the OOTB example). 4. Creating labels for the table header and action title Labels are created using annotations in a java file. In the OOTB example, this is done in the configurableLinkExamplesResource.java file. This file ties the registration of the in the Customize menu on information pages to the link type that is implemented for the table, the table header and the action title. The tie-up for the link type is done in the moreurlinfo field. The value for this field has the configurableLinkType set to the value of the BeginTypeDefView name defined in Step 1. The display text for the action title is set by defining the respective values for the action names created in step 2. This file must be compiled, and the compiled (.class) version of this file must be placed in %WT_HOME%/codebase/com/ptc/windchill/enterprise/ object

Note For steps 5 through 8, the OOTB example code is located in files with the prefix ConfigurableLinkExamples, however you should make any customization changes by creating files with the ConfigurableLinkCustomizations file prefix. ConfigurableLinkCustomizations.xconf ConfigurableLinkCustomizations-wt.properties.xconf ConfigurableLinkCustomizations-service.properties.xconf

5. Registering the Relationship Tables with a Validator Once the actions have been defined, it is necessary to register each newly created action with the common validator in order to ensure that the logic behind the hide/display rules for the action title and relationship table work correctly. In the OOTB example, this is done in the ConfigurableLinkExamples-service.properties.xconf file. The source and target locations for this file are: Source: com/ptc/windchill/enterprise Target: %WT_HOME%/codebase/com/ptc/windchill/enterprise

Configurable Links

1003

Depending on the table being registered - Role A (parent) or Role B (child) (i. e., depending on the selector), the corresponding validator ConfigurableLinkParentTableActionValidator or ConfigurableLinkChildTableActionValidator should be used respectively as the serviceClass. 6. Registering the Relationship Tables with Table Titles In order to see Table Titles on your custom configurable link tables, you need to register each table with ConfigurableLinkDynamicUrlDelegate in ConfigurableLinkCustomizations-service.properties. xconf. In the OOTB example, this is done in the ConfigurableLinkExamples-service.properties.xconf file. 7. Registering the Relationship Tables with Table Views In order to use custom Table Views with your custom configurable link tables, you need to register each table with the appropriate table views class in ConfigurableLinkCustomizations-service.properties. xconf. If the base type of the configurable link is ConfigurableReferenceLink, then you would register your configurable link with ConfigurableReferenceLinkTableViews. Likewise links of base type ConfigurableDescribeLink should be registered to ConfigurableDescribeLinkTableViews and those with base types of ConfigurableMasterLink should be registered to ConfigurableMastersLinkTableViews. The selectors that are used should be the logical identifier defined for the configurable links, followed by either _childTable or _parentTable depending on if it is a Role A or Role B table. For example, CustomReferenceLink's selectors would be com.ptc. CustomReferenceLink_childTable and com.ptc. CustomReferenceLink_parentTable. In the OOTB example, this is done in the ConfigurableLinkExamples-service.properties.xconf file. 8. Registering the Relationship Tables with the Action Command Delegate This is a required step for all configurable link tables that have toolbar actions. In order to make the configurable link toolbar actions work properly, register every configurable link table with ConfigurableLinkTableToolbarActionCommandDelegate. Use the same selector from Step 7 (ex. com.ptc.

1004

Windchill Customization Guide

CustomReferenceLink_childTable). These entries should be made in ConfigurableLinkCustomizations-service.properties. conf. In the OOTB example, this is done in the ConfigurableLinkExamples-service.properties.xconf file. 9. Registering the actions and actionmodels files The next step is to add the newly created actions and actionmodels files (from steps 2 and 3 respectively) to the application wide list of actions/actionmodels files that are picked up by the actions service. This is done in the OOTB example by the ConfigurableLinkExamples-wt.properties.xconf file. An important point to keep in mind is that the newly created actions and actionmodels files (as part of the customization) now contain overrides to models that were originally defined OOTB. If this step of adding these new files is not performed, then the original definition of these models will be used by the application. In the OOTB example as described above, the "third_level_nav_part" model has been overridden to include the "configLinksExamples" submodel. It is important to perform Step 9 in such a way that these new files are added to the global definition after the OOTB definition. In this example, ConfigurableLinksExample-actionmodels.xml must be added after PartClient-actionmodels.xml and DocumentManagement-actionmodels.xml. This is because the OOTB example overrides the definition of the "third_level_nav_part" and "third_level_nav_doc" models. All the actions and actionmodels files are placed in wt.properties (step 10) and the last definition of a specific model is what will take effect. If the newly created actions and actionmodels files are removed from wt. properties, or are not registered as required here in Step 8, or placed before the OOTB model definitions, then the OOTB behavior will be observed for the specific Customize menu options on information pages. 10. Collecting the registration in Steps 5 through 9 together. For convenience in the installation process, the xconf settings (containing registrations such as those in steps 5 and 6) specific to a module are placed together in one file. In the OOTB example, this file is ConfigurableLinkExamples.xconf.

Configurable Links

1005

This file references the files created in steps 5 through 9 above and puts them together in one location for the xconfmanager to pick up and propagate the changes. The xconfmanager places all actions and actionmodels files in wt. properties, and this is used eventually by the action service. The above steps create a customized Configurable Link Table. In order to install this, follow the instructions under the Installing the Configurable Links Example on page 999.

Defining Access Control Policy Rules for Configurable Links


After defining a Configurable Link Soft Type based on ConfigurableMastersLink, the access control policy rules for the configurable link soft type must be defined or loaded so that the to grant the product or library or project team members the appropriate access rights. There are no OOTB access rules for ConfigurableMastersLink object or any of its soft types. Therefore, OOTB only the administrative users have the right to create these links. The access control policy rules for the ConfigurableMastersLink can be defined in one of the following three ways: 1. Use Policy Administration to add access policies for the ConfigurableMastersLink soft types. 2. Load the access control policy rules using the csvAccessRule tag in an XML load file. Following is an example of an access control policy rule that can be loaded via an XML file that will grant everyone permissions read, modify, create and delete ConfigurableMastersLink objects. More specific access control policy rules can be defined for soft types of ConfigurableMastersLink.
<csvAccessRule handler="wt.load.LoadUser.createAccessRule"> <csvuser/> <csvdomain>/System</csvdomain> <csvtypeId>wt.configurablelink.ConfigurableMastersLink</csvtype Id> <csvpermission>+</csvpermission> <csvprincipal>ALL</csvprincipal> <csvpermissionList>0/1/2/5</csvpermissionList> <csvstate/> </csvAccessRule>

3. Update the product and/or library container templates to include the access control policy rules for the ConfigurableMastersLink and/or its soft types. Any new products or libraries created with the updated templates will automatically load the access control policy rules. Following is an example of an access

1006

Windchill Customization Guide

control policy rule that can be added to a product or library templates that will grant the teamMembers permissions read, modify, create and delete ConfigurableMastersLink objects. More specific rules can be defined for soft types of ConfigurableMastersLink.
<AccessControlRule> <domainName>/Default</domainName> <externalTypeId>wt.configurablelink.ConfigurableMastersLink</ex ternalTypeId> <lifecycleState>ALL</lifecycleState> <WTPrincipalReference isInternal="true"> <groupName>teamMembers</groupName> <groupType>teamMembers</groupType> </WTPrincipalReference> <grantPermissionSet> <AccessPermissionSet> <permissionField name="READ"/> <permissionField name="MODIFY"/> <permissionField name="CREATE"/> <permissionField name="DELETE"/> </AccessPermissionSet> </grantPermissionSet> </AccessControlRule>

Configurable Links

1007

20
Customizing Online Help
Customizing Windchill Help Center Content ............................................................. 1011 Linking to Help Topics ............................................................................................ 1013 Uninstalling the Windchill LearningConnector .......................................................... 1016

This section explains how to customize Windchill online help. Customizers of online help should have advanced knowledge of HTML and JavaScript, and some familiarity with XML. Windchill solutions deliver online help in the Windchill Help Center. The Windchill Help Center is a cross-browser, DITA-based format that provides a three-pane window. The top pane contains buttons to select navigation features. The left pane is a tabbed view that contains the table of contents, the index, and a search form for navigating and searching the help system. Online help content appears in the right pane. The Windchill Help Center refers to a collection of topic files and their corresponding tables of contents and full-text search files. In the Windchill Help Center, the term topic refers to a single HTML file that is displayed in the right pane of the Windchill Help Center window. For more information about the Windchill Help Center features, see the home page of the Windchill Help Center. The default location of your Windchill Help Center is the <Windchill>/WHC/ directory, where <Windchill> is the Windchill installation directory.

1009

Caution When you customize online help, always work with a copy of the online help files. After you have ensured that your customizations work properly, you can copy your changes to the appropriate directory.

1010

Windchill Customization Guide

Customizing Windchill Help Center Content


This section describes how to edit online help topic content. To update topics in the Windchill Help Center, you must have the appropriate permissions to replace files on your server.

Modifying an Existing Topic


To modify the text of an existing topic, use a standard HTML editor or text editor. Modification of HTML content other than text is not recommended. Use the following steps to access, modify, and replace help topics. 1. Right click the topic you want to change in the table of contents of the Windchill Help Center. 2. Select Copy Link Location from the menu. 3. The portion of the Address (URL) after http://<server location>/Windchill-WHC/ contains the file name of the topic you want to edit. For example, for http://user.ptc.com/Windchill-WHC/ UserSetupPreferences.html#styler-id1.1.1.4.4.4.4.1 you would edit UserSetupPreferences.html (you can ignore the #styler-id1.1.1.4.4.4.4.1 part of the URL). 4. Navigate to the installed location of your Windchill Help Center and locate the zip file that contains the HTML help topics. By default, the installed location is <Windchill>/WHC/WEB-INF/volume, where <Windchill> is the Windchill installation directory. 5. Open the appropriate ZIP file for your locale, for example, wc_en.zip. 6. Extract all of the contents of the ZIP file to a temporary directory. 7. In your temporary directory, open the help topic in a standard HTML editor to modify the content. Modification of colors, headers, or other styles is not recommended. Be sure to maintain the same file name. 8. When you have finished and saved all of your modifications, select all of the Windchill Help Center content.

Customizing Online Help

1011

9. Create a new ZIP file with the same name as the original Windchill Help Center ZIP file. Be sure that the zip file has the same flat directory structure as the original zip file. 10. Replace the current Windchill Help Center ZIP file with your modified ZIP file.

1012

Windchill Customization Guide

Linking to Help Topics


This section explains how to link to topics in the Windchill Help Center (WHC) from common component user interfaces. The WHC is the repository for all help topics. The web app for the WHC is different than the web app for Windchill. URL Details The wt.whc.url property in the wt.properties file defines the URL to the WHC. The wt.help.HelpLinkHelper.createHelpHREF(String) API returns the correct fully qualified WHC URL.

How to Link to Help Topics


This section explains how to link to help topics in the WHC from the Windchill UI. Information Pages The help button ( ) will appear in the upper right corner of the information page if you set a help context in your info builder:
// sets the help topic to use from the Windchill Help Center infoConfig.setHelpContext("HelpTopicName");

Table/Tree Table/Tree The help button ( ) will appear in the upper right corner of the table/tree if you set a help context in your builder:
// sets the help topic to use from the Windchill Help Center tableConfig.setHelpContext("HelpTopicName");

If your table/tree is still defined in a jsp instead of with a builder, adding the help topic would be as follows:
<renderTable model="${tableModel}" helpContext=" HelpTopicName"/>

Wizards The help button ( ) will appear in the upper right corner of the wizard if you specify a help selector key in the wizard tag:
<jca:wizard helpSelectorKey="HelpTopicName" >

Customizing Online Help

1013

Other Pages If you are not using a common component but would like to produce a link to the WHC in your UI, you can use the helpButton tag in a jsp to output a button on the page:
<%@taglib uri="http://www.ptc.com/windchill/taglib/wrappers" <w:helpButton helpSelectorKey="HelpTopicName"/> prefix="w" %>

This results in a help button (

) in the UI.

If for some reason the helpButton tag cannot be used for a particular UI, you can get a URL to a help topic with the HelpLinkHelper.createHREF (String) API. For example, wt.help.HelpLinkHelper.createHelpHREF ("HelpTopicName") will return a URL to the given help topic in the WHC in the following form form: <value from wt.whc.url property in wt. properties>/HelpTopicName.html. For example: http://<localhost>/Windchill-WHC/ HelpTopicName.html If any xconf entry exists overriding HelpTopicName with some other topic, then that URL would be returned instead. SeeCustomization Points on page 1014. For launching that URL you could use the javascript API: PTC.help. openHelpWindow(helpUrl); This would launch the help topic in a popup window, and on subsequent clicks of the help link would refocus that same help window instead of launching a new one.

Customization Points
To override an out of the box info page help topic, you can replace the content of the HelpTopic.html file in the WHC. Or you can add a new CustomHelpTopic. html file in the WHC. Register your custom topic with an xconf entry such as:
<Resource context="default" name="wt.help.HelpTemplate"> <Option requestor="java.lang.Object" resource="CustomHelpTopic" selector="HelpTopic"/> </Resource>

For JCA components, there is no context object used for this lookup so the requestor should just be java.lang.Object. It may be difficult to figure out what selector should be used. You can enable debug logging for wt.help. HelpLinkHelper by setting log4j.logger.wt.help. HelpLinkHelper=DEBUG which will allow you to see what selector key is being used to get the help links for the UI. You will then see messages in the

1014

Windchill Customization Guide

method server log like createHelpHREF called with selector SomeSelector and requestor java.lang.Object. The HelpLinkHelper will find your custom topic. So for example if the UI had linked to http://<localhost>/Windchill-WHC/HelpTopicName.html, you can register your custom topic with the above xconf entry and the resulting link in the UI should be: http://<localhost>/Windchill-WHC/CustomHelpTopic.html This assumes the UI you are trying to customize was using the HelpLinkHelper.createHelpHREF(String) API to produce the link to the WHC. Changes from Previous Releases In past releases xconf entries were required to specify help topics. That is no longer the case forWindchill Release 10.x. The existing xconf entries will continue to work, but going forward you can add the help topic directly in your builder and skip the xconf entry. In general, only customizer s would need to add an xconf entry to override the OOTB help.

Customizing Online Help

1015

Uninstalling the Windchill LearningConnector


If for any reason you wish to uninstall the Windchill LearningConnector you can do so by removing the LearningConnector code from the Help Center. See the Windchill LearningConnector for more information on the Windchill LearningConnector. 1. Open the toolbar.js file located in <WT_HOME>\WHC\_templates\frame\javascript\ with a simple text editor. 2. The LearningConnector code starts on line 18 of the toolbar.js file. To remove it, delete the following block of code:
// LearningConnector var ptc_plms_precheck=(function(){var f="https://precisionlms.ptc.com/"; var g="";var h={},pause=true,plms_server_alive=true,tid=0;function pause_load(){pause=true}function resume_load(){pause=false}function getIframeDocument(a){return(a.contentDocument)?a.contentDocument:a. contentWindow.document}function getFrameTagByName(a,b){var c= a.getElementsByTagName("frame");if(c.length==0){return null}for(var i=0 ;i<c.length;i++){if(typeof(c[i].id)!="unknown"){if(c[i].id==b){return c[i]}}}var d=null;for(var i=0;i<c.length;i++){d=getFrameTagByName(getIframeDocument (c[i]),b);if(d!=null){break}}return d}var j={"header_en":"en_US","header_cn" :"zh_CN","header_cs":"zh_CN","header_tw":"zh_TW","header_fr":"fr_FR" ,"header_de":"de_DE","header_it":"it_IT","header_ja":"ja_JP","header_ko ":"ko_KR","header_es":"es_ES","header_ru":"ru_RU"};var l=["en_US"," zh_CN","zh_TW","fr_FR","de_DE","it_IT","ja_JP","ko_KR","es_ES", "ru_RU"];var m=" <a href='javascript:void(0);' onclick='parent.ptc_plms _precheck.tryAgain()'>";var n="</a>";var o={"en_US":"LearningConnector is unavailable."+m+"Try again"+n,"zh_CN":"LearningConnector \u4e0d\u53ef\u7528\u3002"+m+"\u8bf7\u91cd\u8bd5"+n,"zh_TW": "\u76ee\u524d\u7121\u6cd5\u63d0\u4f9b LearningConnector\u3002" +m+"\u518d\u8a66\u4e00\u6b21"+n,"fr_FR":"LearningConnector n'est pas disponible."+m+"Ressayez"+n,"de_DE":"LearningConnector ist nicht verfgbar."+m+"Versuchen Sie es erneut"+n,"it_IT":"LearningConnector non disponibile."+m+"Riprovare"+n,"ja_JP":"LearningConnector \u306f\u4f7f \u7528\u3067\u304d\u307e\u305b\u3093\u3002"+m+"\u518d\u5b9f\u884c"+n, "ko_KR":"LearningConnector\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\ uc2b5\ub2c8\ub2e4."+m+"\ub2e4\uc2dc \uc2dc\ub3c4\ud574 \uc8fc\uc2ed\ uc2dc\uc624"+n,"es_ES":"LearningConnector no est\u00e1 disponible."+m+ "Int\u00e9ntelo de nuevo"+n,"ru_RU":"LearningConnector \u043d\u0435\u0434 \u043e\u0441\u0442\u0443\u043f\u0435\u043d."+m+"\u043f\u043e\u043f\u0440 \u043e\u0431\u0443\u0439\u0442\u0435"+n};function detect_locale() {var a=getFrameTagByName(window.top.document,"bannerFrame");if(a) {var b=getIframeDocument(a);for(var k in j){if(b.getElementById(k)){return j[k]}}}var c=getFrameTagByName(window.top.document,"searchFrame"); if(c){var d=getIframeDocument(c).getElementsByName("locale");if(d){var e=d[0].value;for(var i in l){if(e==l[i]||e.toLowerCase()==l[i].toLowerCase()) {return l[i]}}}}return"en_US"}function addScriptLC(a,b){var c=a.getElementsBy TagName("head")[0];var d=a.createElement("script");d.src=b;c.appendChild (d)}function addBootstrapScript(){addScriptLC(document,f+"static/javascript/

1016

Windchill Customization Guide

learningconnector/bootstrap.helpcenter.nocache.js")}function showErrorMsg (a,b){if(a.getElementById("errLC")){return}var c=a.getElementsByTagName ("div");if(c.length==0){c=a.getElementsByTagName("h2")}if(c.length==0) {c=a.getElementsByTagName("iframe")}if(c.length==0){c=a.getElements ByTagName("p")}if(c.length){var d=a.createElement("div");d.innerHTML =b;d.id="errLC";d.style.background="#eee";d.style.border="1px solid #819fbc";d.style.color="#888";d.style.fontFamily="arial, verdana, sans-serif";d.style.fontSize="15px";d.style.fontWeight="bold"; d.style.padding="10px";(c[0].parentNode).insertBefore(d,c[0])}} function removeErrDiv(a){var b=a.getElementById("errLC");if(b) {(b.parentNode).removeChild(b)}}function sniff(b){if(tid) {clearInterval(tid);tid=0}plms_server_alive=true;var c=new Image();pause_load();c.onerror=function(a){ptc_plms_ bootstrap=undefined;plms_server_alive=false;resume_ load()};c.onabort=function(a){ptc_plms_bootstrap=undefined; resume_load()};c.onload=function(a){plms_server_alive=true; resume_load();if(b===false){return}if(typeof(ptc_plms_bootstrap) =="undefined"||ptc_plms_bootstrap==null){addBootstrapScript()} setTimeout(function(){if(window.ptc_plms_bootstrap&&typeof (ptc_plms_bootstrap.onload)=="function"){removeErrDiv(h._doc); h._tbar.ptc_plms_bootstrap=ptc_plms_bootstrap;ptc_plms_ bootstrap.bootstrap(h._win,h._doc)}},1000)};c.src=f+"static/images /blank.gif?"+new Date().getTime()}sniff(false);h.tryAgain=function() {sniff(true)};h.loadLC=function(a,b,c){if(tid){clearInterval(tid);tid=0} tid=setInterval(function(){if(pause){return}if(tid){clearInterval(tid); tid=0}if(plms_server_alive&&b.ptc_plms_bootstrap&&typeof(b.ptc_ plms_bootstrap.bootstrap)=="function"){b.ptc_plms_bootstrap.bootstrap (a,c)}else{h._win=a;h._tbar=b;h._doc=c;showErrorMsg(c,o[detect_locale()])}},1)}; document.write('<meta name="lc:property" content="com.ptc. fusion.learningconnector.product=windchill"/>'); document.write('<meta name="lc:property" content="com.ptc .fusion.learningconnector.version=10.0"/>'); document.write("<meta name='lc:property' content='com.ptc. fusion.learningconnector.plmsUrl="+f+g+"'/>"); document.write("<meta name='lc:property' content='com.ptc. fusion.learningconnector.bootstrap.home="+f+"static/javascript/ learningconnector/learningconnector.nocache.js'/>"); document.write('<meta name="lc:property" content="com.ptc. fusion.learningconnector.supportTab=true"/>'); document.write("<script src='"+f+"static/javascript /learningconnector/bootstrap.helpcenter.nocache.js'></script>"); return h}());

3. Save and close the toolbar.js file. 4. If you have any open instances of Windchill or the Windchill Help Center, close them and restart your browser. The changes will be visible after the restart.

Customizing Online Help

1017

21
Customizations in the Type Manager
Adding Columns to Types....................................................................................... 1020

1019

Adding Columns to Types


Standard attributes are soft attributes that can only store zero or one value for an attribute. The values of these attributes are stored in one or more modeled columns in the table associated with the class. A class must be explicitly modeled to include these flex columns in order for this feature to be available. The columns will be added through annotations. The following column datatypes are supported: String Long Double Boolean Timestamp ObjectReference InlineBLOB

Note For general information on creating new attributes through the Type Manager, see the online help topic Creating a New Attribute.
Add Column Utilities There are two tools provided, AddColumns and AddStandardColumnsToAllTypes, that can programmatically add columns to type(s) to be used for storing standard attributes. These tools will generate the *TypeInfo.java and *TypeInterface.java source files for the specified type(s). They then compile those source files to generate the corresponding _*TypeInfo.java and _*TypeInterface.java parent source files and class files. The tools also update the database schema to reflect the new columns. This section contains two examples using the AddColumns tool and one example of the AddStandardColumnsToAllTypes tool. The first example describes the process for defining the initial allocation of columns for a type. The second example explains how to allocate additional columns if the first set of columns becomes insufficient. The third example explains how to allocate an additional ten columns of each datatype for all types in the installation.

Note There is a limit of thirty-six objectreference columns.


Windchill Customization Guide

1020

To see the usage details for the AddColumns tool, execute the following command from a Windchill shell:
C:\<WT_HOME>\Windchill>AddColumns Usage: AddColumns [-a] type_name datatype=number {datatype=number} [directory] AddColumns -u -a This option causes the tool only to add columns to the specified type class without upgrading database schema. type_name The type full name to add columns. datatype The column datatype. The legal values are: String, Long, Double, Boolean, Timestamp, ObjectReference, InlineBLOB. number The quantity of column to add. directory The directory to store generate type column java files. This argument is optional. Without this argument, those generated java files are stored into $(wt.temp)\src. -u This argument causes the tool only to upgrade database schema. -d This is the deploy mode to add columns to the specified type class. Example Usage: AddColumns wt.part.WTPart String=3 Long=4 Double=1 Z:\Windchill\src This example adds 3 String columns, 4 Long columns and 1 Double columns to WTPart type's database schema. The generated WTPartTypeInterface.java an WTPartTypeInfo.java are stored into Z:\Windchill\src. Customer added columns report D:\Windchill\installer\ext\AddColumns.txt is generated or updated.

Customizations in the Type Manager

1021

Example 1 : Allocating the Initial Columns for a Type, 10 of Each Datatype


This example details how to add additional columns to a given type for the first time. The example below will add ten columns of each datatype (String, Long, Double, Boolean, Timestamp, ObjectReference and InlineBLOB) to the WTPart type. This example is only used to the type which has not been enabled to add column. The following Example 2 and Example 3 should be used to add additional columns for most types since they already have been enabled to add columns. 1. From a Windchill shell run the following command (the expected console output is also shown):
D:\<WT_HOME>\Windchill>AddColumns a wt.part.WTPart String=10 Long=10 Double=10 Boolean=10 Timestamp=10 ObjectReference=10 InlineBLOB=10 D:\<WT_HOME>\Windchill\src Annotation processing round 1 complete -- 2 file(s) generated. Annotation processing generation COMPLETE. ALL ERRORS BEYOND THIS POINT ARE REAL!!! Attribute columns are added to wt.part.WTPart successfully. Annotated source files: WTPartTypeInfo.java, WTPartTypeInterface. java are generated at D:\<WT_HOME>\Windchill\src. Customer added columns report D:\Windchill\installer\ext\AddColumns.txt is generated or updated.

The WTPartTypeInfo.java and WTPartTypeInterface.java class files are generated at the location you specified on the above command line. The location for generated code is optional. If you dont specify the location, the code will be stored in the <WT_HOME>\temp\src directory. In this case, they are stored in the Foundation modules src directory.
package wt.part; import wt.part.WTPartTypeInfo; import com.ptc.windchill.annotations.metadata.*; @GenAsUnPersistable( properties={ @GeneratedProperty(name="typeInfoWTPart", type=WTPartTypeInfo.class, initialValue="new WTPartTypeInfo()", accessors=@PropertyAccessors(setExceptions={}), constraints=@PropertyConstraints(required=true)) }) public interface WTPartTypeInterface extends _WTPartTypeInterface{ }

This is the generated code for WTPartTypeInterface.java:


package wt.part;

1022

Windchill Customization Guide

import import import import import import import import

java.lang.Boolean; java.lang.Double; java.lang.Long; java.lang.String; java.sql.Timestamp; wt.fc.ObjectReference; wt.util.WTException; com.ptc.windchill.annotations.metadata.*;

@GenAsObjectMappable( serializable=Serialization.EXTERNALIZABLE_BASIC, properties={ @GeneratedProperty(name="ptc_str_1", type=String.class), @GeneratedProperty(name="ptc_str_2", type=String.class), @GeneratedProperty(name="ptc_str_3", type=String.class), @GeneratedProperty(name="ptc_str_4", type=String.class), @GeneratedProperty(name="ptc_str_5", type=String.class), @GeneratedProperty(name="ptc_str_6", type=String.class), @GeneratedProperty(name="ptc_str_7", type=String.class), @GeneratedProperty(name="ptc_str_8", type=String.class), @GeneratedProperty(name="ptc_str_9", type=String.class), @GeneratedProperty(name="ptc_str_10", type=String.class), @GeneratedProperty(name="ptc_lng_1", type=Long.class), @GeneratedProperty(name="ptc_lng_2", type=Long.class), @GeneratedProperty(name="ptc_lng_3", type=Long.class), @GeneratedProperty(name="ptc_lng_4", type=Long.class), @GeneratedProperty(name="ptc_lng_5", type=Long.class), @GeneratedProperty(name="ptc_lng_6", type=Long.class), @GeneratedProperty(name="ptc_lng_7", type=Long.class), @GeneratedProperty(name="ptc_lng_8", type=Long.class), @GeneratedProperty(name="ptc_lng_9", type=Long.class), @GeneratedProperty(name="ptc_lng_10", type=Long.class), @GeneratedProperty(name="ptc_dbl_1", type=Double.class), @GeneratedProperty(name="ptc_dbl_2", type=Double.class), @GeneratedProperty(name="ptc_dbl_3", type=Double.class), @GeneratedProperty(name="ptc_dbl_4", type=Double.class), @GeneratedProperty(name="ptc_dbl_5", type=Double.class), @GeneratedProperty(name="ptc_dbl_6", type=Double.class), @GeneratedProperty(name="ptc_dbl_7", type=Double.class), @GeneratedProperty(name="ptc_dbl_8", type=Double.class), @GeneratedProperty(name="ptc_dbl_9", type=Double.class), @GeneratedProperty(name="ptc_dbl_10", type=Double.class), @GeneratedProperty(name="ptc_bln_1", type=Boolean.class), @GeneratedProperty(name="ptc_bln_2", type=Boolean.class), @GeneratedProperty(name="ptc_bln_3", type=Boolean.class), @GeneratedProperty(name="ptc_bln_4", type=Boolean.class), @GeneratedProperty(name="ptc_bln_5", type=Boolean.class), @GeneratedProperty(name="ptc_bln_6", type=Boolean.class), @GeneratedProperty(name="ptc_bln_7", type=Boolean.class), @GeneratedProperty(name="ptc_bln_8", type=Boolean.class), @GeneratedProperty(name="ptc_bln_9", type=Boolean.class), @GeneratedProperty(name="ptc_bln_10", type=Boolean.class), @GeneratedProperty(name="ptc_tms_1", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_2", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_3", type=Timestamp.class),

Customizations in the Type Manager

1023

@GeneratedProperty(name="ptc_tms_4", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_5", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_6", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_7", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_8", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_9", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_10", type=Timestamp.class), @GeneratedProperty(name="ptc_ref_1", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_2", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_3", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_4", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_5", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_6", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_7", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_8", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_9", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_10", type=ObjectReference.class), @GeneratedProperty(name="ptc_rht_1", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_2", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_3", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_4", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_5", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_6", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_7", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_8", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_9", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_10", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)) }) public class WTPartTypeInfo extends _WTPartTypeInfo { static final long' serialVersionUID = 1; public static WTPartTypeInfo newWTPartTypeInfo() throws WTException { WTPartTypeInfo instance = new WTPartTypeInfo(); instance.initialize(); return instance; }

1024

Windchill Customization Guide

protected void initialize() throws WTException { } }

2. Manually add the WTPartTypeInterface.class as an interface in the annotatation code of the WTPart.java source file:
@GenAsPersistable(superClass=RevisionControlled.class, interfaces={..., WTPartTypeInterface.class} WTPartTypeInterface.class

3. Rebuild the src variant of the Foundation module by running:


ant clobber ant all

4. From a Windchill shell, run the following command (the expected console output is also shown):
D:\<WT_HOME>\Windchill>AddColumns u Updating database schema... be patient.

The Upgrade Schema window will display.

The Upgrade Schema window disappears when the process is finished. Once the AddColumns tool is finished, the following artifacts will be available:

Customizations in the Type Manager

1025

The console shows the following message: Database schema is updated. An upgrade_tool.log file is created in the directory from which the command was run. WTParts database schema is now updated to include ten columns of each datatype: String, Long, Double, Boolean, Timestamp, ObjectReference and InlineBLOB.

5. Reboot the Method Server to make the new added columns available for the standard attribute.

1026

Windchill Customization Guide

Example 2 : Allocating Additional Columns for a Type


This example details how to add additional columns for a type. You would need to do this if all of the initially allocated columns for a given type are in use and additional columns are required. The example below will add five additional columns for a subset of the available datatypes (String, Long, Double) to the WTPart type. 1. From a Windchill shell, run the following command (the expected console output is also shown):
D:\<WT_HOME>\Windchill>AddColumns D:\<WT_HOME>\Windchill> wt.part.WTPart String=5 Long=5 Double=5 Annotation processing round 1 complete -- 2 file(s) generated. Annotation processing generation COMPLETE. ALL ERRORS BEYOND THIS POINT ARE REAL!!! Attribute columns are added to wt.part.WTPart successfully. Annotated source files: WTPartTypeInfo.java, WTPartTypeInterface. java are generated at D:\Windchill_installation\Windchill\temp\src\wt\part. Customer added columns report D:\Windchill\installer\ext\AddColumns.txt is generated or updated. Updating database schema... be patient.

2. The Upgrade Schema window will display.

Customizations in the Type Manager

1027

The Upgrade Schema window disappears when the process is finished. Once the AddColumns tool is finished, the following artifacts will be available: The console shows the following message: Database schema is updated. An upgrade_tool.log file is created in the directory from which the command was run. WTParts database schema is now updated to include five additional columns of each of the following datatypes: String, Long, Double. The WTPartTypeInfo.java and WTPartTypeInterface.java class files are generated at the location you specified on the above command line. The location for generated code is optional. If you dont specify the location, the code will be stored in the <WT_HOME>\temp\src directory. In this case, the default location is used.

This is the generated code for WTPartTypeInterface.java:


package wt.part; import wt.part.WTPartTypeInfo; import com.ptc.windchill.annotations.metadata.*; @GenAsUnPersistable( properties={ @GeneratedProperty(name="typeInfoWTPart", type=WTPartTypeInfo.class, initialValue="new WTPartTypeInfo()", accessors=@PropertyAccessors(setExceptions={}), constraints= @PropertyConstraints(required=true)) }) public interface WTPartTypeInterface extends _WTPartTypeInterface{ }

This is the generated code for WTPartTypeInfo.java:


package wt.part; import import import import import import import import java.lang.Boolean; java.lang.Double; java.lang.Long; java.lang.String; java.sql.Timestamp; wt.fc.ObjectReference; wt.util.WTException; com.ptc.windchill.annotations.metadata.*;

@GenAsObjectMappable( serializable=Serialization.EXTERNALIZABLE_BASIC, properties={ @GeneratedProperty(name="ptc_str_1", type=String.class), @GeneratedProperty(name="ptc_str_2", type=String.class), @GeneratedProperty(name="ptc_str_3", type=String.class), @GeneratedProperty(name="ptc_str_4", type=String.class),

1028

Windchill Customization Guide

@GeneratedProperty(name="ptc_str_5", type=String.class), @GeneratedProperty(name="ptc_str_6", type=String.class), @GeneratedProperty(name="ptc_str_7", type=String.class), @GeneratedProperty(name="ptc_str_8", type=String.class), @GeneratedProperty(name="ptc_str_9", type=String.class), @GeneratedProperty(name="ptc_str_10", type=String.class), @GeneratedProperty(name="ptc_str_11", type=String.class), @GeneratedProperty(name="ptc_str_12", type=String.class), @GeneratedProperty(name="ptc_str_13", type=String.class), @GeneratedProperty(name="ptc_str_14", type=String.class), @GeneratedProperty(name="ptc_str_15", type=String.class), @GeneratedProperty(name="ptc_lng_1", type=Long.class), @GeneratedProperty(name="ptc_lng_2", type=Long.class), @GeneratedProperty(name="ptc_lng_3", type=Long.class), @GeneratedProperty(name="ptc_lng_4", type=Long.class), @GeneratedProperty(name="ptc_lng_5", type=Long.class), @GeneratedProperty(name="ptc_lng_6", type=Long.class), @GeneratedProperty(name="ptc_lng_7", type=Long.class), @GeneratedProperty(name="ptc_lng_8", type=Long.class), @GeneratedProperty(name="ptc_lng_9", type=Long.class), @GeneratedProperty(name="ptc_lng_10", type=Long.class), @GeneratedProperty(name="ptc_lng_11", type=Long.class), @GeneratedProperty(name="ptc_lng_12", type=Long.class), @GeneratedProperty(name="ptc_lng_13", type=Long.class), @GeneratedProperty(name="ptc_lng_14", type=Long.class), @GeneratedProperty(name="ptc_lng_15", type=Long.class), @GeneratedProperty(name="ptc_dbl_1", type=Double.class), @GeneratedProperty(name="ptc_dbl_2", type=Double.class), @GeneratedProperty(name="ptc_dbl_3", type=Double.class), @GeneratedProperty(name="ptc_dbl_4", type=Double.class), @GeneratedProperty(name="ptc_dbl_5", type=Double.class), @GeneratedProperty(name="ptc_dbl_6", type=Double.class), @GeneratedProperty(name="ptc_dbl_7", type=Double.class), @GeneratedProperty(name="ptc_dbl_8", type=Double.class), @GeneratedProperty(name="ptc_dbl_9", type=Double.class), @GeneratedProperty(name="ptc_dbl_10", type=Double.class), @GeneratedProperty(name="ptc_dbl_11", type=Double.class), @GeneratedProperty(name="ptc_dbl_12", type=Double.class), @GeneratedProperty(name="ptc_dbl_13", type=Double.class), @GeneratedProperty(name="ptc_dbl_14", type=Double.class), @GeneratedProperty(name="ptc_dbl_15", type=Double.class), @GeneratedProperty(name="ptc_bln_1", type=Boolean.class), @GeneratedProperty(name="ptc_bln_2", type=Boolean.class), @GeneratedProperty(name="ptc_bln_3", type=Boolean.class), @GeneratedProperty(name="ptc_bln_4", type=Boolean.class), @GeneratedProperty(name="ptc_bln_5", type=Boolean.class), @GeneratedProperty(name="ptc_bln_6", type=Boolean.class), @GeneratedProperty(name="ptc_bln_7", type=Boolean.class), @GeneratedProperty(name="ptc_bln_8", type=Boolean.class), @GeneratedProperty(name="ptc_bln_9", type=Boolean.class), @GeneratedProperty(name="ptc_bln_10", type=Boolean.class), @GeneratedProperty(name="ptc_tms_1", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_2", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_3", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_4", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_5", type=Timestamp.class),

Customizations in the Type Manager

1029

@GeneratedProperty(name="ptc_tms_6", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_7", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_8", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_9", type=Timestamp.class), @GeneratedProperty(name="ptc_tms_10", type=Timestamp.class), @GeneratedProperty(name="ptc_ref_1", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_2", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_3", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_4", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_5", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_6", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_7", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_8", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_9", type=ObjectReference.class), @GeneratedProperty(name="ptc_ref_10", type=ObjectReference.class), @GeneratedProperty(name="ptc_rht_1", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_2", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_3", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_4", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_5", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_6", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_7", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_8", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_9", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)), @GeneratedProperty(name="ptc_rht_10", type=String.class, columnProperties=@ColumnProperties(columnType=ColumnType. INLINE_BLOB)) }) public class WTPartTypeInfo extends _WTPartTypeInfo { static final long serialVersionUID = 1; public static WTPartTypeInfo newWTPartTypeInfo() throws WTException { WTPartTypeInfo instance = new WTPartTypeInfo(); instance.initialize(); return instance; } protected void initialize() throws WTException {

1030

Windchill Customization Guide

} }

3. Reboot the Method Server to make the new added columns available for the standard attribute.

Customizations in the Type Manager

1031

Example 3 : Allocating 10 Additional Columns of Each Datatype for all Types that Support Standard Attributes in an Installation
This example details how to add ten additional columns of each datatype to all types in an installation. 1. From a Windchill shell, run the following command:
windchill --jap=wt.properties?com.ptc.windchill.upgrade.tools. upgradeframework.java.args --cpp=wt.properties?com.ptc.windchill.upgrade .tools.classpath --javaargs="-Xmx1024m -XX:MaxPermSize=128m" com.ptc. core.lwc.server.AddStandardColumnsToAllTypes

The console output is similar to previous examples. 2. The Upgrade Schema window disappears when the process is finished. Once the AddColumns tool is finished, the following artifacts will be available: Ten additional columns of each datattype for all types that support standard attributes in your installation

3. Reboot the Method Server to make the new added columns available for the standard attribute.

1032

Windchill Customization Guide

22
Customizing Business Logic
Customizing a Bill of Materials ................................................................................ 1034 Context Builder Customization Example .................................................................. 1039

This chapter describes how to customize business logic.

1033

Customizing a Bill of Materials


A Bill of Materials (BOM) is a product structure report that identifies the items required to assemble a product. Currently, the BOM report includes only items from a part structure. Two types of BOMs are supported. A BOM Hierarchy report shows the quantity and unit attributes of the "usage" associations and visually indicates the hierarchical levels. A Parts List report is a list of all of the components (that is, parts that do not use other parts) in the part structure hierarchy. It uses information in the "usage" associations to determine the quantity of each component. Basically, it answers the question "When a part assembly is completely disassembled, what parts and how many of each do I have?".

Both of these reports are defined to be generated as an HTML page optimized for printing from a Web browser. Both the BOM generation and formatting can be customized as needed. A BOM report is generated using a template processor. The actual BOM information is generated entirely by Visitor objects. These objects are a means of specifying a "callback" operation for each node in a "tree" data structure. For example, a part structure contains Part objects linked together through the "uses" relationship. Starting from a top-level part, the entire part structure is traversed and a "visit" method is called on the Visitor object passing the current part object and the related usage information. This method can be overridden to provide customized BOM computation and formatting.

Customization
The remainder of this section describes an example of a BOM that is provided outof-the-box with Windchill. Understanding this example provides a basis for implementing other BOM customizations. There are two types of customization for a BOM. BOM computation refers to the work that is done on each item as the structure is traversed. Windchill provides two types of BOM computation: hierarchy and parts list. The second customization is for formatting the output that is displayed to the user. This formatting is dependent on the type of information displayed. The Hierarchy Visitor is an implementation that shows the quantity and unit attributes of the "usage" associations and visually indicates the hierarchical levels. The only computation that is required is to output this information. This class extends the TextOutputVisitor, which provides standard helper methods for outputting localizable messages to an output stream. In addition to providing the

1034

Windchill Customization Guide

implementation for the "visit" method, this class defines the customization points for altering the format of the output. These methods are designed to be called at various points as the output is being generated.
public abstract class BOMHierarchyVisitor extends TextOutputVisitor { // Define methods that should be overridden to allow for // formatting customization protected abstract void preVisitWrite( int a_level ); protected abstract void postVisitWrite( int a_level ); public void preNavigateWrite() { } public void postNavigateWrite() { } }

The visit method performs a basic output of the part identity and usage information. The preVisitWrite() and postVisitWrite() calls are significant because they allow for formatting customization.
public boolean visit( Persistable fromNode, Link link, Persistable toNode, int level, boolean previouslyVisited ) throws WTException { PrintWriter out = getPrintWriter(); preVisitWrite(level); String partIdentity = ((WTPart) toNode).getDisplayIdentity(); if(link == null) { out.print(partIdentity); } else { // Display part and usage information as a // localized message Quantity quantity = ((WTPartUsageLink) link).getQuantity(); Object[] params = { new Double(quantity.getAmount()), quantity.getUnit().getDisplay(), partIdentity }; printLocalizedMessage(partResource.PART_USAGE, params); } postVisitWrite(level); return true; }

The BOMHierarchyVisitor class is abstract and therefore cannot be used directly. The formatting must be customized by implementing the preVisitWrite() and postVisitWrite() methods in a descendant class. The following class is a customization example for use when the BOM is

Customizing Business Logic

1035

displayed in an HTML page. It displays the hierarchical level through HTML heading tags. The methods preVisitWrite() and postVisitWrite() wrap the part information in and tags where n is the level number.
public class HtmlHeadingHierarchyVisitor extends BOMHierarchyVisitor { protected void preVisitWrite( int a_level ) { PrintWriter out = getPrintWriter(); out.print("&lt;H"); out.print(a_level + 1); out.print('>'); protected void postVisitWrite( int a_level ) { PrintWriter out = getPrintWriter(); out.print("&lt;/H"); out.print(a_level + 1); out.print('>'); out.flush(); } }

After the customization is complete, you need only specify that the new customized class should be used when the BOM is generated. By default, the BOM template processors use the application services mechanism to instantiate a Visitor object that is used to generate the BOM. The service can be replaced by changing the appropriate entry in the services.properties file. Change the following entry in the file:
wt.services/svc/default/wt.part.BOMHierarchyVisitor/print/ wt.fc.WTObject/0=wt.part.HtmlNumberedHierarchyVisitor/duplicate

to:
wt.services/svc/default/wt.part.BOMHierarchyVisitor/print/ wt.fc.WTObject/0=wt.part.HtmlHeadingHierarchyVisitor/duplicate

Note the use of the "print" value in the "visitor" key in the service entry. Currently, the Windchill client code displays a BOM designed for printing within an HTML page and therefore uses the value "print". This key value is obtained from the URL parameters by the BOM template processor. If the client were customized to provide other types of BOM formats (by specifying different values in the URL), this key could be used for generating different formats. For example, an additional client function could be added for viewing a BOM with embedded graphics. A new value "graphic" could be used that is associated with a customized Visitor that will generate appropriate graphic output. Both types of formatting would then be available to the user.

1036

Windchill Customization Guide

Customizing Existing Reports


Soft attributes on parts are displayed in the BOM reports automatically using the table view, but soft attributes on part usage links cannot be displayed automatically. The soft attributes on the part usage link are shown in the list of available columns, but to get the actual value to display, the corresponding report configuration class needs to be extended to indicate the specific soft attributes from the part usage link to display. As an example, if a soft attribute "LinkName" was added to part usage link, the values of that attribute can be displayed in the Multi-level BOM Report by 1. Creating an extension of the MultiLevelBOMReportTreeBuilder class similar to the following
@ComponentBuilder("part.report.multiLevelBOM") public class MultiLevelBOMReportTreeBuilderCustomAtts extends MultiLevelBOMReportTreeBuilder { @Override public ComponentConfig buildComponentConfig(ComponentParams params) throws WTException { ComponentConfig tableConfig = super.buildComponentConfig(params); ComponentConfigFactory factory = getComponentConfigFactory(); String columnLabel = "Custom column name"; ColumnConfig col = factory.newColumnConfig("IBA|LinkName", columnLabel, true); col.setDataUtilityId("part.report.numberText"); col.setTargetObject("link"); tableConfig.addComponent(col); return tableConfig; } }

2. Register the custom ComponentBuilder in the %WT_HOME%/codebase/config/mvc/PartReport-configs.xml file Add the line
<bean class="custom.MultiLevelBOMReportTreeBuilderCustomAtts"/>

And remove the line


<bean class="com.ptc.windchill.enterprise.part.reports.mvc.builders. MultiLevelBOMReportTreeBuilder"/>

3. Set up a custom table view with that column as one of the selected columns.

Customizing Business Logic

1037

Current Implementation of Visitors


The information in this section is useful for understanding the implementation of the current out-of-the-box Visitors. The computation of the Parts List BOM (in BOMPartsListVisitor) uses two separate internal data structures to store information about the part structure as it is traversed. An assembly table keeps track of the current quantity and unit for each subassembly part as successive levels are encountered. A component table keeps track of the nonseparable parts (leaf nodes in the structure) that become the parts list. The assembly table information is maintained by multiplying the parent parts quantity and the current parts quantity. For example, if part A uses 3 of part B, which uses 5 of part C, then 15 of part C are required. The component table stores information for the actual parts that make up an assembly. This is used when generating the final report on the parts list. It is possible that a part can be used in separate branches in the part structure. In these cases, the quantity in each branch should be added. To continue the example, if part A uses 1 of part D, which uses 6 of part C, then the total number of part C for the entire part structure is 21 ((3 * 5) + (1 * 6)). A related issue is how to handle processing the quantities with respect to the quantity units. The following rules are applied: If the units are identical, the new unit is the current unit. If either unit is AS_NEEDED, the new unit is AS_NEEDED. If either unit is EACH, use the other unit.

Both the Hierarchy and Parts List Visitor objects are dependent on a depth first traversal of the part structure. The Hierarchy Visitor outputs the structure as it is traversed so the order in which part nodes are visited is significant. The Parts List computation relies on multiplying quantities between levels and storing the result internally. If a part were to appear in separate branches of a structure and depth first traversal were not used, then the computed quantity for a subassembly can be overwritten before its component parts use that information.

1038

Windchill Customization Guide

Context Builder Customization Example


Enabling the example To enable the Context Builder customization example: 1. Add the following entry to %WT_HOME%/declarations.xconf : <ConfigurationRef xlink:href="codebase/com/ptc/ windchill/enterprise/contextbuilder/ ContextBuilderCustom.xconf"/> 2. Save the change. 3. Exectue the following command: xconfmanager p 4. Restart the MethodServer. 5. Navigate to the Edit Definition tab, there will be two example Context Builder extension actions.

When the xconfmanager propagates the changes, an actions.xml file will be added to the list of actions.xml files read by the actions framework. The wt. properties property com.ptc.netmarkets.util.misc. defaultActions is the property that the actions framework reads to determine

Customizing Business Logic

1039

the set of available actions. The specific actions xml file that defines the custom action that can be exposed in the CAR Context Builder is %WT_HOME%/codebase/config/actions/contextbuildercustomactions.xml. There are four example actions in the contextbuildercustom-actions.xml file that show how multiple actions can be added to the CAR Context Builder. There are two actions exposed on the Rules tab toolbar and two actions exposed on the right click menu of the top level node of the tree. All entries look similar to this example:
<action name="editIncludeExcludeRulesGWT"> <command class= "com.ptc.windchill.enterprise.object.alternaterep.client.action.CustomFilterRuleAction" /> <url=Windchill/netmarkets/jsp/contexbuildercustom/customFilterRulesPopup.jsp </action>

The key to hooking into the Context Builder application is to use the com.ptc. windchill.enterprise.object.alternaterep.client.action. CustomFilterRuleAction as the command class. This takes care of appending the CB_CCID and CB_SEEDID query string parameters to the URL used to launch the custom application. It also makes some javascript APIs available to the custom application to take care of updating the checkboxes in the tree when the custom application has finished and is ready to create rules. The url of the action should be set to point to the resource that provides the custom functionality. In the example provided by PTC it points to a customFilterRulesPopup.jsp. When a Context Builder extension action is selected, a window will be launched and the resource pointed to by the URL will be loaded in it.

1040

Windchill Customization Guide

API s Available for Custom Filter Applications


Server side API available to navigate the Design Context Structure
public interface ContextBuilderInterface { public Collection<CBStructureNode> getChildrenFromCache(String collectorCacheID, Collection<String> seeds, HttpServletRequest request) throws InvalidCollectorCacheException, InvalidCollectorSeedException, CollectionException; }

The inputs to the API are: Collector Cache ID (String): This is the parameter passed to the custom filter application in the URL when the custom filter application is launched (CB_CCID parameter) Seeds/Collection of components to traverse (Collection of Strings) : For the first call, this should contain the id passed to the custom filter application in the URL when the custom filter application is launched (CB_SEEDID), for subsequent calls, the collection should contain the ids of the components returned from previous call that need to be traversed further to get to the CAD modules when all CAD modules are retrieved, then this API should not be called anymore. Request : As the customization may execute within the context of a separate web app, the HTTP request object needs to be passed in as input to the Context Builder API such that Windchill picks up the authenticated user, the user locale, HTTP session specific data, etc to establish the appropriate context for the execution of this API. If the request object is null, then it is assumed that no initialization of context is required. A collection of CBStructureNode : This object would contain a child component id (string), the child Persistable object, a link id (string), the link Persistable object (between parent and child), the parent id (string), a string representing the path of that component in the structure and its inclusion status

The output of this API is:

For each combination of child component id + path we would have a CBStructureNode object Exceptions may be thrown in the following situations: InvalidCollectorCacheException - collector cache id is no longer valid InvalidCollectorSeedException - seed object(s) passed are invalid (we cannot refresh them) CollectionException - collection exception

Customizing Business Logic

1041

These exceptions are extensions of WTException; therefore in any error case mentioned above localized error messages will be returned in them. The caller of this API should also be prepared to deal with runtime exceptions (db unavailable, etc). This API will not return items that are filtered by Expansion Criteria filters (those items are not displayed in the context builder tree and would not be available to this API). This API will return the link and child identifiers and Persistable objects. It is up to the invoker API to then use other services to acquire additional information about the object using other APIs (info engine or other Windchill supported APIs) if not available in the Persistable objects (for example, IBAs would not be available from the Persistable objects). This API will not return any information about the level of representation selected for each item in the structure. The identifier returned in the CBStructureNode object will be of the form: OR:<object class>:<number> Server Side API Available to Update the Context Builder Cache
public interface ContextBuilderInterface { public String addRulesToCache(String collectorCacheID, String seedId, List<CBPath> nodesToUpdate, HttpServletRequest request) throws WTException; }

The following are the inputs to this API: Collector Cache ID This is the parameter passed to the custom filter application in the URL when the custom filter application is launched (CB_CCID parameter) Seed ID This is the parameter passed to the custom filter application in the URL when the custom filter application is launched (CB_SEEDID parameter) List of CBPath items for which we should add new inclusion/exclusion rules this List should include the CBPath items that have been modified by user for items not modified, they should not be passed in. The reason why CBPaths are passed to this API instead of CBStructrueNodes is because, for creation of rules, only the information in CBPaths is required. To create an instance of a CBPath using the path identifier (that was given to the custom filter application in the CBStructureNode objects) and an inclusion value, please use the CBPathFactory.

Please note that instead of a Collection, a List is passed to this API if for some reason, the order of inclusions for paths is important, then it is up to the invoker of the API to pass the CBPaths in appropriate order for creation the order in which rules are created can potentially modify the end result of inclusions in the context.
Windchill Customization Guide

1042

In addition, it is up to the application to decide how to handle multiple paths to same component (if all should be set to same inclusion status or not). Request As the customization may execute within the context of a separate web app, the HTTP request object needs to be passed in as input to the Context Builder API such that Windchill picks up the authenticated user, the user locale, HTTP session specific data, etc to establish the appropriate context for the execution of this API. If the request object is null, then it is assumed that no initialization of context is required. On failure, an exception will be returned the exception will have a localized message with information about the failure. On success, this API will provide as output a string that has a token that is to be used by client Context Builder to refresh the screen after the custom filter UI is dismissed (the tree, visualization and rules panel would be updated accordingly).

As output, this API will:

This API will add rules for the paths passed in (according to the inclusion state passed in) at the bottom of the rules list of the associated context. For CARs, the representation will be set based on the preference value in the system. Client side API to Hand Over Control to Context Builder on Success of Custom Filtering On success of the custom filter application, the custom filter application should hand over control to the context builder and should request it to refresh itself. When called to refresh, the custom builder will close the custom filter application and should go to server (by using token passed by API defined in previous section) to get the data to be refreshed in the Context Builder application. After refresh is done, the modal mode should be dismissed in the Context Builder application and should be fully functional again for the user. The following API is available to the custom filter application to hand over control to the context builder application (this is a JavaScript API) opener.CB.refreshContextBuilderForCustomFilter(token); Where the input to this API is: Token This is the string returned by the addRulesToCache API defined in previous section this is a required input and the API will fail if no token is passed.

This API does not produce any output (void call).

Customizing Business Logic

1043

Client side API to Cancel Custom Filter When the custom filter window is closed, a JavaScript API should be called on the opener window (the Context Builder window) to reset the modal mode. This API should be invoked when a cancel button is pressed on the custom filter window or when the custom filter window is unloaded (closed by pressing the X button on the browser window). The API should be called in the following way:
opener.CB.closeCustomFilterWindow();

This API does not produce any output (void call).

1044

Windchill Customization Guide

23
Customizing Change Management
Association Constraints.......................................................................................... 1046 Customizing Multiple Inventory Dispositions ............................................................ 1050 Mass Change Operations....................................................................................... 1060 Mass Change Supported Types .............................................................................. 1067 Sponsored Problem Report and Variances .............................................................. 1071 Change Management Cardinality ............................................................................ 1074

This chapter describes how to customize change management.

1045

Association Constraints
This section explains how to create association constraints within change management. Background Association constraints can now be created for restricting the types of affected and resulting objects that can be associated to a change object. The association links for the affected and resulting objects are now typed which will allow for creating multiple soft types of the links. This means that a change object type X can be constrained for using a particular type of affected data, while a different change object type Y can be constrained using an entirely different soft-type link of affected data. By default, no constraints are defined against any of the change objects and their affected or resulting links. When no constraints are defined, all supported changeable objects can be associated to affected or resulting object tables. Association constraints might be used if you have multiple types of change objects for different purposes. For example a Publications Request is used for processing a change request for documents. In this case an association constraint could be created for the change request Publications Request and documents, that only allow users the ability to associate documents and no other objects to the affected objects of Publications Requests. All supported objects types in the affected objects table for the base type change request would still be allowed. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions Assumes you have used the type manager and created constraints. General Knowledge of the change objects and the role they play in the change process.

Intended Outcome The expected results of applying this solution will be that affected and resulting objects can be constrained to particular types for a specified change object type.

1046

Windchill Customization Guide

Solution
Use the Type Manager to constrain the types of objects that can be associated in the affected and resulting objects tables associated to the change object. Prerequisite Knowledge To perform this task, you must have an understanding of the following: Using the Type Manager and creating association constraints. Basic Knowledge of the change objects and the role they play in the change process.

The section below includes references to many or all of these subjects. Solution Elements Element wt.change2. ReportedAgainst wt.change2. RelevantRequest Data2

Type Link class Link class

Description The link class for associating affected objects on a Problem Report or Variance The link class for associating affected objects on a Change Request

Customizing Change Management

1047

Element wt.change2. AffectedActivity Data wt.change2. ChangeRecord2 wt.change2. HangingChangeLink StandardardChange Service

Type Link class Link class Link class Default change service

Description The link class for associating affected objects on a Change Task The link class for associating resulting objects on a Change Task The link class for associating hanging changes on the resulting objects of a Change Task The default implementation of the change service for creating, updating, deleting for change objects and associations. Package: wt.change2 A helper class for managing constraints within change. Package: wt.change2.constraints

ChangeMgmt ConstraintHelper

Helper class

When defining the association constraint the Change Object type is the driver for what relationship link is used. The ChangeService2.storeAssociations will derive the correct link type given the Change Object and the base link class and update the link to use the right type for the defined constraint.

Customization Points
The change wizard form delegates and processes will create the links automatically for the defined constraint link type. Typical use cases to customize the creation of the links may be due to adding additional attributes on the link or customized processing of change. When customizing the creation of the affected or resulting links the following order should be followed: 1. The new link object should be created. 2. Any attributes should be initialized with the default or user entered values 3. The change service store association service should be called. For details on the steps for creating new associations see the javadoc for StandardardChangeService.storeAssociations(ChangeItemIfc, WTCollection) and ChangeMgmtConstraintHelper. Prior to setting soft type attributes on a soft type link the type definition reference needs to be set. To set the type definition reference, see the javadoc

1048

Windchill Customization Guide

for ChangeMgmtConstraintHelper.getTypeDefinitionReference(Class, ChangeItemIfc).

Limitations
Only one constraint can be defined per Change Object and a relationship link. For example if a constraint is defined for a Problem Report base type and wt.change2. ReportedAgainst link then another constraint for the Problem Report base type and a soft type of wt.change2.ReportedAgainst link cannot be created. However, another constraint can be defined for a Problem Report soft type and wt. change2.ReportedAgainst or soft type link even though a constraint has already been defined for the Problem Report base type. It is very easy to define constraints which may severely limit the ability of users to be flexible in their associations to changes. Before establishing new constraints on the links, careful examination of the roles of the users in the change process should be conducted and the rules should be as open as possible (as opposed to as constrained as possible).

Customizing Change Management

1049

Customizing Multiple Inventory Dispositions


This section contains information on customizing Multiple Inventory Dispositions on the AffectedActivityData link. Background As of the Windchill 10.0 release, Multiple Inventory Dispositions on the AffectedActivityData Link shall be available OOTB. This document details steps on how to customize Multiple Inventory dispositions by; Adding new inventory disposition types Adding new inventory disposition values to be used by inventory disposition types Setting a default disposition value.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions The action to set inventory dispositions is exposed on the toolbar or on the actions menu drop-down of the Affected Objects table in the create/edit Change Task wizard. It is assumed that you have the ability to navigate to that table. New inventory disposition values can be added using Enumerated Type Customization utility (enumCustomize tool). It is assumed you have the basic knowledge on how to use the tool, if you are not familiar with the tool see The Enumerated Type Customization Utility on page 1323 for more information. Use the Enumerated Type Customization utility (enumCustomize tool) to introduce new inventory disposition values for use in the inventory disposition types Use the Enumerated Type Customization utility (enumCustomize tool) to specify a default inventory disposition value Use the Type Management utility to introduce new types of inventory dispositions.

Intended Outcome You shall be able to introduce new inventory disposition values You shall be able to specify a default inventory disposition value

1050

Windchill Customization Guide

You shall be able to introduce new types of inventory disposition types

Solution
Prerequisite Knowledge To apply this best practice, you need to have an understanding of the following: Basic knowledge of change management process The management of RBINFO files customizations
Management utility

Basic knowledge on how to use the new Windchill Release 10.0 Type Java Language

Solution Elements Element inventory DispositionRB .rbInfo

Type rbInfo

Description Contains the master list of inventory disposition values. Runtime location: \<Windchill>\src \wt\change2 Resource bundle for inventory disposition types Runtime location: \<Windchill>\ srclib\wnc\Change Management.jar Loader for AffectedActivityData Link. Contains OOTB dispositions and their values. Runtime location: \<Windchill>\ loadFiles\type\ DTD for disposition elements Runtime location: \<Windchill>\ loadXMLFiles

change2Client Resource.java

Class

AffectedActivity Data.xml

XML

standardX20.dtd

DTD

Customizing Change Management

1051

Element Coreobjects.dtd

Type DTD

Description The IXB DTD for disposition elements Runtime location: \<Windchill>\ codebase\registry \ixb\dtds \standardX20.dtd OOTB link class Runtime location: \<Windchill> \srclib\wnc\ Foundation.jar Default disposition handler. You will need to extend this handler or implement DispositionHandler Interface. Runtime location: \<Windchill> \srclib\wnc \Change Management.jar If not extending DefaultDispositionHandler, implement this interface. Runtime location: \<Windchill> \srclib\wnc \Change Management.jar Contain configurable views for affected items table Runtime location: \<Windchill> \srclib\wnc\ Change Management.jar

AffectedActivity Data.java

Java class

DefaultDisposit ionHandler.java

Class

Disposition Handler.java

Interface

ChangeTask AffectedItems TableViews .java

Class

1052

Windchill Customization Guide

Element Type AffectedItems Class TableBuilder.java

Description Builder for affected items table Runtime location: \<Windchill> \srclib\wnc \Change Management.jar Defines actions related to inventory dispositions Runtime location: \<Windchill> \codebase\config\ actions Sets the value of an inventory disposition type which is a column in the affected items table Runtime location: \<Windchill> \srclib\wnc \Change Management.jar Links the disposition handler with inventory disposition types Runtime location: \<Windchill> \codebase\ service. properties This is where to register the data utilities Runtime location: \<Windchill> \codebase\com\ptc \ core\components\ components.data Utilities
1053

ChangeManag XML ement-actions.xml

Disposition DataUtility.java

Class

Change Managementservice. properties .xconf

xconf

ChangeManagement- xconf components.data Utilities. properties .xconf

Customizing Change Management

Element

Type

ChangeManag XML ement-configs.xml

Description .properties This where the builder is registered so the MVC framework can find it. Runtime location: \<Windchill> \codebase\config \mvc

Customization Points
Introducing New Values for Use in the Disposition Types Out-of-the-box (OOTB) inventory disposition attribute values are fixed lists of values. If you want to customize an available OOTB disposition type by adding a new entry you must define an entry in the InventoryDispositionRB. rbinfo file. The InventoryDispositionRB.rbinfo file contains a fixed set of master lists of inventory disposition values. To add an entry in the InventoryDispositionRB.rbinfo file, use the enumCustomize tool to edit the file. See The Enumerated Type Customization Utility on page 1323 for more information. After you have customized the disposition type, use the Type and Attribute Management utility. On the Affected Activity Data Type , select the disposition attribute and edit the Enumerated Value List from the Constraints tab Specifying a Default Value for Disposition Use enumCustomize tool to select a default disposition value. See The Enumerated Type Customization Utility on page 1323 for more information. If the default disposition value is not added to the constraint set of an inventory disposition type, a blank shall be shown as the preselected value in the inventory disposition UI drop down

1054

Windchill Customization Guide

Adding New Disposition Types Inventory disposition types are enumerated columns that are added to the AffectedActivityData Link. There are inventory dispositions types that are added OOTB; customizers can add more inventory disposition types as soft attributes on the AffectedActivityData Link to meet their business needs by using the Type Manager. Here are the steps to follow 1. Extend AffectedItemsTableBuilder and Override getDispositionComponentIds API to account for your new inventory disposition types. Also, if you decide to extend ChangeTaskAffectedItemsTableViews as opposed to just changing it, then you will need to override buildConfigurationTable to return your new table views.
@ComponentBuilder("changeTask.affectedItemsTable") public class YourNewTableBuilder extends AffectedItemsTableBuilder { /** * Returns the list of supported disposition types. */@Override public List <String> getDispositionComponentIds() { } /** * Returns the configurable table. */@Override public ConfigurableTable buildConfigurableTable(String id) throws WTException { } }

2. Register your builder. The builder will be discovered dynamically by the MVC framework. In order for the framework to find your builder, you will need to register either the base package location of the builder or the builder class in the xml configuration file under the mvc package in the src_web variant. Here is an example for AffectedItemsTableBuilder as registered in ChangeManagementconfigs.xml. To register the base builder package. Add this to the xml configuration file:
<mvc:builder-scan base-package="com.ptc.windchill.enterprise. change2.mvc.builders"/>

Or register the builder class. Add this to the xml configuration file:
<bean class=" com.ptc.windchill.enterprise.change2.mvc.builders.tables. AffectedItemsTableBuilder "/>

3. The @ComponentBuilder annotation connects the builder with other components in the system such as JSPs. The string you put in the @ComponentBuilder(changeTask.affectedItemsTable )
Customizing Change Management 1055

annotation in the builder must be the same builder ID you include in the JSP. For example affectedItemsTable.jsp has the following to request the change task affected item component.
<jsp:include page="${mvc:getComponentURL('changeTask.affectedItemsTable')}"/>

4. Extend ChangeTaskAffectedItemsTableViews to add your new inventory disposition types to the link
public class YourTableViews extends ChangeTaskAffectedItemsTableViews { /** * Get the disposition columns */ @Override public List <?> getSpecialTableColumnsAttrDefinition(Locale locale) { } }

5. Extend DefaultDispositionHandler to get/set the values of your new inventory disposition types. At a minimum, you will need to override the APIs given below:
public class YourNewDispositionHandler extends DefaultDispositionHandler { /** * Get disposition value for a given disposition type. */ @Override public InventoryDisposition getDispositionValue(String componentId, BinaryLink link) { } /** * Set the disposition value for a given disposition type. */ @Override public boolean setDispositionValue(String componentId, BinaryLink link, InventoryDisposition disposition) throws WTException { } /** * Get the default disposition value for a given disposition type */ @Override public InventoryDisposition getDefaultInventoryDisposition( ChangeLinkAttributeBean linkBean, String component_id) { } /** * Get the disposition value set of a given disposition type */ @Override public ArrayList <InventoryDisposition> getInventoryDispositionSet

1056

Windchill Customization Guide

(ChangeLinkAttributeBean linkBean, String component_id) { } }

6. Register your new disposition handler in the service properties file (ChangeManagement-service.properties.xconf). The selector attribute is your new inventory disposition type and the serviceClass is your new disposition handler.
<! -- Handler for processing the disposition types --> <Service context="default" name="com.ptc.windchill.enterprise.change2. handler.DispositionHandler"><Option serviceClass="com.ptc. windchill.enterprise. change2.handler.YourNewDispositionHandler YourNewDispositionHandler" selector="YourNewDispositionType YourNewDispositionType" requestor="null" cardinality="duplicate"/> </Service>

7. Register your disposition types against DispositionDataUtility. You may also choose to extend DispositionDataUtility to meet your business need. The service property file to register the dispositions is ChangeManagement-components.dataUtilities.properties. xconf. For example:
<Option serviceClass="com.ptc.windchill.enterprise.change2. dataUtilities.DispositionDataUtility" requestor="java.lang.Object" selector="YourNewDisposition YourNewDisposition" cardinality="duplicate"/>

Customizing through the UI 1. As the site administrator, go to Type Manager and create a new soft attribute for AffectedActivityData Link, this is the inventory disposition type

Customizing Change Management

1057

2. Constrain the attribute to the new disposition values you created in Introducing New Values for Use in the Disposition Types on page 1054.

3. Now that we have configured multiple disposition types and values, it is time to create an instance of multiple dispositions on the AffectedActivityData link.

1058

Windchill Customization Guide

Create a change notice and update the default change task by going to Select Affected/Resulting Objects step Your new disposition type(s) should show as column(s) on the affected objects table The drop-down under your new disposition type (column) should show your new disposition values constrained to that type To change the disposition values for a disposition type, click Actions dropdown and select Set Dispositions

Customizing Change Management

1059

Mass Change Operations


You want to understand how to add or modify mass change operations. The expectation is that you will be able to add new Mass Change operations and extend processing of existing Mass Change operations. Background As a customizer you may want to add additional operations for use in the mass change wizard. For example to create a new operation for a custom association and/or object type. You also may want to extend existing mass change operations in order to insert additional processing validation. For example, to validate that the revisions are all at a RELEASED state prior to performing the Insert Existing Part operation. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions Performing this task assumes pre-existing knowledge of: Java Creating JSPs actions.xml Updating properties

Solution
Register filter delegates for processing new or existing operations. Create new actions, properties and JSP for new operations. Prerequisite Knowledge To apply this best practice, you need to have an understanding of the following: Basic development involving Java HTML forms, JSP, and XML. The actions framework in the Windchill client architecture The management of RBINFO file Xconfmanager, wt.poperties and service.properties.

Solution Elements Element Type com.ptc.windchill Class .enterprise.mass Change.filters. MassChangeFilter

Description A filter delegate is used for the mass change client to filter out objects selected by the user that are

1060

Windchill Customization Guide

Element Delegate

Type

config/actions/ MassChangeactions.xml service. properties

XML

properties

com.ptc. Class windchill. enterprise.mass Change .filters.Abstract DefaultFilter Delegate com.ptc.windchill Class .enterprise.mass Change.filters. AbstractWorkable FilterDelegate

Description ineligible for a specific mass change operation. Using the filtered list of eligible objects the filter delegate then creates, modifies, or deletes associations for the selected mass change operation. If an object is ineligible for the selected mass change operation, the ineligible object will not be processed Location for registering operations and associated filter delegates. Location for registering the associating delegates for processing mass change document relationships. This class is responsible for implementing functionality common for processing the selected mass change operations. Handles the command bean and server excluded items. This class is responsible for processing the selected mass change operation. Also contains common filter logic for excluding logic for objects that are not eligible for the mass change operation. Performs operations that are specific to Workable including handling checkout operations.
1061

Customizing Change Management

Element Type com.ptc.windchill Class .enterprise.mass Change.filters. AbstractPart UsageFilter Delegate com.ptc.windchill Class .enterprise. massChange. filters.Abstract DocumentLink FilterDelegate

com.ptc.windchill Class .enterprise.mass Change.filters. AddPartUsage FilterDelegate

com.ptc.windchill Class .enterprise.mass Change.filters. AddDocument LinkFilter Delegate

Description This delegate contains filter logic to exclude row objects from a mass change operation based on logic that is specific to WTPartUsageLink operations. This filter delegate determines whether the selected objects are eligible for the mass change operation on the selected document. The supported document types are wt. doc.WTDocument and wt.epm.EPMDocument. This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected parts. The delegate will filter invalid selected objects and creates new part usage links for any valid objects selected given the user specified part This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected document. The AssociationDelegate registered for the selected association type ("Referenced By", "Described By", or "Passive") which is used to filter or create the appropriate association links for the selected objects
Windchill Customization Guide

1062

Element

Type

com.ptc. windchill. enterprise.mass Change.filters. AddPart UsageFilter Delegate

Class

com.ptc.windchill Class .enterprise.mass Change.filters. ChangePartUsage FilterDelegate

com.ptc. windchill. enterprise.mass Change.filters. RemoveDocument LinkFilter Delegate

Class

Description and the selected document. The supported document types are wt. doc.WTDocument and wt.epm.EPMDocument. This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected parts. The delegate will filter invalid selected objects and creates new part usage links for any valid objects selected given the user specified part. This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected parts. The delegate filters out invalid objects selected prior to performing the operation. Valid objects associated to the user specified part will have their attributes updated. This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected document. The AssociationDelegate registered for the selected association type ("Referenced By", "Described By", or "Passive") which is used to filter or remove the appropriate association links
1063

Customizing Change Management

Element

Type

com.ptc.windchill Class .enterprise.mass Change.filters .RemovePart UsageFilter Delegate

com.ptc.windchill Class .enterprise .massChange .filters. ReplacePart Usage FilterDelegate

com.ptc.windchill Interface .enterprise .associations .Association Delegate

com.ptc.windchill Class

Description for the selected objects and the selected document. The supported document types are wt. doc.WTDocument and wt.epm.EPMDocument. This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected parts. The delegate will filter invalid selected objects and removes the part usage links for the valid selected objects based on the user specified part. This filter delegate determines whether the selected objects are eligible for the mass change operation for the selected parts. The delegate filters invalid selected objects or replaces the part usage links for the valid objects selected with the user specified replacement part. This delegate is used to determine the appropriate association link to create or to retrieve the appropriated associated objects. A specific delegate is selected based on the registered selector type registered in service. properties. Helper methods for

1064

Windchill Customization Guide

Element .enterprise. associations. Association DelegateHelper com.ptc.windchill .enterprise.mass Change. associations. DescribedByLink Assocation Delegate com.ptc.windchill .enterprise.mass Change. associations. ReferencedBy LinkAssociation Delegate com.ptc.windchill .enterprise.mass Change. associations .PassiveLink Association Delegate

Type

Description association delegates.

Class

This delegate is used for managing WTPartDescribeLink associations.

Class

This delegate is used for managing WTPartReferenceLink associations.

Class

This delegate is used for managing EPMDescribeLink associations.

Customization Points
Adding and Extending Operations The mass change client supports the ability to add new or extend existing operations to the client. The javadoc in the class MassChangeFilterDelegate has detailed instructions on how to do this. While the filter delegate handles the processing of the mass change operation, not all operations will be applicable for the selected object types. (For example a WTDocument is not valid for mass change operations handling part usage links.) In order to indicate which operations are supported for the selected objects validation is required. See the Mass Change Supported Types best practice for details.

Customizing Change Management

1065

Extending Specific Operations When processing the document operations Insert existing document or Remove related document there is a delegate that is used based on the relationship selected and the selected objects for the mass change. New delegates can be implemented to process relationships and/or selected objects. Currently the document relationships supported are Described By and Referenced By for Documents and Passive for CAD Documents. See javadoc in the AssociationDelegate and implementing classes for more details on the implementation and configuration.

Related Documentation
See Mass Change Supported Types on page 1067 for information on modifying the supported object types for a mass change operation.

1066

Windchill Customization Guide

Mass Change Supported Types


This section explains how to modify the supported object types for a mass change operation. The supported types for a mass change operation may need to be modified to include or exclude certain types of objects. For example the default supported type for the Insert Existing Part operation is to support all part object types. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This documentation assumes that you are familiar with updating property files. During this process you ill update the mass change operation properties in wt. properties with the supported or excluded object types. Prerequisite Knowledge To perform this operation, you must have an understanding of the following: xconfmanager wt.properties service.properties

Solution
Solution Elements Element wt.properties Type properties Description Location for registering the supported and excluded types Location for registering the validation supported types for operations. Validates that the operation has valid types of objects

service. properties

properties

com.ptc.windchill class .enterprise. massChange. validators. MassChange Operation Validator

Customizing Change Management

1067

Including and Excluding Types The mass change operations are controlled by properties for supported and excluded types for a specific operation. The supported and excluded types for selected target objects for the mass change operation can be registered against the mass change operation in wt.properties. To specify the supported types for a particular mass change operation the following name convention should be followed: supportedTypes Supported types: massChange.operationName.supportedTypes Excluded types: massChange.operationName.excludedTypes excludedTypes

To include or exclude an object type the external form of the type is used. For example, to include the root type Part in the string use WCTYPE|wt.part. WTPart. If no supported types are specified for a mass change operation then all selected objects are supported for the operation. It is recommended to specify at least one supported type due to multiple launch locations of the mass change wizard. Out-of-the-box, the validator MassChangeOperationValidator, is provided that can be used to leverage the supportedTypes and excludedTypes. This validator should be able to handle most cases in the field. The validator is used to present the user with the list of operations which are applicable based on the selected objects. Validating the items applicability beyond its type (for example not allowing mass change on checked-out items) should be handled within the Filter delegates (overriding the evaluate() or getServerExcludedItems() methods) see the Mass Change Operations on page 1060. Restricting the mass change operation to only certain types:

Note The following example uses the out of the box supported types for the Insert Existing Part operation (addPartUsage).
1. Using xconfmanager, add a property to wt.properties that specifies the supportedTypes. The output should look similar to the Insert Part Usage operation property.
massChange.addPartUsage.supportedTypes=WCTYPE|wt.part.WTPart

2. Register a validator using xconfmanager for the operation key in service. properties. Note that the selector is the operation with _filter appended to the end. As stated above, the MassChangeOperationValidator is designed to use the supportedTypes and excludedTypes property entries automatically.
wt.services/svc/default/com.ptc.core.ui.validation.UIComponentValidator

1068

Windchill Customization Guide

/addPartUsage_filter/null/0=com.ptc.windchill.enterprise.massChange. validators.MassChangeOperationValidator/duplicate

Identifying the Property to Update Use the following table identify the property that you must update for a specific operation. Property Name massChange. replacePart Usage. supportedTypes massChange. replacePart Usage.excluded Types massChange. addPartUsage .supportedTypes massChange. addPartUsage. excludedTypes massChange. removePartUsage .supportedTypes massChange. removePartUsage .excludedTypes massChange. changePartUsage .supportedTypes massChange. changePartUsage. excludedTypes massChange. addDocument Usage.supported Types massChange. addDocument Usage.excluded Types Description The supported types for the Replace ExExisting Part operation.

Used to exclude types for the Replace


Existing Part operation.

ExistThe supported types for the Insert Existing Part operation. ExUsed to exclude types for the Insert Existing Part operation.

The supported types for the Remove


Part Usage operation.

Used to exclude types for the Remove


Part Usage operation.

The supported types for the Edit Part


Usage operation.

Used to exclude types for the Edit Part


Usage operation. ExistThe supported types for the Insert Existing Document operation.

isting Document operation.

ExUsed to exclude types for the Insert Ex-

Customizing Change Management

1069

Property Name massChange. removeDocument Usage.supported Types massChange. removeDocument Usage.excluded Types

Description The supported types for the Remove ReRelated Document operation.

Related Document operation.

Used to exclude types for the Remove

Related Documentation
Mass Change Operations on page 1060

1070

Windchill Customization Guide

Sponsored Problem Report and Variances


An organization can extend change management process for Problem Reports and Variances to members of an external organization. To distinguish this problem reports and variances that are exposed outside the host organization from their regular counterparts that are not exposed, they are designated Sponsored. The host organization creates a project in ProjectLink to be used as a repository for these sponsored objects. Preferences There are two preferences that need to be enabled for Sponsored Problem Reports and Variances functionality; they are Sponsored Problem Report Process and Sponsored Variance Process. The preferences can be enabled at the site, organization, and/or container level (on the project). Both preferences are under the "Change Management" category. As a project creator or site administrator, use the preference manager to enable the preferences. Object Initialization Rule (OIR) The OIR defines rules by the objects type at the site, organization, and/or container levels. Such rules stipulate whether the server assigns an attributes value or it is entered by the user. For the Sponsored change objects, the attributes of interest include: Number Folder location Life cycle Team template

The OIR can be used to manage these attributes and when the rules are defined, careful consideration is needed so that rules defined for projects do not interfere with rules defined for products and libraries. Project Team Roles The Project manager should add Team Roles to the project team based on the roles needed by the Lifecycle and the Workflow Process Templates to be assigned to the sponsored changes. Change Administrator I role is needed for sponsored problem reports, Variance Approvers role is required if you intend to use sponsored variances. See the Windchill Business Administrator's Guide on how to add roles to the team.

Customizing Change Management

1071

Custom numbering schemes By default the number attribute is auto generated for change objects. This can be changed using object initialization rules for the Problem Report or Variance to allow the number to be manually entered or other configurations as supported by Windchill. See the Number Schemes Administrator for further details. Basic Access Policies for the Project These are the minimal policies OOTB that are required to successfully create, edit and view sponsored objects. Context Project Project Project Object Type WTChangeIssue WTChangeIssue WTChangeIssue State All All Open ParticiParticipant Project Creator Team members Team members PermisPermissions Full Control (All) Read, Download Create, Modify, Modify Content Full Control (All) Full Control (All) Read, Download Create, Modify, Modify Content Read, Download Full Control (All)

+ + +

Project

WTChangeIssue

All

Project Project Project

WTVariance All WTVariance All WTVariance Open

CHANGE ADMINISTRATOR I Project Creator Team Members Team Members

+ + +

Project Project

WTVariance Under Review WTVariance All

+ Variance Approvers CHANGE + ADMINISTRATOR I

Optional policies recommended for sponsored changes in projects: Context Project ObjectObjectType State All ParticiParticipant Organization PermisPermissions Full Control

1072

Windchill Customization Guide

Context

Project

Project

ObjectObjectState Type WTChangeIssue and WTVariance WTChanAll geIssue and WTVariance All WTChangeIssue and WTVariance

ParticiParticipant Administrator Guest +

PermisPermissions (All)

Read

Site Admin- + istrator

Full Control (All)

Project Folders By default the folder location is auto generated for change objects; when a new sponsored object is created, it should be saved in the root folder of the project.
Administration to change the default.

This default behavior can be changed. Use Object Initialization Rules

Project Template An organization can choose to configure suitable rules and policies that meet their business needs using a project template. See the Windchill Business Administrator's Guide for further details.

Customizing Change Management

1073

Change Management Cardinality


You can modify the cardinality or workflow closure rules for change requests from change orders or change issues from change requests. Background The cardinality of the AddressedBy link and the FormalizedBy link is driven by a delegate infrastructure. The default implementation for out-of-the-box change object types provided in Windchill 10.0 M20 or later is a delegate supporting 1-N, N-1, or N-M cardinality. The later is only applicable if the change object cardinality preferences are enabled. A new delegate is also available to support 1-1 cardinality. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions Assumes you have general knowledge about Java classes and concepts such as class extension Assumes you have general knowledge about the xconf mechanism to create properties.

Intended Outcome After reading this, you should know how to create custom cardinality rules for change requests and change orders, or change requests and change issues. Solution Solution: Create a custom class that extends a default delegate, and create an xconf entry to register your custom delegate. Prerequisite knowledge To apply this best practice, you need to have an understanding of the following: Java class extension Xconfmanager

Solution Elements Element Type wt.change2.ChangeCardi- Interface nalityDelegate wt.change2.DefaultAdLink class dressedByDelegate wt.change2. Link class

Description Generalizable Interface for cardinality rules Supports 1-1 ChangeRequest2 to ChangeOrder2 cardinality Supports 1-1
Windchill Customization Guide

1074

Element Type DefaultFormalizedByDelegate wt.change2. Link class AddressedByDelegate

wt.change2. FormalizedByDelegate

Link class

ChangeMgmt-service. properties.xconf

Default change service properties

Description ChangeRequest2 to ChangeIssue2 cardinality Supports 1-N, N-1 or NM (preference driven) WTChangeRequest2 to ChangeOrder2 cardinality Supports 1-N, N-1 or NM (preference driven) WTChangeRequest2 to ChangeIssue2 cardinality Property file which registers the above cardinality rules out-of-the-box.

Customization Points 1. If you want to customize the cardinality for the AddressedBy2 link, then you should create a new java class (your delegate) which extends the DefaultAddressedByDelegate or the AddressedByDelegate (depending on which existing functionality closest matches the behavior desired)
public class YourCustomAddresssedByDelegate extends DefaultAddressedByDelegate { /** * Determines if the change request is 'properly addressed'. Default implementation of * addressed by means that one change request can be addressed * by only one change notice and vice-versa. * @param ChangeIssue * @param ChangeRequest2 * @return void * @throws WTException - If the cardinality is invalid, a ChangeException2 should be thrown along with the reason why the cardinality is not valid. */ @Override public void validateCardinalityConstraints(ChangeRequest2 cr, ChangeOrder2 co) { //YOUR RULES IMPLEMENTED HERE } /** * Overriding this method will handle the closure of the ChangeRequest2 * object based on a delegate implementation. * Ultimately, the closure of the ChangeRequest2 will require the closure of all * associated ChangeOrder2 objects * which are registered against the same delegate. * * @param changeObjects * @param changeObjects

Customizing Change Management

1075

* @return */ @Override public boolean isReadyForResolution(ChangeRequest2 cr, Set<ChangeOrder2> objs) { //YOUR RULES IMPLEMENTED HERE return true; // if the change request is ready } }

2. If you want to customize the cardinality for the FormalizedBy link, then you should create a new java class (your delegate) which extends the DefaultFormalizedByDelegate or the FormalizedByDelegate (depending on which existing functionality closest matches the behavior desired)
public class YourCustomFormalizedByDelegate extends DefaultFormalizedByDelegate { /** * Determines if the change request is 'properly addressed'. Default implementation of * addressed by means that one change request can be addressed * by only one change notice and vice-versa. * @param ChangeIssue * @param ChangeRequest2 * @return void * @throws WTException- If the cardinality is invalid, a ChangeException2 should be thrown along with the reason why the cardinality is not valid. @Override */ public void validateCardinalityConstraints(ChangeRequest2 cr, ChangeOrder2 co) { //YOUR RULES IMPLEMENTED HERE } /** * Overriding this method will handle the closure of the ChangeRequest2 * object based on a delegate implementation. * Ultimately, the closure of the ChangeRequest2 will require the closure of all * associated ChangeOrder2 objects * which are registered against the same delegate. * * @param changeObjects * @return */ @Override public boolean isReadyForResolution(ChangeIssue ci, Set<ChangeRequest2> set) { //YOUR RULES IMPLEMENTED HERE } }

1076

Windchill Customization Guide

Note When defining this xconf configuration, it is important that the requestor (in this case the ext.change2.YourChangeRequest2) is not an abstract type, this is because the framework performs the lookup based on a concrete class name (and it does not support hierarchical lookup of types). The selector class, however, can be an abstract type. If you do not register your delegate, then the default Windchill implementation would be used instead of your delegate. This default implementation supports 1-N, N-1, N-N (if the change object cardinality preference is enabled). Modifying the cardinality of out of the box Windchill types: For example, if you wanted to apply 1-1 cardinality between the WTVariance and the WTChangeRequest2, you would have add the following properties to xconf configuration:
<Service context="default" name="wt.change2.ChangeCardinalityDelegate"> <Option requestor="wt.change2.WTChangeRequest2" cardinality="singleton" serviceClass="wt.change2.DefaultFormalizedByDelegate" selector="wt.change2.WTVariance"/> </Service>

Customizing Change Management

1077

24
Customizing Workflow Administration
Customizing Workflow HTML Templates .................................................................. 1081 Customizing Change Management Workflow Process Templates .............................. 1085 Customizing Promotion Request Workflow Processes .............................................. 1091 Enhanced Promotion Process ................................................................................ 1094 Customizing Workflow Events on an Object ............................................................. 1105 Customizing Workflow Task Pages.......................................................................... 1107 Refine and Review Workflow Transitions ..................................................................1115 Adding Custom Workflow Attribute to Workflow Processes........................................ 1122

This chapter describes how to customize workflow.

1079

1080

Windchill Customization Guide

Customizing Workflow HTML Templates


This section describes how to customize HTML templates for workflow activities. Following are possible ways you could use this capability: To change the layout of the standard workflow activity property pages to add customer logos and so forth. To add read-only displays of process variables. To integrate information (attributes, icon, associations, and so on) of the primary business object of the workflow. To display a summary of process variables, for example, the voting and comments of different reviewers as the basis for a promote decision.

The functionality to perform all of these customizations is available through existing Windchill scripts, as seen in the standard Windchill HTML client. As a result, you can make these customizations without programming Java (possibly only one resource bundle change), but only editing HTML and some entries in a Windchill properties file. For both an overview and detailed information about customizing HTML clients, see the Customizing HTML Clients Using the Windchill JSP Framework. This section discusses the HTML client only as it applies to workflow. To customize a workflow HTML template, perform the following steps: 1. Create a workflow activity that you want to be represented by the customized HTML page with the workflow administrator applet. The action argument of the activities property page URL is specified by the type of workflow task (see the following figure).

Customizing Workflow Administration

1081

For customizations, you can use the predefined HTML templates UserTask1. html through UserTask7.html, or create your own named templates, for example CustomTask.html. If you create your own task template, you must add an entry to the wt.properties file, as shown in the following example, to cause the new task to appear in the list of available tasks:
wt.clients.workflow.tasks.task.1=WfTask wt.clients.workflow.tasks.task.2=WfUpdateContent wt.clients.workflow.tasks.task.3=WfAugment wt.clients.workflow.tasks.task.4=review wt.clients.workflow.tasks.task.5=promote wt.clients.workflow.tasks.task.6=observe wt.clients.workflow.tasks.task.7=submit wt.clients.workflow.tasks.task.8=WfDefineProjects wt.clients.workflow.tasks.task.9=WfChgMgmt wt.clients.workflow.tasks.task.10=UserTask1 wt.clients.workflow.tasks.task.11=UserTask2 wt.clients.workflow.tasks.task.12=UserTask3 wt.clients.workflow.tasks.task.13=UserTask4 wt.clients.workflow.tasks.task.14=UserTask5 wt.clients.workflow.tasks.task.15=UserTask6 wt.clients.workflow.tasks.task.16=UserTask7

wt.clients. wt.clients.workflow. workflow.tasks. tasks.task.17=CustomTask task.17=CustomTask

The default behavior of workflow task processing recognizes these tasks by their template name, for example, CustomTask. If you want to change the display name of your task, you should add entries to the wt.clients.workflow. tasks.TasksRB.rbInfo file as follows:
CustomTask.value="Customized Task Name" CustomTask.constant=MYCUSTOMIZEDTASK

The string "Customized Task Name" is displayed in the drop-down list and must be localized. The string "CustomTask" is the value of the action argument in the URL requests of the HTML page for a workflow activity of that type. 2. Add or modify the appropriate entries in the service.properties and htmltemplate.properties files. If you add an entry in the resource bundle, you must add a line similar to the following in the service.properties file:
wt.services/svc/default/wt.enterprise.TemplateProcessor/ CustomTask/java.lang.Object/ 0=wt.workflow.worklist.WfTaskProcessor/ duplicate

You must also add a line similar to the following in the htmltemplate.properties file:
wt.services/rsc/default/wt.templateutil.DefaultHTMLTemplate/ CustomTask/java.lang.Object/0=

1082

Windchill Customization Guide

customizations.workflow.templates.CustomTask

3. Create or modify the HTML template file (customizations.workflow.templates. CustomTask). For examples, see the standard HTML template files listed in the htmltemplate.properties file. The Windchill scripts you can use are defined primarily by the wt.workflow.worklist.WFTaskProcessor and the wt.enterprise. BasicTemplateProcessor (see the Javadoc for further information). The following are examples of useful functionality from the more commonly used Windchill scripts: From wt.workflow.worklist.WFTaskProcessor: To print workflow variables, use the following scripts:
activityVariable variable=<Yourvariablename> rows=# columns=# processVariable variable=<Yourvariablename> rows=# columns=#

To print information about the Process, Activity, and PrimaryBusinessObject in the same page, use the following script:
setContextObject context=process | activity| primaryBusinessObject

This script does not print any HTML code but switches the ContextObject of the TemplateProcessor. This means the scripts that follow this script in the HTML page can generate information about the new ContextObject (for example, attribute names and values of the primaryBusinessObject or a table of associated objects). From wt.enterprise.BasicTemplateProcessor: To create a link to another dynamically generated page, use the following script (see the Javadoc for further information):
objectActionLink action="action" [label="label"] labelPropertyName="labelPropertyName" ]

To display the label and value of attributes of a Windchill object, enter the following scripts:
objectPropertyName propertyName="propertyName" objectPropertyValue propertyName="propertyName"

Attributes can be "name", "number", "checkoutInfo", "location", and so on. To display a subtemplate (for example, to display a usedBy-table), enter the following script:
processSubTemplate action="action" [SubTemplate depending name/value pairs]

Customizing Workflow Administration

1083

Most of the time you will have to add entries in the properties files to create new actions and new related HTML template files that hold only a part of an HTML page (for example, a single table).

1084

Windchill Customization Guide

Customizing Change Management Workflow Process Templates


Introduction
Synchronization robots are a critical part of the Change Management workflow process template examples. Originally, these robots were developed as pure expression robots. However, use of normal expression synchronization robots causes very heavy Oracle activity, resulting in frequent Oracle redo log turnover. At Release 5.1, therefore, these robots were updated to use object or class event synchronization in conjunction with an expression. These change affect only out-of-the-box example workflow process templates in loadfiles\ChangeManagement.csv. If you use these templates but have not customized them, simply delete the existing templates and load the modified ones. If you have customized the out-of-the-box workflow process templates, you should manually incorporate the changes, as described in the remainder of this section, into your customizations to take advantage of the improved performance. If your own expression synchronization robots are problematic, you should manually incorporate changes similar to those described in this section. Following are the Change Management workflow process templates that have been enhanced to improve system performance: Change Issue Process Change Request Process 2 Change Investigation Process Change Proposal Process Change Analysis Process Change Order Process Change Activity Process

Change Issue Process


Both of the existing robots in this template have been converted to object event synchronization robots, and a new robot of that type has also been added: Template Change Issue Process Change Issue Process Change Issue Process Robot Sync on Request Association Listen for Request Disassociation Sync on Request Complete

Customizing Workflow Administration

1085

The expression logic of change issue robots is illustrated in the following figure. The following table explains the details of this figure; the numbers in the table correspond to numbers in the figure. 1a) This conditional router checks if the change issue is already associated to a change request. If so, the workflow continues to the conditional at 3a; otherwise, it proceeds to the sync robot at 1b. 1b) The Sync on Request Association robot waits until the event ISSUE_FORMALIZED is emitted for the primaryBusinessObject (the change issue), signaling the change issue has been attached to a change request. The workflow then continues to the conditional at 2a and the conditional at 3a simultaneously. 2a) This conditional router checks if the 3a) This conditional router checks the change issue has been immediately state of the associated change request. If disassociated with the change request. If it is in state Completed, the workflow so, the workflow cycles back to 1a; continues to 3b (the end of the process). otherwise, it continues to the sync robot If it is in state Cancelled, the workflow at 2b. loops back to a point near the beginning of the process. Otherwise, the workflow continues to the sync robot at 3b. 2b) The Listen for Request 3b) The Sync on Request Complete Disassociation sync robot listens for the robot waits until the state of the event ISSUE_UNFORMALIZED on associated change request changes. If the primaryBusinessObject, signaling the state is Completed, the workflow the change issue has been disassociated continues to 3b (the end of the process). from its change request. This causes the If it is in state Cancelled, the workflow sync robot at 3b () to terminate, and loops back to a point near the beginning the workflow to loop back to the of the process. Otherwise, the sync conditional at 1a. robot continues to wait for one of those two states.

Sync on Change Request Submit


Each of the following robots has been converted to an object event synchronization robot as described below: Template Robot Change Investigation Process Sync on Request Submit Change Analysis Process Sync on Request Submit Change Proposal Process Sync on Request Submit Change Order Process Sync on Request Submit Change Activity Process Sync on Request Submit
Windchill Customization Guide

1086

Before Release 5.1, the expression logic performed the following actions: 1. Determine the parent change request by navigating one or two levels of associations based on the change object: For a change investigation or change proposal, navigate the ResearchedBy association. For a change order, navigate the AddressedBy2 association. For an analysis activity, first navigate the DetailedBy association to obtain a change investigation or change proposal, then navigate the ResearchedBy association. For a change activity, first navigate the IncludedIn2 association to obtain a change order, then navigate the AddressedBy2 association.

2. Determine the current life cycle state of the change request. 3. Determine the current value stored in the Complexity attribute (for Sync on Request Submit only). 4. Based on the results of step 2 and step 3, either continue holding or move on to one of several possible activities that follow in the workflow. The following changes have been made to this logic: A new process variable named parentChangeRequest has been introduced in each workflow. It holds the parent request and is initialized when the workflow begins through a transition expression on the process Start transition. The following figure shows the expression synchronization robot as it existed before Release 5.1. This robot has been replaced with a conditional router followed by the sync robot. The new robot, which has been changed to an object event synchronization robot, is shown in the following figure. The object is the new change request process variable just described. The event is STATE CHANGE in each case. The conditional router contains exactly the same logic as the expression in the object event subscription robot. The purpose for this conditional router is to immediately check whether the state has already been reached. This helps avoid the race condition of the state being achieved prior to the instantiation of the synchronization robot. (In both figures, the parentChangeRequest variable is assumed to be initialized already.) The expression in the object event synchronization robot and conditional has been changed to use the workflow variable parentChangeRequest directly, rather than access the database repeatedly to determine the parent change request.

Customizing Workflow Administration

1087

These changes resulted in the following performance improvements: Lookup time during each execution of the synchronization expression has been shortened as a result of saving the change request in a workflow variable. The synchronization expression executes only after the state of the change request has changed. As a result, there is a very good chance the proper state has been reached each time the expression runs.

Sync on Multiple Object State Change


Each of the following robots has been converted to a class event synchronization robot as described below. Template Robot Change Request Process 2 Sync on Investigation Change Request Process 2 Sync on Proposal Change Request Process 2 Sync on Change Orders Change Investigation Process Sync on Analysis Activities Change Proposal Process Sync on Activities Change Order Process Sync on Change Activities Before Release 5.1, the expression logic performed the following actions: 1. Determine which children objects are applicable to the synchronization. For example, in the Sync on Change Activities robot, all the change activities related to the change order are relevant. 2. Determine the life cycles states of all the relevant objects. 3. Based on the result of step 2, either continue holding or move on to one of several possible activities that follow in the workflow. Release 5.1 includes the following changes to this logic: The expression synchronization robot has been replaced with a conditional router followed by the sync robot. The sync robot has been changed to a new class event synchronization robot. The class differs depending on the particular synchronization robot, but the event is always STATE CHANGE. The conditional router contains exactly the same logic as the expression in the object event subscription robot. The purpose for this conditional router is to immediately check whether the state has already been reached. This helps avoid the race condition of the state being achieved prior to the instantiation of the synchronization robot. This change resulted in the following improvements:

1088

Windchill Customization Guide

The synchronization expression is executed only when an object in the proper class has changed state. As a result, the expression is executed only when there is a chance that the states of all related objects are in synchronization.

Installation and Upgrade


The file \Windchill\loadfiles\ChangeManagement.csv contains the definition of the following items: ChangeItems Domain Example Projects Example Workflows Example Life Cycle Templates

New Installations
A new Windchill installation will include the new Change Management workflow process templates. Be sure to load the "Change Management lifecycles and workflows" during the initial database load. For further information about loading data, see the Windchill Installation and Configuration Guide.

Existing Installations
If you are not concerned about overwriting existing demo workflow process or life cycle templates, you can simply initiate "java wt.load.Demo " and answer "no" to all questions except "Change Management lifecycles and workflows" (see the Windchill Installation and Configuration Guide for further information about loading data). You can ignore errors regarding the "Change Items" Domain and the example projects. However, to avoid these errors, remove all sections from ChangeManagement.csv except those for the Change Management workflow process templates and life cycle templates. If you do not want to overwrite the existing demo workflow process templates, PTC recommends that you perform one of the following options before loading the new workflow and life cycle templates: Rename the existing workflow and life cycle templates using the Workflow Administrator and Life Cycle Administrator. Rename the new workflow and life cycle templates by manually editing the ChangeManagement.csv file.

Customizing Workflow Administration

1089

After loading the Release 5.1 workflow process and life cycle templates, you can restore them to their original state one at a time by clicking Delete Latest Iteration from the Workflow Administrator or Life Cycle Administrator page.

Custom Workflow Process Templates


If you have custom workflow process templates that contain synchronization robots, PTC suggests that you load the Release 5.1 example workflow process templates and study how they work, along with this document. This will help you determine if you would benefit from implementing these techniques in your own synchronization robots.

Code Impacted
The following code has been impacted by the enhancements: The workflow processes in loadfiles\ChangeManagement.csv, including the changes described in this section. wt.change2.process.ProcessHelper A new, overloaded version of the checkRequestFinished method has been added, which takes a change request and checks the state of the passed object. wt.change2.StandardChangeService The methods saveFormalizedBy and deleteFormalizedBy now emit the events ISSUE_FORMALIZED and ISSUE_UNFORMALIZED, respectively. wt.admin.AdminEventResource The ISSUE_FORMALIZED and ISSUE_UNFORMALIZED events were added to this resource bundle (and all of its language variants). wt.workflow.robots.synchEventResource The ISSUE_FORMALIZED and ISSUE_UNFORMALIZED events were added to this resource bundle (and all of its language variants). wt.notify.notify.properties The ISSUE_FORMALIZED and ISSUE_UNFORMALIZED events were added to this property file.

1090

Windchill Customization Guide

Customizing Promotion Request Workflow Processes


The client that is used to Promote objects offers users a choice of two workflow processes to choose from: promotion request approval and promotion request review. These workflows can be customized. The out-of-the-box workflows are shown below:

Promotion Request Approval Process

Customizing Workflow Administration

1091

Promotion Request Review Process

Key Customization Points


You msut keep the following key points in mind when customizing these workflows.

Lock/Unlock Lock/Unlock Promotion Targets


As you notice there are two "Conditional" routers that you see in the above workflows. They handle important tasks. One of them does the job of locking targets. The promotion targets could be parts, CAD documents, docs etc. These promotion targets could be associated with a lifecycle that has lock transitions. If so, and if there is a need to move the targets to a desired lock state before reviewing the Promotion Request, and if there is lock transition that exists with that desired lock state as the end state, then those targets have to be locked before review tasks can be fired to the promotion review team members. The out-of-the-box conditional for locking has an expression similar to the below code snippet:
wt.maturity.PromotionNotice pn = (wt.maturity.PromotionNotice)primaryBusinessObject; try { wt.maturity.MaturityServerHelper.service.lockTargets( pn ); result = "Accepted"; }

1092

Windchill Customization Guide

catch( Exception wte ) { result = "Rejected"; }

// send notification to owner

The customized workflow should also have a similar locking mechanism before including the task for review. The second conditional does the actual promotion of the targets and has code like:
wt.maturity.PromotionNotice pn = (wt.maturity.PromotionNotice)primaryBusinessObject; try { wt.maturity.MaturityServerHelper.service.promoteTargets (pn); result="Approved"; } catch (wt.maturity.MaturityException me) { result="Rejected"; }

The promoteTargets API also takes care of the process of unlocking the targets before promoting them. This kind of an unlocking mechanism should also be incorporated in the customized workflow.

Review Promotion Request Activity


The task that should be included in the workflow must be of the type Promotion Request Task. This special task type will be available as a drop down while defining the review activity in the workflow.

Customizing Workflow Administration

1093

Owner Role in Promotion Request Team Template


Another important rule that must be strictly followed is to include the "Owner" role in the team template that would be used for Promotion Request. The owner role is a participant in many of the activities and robots in the PR workflow.

Enhanced Promotion Process


There is currently no out of the box solution to refresh promotion objects to their latest iterations or automatically revise the promotion candidates that are being promoted through a revision series change. Background During the Promotion Request review and approval process, it is not uncommon for the participants to uncover issues associated with the promotion candidates. Rather than rejecting the Promotion Request, the process can be more efficient with the introduction of a rework loop. This rework loop allows the creator of the Promotion Request to review the comments, make appropriate adjustments to the promotion candidates, and have the workflow automatically refresh the Promotion Request for another review and approval. It is also good practice to avoid sending promotion targets for approval when the result will be a validation error. The rework loop contains this validation based on the current iterations of promotion targets or the refreshed iterations if Automatic Refresh is enabled. For companies that use the Promotion Request as a "Gate Review" for production, a best practice is to switch the revision labels for objects from a numeric series to an alphanumeric series. With a proper life cycle design, such a gate state can be modeled that achieves the desired target state and automatically revises the promotion candidates to the initial revision label of the new revision series. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions These instructions assume a pre-existing knowledge of modifying workflow processes and how to call Windchill methods within the workflow. Intended Outcome The expectation is that you will be able to add the auto-refresh or the automatic revise functionality to your customized workflows.

1094

Windchill Customization Guide

Solution
The out-of-the-box promotion request process templates illustrate how to implement both the auto-refresh and the automatic revise functionality. Also included in the template is the review validation. Prerequisite knowledge To achieve this result, you need to have an understanding of the following: Basic Java development Workflow process modification including tally expressions and robot expressions The management of resource bundle file. Windchill Preference Management utility

Note The workflow process templates provided out-of-the-box should not be modified directly. These process templates should be renamed prior to modification.
Solution Elements Element Type wt.maturity.MaturitySer- method verHelper.service.unlockTargets (pn)

wt.workflow.work. WfTally

class

com.ptc.windchill.enter- method prise.maturity.PromotionNoticeWorkflowHelper.

Description This method call can be added to a workflow expression that will unlock the promotion targets in this case for rework. The result of this is the promotion targets will be at the state they were at, at the moment the promotion request was created. Unlocking the promotion targets may allow the user assigned to rework to perform updates on the objects (subject to access control). This class is used to tally votes of a workflow task. For example if a task is assigned to the approval role multiple users could receive that task and vote differently. This class provides methods that define which route to take based on if all have to vote for that option or any have to vote for that option. This method can be added to a workflow expression that provides the update handling of promotion objects.

Customizing Workflow Administration

1095

Element refresh(pn);

Type

Description Internally this method uses a new preference Latest Iteration Refresh to control the behavior. Here are the values 1. Refresh promotion candidates (default setting). This value only refreshes the promotion candidates. 2. Refresh all objects. This value refreshes all promotion objects: The promotion candidates and the other objects in the Maturity baseline. 3. Do nothing. This option will not refresh any promotion objects. 4. Validate promotion targets. (see Procedure Validation of Promotion Targets in Rework on page 1104for more information) This method call can be added to a workflow expression that will lock the promotion targets. Only promotion targets that have a lock transition will be subject to locking. This method can be added to a workflow expression to automatically revise promotion objects. Internally this

wt.maturity.MaturitySer- method verHelper.service.lockTargets (pn);

com.ptc.core.ui.validation.UIValidationResultSet set= com.ptc. windchill.enterprise.maturity.PromotionNoticeWorkflowHelper.revisePromotables(pn, pn. getCreator(), locale);

method

1096

Windchill Customization Guide

Element

Type

Description method uses two new preferences : 1. Automatic Revision Mode. There are 3 modes: a. Do nothing. This mode will not perform any automatic revisioning. b. Automatically revise only the promotion candidates. This mode will automatically revise only promotion candidates c. Automatically revise only the promotion candidates with versioning scheme changed This mode will only revise promotion candidates that will be revising to a state that result in a versioning scheme change. 2. Automatic Revision States. This preference is a multi valued list containing states that are valid for automatic revisioning. This preference only takes effect if the Automatic Revision Mode preference is something besides Do-nothing.

Customizing Workflow Administration

1097

Procedure Adding Automatic Refresh


A customized workflow process template used by promotion requests can be modified to support automatic refresh. The following example will outline to procedure used in the latest iteration of the Promotion Request Approval Process provided out-of-the-box.

In this example a rework loop has been added. The loop begins at the Approve Promotion Request task. Members of the Promotion Approvers receive this task. An addition route has been added to the Approve Promotion Request task called Rework. In this example, a tally expression is defined that determines, based on all the approvers votes, which route to take.
Vector v = new Vector(); v.addElement("Approve"); v.addElement("Reject"); v.addElement("Rework"); Vector vResult = wt.workflow.work.WfTally.any(self, v); if( vResult.contains("Rework")) { result = "Rework"; } else if ( vResult.contains("Reject") ) { result = "Reject"; }else { vResult = WfTally.all(self,v); if( !vResult.isEmpty() ) { result = (String)vResult.get(0); } }

1098

Windchill Customization Guide

This expression says if any approvers choose Rework then the Rework option is taken. If no approvers select rework but any select Reject then Reject is taken. Otherwise the Approve route is taken. The approver task no longer contains special instructions. However, there exists a process variable called special_instructions. This field is global to the process and therefore can be set programmatically. The enhanced workflow uses the Comment field of the Approve Promotion Request task to assemble a string of comments that approvers voted Rework. This String is set on the Rework special instructions. For example, if there are three users in the approvers role: user1, user2 and user3. User1 votes approve with the comment: Looks good User2 votes rework with the comment: Modify User3 votes rework with the comment: Resize [User2]: Modify [User3]: Resize

In this case, the reworker will receive a task with the special instructions:

Once the Rework route is chosen the promotion targets are locked for rework and the promotion creator will receive the Rework Promotion Request task. This task will provide special instructions supplied by the approver of what promotion items need rework. This special instructions field is writable for the Approve task and read only for the Rework task. The creator can then iterate certain promotable objects for this task. The creator could determine that the promotion in not longer viable and can choose the reject option. In this case the promotion request is rejected. The user performing the rework can only update objects that they have permission to modify. If the content of the promotion request is not able to be modified, major reworking of the promotion request will require a rejection followed by a new promotion request with the reworked items. The rework loop is meant to address minor issues such as typographical errors, issues with quantity or units, minor geometry changes rather than significant structural changes. Once the promotion creator chooses the Submit option the promotion request will execute the Refresh Promotion Objects expression.
wt.maturity.PromotionNotice pn = (wt.maturity.PromotionNotice) primaryBusinessObject; try { com.ptc.windchill.enterprise.maturity.PromotionNoticeWorkflowHelper. refresh(pn); wt.maturity.MaturityServerHelper.service.lockTargets (pn); catch( Exception wte )

Customizing Workflow Administration

1099

} { wte.printStackTrace(); }

The PromotionNoticeWorkflowHelper.refresh(pn) method will refresh the promotion objects to their latest iteration following the preference rules defined in Solution on page 1095. Finally the loop is finished and the approvers again receive the Approve Promotion Request task. It is important to include the call to lockTargets() to ensure the promotion targets are not inadvertently modified before approval if locking is supported. FIT Table The following fit table describes how the Latest iteration Refresh preference affects automatic refresh. Promotable Is Promotion Latest iteration Eligible to be Refreshed Target refresh preference value part_1 N/A Do Nothing false part_2 part_3 part_4 part_5 Y Y N Y Refresh promotion candidates All Refresh promotion candidates All true true false true

1100

Windchill Customization Guide

Procedure Adding Automatic Revisioning


The workflow template used by the promotion request can be modified to support automatic revisioning. The following example will outline the procedure used in the latest iteration of the Promotion Request Approval Process provided out-of-the-box.

In this example an additional conditional expression is added. It is added after the conditional that promotes the targets. The Conditional looks like the following:

The Routing Expression expanded:

Customizing Workflow Administration

1101

wt.maturity.PromotionNotice pn = (wt.maturity.PromotionNotice) primaryBusinessObject; try { java.util.Locale locale = wt.session.SessionHelper.getLocale(); com.ptc.core.ui.validation.UIValidationResultSet set= com.ptc.windchill.enterprise.maturity.PromotionNoticeWorkflowHelper. revisePromotables(pn, pn.getCreator(), locale); reviseValidationMsg= com.ptc.windchill.enterprise.maturity.validators. PromotionTargetsReviseValidator.getReviseResultSetMessage(set, locale); if (!reviseValidationMsg.isEmpty() ) result="Partial"; else result="Full"; } catch( Exception wte ) { wte.printStackTrace(); }

The method revisePromotables(pn, pn.getCreator(), locale); performs the revision of the promotion objects following the preferences defined above in Solution on page 1095. Once the eligible promotion objects have been revised a message is created containing any promotion targets not eligible for promotion along with the reason why the promotion object was disqualified. This message is sent to the promotion creator. Any valid promotion targets will be revised independent of whether there are any disqualified targets.

Note If promoting CAD Documents and Parts together, if the revise disqualifies either the part or CAD document, the objects will not be revised together and will need to be correctively fixed by the promotion request creator (or another user) after promote.
Promotion Process as a Gate Review Process For companies that use the Promotion Request as a "Gate Review" for production, a best practice is to switch the revision labels for objects from a numeric series to an alphanumeric series. With a proper life cycle design, such a gate state can be modeled that achieves the desired target state and automatically revises the promotion candidates to the initial revision label of the new revision series. The following FIT table describes how this scenario would work based on various values of the preferences described in Solution on page 1095.

1102

Windchill Customization Guide

PromotPromot- Is Life able Cycle State Based part_1 No

PreferPreference Automatic Revision States Automatic Revision States Automatic Revision States Automatic Revision States

PreferPreference Value Released

PreferPreference Revise Mode Revise Mode Revise Mode Revise Mode

PreferPreference Value

Valid for revise

Revise all Yes

part_2

Yes

Released

part_3

No

Released

part_4

No

In Work

Yes Revise State Based No Revise State Based Revise All No

For this example the Maturity State of the promotion request is Released. In addition each part is in its own unique container.

Customizing Workflow Administration

1103

Procedure Validation of Promotion Targets in Rework


The automatic refresh capability detailed in Procedure Adding Automatic Refresh on page 1098 has been extended to check that if there is a later iteration of the promotion target to be refreshed, that this iteration is valid for promotion. The following checks are made: Promotion Target is not checked out. The creator has modify access on the Promotion Target. The LifeCycle of the promotion target has not changed since the promotion was created. The State of the promotion target has not changed since the promotion was created.

Workflow Template Here is the expanded promotion notice workflow template with validation.

A conditional has been added to perform the above checks. An email is sent to the creator with a list of promotion targets that cannot be promoted (if any). If some targets of the Promotion Request cannot be promoted, the Promotion Request is sent back for rework where the creator can either submit or reject. If all targets are valid the promotion request is sent for approval.

1104

Windchill Customization Guide

Customizing Workflow Events on an Object


Creating a customized event on an object
The following is an example of how to create a customized workflow event (wt. workflow.engine.WfCustomEvent) on an object. In this example, the customized event is MY_EVENT. 1. Add the following entry to <Windchill>/codebase/wt/workflow/robots/ synchEventResource.rbInfo:
*/wt.workflow.engine.WfCustomEvent/MY_EVENT.value=MY_EVENT

2. Add the following entries to <Windchill>/codebase/wt/workflow/engine/ WfCustomEventType.rbInfo:


MY_EVENT.value = MY_EVENT MY_EVENT.constant = MY_EVENT

3. Rebuild the client JARs (see Rebuilding Client JARs in Best Practices for Customizing Files Supplied by PTC). 4. Clear the Java Plug-in cache on your client machines. 5. Restart the Method Server. 6. Use the Workflow Process Editor to design a workflow template with a Synchronization robot, as shown below: In the Synchronization robot properties window: a. Select object event b. Make sure MY_EVENT is listed in Event dropdown list. c. Choose MY_EVENT d. Write appropriate expressions in the initial and routing expressions. For more information on the Workflow Process Editor, see the Windchill Business Administrator's Guide.

Emitting a customized event


Continuing the above example, the following code is required to emit the customized event.
java.util.Hashtable valueMap = new java.util.Hashtable(); wt.workflow.engine.WfEngineServerHelper.service.emitCustomObjectEvent ("MY_EVENT", primaryBusinessObject, valueMap);

Customizing Workflow Administration

1105

Where: MY_EVENT is the customized event as created above. Alternatively, any event selected in the Event dropdown list in the Synchronization robot properties window would be substituted in its place. PrimaryBusinessObject is the object on which we want to emit an event. In other words, the object on which the Synchronization robot is listening for MY_EVENT (the customized event).

Note A customized event can be emitted from any customized code or from an expression robot.
In handling an emitted event, there is no way to retrieve the valueMap Hashtable from the event, since the synchronization expression syntax does not provide a way to get the event object for an object-based event.

1106

Windchill Customization Guide

Customizing Workflow Task Pages


The new Workflow Task pages need to be designed such that they may be easily customized by the customer. Rendering custom workflow activity variables on page 1107 Rendering PBO UI Components on page 1108 Auto Create Change Notice customization on page 1112 Auto Create Change Notice customization on page 1112 Implementing customized Task Page JSP on page 1113

Rendering custom workflow activity variables


There exists a tag file (workItemInfo.tag) that must be included within each task page JSP, before the actual rendering of the components. This tag describes and gets the model of GUI Components for the given task page. For any custom workflow activity variables, the user will need to specify either a comma-delimited list of the activity variable names (which have been defined in the Workflow Definer) and/or specify the reserved keyword of "all_activity_variables". Height and/or width for each listed custom variable may also be specified using CSS style syntax. ". (Note: height and width may only be applied to java.lang.String activity variables, and width (only) may be applied for java.net.URL, java.util.Date, and wt.workflow.engine.WfDueDate custom activity variable types). A default height (1 character) and width (50 characters) will be used, when none is specified. For example, a list of variable names may be specified as follows:
"variable_name1{height:1;width:2},variable_name2{height:1},variabl e_name3{width:2},variable_name4".

Specifying "all_activity_variables" will display all visible activity variables except for those named "special_instructions", "instructions", or "primaryBusinessObject". The customizer will be required to explicitly list these three activity variable names (if defined in the Workflow definer as such), in addition to the "all_activity_variables". For the Windchill R9.0 out-of-the-box templates, the default will render all_activity_variables. In addition, the Change Management template will also include the specification of the special_instructions activity variables. Describe Examples:
<tags:workItemInfo custom_variables="variable_name1,variable_name2{height:1}"/> <tags:workItemInfo custom_variables="all_activity_variables"/> <tags:workItemInfo custom_variables="all_activity_variables,special_instructions{widt h:50;height:5}"/

Customizing Workflow Administration

1107

If you specify to render a particular custom activity variable (other than special_instructions, instructions, or primaryBusinessObject) with the all_activity_variables, the specified custom activity variable will get rendered twice. Once the customizer has described and retrieved the property model (via the workItemInfo.tag), they will then need to specify where on the page to render the particular workflow activity variable's GUI component. This is done by including the taskPanelValue tag, along with the new property model and the list of variables to display at the desired location of the JSP. (Note: the list of variable names must match the names listed for tags:workItemInfo. That is, if "all_activity_variables" was specified, then this same name must be used to render the GUI Components for "all_activity_variables.) Render Examples:
<tags:taskPanelValue propertyModel="${propertyModel}" attrs="variable_name"/> <tags:taskPanelValue propertyModel="${propertyModel}" attrs="special_instructions"/ <tags:taskPanelValue propertyModel="${propertyModel}" attrs="all_activity_variables"/>

Rendering PBO UI Components


The info page of a Primary Business Object (PBO) may be included in its entirety (as is already done the in the out-of-the-box Change Management task pages) using the infoPageLink tag file:
<tags:infoPageLink>

A customer may also choose to customize the task form template (i.e., the customized JSP) to only display individual components of the PBO. For example, they might want to include just the top attributes, affected data, affected end items, attachments, attribute detail (including soft or modeled), or related change items. The tag tablePageLink can be used to display one or more tables that are defined together in one custom jsp. The parameter path is the jsp that will be included. The tablePageLink tag can only be used once on a page to render one jsp file and it cannot be used on the same page as infoPageLink.
<tags:tablePageLink path="/netmarkets/jsp/change/affectedEndItemsTable.jsp"/

1108

Windchill Customization Guide

The following table lists the paths that can be used for tablePageLink for a specific object. PBO Component Affected Data Path Available Function Change RequestWTChangeRequest 2 Change Issue or VarianceChangeIssue Change RequestWTChangeRequest 2 Change Issue or VarianceChangeIssue Change TaskWTChangeActivity2 Change TaskWTChangeActivity2 Change RequestWTChangeRequest 2 Change NoticeWTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion NoticePromotionNotice Change RequestWTChangeRequest 2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Change RequestWTChangeRequest 2 Change Notise-

/netmarkets/jsp/change/affecte dDataTable.jsp

Affected End Items

/netmarkets/jsp/change/affecte dEndItemsTable.jsp

Affected Items Affected and Resulting Items Attributes and Attachments

/netmarkets/jsp/changeTask/af fectedItemsTable.jsp /netmarkets/jsp/changeTask/af fectedAndResultingItems.jsp /netmarkets/jsp/object/attribute s.jsp (no attachments for CA)

Annotations

/netmarkets/jsp/annotation/ann otationChangeTable.jsp

Baselines

/netmarkets/jsp/object/ relatedB aselines.jsp

Customizing Workflow Administration

1109

PBO Component

Path

Available Function WTChangeOrder2 Change TaskWTChangeActivity2 Change RequestWTChangeRequest 2 Change NotiseWTChangeOrder2 Change Issue or VarianceChangeIssue Promotion NoticePromotionNotice Change RequestWTChangeRequest 2 Change NotiseWTChangeOrder2 Change Issue or VarianceChangeIssue Promotion NoticePromotionNotice Change RequestWTChangeRequest 2 Change NotiseWTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion NoticePromotionNotice Promotion NoticePromotionNotice

Contexts

/netmarkets/jsp/object/ relatedC ontexts.jsp

Discussion

/netmarkets/jsp/forum/discuss. jsp

Maturity History /netmarkets/jsp/history/maturit yHistory.jsp Promotion Items /netmarkets/jsp/promotionReq uest/promotionItemsTable.jsp Reassignment

1110

Windchill Customization Guide

Path Available Function PBO Component Related Changes /netmarkets/jsp/change/related Change RequestChanges.jsp WTChangeRequest 2 Resulting Items Routing/Process /netmarkets/jsp/changeTask/re sultingItemsTable.jsp /netmarkets/jsp/workflow/proc essHistory.jsp Subscriptions /netmarkets/jsp/subscription/o bjectSubscriptions.jsp Change NotiseWTChangeOrder2 Change Issue or VarianceChangeIssue Change TaskWTChangeActivity2 Change RequestWTChangeRequest 2 Change NotiseWTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion NoticePromotionNotice Change RequestWTChangeRequest 2 Change NotiseWTChangeOrder2 Change TaskWTChangeActivity2 Change Issue or VarianceChangeIssue Promotion NoticePromotionNotice

The following table lists the tag files that can be used to include tables. If there is a tablePageLink or infoPageLink these tags must precede it. PBO Component Promotion Notice Table Syntax for including on JSP If the PBO is a PromotionNotice, the customizer may include

Customizing Workflow Administration

1111

PBO Component

Syntax for including on JSP the promotion objects table as follows:


<workItem:setPrimaryBusinessObject/> <workItem:promotionObjects/

Notebook Table <workItem:notebook displayType="Table"/ Discussion Table <workItem:discussions displayType="Table"/> Routing History To display routing history for all activities: Table <tags:routingStatus dispProcess="All"/> To display routing history for just the current activity:
<tags:routingStatus/>

Reassignment Table

Note The display of the routing history table currently includes the reassignment table as well. An SPR exists to allow the routing history table to be displayed independent of the reassignment history table. To display the reassignment history table as embedded and expanded in the JSP:
<tags:reassignHistory showRH="Table"/>

To display the reassignment history table as a link:


<tags:reassignHistory showRH="Link"/>

Auto Create Change Notice customization


The customizer may also re-implement the handler for auto-creating the default change notice and corresponding change task (DefaultAutomateCreateChangeNoticeHandler.java), and override the following method:
public abstract void createChangeNoticeFromChangeRequest(WTChangeRequest2 changeRequest, NmCommandBean cb) throws WTException;

To register the new handler within the configuration file ChangeManagementservice-properties.xconf:


<Service context="default" name="com.ptc.windchill.enterprise.change2.handler.AutomateCreateC hangeNoticeHandler"> <Option

1112

Windchill Customization Guide

serviceClass="com.ptc.windchill.enterprise.change2.handler.Defa ultAutomateCreateChangeNoticeHadler" selector="DefaultHandler" requestor="null" cardinality="duplicate"/ </Service>

Implementing customized Task Page JSP


The customer may create their own Tag file, to define their own custom task page for one of their organizations. They would have the choice of writing it from scratch, or using the provided testPage template. This template would provide a starting point for development. A "testPage" JSP, that contains all possible out-of-the-box attributes and components, will be available to the customer as an example page for customization. This JSP will list each out-of-the-box attribute and component using HTML constructs, similar to the out-of-the-box task pages. This "testPage" will also include the alternate rendering options for tables and actions (e.g., display as a link and as an embedded table).

Use of Customized Tag Library and/or and/or 3rd Party Tag Library
The customizer might also choose to use a third party tag library, or one of their own custom tag libraries, for use in the custom task page. They would just need to include a "taglib" directive at the top of their page to specify the location of the custom tag library. If they were to specify a custom tag library, they might choose to use the same location as Windchill tags (WEB-INF/tags). However, it is recommended that they use a unique prefix of their own (we use "tags" as a prefix). Otherwise, they would have to make sure that they have unique tag names.

Overriding an out-ofout-of-thethe-box box Task JSP


Once a custom task page is created, the "Create Task Form Template" page is used to upload the custom page, and register it with the given change item, task type, and container.

Customizing Workflow Administration

1113

Customer authors a JSP template and uses the following UI to upload it to Windchill for a given combination of task type and PBO Class. Clicking on Create Template opens up the following page using which the JSP file can be uploaded Once the new template is uploaded, a new JSP file gets created in the codebase/ netmarkets/jsp/customtemplates folder. The name of the new JSP will be generated based off a mapping mechanism, using the Container, PBO class, Activity Type, and JSP template name. (See Project 14216460 Workflow Task Forms). The JSP name will be generated using the mapping mechanism as follows:
<ContainerName>_<PBOType>_<ActivityType>_<Template Name>.jsp

Note It's assumed that at least the out-of-the-box templates are present in the system. If no template is found due to deletion of templates then an exception will be raised.

1114

Windchill Customization Guide

Refine and Review Workflow Transitions


Sometimes you need to set all the Resulting Items into a new state that cannot be checked out or modified so everyone has a consistent view of the Resulting data. Prerequisite knowledge To apply this knowledge, you need to have an understanding of the following: Knowledge of creating and modifying a workflow. Fmiliarity with change management concepts such as resulting data. Access to a system where the Refine and Review workflow transitions are supported. That you have administrator access to the workflow and life cycle back end on the Windchill application.

Adding the Transitions


1. Navigate to Site UtilitiesWorkflow UtilitiesWorkflow Administration 2. Edit the Change Notice Workflow 3. Upon editing the Change Notice workflow, add a new Expression Robot. a. Select the icon. b. Click the workflow to add the transition.

4. Next you must link the expression with the workflow so it is executed. a. You can modify or add new arrows using the Action tool ( ).

b. Holding CTRL and drag arrows between states. In this example it is added before the Change Notice is submitted.

Customizing Workflow Administration

1115

5. Now that it is part of the Change Notices workflow execution, you must make it a Refine or Review transition. You can do this by adding some code to the expression. Double click the new Expression and then select the Expression tab. a. To add a Refine transition add the following expression code to the transition:
wt.maturity.TransitionHandlerFactory.getInstance().transitionTargets (primaryBusinessObject,wt.life cycle.Transition.toTransition(REWORK"),false);

b. To add a Review transition add the following expression code to the transition:
wt.maturity.TransitionHandlerFactory.getInstance().transitionTargets (primaryBusinessObject,wt.life cycle.Transition.toTransition("REVIEW"),false);

c. In this example a Review Transition has been added.

1116

Windchill Customization Guide

6. Select Check Syntax.

Note If you copy and paste the transition code out of Word and directly into Windchill, Word will copy invalid quotes which are not valid for the java compiler. To get around this, when adding your expression code, paste it into a Notepad first, copy it from Notepad, then paste into the Windchill Expression box.
7. Save your changes and then Exit the Change Notice Workflow window. Now you have a working copy of the new workflow with a Review Transition. You can use the same process to add Refine transitions.

Understanding the Transitions


After the default Change Notice life cycle has been modified to contain the Refine and Review transitions, you might have a workflow that looks something like this:

Customizing Workflow Administration

1117

Understanding the execution of Refine and Review above If an Auditor is reviewing changes made to several Resulting Objects on a Change Notice. When the Auditor reviews them, the changes do not appear to be complete, so the changes are disapproved. The Refine and Review transitions will help to complete the changes and get to the Auditor so that he or she can review the complete changes. 1. During the Audit Change Notice, the changes are disapproved. 2. Refine Transition will be executed internally, changing the state of the Resulting objects back to something modifiable. 3. The workflow will create a task for the Change Admin I to make the proper updates. This is the Rework Task. 4. The Change Admin I makes the proper updates, and completes the Rework Task. 5. Next, the workflow will execute the Review Transition. Once this Review Transition is executed, the workflow will internally set the Resulting objects to a state in which they can no longer be modified. Once the Review Transition is executed, the Auditor who originally disapproved the changes would be able to review the new complete changes.

Changing the Life Cycle of Part to Handle Refine and Review Transitions
In this scenario, the part is using the Two Phase Development Life cycle instead of the default one. 1. Navigate to the Site/Utilities level of Windchill 2. Find the Life Cycle Administrator and navigate to it 3. Edit the Two Phase Development Life Cycle, you will have to check it out 4. Configure what the new state will be when the Review transition is executed. Suppose the business needs require to set the state of the Resulting objects to Under Review if the Review transition is executed. To configure this, make the following change in the life cycle:

1118

Windchill Customization Guide

5. Configure what you want the state to do if it is under the Refine transition. Keep in mind this would likely be useful to use just after the Review has occurred. Because of this, when the Change Notice is in Under Review state, you will want to use the Refine transition to change the object back into something editable. To do this, change the state to Production Change:

Customizing Workflow Administration

1119

6. Once the changes are made, click Save 7. Click Ok. 8. Back in the Life Cycle Administrator, check in the changes to the Two Phase Life cycle

Executing the Use Case


Verify the changes with the UI. 1. Create a few new Parts (this will ensure they are all in the design state) 2. Copy the new Parts to the clipboard 3. Launch Create Change Notice wizard 4. On the implementation table of the Change Notice wizard, find the Default Change Task, edit it.
1120

Windchill Customization Guide

5. Go to the Affected and Resulting step of the Change Task 6. Paste the parts into the Resulting Objects table. 7. Finish the Change Task wizard. 8. Finish the Change Notice, and select submit now. 9. Modify the Resulting Object, and complete the workflow tasks for the Change Task 10. Upon Auditing the Change Notice, disapprove the changes made. The Change Notice will now enter Refine Transition Rework Task Review Transition depicted above. At this point, the workflow will execute the Refine Transition. This takes the Change Notice and places it into a state in which the Resulting objects can be modified. 11. As the Change Admin I, go back and modify the Resulting Object again. This time, modify it correctly so that the changes will be approved by the Auditor. 12. Complete the Rework Task. At this point, the Rework Task is completed, and the workflow will internally run the Review Transition. This results in placing the Resulted objects back into a state which cannot be modified. This ensures that the proper changes will be reviewed by the Auditor the next time around.

Customizing Workflow Administration

1121

Adding Custom Workflow Attribute to Workflow Processes


There are times when you might want to view variables from a workflow process on the primary business objects info page as an attribute. This section details how to add customized workflow process attributes to the info page of an object. This is accomplished by adding WFVariables of the WFProcess object to the primary business objects information page. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions This documentation assumes familiarity with: type attribute layouts creating new xconf entries using xconfmanager resource bundles defining variables in a workflow process

Adding the Custom Workflow Attribute to the Workflow Process


This section contains an example of adding a work flow item attribute to the info page of a Problem Report object. You will add a new workflow item variable to a task by using Workflow Process Management utility. In this example, add a variable with the name testNewAttribute to the WFProcess. The supported data types for the data utility are String, Date, Boolean, and Number.

1122

Windchill Customization Guide

Adding the New Attribute to the Type Attribute Layout Next, you must add a new attribute to the type attribute layout of the Primary Business Object. In this case, you will add this entry to the info page attribute layout for the loadFiles/type/WTChangeIssue.xml. The csvname is important. The csvname must be the string WFVAR_ followed by the variable name chosen above for the WfProcesss new variable. In this case, the full text of the csvname is WFVAR_testNewAttribute.
<csvBeginAttributeDefView handler="com.ptc.core.lwc.server. TypeDefinitionLoader.beginProcessAttributeDefinition"> <csvname>WFVAR_testNewAttribute</csvname> <csvname>WFVAR_testNewAttribute</csvname> <csvattDefClass>com.ptc.core.lwc.server.LWCNonPersistedAttDefinition </csvattDefClass> <csvdatatype>java.lang.String</csvdatatype> <csvIBA/> <csvQoM/> <csvviewStyle/> <csveditStyle/> <csvdefaults/> </csvBeginAttributeDefView>

Customizing Workflow Administration

1123

Registering the new attribute with xconfmanager You will have to add this new attribute to be registered against the WorkItemAttributeDataUtility. This can be done by adding the following to an xconf entry to WorkItem-components.dataUtilities.properties, and propagating xconf properties (xconfmanager pF)
<Option cardinality="duplicate" requestor="null" selector="WFVAR_testNewAttribute" serviceClass="com.ptc.windchill.enterprise. workitem.dataUtilities.WorkItemAttributeDataUtility" />

Changing the name of the attribute in the UI By default, the name of the attribute would use the name of the key. At this point, the information page would display a new attribute with the name testNewAttribute. If you want to customize this value to a localized attribute, you can add a new entry within the WorkItem/src/com/ptc/windchill/enterprise/workitem/ workItemAttributeResource.java resource. The name of the rbinfo key should match the variable name:

After you have done this, the attribute will now show up with the value defined by the RBEntry annotation: Verifying the Customization Your customized attribute will be displayed on the information page of the primary business object.

1124

Windchill Customization Guide

25
Customizing Windchill VisualizaVisualization Services
Custom Publishing................................................................................................. 1126 Interference Detection............................................................................................ 1144

This chapter describes how to customize Windchill Visualization Services.

1125

Custom Publishing
Objective
You want to initiate publishing from another product area or from custom code. You may also want to define alternative inputs to the creation of a representation such as naming, descriptions, or configuration specifications to an OOTB publishing mechanism (i.e. check-in driven and scheduled publishing).

Background
Out-of-the-box Windchill Visualization Services can create representations three ways. They are by manual creation from the Windchill UI, the check-in of a Representable (an object that can have Representations; i.e. EPMDocument, WTPart, WTDocument), and by a schedule job. This document will help explain how to initiate publishing in other ways such as custom code for workflows, from a custom UI, etc. This topic also explains how to customize the creation of representations from such existing mechanisms like the check-in of a Representable or by a schedule job. Unlike manual creation, there is no out-of-the-box way to specify special configuration specifications for publishing, or provide business specific information you may want to capture in the name or description of the Representation.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


Custom publishing should be used when there is a requirement to initiate publishing in Windchill from a non-standard way (something other than check-in, manual or schedule), or if you need to modify the input information for a Representation. Publishing can only be performed on wt.representation. Representable objects (i.e. EPMDocuments, WTPart, WTDocuments; including soft and hard typed children).

Intended Outcome
Using the information in this topic will allow end users to perform publishing in a manner in-line with their business requirement whenever the out-of-the-box publishing mechanisms are not sufficient.

1126

Windchill Customization Guide

Solution
Customize publishing by implementing public WVS APIs in custom code and making WVS aware of this custom code via appropriate WVS property changes.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Java Development Standard WVS publishing setup and configuration WVS concepts such as Representable and Representation Basic understanding of publishable business objects such as EPMDocuments, WTParts and WTDocuments and their relationships/structure The use of configuration specifications (ConfigSpecs)

Note The use of configuration specifications (ConfigSpecs) Additional Resources on page 1142 includes references to many or all of these subjects.

Solution Elements
Element Publisher.class Type Description Class file Contains api for doPublish needed for invoking publishing from code.

Runtime Location: <Windchill>\codebase\com\ptc \wvs\common\ui PublisherAction. Class file Used to create the optional actionString to be class passed to the doPublish method in Publisher. See JavaDoc for details. Runtime Location: <Windchill>\codebase\com\ptc \wvs\common\ui Class file Contains helper apis such as findRepresentable and getRepresentation often needed in custom code. Runtime Location: <Windchill>\ codebase\com\ptc \wvs\common\ui Class file Contains getCurrentContainer method needed when writing custom schedule jobs. Runtime Location: <Windchill>\codebase\com\ptc \wvs\server\schedule

Visualization Helper.class

ScheduleJobs .class

Customizing Windchill Visualization Services

1127

Element wvs.properties

Type Description Properties Contains specific properties used with the Windfile chill Visualization Service. Runtime Location: <Windchill>\codebase

Procedure Invoking Publishing from Custom Code/ Workflow


This section details how to use the following supported APIs and classes: doPublish from Publisher class see Simple Publish on page 1128 PublisherAction class for advanced use of doPublish see Advanced Publish on page 1130

To invoke publishing from custom code or from an Expression Robot in a Workflow the key method to understand and use is the supported doPublish method in the com.ptc.wvs.common.ui.Publisher class.
public boolean doPublish (boolean viewableLink, boolean forceRepublish, String objectReference, ConfigSpec configSpec, ConfigSpec partConfigSpec, boolean defaultRep, String repName, String repDescription, int structureType, String actionString, int jobSource)

For more details on this method and its parameters, see the JavaDoc in <Windchill>\codebase\wt\clients\library\api\index.html. Simple Publish You have an EPMDocument instance with publishable data and you want to create a default Representation.
String objRef = ObjectReference.newObjectReference(myepmdoc).toString(); Publisher pub = new Publisher(); boolean result = pub.doPublish(false, true, objRef, (ConfigSpec)null, (ConfigSpec)null, true, null, null, Publisher.EPM, null, 0);

1128

Windchill Customization Guide

This simple example will simply add a publish job to the publishing queue for myepmdoc. The resulting default representation named default will be published using the As-Stored or Latest ConfigSpec as defined in wvs.properties (publish. configspec.default.useasstoredifavailable). Since the forceRepublish parameter was true, an existing representation with the same name would be replaced. If you wanted to programmatically provide a name for the representation, or insert useful business information into the description modify the parameters. For example:
Publisher pub = new Publisher(); boolean result = pub.doPublish(false, true, objRef, (ConfigSpec)null, (ConfigSpec)null, true, MyRep, (ConfigSpec)null, true, MyRep, My Description, Publisher.EPM, null, 0);

The only difference between this and the previous example is that the resulting default representation will have the name MyRep and have the description My Description. If you wish to retrieve a reference to an existing Representation, set the viewableLink parameter to true and the forceRepublish parameter to false. If there is an existing Representation with the repName you provided associated to the Representable, you can call getViewableObjRef() following a call to doPublish. This will provide a String object reference if the Representation was found. Otherwise null will be returned.
String repObjRef = null; Publisher pub = new Publisher(); if (pub.doPublish(true, false, objRef, (ConfigSpec)null, (ConfigSpec)null, true, MyRep, My Description, Publisher.EPM, null, 0)) { repObjRef = pub.getViewableObjRef(); }

In addition to getting the object reference of an existing Representation, you can also get an HTML fragment to use for launching Creo View to view the representation by using the getViewableLink() api following a call to doPublish. Again, viewableLink must be true, forceRepublish must be false, and a Representation with the name passed in for repName must exist on the Representable supplied by the objRef parameter.
String repLink = null; Publisher pub = new Publisher(); if (pub.doPublish(true, false, objRef, (ConfigSpec)null, (ConfigSpec)null, true, MyRep, My Description, Publisher.EPM, null, 0)) { repLink = pub.getViewableLink();

Customizing Windchill Visualization Services

1129

Advanced Publish You have an EPMDocument instance with publishable data and you want to create a default Representation with your own configuration specification and have the publish job processed on the high priority publishing queue. The more advanced features of publishing require using the use of the PublisherAction class. See the JavaDoc for full details; a couple examples are shown below.
String objRef = ObjectReference.newObjectReference(myepmdoc).toString(); PublisherAction pa = new PublisherAction(PublisherAction.QUEUEPRIORITY, H); ConfigSpec configSpec = <MyHelper.getBaselineConfigSpec()>; Publisher pub = new Publisher(); boolean result = pub.doPublish(true, true, objRef, configSpec, null, true, null, null, Publisher.EPM, pa.toString(), 0);

You have a WTDocument with several pieces of content. For example, doc1.doc, doc2.doc and doc3.doc are all content of your WTDocument and you only wish to publish doc3.doc (by default all docs would be published).
String objRef = ObjectReference.newObjectReference(mydoc).toString(); PublisherAction pa = new PublisherAction(PublisherAction.DOCUMENTFILE, doc3.doc); Publisher pub = new Publisher(); boolean result = pub.doPublish(true, true, objRef, (ConfigSpec)null, (ConfigSpec)null, null, null, Publisher.NONE, pa.toString(), 0);

Note For WTDocuments, a ConfigSpec is not used and the structureType is Publisher. NONE.
This sort of processing could be useful if you established a business practice of naming certain content files in a particular way if you wanted them to be published.

1130

Windchill Customization Guide

Procedure Getting Representables and Representations


This section details how to use the following supported APIs and classes: findReprentable from VisualizationHelper class see findRepresentable on page 1131 getRepresentation and getRepresentations from VisualizationHelper class see getRepresentation on page 1131

The association of Representables to Representations is one to many. The key concept when finding these relationships is to understand that when you have an EPMDocument (i.e. Representable) its Representations arent necessarily directly associated. In the case where an EPMDocument has an actively associated WTPart (i.e. option of creating associated parts in the workgroup manager was used when checking-in the EPMDocument), the Representations are linked to the WTPart. In all other cases the Representations are directly associated with the Representable (i. e. non-actively associated EPMDocuments, DynamicDocuments, WTParts, WTDocuments and MPMLink Representables). findRepresentable To simplify the concept discussed above, there is a method called findRepresentable on page 1131 in com.ptc.wvs.common.ui.VisualizationHelper. This method allows you to pass in a Representable and always get back the right Representable in the case where actively associated parts are involved. In the case where there are no actively associated parts, it simply returns the object you passed in. The method signature is shown below:public Representable findRepresentable (Persistable d)
public Representable findRepresentable(Persistable findRepresentable d)

If you have custom code that is dealing with Representables, it is a good practice to use this method so you can be sure to have the right Representable that is associated to the Representations. Also, note that if you pass in a Persistable that is not a Representable, the method will return null. You must have an instance of VisualizationHelper to use this method. For example:
VisualizationHelper vizHelper = new VisualizationHelper(); Representable repable = vizHelper.findRepresentable(d);

getRepresentation In the com.ptc.wvs.common.ui.VisualizationHelper there are also some convenience methods for getting Representations from a Representable.
public Representation getRepresentation (Persistable d)

Customizing Windchill Visualization Services

1131

As noted previously, the relationship of Representables to Representations is one to many. However, one of the Representations may be noted as the default Representation. There will be 0 or 1 defaults. The above method will return the default Representation if one exists. Otherwise, null will be returned.public Representation getRepresentation (Persistable d, String repName)
public Representation getRepresentation (Persistable d, String repName)

The method above will return the Representation associated to the Persistable with the name passed in to the repName argument. If there are no Representations or one cant be found with the supplied name, null will be returned.
public QueryResult getRepresentations(Persistable getRepresentations d)

This method will return all of the Representations associated to the Persistable passed in. If there are no Representations, null will be returned. All three methods in this subsection require that you have an instance of VisualizationHelper:
VisualizationHelper vizHelper = new VisualizationHelper(); Representation rep = vizHelper.getRepresentation(d);

Note All three of the above methods make use of the findRepresentable method, so you do not need to worry about actively associated parts when calling it. Additionally, if the Persistable passed in is not a Representable, null will be returned.

Procedure Creating Custom Schedule Jobs


This section details how to use the following supported APIs and classes: Creating a custom schedule job step-by-step and using supported api getCurrentContainer from ScheduleJobs class see Custom Schedule Job Fundamentals on page 1132 Incorporating the use of doPublish from the Publisher class in your custom schedule job see An Advanced Technique for Custom Schedule Jobs on page 1135

Custom Schedule Job Fundamentals In addition to the out-of-the-box Schedule Jobs, you can also create your own custom jobs. To do this, start by creating or adding to a custom class in the Windchill codebase; for example ext.wvs.CustomJobs. In this class create a method with the following signature:
public static WTList <nameOfMethod>() or public static QuerySpec <nameOfMethod>() or public static QueryResult <nameOfMethod>()

1132

Windchill Customization Guide

You can use whatever method name you want, but it is important that the method be public, static, return a WTList and accept no arguments. Then add the following to your wvs.properties.xconf file (edit as needed):
<Property <Property <Property <Property <Property default="MyCustomJob" name="myJob.description"/> default="ext.wvs.CustomJobs" name=" myJob.class"/> default="myCustomJob" name=" myJob.method"/> default="true" name=" myJob.enableOnContainers"/> default="myJob" name="schedulejobs<N>"/>

Line 1 (<Property default="MyCustomJob" name="myJob.description"/>) is what you see in the Scheduler UI to identify your custom job. Line 2 (<Property default="ext.wvs.CustomJobs" name=" myJob.class"/>) is the fully qualified class where your custom method resides. Line 3 (<Property default="myCustomJob" name=" myJob.method"/>) is the name of your custom method. Line 4 (<Property default="true" name=" myJob.enableOnContainers"/>) defines whether or not the job code will have access to the container that the schedule job was initiated from. For example, the out-of-the-box schedule jobs only handle objects found in the container the schedule job was initiated from (i.e. Project, Product, Library, or Organization) because this value is set to true. If the value is set to false it would be the same as executing the job from the context of the Exchange container, no matter what container the schedule job was initiated from. Line 5 (<Property default="myJob" name="schedulejobs<N>/>) is to display your custom job in the Publish Scheduler Administrator. In the name string you must replace the <N> with the integer that follows that last schedulejobsN that is already defined.

Below is an example of a publish job:


public static WTlist myCustomJob() { WTList wtl = new WTArrayList(); try { QuerySpec qs = new QuerySpec(WTDocument.class); WTContainerRef cr = ScheduleJobs.getCurrentContainer(); ScheduleJobs.getCurrentContainer if (cr != null) { ContainerSpec cs = new ContainerSpec(); cs.addSearchContainer(cr); qs.setAdvancedQueryEnabled(true); qs.appendWhere( WTContainerHelper.getWhereContainerIn(cs, ,new Class[] {WTDocument.class}), new int[]{0}); } if (cr != null) qs.appendAnd(); qs.appendWhere(new SearchCondition(WTDocument.class, Iterated.LATEST_ITERATION, SearchCondition.IS_TRUE),

Customizing Windchill Visualization Services

1133

new int[]{0}); Representable doc = null; int offset = 0; BasicPageableQuerySpec bpqs = new BasicPageableQuerySpec(); bpqs.setPrimaryStatement(qs); bpqs.setOffset(offset); bpqs.setRange(1000); PagingQueryResult qr = (PagingQueryResult)PersistenceHelper.manager.find(bpqs); long sessionId = qr.getSessionId(); int total = qr.getTotalSize(); while (true) { while (qr.hasMoreElements()) { doc = (Representable)((Object[])qr.nextElement())[0]; wtl.add(doc); } offset += qr.size(); if (offset >= total) break; PageableQuerySpec pqs = new PagingSessionSpec(sessionId); pqs.setOffset(offset); pqs.setRange(1000); qr = (PagingQueryResult)PersistenceHelper.manager.find(pqs); } if (sessionId > 0) PagingSessionHelper.closePagingSession(sessionId); } catch(Exception e) {e.printStackTrace(); wtl = new WTArrayList ();} return wtl; }

Note This example contains the use of a BasicPageableQuerySpec and PagingSessions to avoid out of memory errors. See JavaDoc in the wt.query and wt.fc packages for details.
This example would effectively ask for all latest iterations of any WTDocuments found in the current container to be published. In line six of the example the following method is used from com.ptc.wvs.server. schedule.ScheduleJobs:
public static WTContainerRef getCurrentContainer() getCurrentContainer

The result of this method will be null if the schedule job was initiated from the Exchange container (Site) or if the enableOnContainers value is false in the job definition (see line four of properties shown prior to the example above). If the value of enableOnContainers is true, then a WTContainerRef of the container the schedule job was initiated from will be returned. In the example code, this is used to filter the scope of the query to the Organization or the Product/Project/Library container the schedule job was initiated from.

1134

Windchill Customization Guide

Note You can have multiple custom schedule jobs. Just use another method name in the same class, or use a new class altogether. For example:
public static WTList anotherCustomJob(); anotherCustomJob

Then add the following to your wvs.properties.xconf file (edit as needed):


<Property default="AnotherCustomJob" name="anotherJob.description"/> <Property default="ext.wvs.CustomJobs" name=" anotherJob.class"/> <Property default="anotherCustomJob" name=" anotherJob.method"/> <Property default="true" name=" anotherJob.enableOnContainers"/> <Property default="anotherJob" name="schedulejobs<N>"/>

An Advanced Technique for Custom Schedule Jobs Using the technique in the Custom Schedule Job Fundamentals on page 1132 does not allow you to provide input to creating the Publish Job and specify the name of the Representation, description of the Representation, etc. Combining the concepts in theProcedure Invoking Publishing from Custom Code/Workflow on page 1128 with the Custom Schedule Job Fundamentals on page 1132 can open up a lot of flexibility for schedule jobs. The technique simply requires you to insert the use of the doPublish method from the Publisher class into your myCustomJob method. Since myCustomJob must return a QueryResult, simply return an empty QueryResult as the doPublish method will now cause Publish Jobs to be queued up for execution.
public static WTList myCustomJob() { WTList wt = new WTArrayList(); try { QuerySpec qs = new QuerySpec(WTDocument.class); WTContainerRef cr = ScheduleJobs.getCurrentContainer(); if (cr != null) { ContainerSpec cs = new ContainerSpec(); cs.addSearchContainer(cr); qs.setAdvancedQueryEnabled(true); qs.appendWhere( WTContainerHelper.getWhereContainerIn(cs, WTDocument.class), new int[]{0}); } if (cr != null) qs.appendAnd(); qs.appendWhere(new SearchCondition(WTDocument.class, Iterated.LATEST_ITERATION, SearchCondition.IS_TRUE), new int[]{0}); Representable doc = null; String objRef; int offset = 0; BasicPageableQuerySpec bpqs = new BasicPageableQuerySpec(); bpqs.setPrimaryStatement(qs);

Customizing Windchill Visualization Services

1135

bpqs.setOffset(offset); bpqs.setRange(1000); PagingQueryResult qr = (PagingQueryResult)PersistenceHelper.manager.find(bpqs); long sessionId = qr.getSessionId(); int total = qr.getTotalSize(); while (true) { while (qr.hasMoreElements()) { doc = (Representable)((Object[])qr.nextElement())[0]; objRef = ObjectReference.newObjectReference(doc).toString(); Publisher pub = new Publisher(); Publisher(); pub.doPublish pub.doPublish(false, (false, true, objRef, (ConfigSpec)null, (ConfigSpec)null, (ConfigSpec)null, (ConfigSpec)null, true, "My Rep", "My Description", Publisher.NONE, Publisher.NONE, null, 0); 0) } offset += qr.size(); if (offset >= total) break; PageableQuerySpec pqs = new PagingSessionSpec(sessionId); pqs.setOffset(offset); pqs.setRange(1000); qr = (PagingQueryResult)PersistenceHelper.manager.find(pqs); } if (sessionId > 0) PagingSessionHelper.closePagingSession(sessionId); } catch(Exception e) {e.printStackTrace();} return new wtl; }

This is the same example used in Custom Schedule Job Fundamentals on page 1132, but notice the use of the doPublish method shown in bold. This custom job will now create Representations with the name My Rep and a description of My Description. Also, note that the returned WTList from the method is empty. Refer to Procedure Invoking Publishing from Custom Code/Workflow on page 1128 for see other useful ways to use the doPublish method.

Procedure Customizing Check-in Check-in Based Publishing


This section details how to use the following property-driven custom hooks: publish.service.filterepmdocumentpublishmethod see Filter Publishing for EPMDocument Check-in on page 1137 publish.service.filterdocumentpublishmethod see Filter Publishing for WTDocument Check-in or Upload on page 1138 Incorporating the use of doPublish from the Publisher class in your custom hook code see An Advanced Technique for General Publishing on page 1141
Windchill Customization Guide

1136

Filter Publishing for EPMDocument Check-in Once publishing is configured for an Authoring Application (i.e. Creo) publishing will occur out-out-of-the box for all EPMDocuments of that Authoring Application that are checked-in. Sometimes there are business reasons for filtering out some EPMDocuments from publishing based on some criteria. For example a certain lifecycle state, EPMDocumentType, EPMDocSubType, etc. Windchill Visualization Services has a code hook available where you can plug in code to filter on such criteria. In a custom class you can define a method with the following signature:
public static Boolean epmFilterMethod(EPMDocument epmFilterMethod epmdoc)

You can use whatever name you want in place of epmFilterMethod. Make sure the class that contains your custom method is accessible in the Windchill codebase (i.e. ext.wvs.MyFilterMethods). The next step is to add the class and method to wvs.properties.xconf. The following property is empty out-of-the-box. Update it to include your class and filter method in the format class/method.
<Property default="ext.wvs.MyFilterMethods/epmFilterMethod" name="publish.service.filterepmdocumentpublishmethod"/>

Once you make the change use the xconfmanager to propagate the changes to wvs. properties. Every time a check-in occurs where publishing of an EPMDocument would normally occur, this method will now be invoked. If the method returns Boolean. TRUE publishing will be attempted for the specific EPMDocument. If the method returns Boolean.FALSE, publishing will not be attempted. The following is a simple example of how to filter out a specific EPMDocumentType:
public static Boolean epmFilterMethod(EPMDocument epmdoc) { if (epmdoc.getDocType().equals( EPMDocumentType.toEPMDocumentType("MANIKIN_POSTURE"))) { return Boolean.FALSE; } return Boolean.TRUE; }

This is another example where you can filter out the publishing of EPMDocuments that are in the LifeCycle state of InWork.
public static Boolean epmFilterMethod(EPMDocument epmdoc) { if (epmdoc.getLifeCycleState() != State.INWORK) { return Boolean.TRUE; } return Boolean.FALSE; }

Customizing Windchill Visualization Services

1137

Filter Publishing for WTDocument Check-in or Upload Very similar to filtering publishing for EPMDocuments, there is a means for filtering for WTDocument publishing as well. For example, you may want to filter based on specific filenames, lifecycle state, container, etc. If the system has a worker configured for publishing specific WTDocument content, a custom filter method can be used to keep certain content from being published. In a custom class you can define a method with the following signature:
public static Boolean docFilterMethod(WTDocument docFilterMethod doc, ContentItem ci)

You can use whatever name you want in place of docFilterMethod. Make sure the class that contains your custom method is accessible in the Windchill codebase (i.e. ext.wvs.MyFilterMethods). Notice that this method differs from the EPMDocument filter method signature by including ContentItem as a parameter. This method is called for each ContentItem associated to the WTDocument on check-in. It is also called for uploads. For example if you had a WTDocument with .doc file as primary content and a .xls file as secondary content, this method would be called twice; once with each content item (pending a worker was associated to both types of content). The next step is to add the class and method to wvs.properties.xconf. The following property is empty out-of-the-box. Update it to include your class and filter method in the format class/method.
<Property default="ext.wvs.MyFilterMethods/docFilterMethod" name="publish.service.filterdocumentpublishmethod"/>

Once you make the change use the xconfmanager to propagate the changes to wvs. properties. Every time a check-in or upload occurs where publishing of WTDocument content would normally occur, this method will now be invoked. If the method returns Boolean.TRUE publishing will be attempted for the specific WTDocument ContentItem. If the method returns Boolean.FALSE, publishing will not be attempted. The following example shows how to filter if the WTDocuments description is Do Not Publish, or if the filename of the content starts with donotpublish.
public static Boolean docFilterMethod(WTDocument doc, ContentItem ci) { if (doc.getDescription().equals("Do Not Publish")) { return Boolean.FALSE; } if (ci instanceof ApplicationData) { String filename = ((ApplicationData)ci).getFileName(); if (filename.startsWith("donotpublish") { return Boolean.FALSE; } }

1138

Windchill Customization Guide

return Boolean.TRUE; }

An Advanced Technique for Custom Check-in Based Publishing Using the techniques in Filter Publishing for EPMDocument Check-in on page 1137 and Filter Publishing for WTDocument Check-in or Upload on page 1138 do not allow you to provide input for creating Publish Jobs to specify the name of the Representation, description of the Representation, etc. Combining the concepts in Procedure Invoking Publishing from Custom Code/Workflow on page 1128 with the concepts in Filter Publishing for EPMDocument Check-in on page 1137 and Filter Publishing for WTDocument Check-in or Upload on page 1138 can open up a lot of flexibility for check-in based publishing. The technique simply requires you to insert the use of the doPublish method from the Publisher class into the epmFilterMethod or the docFilterMethod shown in the previous subsections. Since the two filter methods must return a Boolean, simply return Boolean.FALSE and use the doPublish method to cause Publish Jobs to be queued up for execution.
public static Boolean epmFilterMethod(EPMDocument epmdoc) { if (epmdoc.getDocType().equals( EPMDocumentType.toEPMDocumentType("MANIKIN_POSTURE"))) { return Boolean.FALSE; } String objRef = ObjectReference.newObjectReference(epmdoc).toString(); Publisher pub = new Publisher(); pub.doPublish(false, true, objRef, (ConfigSpec)null, (ConfigSpec)null, (ConfigSpec)null, "My Rep", "My Description", Publisher.EPM, Publisher.EPM, null, 0); return Boolean.FALSE; }

This is the same example used in Filter Publishing for EPMDocument Check-in on page 1137 , but notice the use of the doPublish method shown in bold. This custom job will now create Representations with the name My Rep and a description of My Description. Also, note that the returned Boolean from the method is Boolean.FALSE. Refer back to Procedure Invoking Publishing from Custom Code/Workflow on page 1128 for see other useful ways to use the doPublish method.

Customizing Windchill Visualization Services

1139

Procedure Customizing General Publishing


This section details how to: Use the property-driven hook: publish.service.filterpublishmethod see Filtering All Publishing on page 1140 Incorporate the use of doPublish from the Publisher class in your custom hook see An Advanced Technique for General Publishing on page 1141

Filtering All Publishing In addition to the filters specifically for EPMDocuments and WTDocuments described in Procedure Customizing Check-in Based Publishing on page 1136, Windchill Visualization Services has a more general hook that is called for anything that can be published (including EPM and WTDocuments). In addition to supporting the filtering of all Representables, this hook also includes publishing of pre-converted data. In a custom class you can define a method with the following signature:
public static Boolean filterMethod(Persistable filterMethod p, Boolean publishFromDB)

You can use whatever name you want in place of filterMethod. Make sure the class that contains your custom method is accessible in the Windchill codebase (i.e. ext. wvs.MyFilterMethods). This method includes a publishFromDB parameter. This Boolean will come in as Boolean.TRUE if the publish is being invoked for data stored in Windchill, i.e. content of an EPMDocument or WTDocument object. The value will come in as Boolean.FALSE if the publish is for data not stored in Windchill, i.e. local data converted from the file system or data from the clipboard. You can use the value of publishFromDB to have your custom code handle the two cases specifically if you wish. The next step is to add the class and method to wvs.properties.xconf. The following property is empty out-of-the-box. Update it to include your class and filter method in the format class/method.
<Property default="ext.wvs.MyFilterMethods/filterMethod" name="publish.service.filterpublishmethod"/>

Once you make the change use the xconfmanager to propagate the changes to wvs. properties. Every time publishing would normally occur, this method will now be invoked. If the method returns Boolean.TRUE publishing will be attempted for the Persistable. If the method returns Boolean.FALSE, publishing will not be attempted.

1140

Windchill Customization Guide

The following is a simple example of how to filter out publishing of the content if the Persistable is LifeCycleManaged and in its final phase of its LifeCyle:
public static Boolean filterMethod(Persistable p, Boolean publishFromDB) { if (!publishFromDB) return Boolean.TRUE; if (!(p instanceof LifeCycleManaged)) return Boolean.TRUE; try { if (LifeCycleHelper.service.isInFinalPhase((LifeCycleManaged)p)) { return Boolean.FALSE; } } catch (WTException wte) { wte.printStackTrace(); } return Boolean.TRUE; }

Note In the above example the second line states that if the data requested for publishing is not from the Windchill DB, then just return true. For example if someone is publishing data on a WTPart that was uploaded from their local disk, we are saying we don't wish to filter this out and to simply return Boolean.TRUE.
An Advanced Technique for General Publishing Combining the concepts in Procedure Invoking Publishing from Custom Code/ Workflow on page 1128 with Filtering All Publishing on page 1140 n you can open up additional flexibility for general publishing. The technique simply requires you to insert the use of the doPublish method from the Publisher class into the filterMethod shown in the previous subsection. Since the filter method must return a Boolean, simply return Boolean.FALSE and use the doPublish method to cause Publish Jobs to be queued up for execution. For example you want to provide specific naming information for publishes that were not made from Windchill stored data.
public static Boolean filterMethod(Persistable p, Boolean publishFromDB) { if (publishFromDB) return Boolean.TRUE; try { String objRef = ObjectReference.newObjectReference(p).toString(); Publisher pub = new Publisher(); pub.doPublish(false, true, objRef, (ConfigSpec)null, (ConfigSpec)null, true, Not From Windchill Data, , Publisher.NONE, null, 0); } catch (WTException wte) { wte.printStackTrace(); } return Boolean.FALSE; }

Customizing Windchill Visualization Services

1141

Note In the example above that the second line states that if we have publishing requested for data from Windchill stored data, just return Boolean.TRUE. For example if the request was to publish the primary content of a WTDocument we just want to return Boolean.TRUE.

Limitations
Customization Boundaries
PTC does not support the customizations of the out-of-the-box CadConvert classes (a.k.a. Publishers), the Worker Agent, or the WVS Loader. These components of WVS were not intended for customization and there is no guarantee that future releases would not break customizations attempted with these components.

Custom Schedule Job Performance


Though schedule jobs are run in the background using queues, it is possible to create very resource intensive queries to return in your custom code. The examples in theProcedure Creating Custom Schedule Jobs on page 1132 section showed one technique of using paging to help avoid problems caused by dealing with large result sets. Be sure your custom schedule jobs are tested on production-like datasets. What works for cases where the result is 100 does not always work as well when you have 10s or 100s of thousands of results.

Custom Check-in Check-in Filtering Performance


Keep in mind with using the check-in filter techniques shown in Procedure Customizing Check-in Based Publishing on page 1136 that your method will be ran for every Representable that is a candidate for publishing. You method should be efficient and try to do as little as possible to determine cases where the true or false result can be returned. If some intense logic needs to occur in the filter method, do all you can to rule out the need before executing it.

Additional Resources
Java Development: http://java.sun.com The "Visualization Services" chapter in the Windchill Business Administrator's Guide

wvs.properties.xconf file in your <Windchill>\codebase directory.

1142

Windchill Customization Guide

Related Package/Class Package/Class Javadoc


com.ptc.wvs.common.ui com.ptc.wvs.server.schedule

Other Related Windchill Documentation


Windchill Business Administrator's Guide Configuration Guide Visualization Services Object Adapters

Customizing Windchill Visualization Services

1143

Interference Detection
You want the Description, Assignee and State for new and existing Interferences in an Interference Report to be set to specific values when Windchill Visualization Services (WVS) is processing Interference Detection results generated by the ProductView Client Adapter. You also want to change the out-of-the-box behavior as to how WVS determines equivalency between Interferences contained in multiple reports. Background When an Interference Definition has been submitted for Interference Detection, the Interference results are returned to WVS to be processed. Based on these results, WVS will create a new Interference Report and associate new or existing Interference objects to that report. Each Interference object has Description, Assignee and State attributes with corresponding out-of-the-box values of blank, unassigned and Open. For the State attribute, the default value of Open is determined by the out-of-box lifecycle template and maybe different depending on the lifecycle template in use. This document will describe how to customize WVS to automatically set the Description, Assignee and State based on customer business needs. Additionally, the first time an Interference Definition is submitted for Interference Detection, only new Interference objects are created. All subsequent submissions of the same Interference Definition will result in a new Interference report that may have existing Interference objects from previous reports. The WVS Interference processor has the ability to identify if existing Interference objects already exist and link them to the new Interference report rather than creating new ones. The processor conforms to a set of rules for determining if an Interference described in the results returned from the ProductView Client Adapter matches an Interference object already associated to the current definition. This document explains how to customize these set of rules for determining equivalency between Interferences. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions Custom Interference Detection should be used if the default values for Description, Assignee and State for new or existing Interference objects are not adequate. Also should be used if the out-of-the-box rules for determining Interference equivalency doesnt meet requirements. Intended Outcome Using this best practice will allow end users to perform Interference Detection in a manner that addresses their business requirement whenever the out-of-the-box Interference mechanisms are not sufficient.

1144

Windchill Customization Guide

Solution
Customize Interference Detection by implementing public WVS APIs in custom code and making WVS aware of this custom code via appropriate WVS property changes. Prerequisite Knowledge To apply this best practice, you need to have an understanding of the following: Java Development WVS Interference Detection concepts such as Interference Definition and Interference Report.

The Additional Resources section below includes references to many or all of these subjects. Solution Elements Element Interference DetectionHooks .java

Type Java file

Description Contains example code for implementing the customizations that this document describes. Runtime Location: Windchill /prog_examples /wvs/com/ptc /wvs/Interference DetectionHooks .java Represents all information regarding a single Interference contained in an Interference Report generated by the ProductView Client Adapter. Used by the WVS Inteference processor for creating new Interference objects or updating existing ones. Runtime Location: <Windchill>/ codebase/com/ptc/

InterferenceInfo.class

Class file

Customizing Windchill Visualization Services

1145

Element

Type

WTDocument.class

Class file

Description wvs/server/ publish/ InterferenceInfo .class An Interference Definition is a Soft Type of WTDocument. Runtime Location: <Windchill>/ codebase/wt/doc/ WTDocument.class Contains specific properties to configure the Windchill Visualization Service to utilize specific customization code. Runtime Location: <Windchill>/ codebase/wvs. properties.xconf All Interference and Interference Report objects in Windchill are LifeCycleManaged WtMarkUps. Runtime Location: <Windchill> /codebase/ wt/ viewmarkup /LifeCycleManaged WtMarkUp.class

wvs.properties.xconf

XConf file

LifeCycleManagedWtMarkUp

Class file

Procedure : Invoke Customization for Determining Interference Attributes Complete the following steps to create a custom hook for setting Interference attributes such as Assignee, Description and State. 1. Create a Java class with a static method in which the arguments and return type matches the method defined in the following example. This customization will return a set of attribute values that will be used to update an existing
Windchill Customization Guide

1146

Interference object and will return a different set of attribute values for new Interference objects that will be created. For existing Interference objects, this example customization will honor the existing Assignee, update the description and set the state to Open if the current state is Closed. It is assumed that the out-of-the-box lifecycle template is in use and there for the states of OPEN, ASSIGNED, CLOSED are available. For new Interference objects that will be created, the Assignee will be set to the modifier of one of the interfering parts, new description value and state will be set to ASSIGNED.
package ext.customhooks; class MyCustomClass { public static Map <InterferenceInfo, Object[]> getInterferenceAttribute Values( Collection <InterferenceInfo> _allInterferenceInfo, WTDocument _interferenceDefinition) throws WTException { Map <InterferenceInfo, Object[]> attributeValueMap = new HashMap <InterferenceInfo, Object[]>(); // Add all interfering part references to a Collection and inflate with one DB query. WTHashSet allInterferingParts = new WTHashSet(_allInterferenceInfo .size() * 2); for (InterferenceInfo interferenceInfo : _allInterferenceInfo) { if (interferenceInfo.getInterferencePartReference1() != null) allInterferingParts.add(interferenceInfo.getInterference PartReference1()); if (interferenceInfo.getInterferencePartReference2() != null) allInterferingParts.add(interferenceInfo.getInterference PartReference2()); } CollectionsHelper.inflate(allInterferingParts); // Loop through all Interference Info and define an Assignee, Description and State // for new and existing Interferences. for (InterferenceInfo interferenceInfo : _allInterferenceInfo) { Object[] attributeValues = new Object[3]; // If the WVS Interference processor has determined that this Interference Info // instance represents an existing Interference object, return attribute values // that will be used to update the existing Interference. if (interferenceInfo.isRepresentedByExistingInterference()) { attributeValues[0] = new Object(); // Honor existing assignee by returning a different type attributeValues[1] = "Updating Description. Old Description was:" + interferenceInfo.getExistingDescription();

Customizing Windchill Visualization Services

1147

State state = interferenceInfo.getExistingState(); if (state != null && state.getStringValue().contains("CLOSED")) { attributeValues[2] = "OPEN"; } else { attributeValues[2] = null; // Setting to null will honor the existing state. } } // Else if the WVS Interference processor has determined that this Interference Info // instance does not represent an existing Interference object, return attribute values // that will be used to create a new Interference object. else { if (interferenceInfo.getInterferencePartReference1() != null) { Persistable p = interferenceInfo.getInterferencePartReference1(). getObject(); WTPrincipalReference assignee = ((RevisionControlled)p) .getModifier(); attributeValues[0] = assignee; attributeValues[1] = "New Interference Description"; // The String value of a state may look like: "wt.lifecycle.State.ASSIGNED". Just // need to specify enough characters that refer to one of the unique states. The // string match uses the "contains" method. attributeValues[2] = "ASSIGNED"; } } attributeValueMap.put(interferenceInfo, attributeValues); } return attributeValueMap; } }

2. Update <Windchill>/codebase/wvs.properties.xconf to configure the WVS Interference processor to call the customization hook. For more information on how to accomplish this step, review the documentation for the property interferencedetection.report.getinterferenceattributevaluesmethod in the wvs. properties.xconf. For configuring this example, the XConf entry will be:
<Property name="interferencedetection.report. getinterferenceattributevaluesmethod " default ="ext.customhooks.MyCustomClass/getInterferenceAttributeValues"/>

1148

Windchill Customization Guide

Procedure : Invoke Customization to Change the Default Set of Rules for Determining Interference Equivalency. The WVS Interference processor needs to determine if an Interference described in an Interference Report generated by a ProductView Client Adapter is equal to any Interference objects already associated to the Interference Definition that exists in an Interference Report created in a prior execution. The default set of rules used for determining if an existing Interference object is equal to an Interference described in an Interference Report are: The Master References of the two parts that are interfering must be equal. The Component Instance Paths of the two parts that are interfering must be equal. The type of Interference must be the same.

Complete the following steps to create a custom hook for overriding the default rules for determining Interference equivalency. 1. Create a Java class with a static method in which the arguments and return type matches the method defined in the following example. This customization will use all the default rules for determining equivalency first by calling a WVS API. If the API returns true, then make an additional check to be sure that the Interference items group names are also equivalent.
package ext.customhooks; class MyCustomClass { public static boolean isInterferenceEquivalent(InterferenceInfo _ interferenceInfo, LifeCycleManagedWtMarkUp _interferenceMarkUp) throws WTException { boolean isEquivalent = false; try { /** * Invoke the default rules and if the two are equivalent, perform one additional check to be * sure that the groups match. */ if (InterferenceDetectionHelper.isInterferenceEquivalent DefaultRulesOnly( _interferenceInfo, _interferenceMarkUp)) { String groupName1 = (_interferenceInfo.getInterference PartGroupName1() == null) ? "" : _interferenceInfo.getInterference PartGroupName1(); String groupName2 = (_interferenceInfo.getInterference PartGroupName2() == null) ? "" : _interferenceInfo.getInterference PartGroupName2();

Customizing Windchill Visualization Services

1149

AdditionalProperties markupProperties = new AdditionalProperties( _interferenceMarkUp.getAdditional Properties()); String existingGroup1 = (String)markupProperties. get( INTERFERENCE_PROPERTIES.INTERFERENCE_PART _GROUP_NAME_1); String existingGroup2 = (String)markup Properties.get( INTERFERENCE_PROPERTIES.INTERFERENCE _PART_GROUP_NAME_2); existingGroup1 = (existingGroup1 == null) ? "" : existingGroup1; existingGroup2 = (existingGroup2 == null) ? "" : existingGroup2; if ((groupName1.equals(existingGroup1) && groupName2.equals (existingGroup2)) || (groupName1.equals(existingGroup2) && groupName2.equals (existingGroup1)) ) { isEquivalent = true; } } } catch (InvalidPropertiesFormatException e) { logger.error("Exception occured in customization method isInterferenceEquivalent", e ); } catch (IOException e) { logger.error("IOException occured in customization method isInterferenceEquivalent", e ); } return isEquivalent; } }

2. Update <Windchill>/codebase/wvs.properties.xconf to configure the WVS Interference processor to call the customization hook. For more information on how to accomplish this step, review the documentation for the property interferencedetection.report. getinterferenceattributevaluesmethod in the wvs.properties.xconf. For configuring this example, the XConf entry will be: <Property name="interferencedetection.report. isinterferenceequivalentmethod " default="ext. customhooks.MyCustomClass/isInterferenceEquivalent"/>

1150

Windchill Customization Guide

Customization Points
Custom Method: getInterferenceAttributeValues Parameter Collection<InterferenceInfo> Description The WVS Interference processor will pass in a Collection of all Interference Information extracted from an Interference Report generated by the ProductView Client Adapter. A reference to the Interference Definition in which the new Interference Report and Interference objects will be associated to. Description Must return a Map in which the key will be the original InterferenceInfo instance passed in and the value will be an Object array of attribute values in which the newly created Interference object or the existing Interference object will be initialized or set to. index 0 WTPrincipalReference to assign the Interference to. If set to null, then the Interference object will be set to unassigned. If set to a different type other than WTPrincipalReference ( e.g Object), then the assignee will be unchanged. index 1 String to set the description to. If set to null, then the Interference object will be set with an empty description. If set to a different type other than String, then the description will be unchanged. index 2 String to set the State to. All states have a String representation. For example, the assigned state string value is wt.lifecycle.State.ASSIGNED in the out-of-the-box lifecycle template. If returning ASSIGNED, the assigned state will be set on the Interference object. If set to null or different object type, then the state will be unchanged.

WTDocument

Return Map<InterferenceInfo, Object[]>

Customizing Windchill Visualization Services

1151

Custom Method: isInterferenceEquivalent Parameter InterferenceInfo Description The WVS Interference processor will pass in a single InterferenceInfo instance with all information extracted from an Interference Report generated by the ProductView Client Adapter. This parameter is an existing Interference object that is associated to a different Interference Report Description Will return true only if the two parameters are considered equal. The WVS Interference processor uses the result to determine when to create new Interference object verses associating an existing Interference object to a new Interference Report.

LifeCycleManagedWtMarkUp

Return boolean

Limitations
The customization for setting Interference attribute values only supports Assignee, Description and State attributes.

Sample Code
Simple examples provided in the Solution section. For more comprehensive examples, see InterferenceDetectionHooks.java located in <Windchill>/prog_examples/wvs/com/ptc/wvs.

Additional Resouces
WVS: See Visualization Services Chapter in the Windchill Business Administrator s Guide WVS: See wvs.properties.xconf file in your <Windchill>\codebase directory. See InterferenceDetectionHooks.java located in <Windchill>\prog_examples\wvs \com\ptc\wvs

1152

Windchill Customization Guide

26
Report Generation
Overview .............................................................................................................. 1155 Basic Report Example ........................................................................................... 1155 Import and Export of Report Templates.................................................................... 1156 Java Methods........................................................................................................ 1159 Customization Details ............................................................................................ 1160 Cognos Presentation Customization ....................................................................... 1179 Reporting Info*Engine Task Data Source Customization ........................................... 1185 Report Loading...................................................................................................... 1191 ReportTemplate Data Source Customization............................................................ 1200 Reporting Input Page Customization ....................................................................... 1204 Report Localization Customization .......................................................................... 1209 Report Selection List Customization ........................................................................ 1215

This chapter describes report generation tools that provide the following functionality: Definition of a broad range of queries against Windchill data using a graphical interface rather than Java programming. Use of these queries to generate reports in several output formats, including HTML, XML, and CSV. Customization of queries and output formats, and re-use of queries and output formats from other customizations. Customization of the Windchill Business Reporting (Cognos) report presentation, data sources, and other features.

1153

To author new queries using existing report formats, you need only be familiar with the UML model for the business objects of interest for the query and have an understanding of the query definition tool. Because the report generation tools build on the capabilities of the Windchill foundation and use HTML, CSS, XML, and XSL technologies, you should also be familiar with these areas to use the tools most effectively for customization.

1154

Windchill Customization Guide

Overview
Reports are generated by applying presentation information to query result data. Queries are built using the Windchill Query Builder tool and stored as a report template business object in Windchill. When a report template query is executed, it operates against the current database and produces output in the form of Java objects or XML. Reports are generated from XML output by applying presentation transformations defined by XSLT (Extensible Stylesheet Transformation) stylesheets. The combination of XML and XSLT allows for a separation between data collection and formatting, thus facilitating separate customization of each. When defining report template objects, you can select from out-of-the-box XSLT formats or specify custom XSLT stylesheets to meet your formatting needs.

Basic Report Example


The Query Builder help includes a step-by-step tutorial for creating a new query. Each step of the tutorial includes links to the relevant help topics for that step.

Report Generation

1155

Import and Export of Report Templates


Two command line utilities are available for import and export of report templates to and from the database. The import utility, LoadReportTemplate, can be used in a standalone manner or from within wt.load.Demo. The export utility, ExportReportTemplate, is available in standalone mode only.

Note Individual report templates can be imported and exported using the Import and Export actions available from Report Management . For more information, see the help available from Report Management .
The LoadReportTemplate utility persists report template objects to the database based on input from an XML file. In this file, each report template object is defined in a csvReportTemplate element. The content of these elements are defined as follows: csvReportTemplate Description element csvfolder Required. This entry is the location of the report templates in Windchill Explorer. If the specified folder does not exist, one is created. csvname Required. csvdescription Optional. csvxml Required. This entry specifies a path to the XML source file. This file is parsed and then validated against the QML DTD (<Windchill>/codebase/wt/ query/qml/qml.dtd). The path is first assumed to be an absolute file path. If the file is not found, the path is then assumed to be relative to the <Windchill>/ loadfiles directory. csvxsltype The XSLT designation; possible options include the following: DEL (delegation), which allows selection from a set of defined XSLT formats. URL, which offers selection of a customized XSLT stylesheet.

csvservice

No entry, which requires the user to select a format style at report template generation time. If the XSLT designation is DEL, this column is required. The formats currently available are as follows:

1156

Windchill Customization Guide

csvReportTemplate element

Description HTML CSV TSV XML PDF HTMLWithSorting HTMLWithMerging MSWord2000Portrait MSWord2000Landscape Optional. This column specifies a container where the report should be stored. If no value is specified, the site container is used by default. If the XSLT designation is URL, this column is required and should contain a URL pointing to a customized XSLT stylesheet. This column is used only if the XSLT designation is URL and, even then, is optional. It defines a second URL location for an XSLT stylesheet. Optional. This entry specifies an input page for the Report. Optional. This entry specifies a resource bundle for the Report.

csvContainerPath

csvurl1

csvurl2

csvinputPage csvresourceBundle

An out-of-the-box XML file, reporttemplates.xml, is provided along with several sample XML source files. These XML files are used for persisting sample report templates during wt.load.Demo. The reporttemplates.xml file is located in <Windchill>/loadFiles and the sample XML files are located in <Windchill>/ loadFiles/reports. There are three options for using the LoadReportTemplate utility in standalone mode: java wt.query.template.LoadReportTemplate No parameters indicate that the default sample files defined earlier are being used. java wt.query.template.LoadReportTemplate c:\loadReports.xml The parameter indicates the absolut path of a user-defined XML file. java wt.query.template.LoadReportTemplate loadReports.xml

Report Generation

1157

The parameter indicates the relative path of a user-defined XML file. The ExportReportTemplate utility downloads multiple, persisted report template objects from the database to the relative file exportreports.xml. This file has the same structure as defined above. The ExportReportTemplate utility has three optional parameters: The first parameter specifies a string to use to search for report template objects by name. The "%" symbol can be used as a wildcard to match any number of characters in the name. If this parameter is not specified, all report template objects are exported. The second parameter specifies the path of the container in which to search. If this parameter is not specified, the site container is searched to find the report template. The third parameter specifies whether the container should be searched hierarchically. If the value is true, the criteria will match the specified container or any of its parent containers. If the value is false, only the specified container will be matched. If this parameter is not specified, a value of true is used.

The following example exports all report template objects in the site container that have a name starting with the characters "monthly":
java wt.query.template.ExportReportTemplate monthly%

The following example exports all report template objects in the Windchill PDM library, the DefaultOrg organization, and site containers that have a name starting with the characters "monthly":
java wt.query.template.ExportReportTemplate monthly% "/wt.inf.container.OrgContainer= DefaultOrg/wt.inf.library.WTLibrary=Windchill PDM"

The following example exports all report template objects in the Windchill PDM library that have a name starting with the characters "monthly":
java wt.query.template.ExportReportTemplate monthly% "/wt.inf.container.OrgContainer= DefaultOrg/wt.inf.library.WTLibrary=Windchill PDM" false

1158

Windchill Customization Guide

Java Methods
The ability to call Java methods has been added to make report authoring easier. Because Java methods are always invoked in a method server, to ensure security only those Java methods specified in a configuration file can be invoked in a report. By default, this configuration file is:
<Windchill>\conf\queryBuilderMethods.xml

where <Windchill> is the installed location of your Windchill solution.

Note The default configuration file can be overridden by setting the wt.query.qml. allowedMethodsXMLFile property in wt.properties.
The following attributes are used in specifying the Java methods in the configuration file: classThe package and class containing the method. This attribute is required. nameThe name of the method. This attribute is required. staticIndicates whether the method is a static method. This attribute is optional, and if not specified the value is assumed to be false.

The format for specifying a Java method in the configuration file is shown in the following example:
<methods> <method class="java.lang.Object" name="toString"/> <method class="java.lang.Object" name="getClass"/> <method class="example.HelloWorld" name="example" static="true"/> </methods>

To add a new Java method, add a new method element to the configuration file, as shown in the example. Java methods can be removed from the configuration file, removing them from availability for use in authoring reports, by deleting its method element. The available methods can be reloaded from within the Query Builder utility by selecting the File Reload Java Methods action. There is no need for a server restart. Once reloaded, the Java methods and classes in the configuration file can be added on the Select tab of the Query Builder while creating or editing reports.

Report Generation

1159

Customization Details
After a report exists, there are a number of ways to customize various aspects of the report: Customizing Macros on page 1160 Customizing Query Builder Types on page 1162 Customizing the Report Output Format on page 1162 Customizing the Report Generation Client on page 1174 Customizing the Report Generation URL on page 1176

For reports using custom input pages, additional customizations are supported:

Customizing Macros
Customizing macros uses the standard Windchill application services delegation mechanism. This customization example creates a new macro to automatically compute a cutoff time. 1. Create a class that implements the MacroExpressionProcessor interface by performing the following steps: a. Create a new package or use an existing one. Name the package, for example, myPackage. b. Create a new class and inherit from the MacroExpressionProcessor interface in the wt.query.report package. Name the class, for example, TimeCutoffMacroProcessor. c. Compile the class. d. Fill in the implementation of the buildExpression( ) method. This implementation reads the current system time in milliseconds, computes the new time, and creates a new Date. The Date value is returned as a wt.query. DateExpression. This is necessary because of special handling of dates in SQL expressions to take into account Java representation of dates and timezone settings.
public class TimeCutOffMacroProcessor implements MacroExpressionProcessor { @Override public ColumnExpression buildExpression( Element a_element, Map a_parameterMap ) throws QMLException { final int DAYS=3; long currentSeconds= (System.currentTimeMillis()/1000); long timeSeconds= currentSeconds - (60*60*24*DAYS); java.util.Date time= new java.util.Date(timeSeconds * 1000);

1160

Windchill Customization Guide

return (ColumnExpression) DateExpression.newExpression(time, Timestamp.class.getName()); }

@Override public Object getValue()throws WTException{ java.util.Date time1= new java.util.Date(); return time1; } }

e. Fill in the implementation of the getValue( ) method. This value is the actual Date value as computed in the preceding step. 2. Create a logical name for the macro and map it to the implementation class. For example, for logical name "TIME_CUTOFF" and class "myPackage. TimeCutoffMacroExpressionProcessor", the entry would be as follows:
wt.services/svc/default/wt.query.report.MacroExpressionProcessor/ TIME_CUTOFF/java.lang.Object/0=myPackage.TimeCutoffMacroProcessor/singleton

The OOTB entries that exist in dbservice.properties.xconf are:


<Service context="default" name="wt.query.report.MacroExpressionProcessor"> <Option cardinality="singleton" requestor="java.lang.Object" selector="CURRENT_TIME" serviceClass= "wt.query.report.CurrentTimeMacroProcessor"/> <Option cardinality="singleton" requestor="java.lang.Object" selector="CURRENT_USER_NAME" serviceClass= "wt.query.report.UserNameMacroProcessor"/> <Option cardinality="singleton" requestor="java.lang.Object" selector="TIME_CUT_OFF" serviceClass="ext.mypkg.TimeCutOffMacroProcessor"/> </Service>

3. Create a new report query that uses the new macro by performing the following steps: a. Open the existing Foldered query and save it as a new query, for example, FolderedModified. b. Remove the criteria based on cabinet name. c. Add criteria. On the Criteria tab, set the following values as shown in the following table: Field Class Attribute Operator Value Value Foldered thePersistInfo.modifyStamp > TIME CUTOFF

Report Generation

1161

The TIME_CUTOFF macro is now available for use in reports from the
Criteria tab of the Query Builder .

d. Save the query. 4. Execute the report. For reports that use macros in criteria or default values, Query Builder evaluates the macro at runtime and displays the resulting value in the Criteria pane of the report generation window. It is also possible to use a macro as input in a Criteria pane input field. The macro name should start and end with the $$ characters to denote the value as a macro. For example, to use the out-of-the-box CURRENT_USER_NAME macro in an input field, enter the value as $ $CURRENT_USER_NAME$$.

Customizing Query Builder Types


Query Builder uses object model information to present the list of all possible types to build queries against. It does this by searching for all types that implement the wt.fc.NetFactor interface. However, there may be classes that do not implement the wt.fc.Net.Factor interface, yet have subclasses that implement the Persistable interface and therefore can be used in queries. An example is wt.index.Indexable. To allow queries to be built using these types, these types can be listed as resources in a service properties file. The out-of-the-box entry in dbservice.properties handles the Indexable interface as follows:
wt.services/rsc/default/wt.query.report.ClassName/ wt.index.Indexable/java.lang.Object/0=wt.index.Indexable

To customize the list of Query Builder types, new entries can be added. For example, for the class myPackage.myClass, the entry would be as follows:
wt.services/rsc/default/wt.query.report.ClassName/ myPackage.myClass/java.lang.Object/0= myPackage.myClass

This is necessary only if the class does not implement the NetFactor interface, but does have subclasses that implement the Persistable interface.

Customizing the Report Output Format


Note This customization is supported for reports using custom input pages. Several report output formats are provided out-of-the-box. All of these formats are intended to be general purpose. That is, they should produce reasonable output from any query. If none of these formats are appropriate, you can modify them or create completely new formats.

1162

Windchill Customization Guide

CSS Customization
All of the HTML report formats provided, except those derived from Microsoft Word, use a CSS1 stylesheet to specify font, color, size, and spacing details. Use of CSS1 allows these details to be separated from other aspects of page layout and placed into one or more re-usable stylesheets. Therefore, the easiest way to customize these aspects of the HTML reports is to edit the CSS files that they use. For further information about CSS1, refer to the W3C CSS1 specification, currently available at the following URL:3 http://www.w3.org/TR/REC-CSS1 Two CSS files are involved: htmlFormat4Print.css and htmlFormat4Screen.css. Both are located in <Windchill codebase>/templates/reports. The htmlFormat4Print.css file is intended to specify the appearance of HTML when printed and the htmlFormat4Screen.css file when viewed on screen. Actually, browsers do not support this aspect of CSS and, therefore, the printed output is controlled by htmlFormat4Screen.css as well. However, you may prefer htmlFormat4Print.css to htmlFormat4Screen.css, which is designed primarily for consistency with other Windchill HTML pages. To change the CSS stylesheet used by a report or to make larger changes to the output format than possible through CSS1, you must customize XSLT stylesheets as described in the next section.

XSLT Customization
As mentioned earlier, reports are produced by applying XSLT stylesheet transformations to XML query results. This includes all the out-of-the-box formats. XSLT stylesheets are capable of producing not only any HTML layout but also any other XML or text format. XSLT stylesheets are based on the concepts of templates and rules. Most XSLT stylesheets are largely composed of XML or HTML tags and text that are static; that is, included verbatim in the output. The remainder of the stylesheet is then composed of rules for computing the dynamic portion of the output from the input XML. Depending on the mix of templates and rules, the nature of XSLT customization can vary from simple HTML authoring to pure programming. For the definitive specification on XSLT, refer to the W3C XSLT specification, currently available at the following URL:4 http://www.w3.org/TR/xslt

3. 4.

If you have difficulty with this URL, try the site URL www.w3.org. If you have difficulty with this URL, try the site URL www.w3.org.

Report Generation

1163

For additional information about XSLT, refer to the What is XSLT? link and the Resources area currently available at the following URL:5 http://www.xml.com

Stylesheets Provided
One technique for customizing the output format is to modify one of the XSLT stylesheets that are provided in <Windchill>/codebase/templates/reports/. These stylesheets are described in detail in the following table.

Note Within fields that specify an XSLT stylesheet in the Windchill UI, you must enter file paths that are relative to <Windchill>/codebase/. For example, excel97WebQuery.xsl must be referenced as "templates/reports/excel97WebQuery. xsl" Description XSLT Standard Stylesheet Format Name XML identity.xsl Performs the identity transformation on the XML query results; that is, it outputs the XML input. csvFormat.xsl CSV (Comma Produces comma-separated-values format Separated (useful for reading into spreadsheets, and so Variable) forth). tsvFormat.xsl TSV (Tab Sepa- Produces tab-separated-values format (userated Variable) ful for reading into spreadsheets, and so forth). Produces a simple HTML format. Unlike simpleHtmlForm HTML at.xsl the other HTML formats provided, this format does no extra formatting on numeric columns. htmlWithSorting HTML (with Similar to simpleHtmlFormat.xsl except .xsl sorting) that sorting is provided through hyperlinks on the column headers. htmlWithMerg- HTML (with Similar to simpleHtmlFormat.xsl except ing .xsl merging) that vertically duplicated cells are merged under certain conditions. This is a time-consuming transformation compared to the others provided. sortedHtmProduces the same results as htmlWithSortlAsXM L.xsl ing.xsl except that the output is well-formed
5. If you have difficulty with this URL, try the site URL www.xslinfo.com.
Windchill Customization Guide

1164

XSLT Stylesheet

Standard Format Name

Description XML rather than traditional HTML, and the results contain additional non-HTML attributes. This is to facilitate application of further XSLT transforms (for example, mergeHTMLCells.xsl) to the result. Merges cells in HTML (which must be well-formed XML) similar to htmlWithMerging.xsl. Additionally, the input must have extra attributes annotations. This stylesheet is not intended for use directly on the query result XML. Instead, when applied to the results of sortedHtmlAsXML.xsl, the overall effect is to produce HTML with both sorting and merging. Produces a simple HTML format containing Microsoft Word 2000 metadata. When the result is dropped onto Microsoft Word 2000, the originally specified margins, table borders, and so on are preserved. Also, decimal tab stops are specified on floating point data columns. The result has landscape page orientation. Same as msw2000ls.xsl except the result has portrait page orientation. Produces XSL Formatting Objects, an XML-based standard for high-precision page layout (see http://www.w3.org/TR/ xsl). This is referred to as PDF format in standard format lists because the default is to post-process this format to dynamically produce PDFs. This is done through Apache FOP (see http://xml.apache.org/ fop) and is controlled by the following user preference: /wt/query/report/template/postprocmap/appl ication/xslfo+xml

mergeHTMLCell s.xsl

msw2000ls.xsl

Microsoft Word 2000 HTML (Landscape)

msw2000p.xsl

xslfo.xsl

Microsoft Word 2000 HTML (Portrait) PDF

Report Generation

1165

XSLT Stylesheet

Standard Format Name

Description This format is currently limited by the capabilities of FOP (for example, column widths must be provided rather than being computed from contents) and will improve in the future as FOP improves. Produces a version of Excel Web Query (. iqy) format compatible with both Excel 97 and higher. This Excel format records the URL from which the spreadsheet data came, and can refresh the data from the URL periodically or on demand. For best results with Excel 2000, set the MIME type for Excel Web Query (IQY) files to be application/x-excel-web-query; on downland, this format is then automatically loaded into Excel 2000 only. With Excel 97, you must save the downloaded file and select it from within the Excel 97 'Run Web Query...' command. Produces a version of Excel Web Query (. iqy) format compatible only with the Excel version currently supported with Windchill. (For details about which third party products are supported, reference the Windchill Software Matrices.) It uses a new feature in Excel Web queries to attempt to preserve the formatting in the spreadsheet rather than that in the HTML URL data source. Produce various types of charts corresponding to their names. The first result column is assumed to contain labels and the rest are assumed to contain chart data. Output is initially produced as SVG (Scalable Vector Graphics), a standard XML-based vector graphics format (see http://www.w3.org/ TR/svg). Because this format requires a client viewer (for exampe, Adobe's free SVG Viewer available at http://www.adobe.com/

excel97WebQuer y.xsl

excel2000WebQ uery.xsl

barChart.xsl llineChart.xsl pieChart.xsl scatterChart.xsl

1166

Windchill Customization Guide

XSLT Stylesheet

Standard Format Name

Description svg/viewer/install/m ain.html), the default is to post-process this format to rasterize the SVG into JPEG. SVG, JPEG, or PNG output formats can be selected by the following user preferences: /wt/query/report/template/postprocmap/ima ge/svg+xml /wt/query/report/template/postprocmap/svg Rasterizer/rasterFormat Provides an XSLT template, generateURLHref, that is used by the provided HTML and XSL FO formats to produce hyperlinks to Windchill objects from XML result nodes that contain additional attribute information provided by the query layer when entire Windchill objects are selected. Object, version, e-mail, and content download links are currently supported. The shared implementation behind excel97WebQuery.xsl and excel2000WebQuery.xsl. This stylesheet allows stylesheets which include it to specify the relative URL of an XSLT stylesheet that produces HTML tables. The produced Excel Web Query then obtains its data by executing the report (again) but using the specified HTML table format. Thus, by changing this HTML format, one can change the data that appears in Excel as a result of this Web query. Currently both excel97WebQuery.xsl and excel2000WebQuery.xsl use simpleHtmlFormat.xsl. The shared implementation behind barChart.xsl, lineChart.xsl, pieChart.xsl, and scatterChart.xsl. This stylesheet works by using Apache Batik (see http://xml.apache.org/batik) on the server to capture JChart graphics as SVG and optionally rasterize them. Note that custom charts and graphics can easily

includes/linker. xsl

includes/excelWe bQueryBase.xsl

includes/chart.xsl

Report Generation

1167

XSLT Stylesheet

Standard Format Name

Description be captured as well by implementing wt. query.template.Chartable interface and replacing "wt.query.template.ChartCreater" in this file with the name of the custom Chartable implementation. The shared implementation behind msw2000ls.xsl and msw2000p.xsl. The page size, margins, and orientation are all specified as inputs. This stylesheet is intended solely for inclusion from other stylesheets. The shared implementation behind htmlWithSorting.xsl and sortedHtmlAsXML.xsl. This stylesheet is intended solely for inclusion from other stylesheets. Provides an XSLT named template (that is, a macro) for localizing strings. The implementation uses an XSLT extension function to call back into Java to access Java resource bundles. This stylesheet is intended solely for inclusion from other stylesheets. Provides an XSLT named template for URL encoding. The implementation uses an XSLT extension function to call WTURLEncoder.encode in Java. This stylesheet is intended solely for inclusion from other stylesheets.

includes/msw200 0.xsl

includes/htmlWit h SortingBase.xsl

includes/localize String.xsl

includes/urlEnco de.xsl

Due to the template-based nature of XSLT, some modifications can be made to the provided stylesheets based almost solely on a knowledge of the intended output format (such as HTML). For example, the provided formats that use CSS1 stylesheets generate the references to these files using the following lines in the XSLT stylesheets:
<link rel="stylesheet" type="text/css" href="{$windchill}/templates/reports/htmlFormat4Screen.css" media="screen"/> <link rel="stylesheet" type="text/css" href="{$windchill}/templates/reports/htmlFormat4Print.css" media="print"/>

1168

Windchill Customization Guide

The only part of these lines that is not strictly HTML is the portion within the { } braces which, though similar to JavaScript expression usage, is actually an XSLT XPath expression. In this case, the expression is referencing the variable windchill, which was previously assigned the URL of the Windchill codebase.

XML Resource Bundles


One aspect of the provided XSLT stylesheets (which is shared with those for the Windchill Product Configurator) is that they use XML resource bundles for localization of text. Rather than producing different versions of each XSLT stylesheet for each locale, the locale-dependent text has been extracted into separate XML files. These are loosely referred to as XML resource bundles, and are retrieved and searched through XSLT based on the locale. This approach was taken for the following reasons: To allow ease of localization by using the same technology, syntax, and tools as those behind XSLT and HTML authoring; that is, XML. To allow a tighter coupling between XSLT stylesheets and their localization data. Because relative URLs are used to look up XML resource bundles, they can be installed relative to the XSLT files that reference them, rather than relative to the Windchill codebase. To allow localization without dependence on XSLT extension functions.

The XML resource bundles used by the provided XSLT stylesheets are located at <Windchill codebase>/templates/reports/defReportRB_*.xml. If you decide to use this technique in your own XSLT stylesheets, see the XML resource bundles provided and the XSLT files provided for usage examples. Keep in mind the following issues: XML resource bundles must be well-formed XML. For further information, refer to XML.coms annotated XML specification, currently available at the following URL:6 http://www.xml.com/pub/axml/axmlintro.html The W3C unannotated, original version of the XML specification is currently available at the following URL:7

6. 7.

If you have difficulty with this URL, try the site URL www.xml.com. If you have difficulty with this URL, try the site URL www.w3.org.

Report Generation

1169

http://www.w3.org/TR/REC-xml The encoding listed in the <?xml ...?> header should match that actually used when saving the file and should be one supported by the XML parser used (Xerxes 1.2.2). For example, on Windows NT, you can use the Save as Unicode option in NotePad and specify an encoding of "unicode" in the XML resource bundle.

New Formats
Besides modifying existing XSLT, you can also author entirely new XSLT stylesheets. You can author new stylesheets using the following steps: 1. Author a sample of the intended output format. For example, use an HTML editor to produce a sample of the intended format; create a sample document in Microsoft Office and save it as HTML (this is how the Microsoft Word-based HTML formats were created); or export an Adobe Illustrator drawing as SVG. 8 2. Copy static pieces of the sample output to a skeleton XSLT stylesheet, editing or escaping them as necessary to ensure that they are well-formed XML. (All XSLT must be well-formed XML.) 3. Author XSLT to transform the input XML into the dynamic portions of the output, using the sample output as a guide. The number and complexity of transformations to be done in step 3 can vary greatly from one format to another and largely determine the effort involved in creating a new format. XSLT provides extensive capabilities for sorting, filtering, summing, and combining XML data. Additionally, you can provide XSLT extension functions and elements that call other languages, including Java and JavaScript. See the Saxon documentation for further details.

XML Result Format


Understanding the query result XML format is extremely important to successfully retrieving the desired data from it using XSLT (or any other technique). An outline of this format is shown below. The portions in bold represent dynamic data and ellipses (...) represent omitted items.
<?xml version="1.0" encoding="UTF-8" ?> <queryResult> <metadata> <name>Report Report Name</name> Name <description>Report Report Description</description> Description <objectIdentifier>Report Report Object Id</objectIdentifier> Id

8.

The use of Apache Batik, as described in the various chart.xsl stylesheets (see the table in the section on Stylesheets Provided earlier in this chapter), provides an alternative means of producing SVG with minimal knowledge of XSLT.
Windchill Customization Guide

1170

<sourceSystem>Windchill Windchill Codebase URL</sourceSystem> URL <sourceGateway>Windchill Windchill Gateway URL</sourceGateway> URL <executingPrincipal> <fullName>User User s Full Name</fullName> Name <objectIdentifier>User User Object ID</objectIdentifier> ID </executingPrincipal> <timeOfExecution>Time Time when Executed</timeOfExecution> Executed <locale>Locale Locale of User</locale> User </metadata> <auxData> <dataItem name="requestParam1 requestParam1">value value</dataItem> . . . <dataItem name="requestParamN requestParamN">value value</dataItem> </auxData> </qml> . . . </qml> <actualParameter parameterId="ParamName1 ParamName1"> Value </actualParameter> . . . <actualParameter parameterId="ParamNameN ParamNameN"> Value </actualParameter> <result> <heading tag="column1TagName column1TagName" type="Java Java data type">column type column header</heading> header . . . <heading tag="columnNTagName columnNTagName" type="Java Java data type">column type column header</heading> header <row idx="1"> <column1TagName column1TagName>value value</column1TagName column1TagName> . . . <columnNTagName columnNTagName>value value</ColumnTagName ColumnTagName> </row> . . . <row idx="N N "> . . . </row> </result> </queryResult>

If an entire Windchill top-level object (a Persistable) is selected, additional attributes are generated on the column tag element, including the object ID, branch ID (if the object is versioned), and classname of the object. WTUser objects also include email attributes. These attributes are generated primarily to facilitate generation of hyperlinks. Out-of-the-box XSLT stylesheets for HTML and PDF formats use these attributes whenever they are present to produce hyperlinks to the objects. Additional flexibility for generating hyperlinks is provided by use of the characters $$ in column names. If a column name containing $$ is specified through the Query Builder, an individual cell is not created for it; instead, the name is parsed as

Report Generation

1171

follows. If the part of the column name preceding $$ matches another column name that does not contain $$, its data is added to the other column as an attribute, which is determined by the part following $$. For example, assume the following columns are specified through Query Builder: Part Part$$branchID Part$$type
<Part branchID="dataFromBranchIdColumn" type="dataFromTypeColumn">dataFromPartColumn</Part>

Each XML row would then contain a Part element like the following:

Rows would not contain individual Part$$branchID or Part$$type columns. This functionality allows you to select the right data to obtain hyperlinks (as described earlier in this section) without having to select entire Persistable objects. If the column type is java.util.Date, column data is formatted based on the HTTP request's Locale. In addition, the column element has a "value" attribute containing the raw Java string value. If other date-formatting customization is needed, this value could be used. The table below summarizes the data conveyed by the various top-level elements in the query result XML. Element metadata auxData qml Description Meta-information about the query from which the data resulted and the user executing it. The request parameters used. Fully defines the details of the report template query which was made (see <Windchill codebase>/wt/query/qml/qml. dtd for further details). The query parameters used when executing the query. The column headers and types, and the rows of data.

actualParameters result

Using XSLT Stylesheets as Report Formats


To use an XSLT stylesheet as a report format, you must specify it either in the report template user interface or, for report templates that specify their format as Ask Upon Generate , upon generation using the HTML report generation form. In either case, two means of specifying formats are allowed: custom and standard. Specification of custom formats is done using up to two relative or absolute URLs. When the URLs are not absolute, they are relative to the Windchill codebase. When two XSLT URLs are specified, they are applied to the report results in
Windchill Customization Guide

1172

series. The custom specification mechanism allows use of XSLT stylesheets that are not located on the Windchill server and facilitates testing of new stylesheets. It also allows the application of two XSLT stylesheets in a series, which is not possible through the standard format mechanism. Specification of standard formats is done by selecting one from a list. Most of the provided XSLT stylesheets are part of this list. Additional formats can be added to this list by editing dbservice.properties. These property entries begin with wt. services/rsc/default/wt.query.report.DefaultXSL. If an existing format is being replaced with a customization, then there may be an additional property entry for the format type that overrides the XSL. This property begins with wt.services/svc/default/com.ptc.core.query.report.client.generation. ReportSAXTransform and should be removed. The format of these entries is that of the Windchill application services delegation mechanism. If localization of the additional entries is required, edit the Java resource bundle wt.query.template.TemplateResource.

Report Generation

1173

Customizing the Report Generation Client


Note This customization is supported for reports using custom input pages. The report generation client consists of an HTML form that can prompt the user for additional report generation input and an HTTP processor that executes the report and applies the XSL transformations. Both of these clients can be customized in the same manner as typical HTML client customizations. For further information, see Customizing HTML Clients Using the Windchill JSP Framework .
In addition, report generation-specific code is available as static methods in a separate class so it can be reused. The ReportTemplateHelper class provides many methods for processing reports (See the wt.query.template.ReportTemplateHelper class entry in your installed Windchill Javadoc for more information).

Note In previous releases, reports that used subtypes (that is, types created using the Type and Attribute Management utility) needed to be processed using the report commands (See the com.ptc.core.query.report.command.common package entry in your installed Windchill Javadoc for more information). The ReportTemplateHelper APIs now directly support subtypes and customer-created attributes. While report commands are still supported, they are no longer required.
Both of the clients mentioned above rely on a wrapper API developed for XSLT processors. The API can be found in the wt.xml.xslt package entry in your installed Windchill Javadoc for more information. This API provides the following functionality: Independence from individual XSLT implementations (for example, Saxon, the XSLT processor library currently in use) A high-level abstraction for XML source that hides the details of a particular implementation (for example, String, Java IO stream, DOM, or SAX) A clean API for XSLT operations in Windchill Easy-to-use, high-level facilities for complex chaining of XSLT transformations

For additional capabilities beyond those provided through this API, you can use the standard JAXP (Java API for XML Processing) APIs, or access Saxon directly. For further information, see the Saxon Web page, currently available at the following URL: http://saxon.sourceforge.net

1174

Windchill Customization Guide

Note, however, that the XSLT library bundled with Windchill may change in the future and that users of the Windchill XSLT and JAXP APIs will be affected less by any such change.

Report Generation Form


The report generation form is used to gather additional report input parameters prior to execution. It consists of two main sections: report parameters and output format. The report parameters section is built from data specified in the query. Given a report query as an XML source, the ReportTemplateHelper buildParameterTemplates( ) method returns an array of ParameterTemplate instances that represent the parameters of the query. The current client accesses this parameter template data to build the form to prompt the user for input. Note that the processing bypasses any parameter templates if the specified name is included in the HTTP parameters (see the section Customizing the Report Generation URL that follows). This is an indirect way to customize the form. For example, fully specifying all parameter values in the report generation URL would cause no parameter input fields to be generated. Also, the current form processing completely bypasses the form and goes directly to the report execution processing if the XSL specification has been set in the report template and all required parameters (if any) have had values specified in the HTTP parameters. The output format section is generated based on the XSL specification of the report template object. If one exists, the output format section is bypassed. Otherwise, the input fields for specifying the format are generated. The ReportTemplateHelper getAvailableXSLFormats( ) method is used to build the drop-down choice for the standard XSL.

Report Generation Output


The report generation output relies on the XSLT API. The basic steps are as follows: 1. Generate report data as XML using the ReportTemplateHelper generateXML() method. 2. Obtain a list of XSL stylesheets to apply. This can be specified as an attribute of the report template object or as HTTP parameters. The report template object XSL Specification attribute has precedence over the HTTP parameter values. This logic is implemented in the ReportTemplateHelper.getXSLSpec() method. 3. Create XSLT Transform objects chaining together the array of Stylesheets as necessary. This method is implemented in ReportTemplateHelper.getTransform ().

Report Generation

1175

4. Get the post-processor based on the output media type using ReportTemplateHelper.getPostProcessor(). This method uses the preferences mechanism to retrieve the class name of the post-processor. 5. Set the response output type and generate data to the response output stream:
if(postProcessor==null) { // No post processor found response.setHeader("content-type", ReportTemplateHelper.concatMediaTypeAndEncoding( outputMimeType, finalSheet.getOutputEncoding())); transform.outputToStream( response.getOutputStream() ); } else ( // Post processor found response.setHeader("content-type", ReportTemplateHelper.concatMediaTypeAndEncoding( postProcessor.getOutputMediaType(), postProcessor.getOutputEncoding())); postProcessor.process( transform, response.getOutputStream() );

Creating a New Client


The preceding sections describe the current report generation client and some simple customization points. Using the XSLT API, ReportTemplateHelper methods, and report commands as a basis, there are many ways that an entirely new client could be created. However, detailed discussions on this topic are beyond the scope of this document. The following are possible example customizations: Use the ReportTemplateHelper APIs or report commands that return TypeInstances, QueryResult or Java Swing TableModel objects. These methods can be used in a Java client that uses a specific type of display or must implement additional result set processing. Execute report generation in a background or batch mode (for example, running reports nightly) and saving the results in Windchill.

Customizing the Report Generation URL


Note This customization is supported for reports using custom input pages. Understanding the report generation URL is important for customizing applications to seamlessly integrate report generation functionality. The URLs that invoke reports can be created dynamically or set up statically (for example, bookmarked) with known URL parameters. There are two types of report generation URLs:

1176

Windchill Customization Guide

Generate Form and Execute Report. The Generate Form URL requests additional input from the user (only if necessary) and generates a form action button that leads to the Execute Report page. The Execute Report page executes the query and returns output to the HTTP request output stream. Both of these URLs can be edited directly to add URL parameters. Either the original or the edited URL can be bookmarked or used in a hyperlink for future reuse. The URLs can also be generated programatically. The ReportTempateHelper class provides APIs for each type of URL. Several versions, each taking different parameters, are also available. See the getGenerateFormURL( ) and getExecuteReportURL( ) classes entry in your installed Windchill Javadoc for more information. The Generate Form URL can have parameter values specified directly. For any parameter names that are specified on the URL, the input field is bypassed. In addition, all URL parameters are passed to the Execute Report URL through the forms action button. The Execute Report URL also derives all report parameter values from the URL parameters (through ReportTemplateHelper methods). If a URL parameter does not exist for a report parameter, then the report parameter s default value is used. In addition, several other URL parameters, described in the following table, can be used. URL Parameter Name jrb Description Name of a Java resource bundle for localization of result column headers. The provided XSLT stylesheets are all capable of localizing the result column headers if the name of a Java resource bundle is provided to them. This is intended to allow for re-use of a single query to support multiple locales because the report template user interface provides no means of entering strings per locale. Specifies the format type: formatDelegate or formatCustom. This parameter is used only if the report template object has no XSL specification. Specifies the delegate name to obtain an XSL stylesheet from Windchill codebase. The delegate name must match a value specified in the dbservice.properties file. This parameter is used only if the report template object has no XSL specification and the format URL parameter has a value of "formatDelegate". Specifies a URL for a custom XSL stylesheet. This stylesheet is applied immediately to the query result and can generate direct output to the user, or output suitable for input to another XSL stylesheet. This parameter is used

format

delegateName

xsl1

Report Generation

1177

URL Parameter Name

Description only if the report template object has no XSL specification and the cformat URL parameter has a value of "formatCustom". Specifies a URL for a custom XSL stylesheet. This stylesheet is applied to the output of the first XSL stylesheet (specified by xsl1) and should generate output to the user. This parameter is used only if the report template object has no XSL specification, the format URL parameter has a value of "formatCustom", and the xsl1 URL parameter has been specified.

xsl2

1178

Windchill Customization Guide

Cognos Presentation Customization


Objective
You want to create a Cognos report that queries data from an existing Windchill Data Source.

Background
Cognos is a third party reporting tool that is integrated with Windchill. It exposes Windchill Data Source objects in Cognos that can be used in Cognos reports to retrieve data from Windchill. Cognos is used to format and present the data for your report.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This documentation assumes that the Windchill Business Reporting (WBR) solution (i.e. Cognos) has been successfully installed and configured. The Windchill instance name is referred to as <WindchillInstanceName>. The Cognos root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is installed on <WBRHost>, then the <WBRHomeURL> would be http:// <WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to <WBRHomeURL> and you have sufficient Cognos privileges to view Windchill Data Source objects and create reports. Assume you will name your new report <MyReport> and it will use the <MyDataSource> object to retrieve data from Windchill. It is also assumed that you will be able to create a Report object in Windchill in the Site context. The WBR solution provides several out-of-the-box Windchill Data Source objects. If custom Windchill Data Source objects are required for your report, see the Reporting Data Source customization best practice documentation in the ReportTemplate Data Source Customization on page 2759 for more details.

Report Generation

1179

Intended Outcome
The end result of this solution is the creation of your report in Cognos. A sample output of a report is shown below.

Solution
Use Cognos Report Studio to create a report using a Windchill Data Source.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Cognos Report Authoring JMX Console Basic Usage

Solution Elements
Element Type <MyDataSource> Cognos Cognos Object Data Source Description The Cognos object that is used to query data from Windchill.
Windchill Customization Guide

1180

Element <MyReport> Cognos Report

Type Cognos Object

<MyReport> Windchill Report

Windchill Object

Description The Cognos object for a report that contains the definition of the query and specifies the presentation formatting. The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object.

Procedures
This section contains detailed information about the following customization procedures: Creating a Report on page 1181 Creating a Report in a non-Site context on page 1182 Deleting a Report on page 1183

Creating a Report 1. Login to Cognos using the <WBRHomeURL>. 2. Navigate to Public Folders > Windchill. 3. Launch Report Studio. 4. Select <MyDataSource> as the Data Source for the report. These appear in the Insertable Objects window under the Source tab. 5. Use Cognos Report Studio features to complete the report. 6. Save the report to top level Public Folders > Windchill folder as <MyReport>. 7. Verify the report in Cognos. Refresh the Public Folders > Windchill folder and the <MyReport> object should be listed. Use the Run with options action to run the report. 8. Expose your report to Windchill. Launch Java Console from installed Windchill shortcuts. There are two ways to do this: Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts >

Report Generation

1181

<WindchillInstanceName> > Monitors > ReportingSystem. From the Operations tab, click exposeReports. Select the Refresh Reports List button in Windchill Site/Reports to refresh the page.

9. View the <MyReport> Report in Windchill. The object will be displayed in Site > Reports . Note that the Ready For Use column shows No for this object. This means that other users with read-only access will not see this report. The Ready For Use attribute can be used to limit report access to end users while the report is being developed. 10. Edit <MyReport> to make the Report accessible to end users. Select the Edit action, then Select Home for Display Context(s) and check the Ready For Use checkbox. Click OK to save these changes. <MyReport> will now be visible to all users with read access from both Site > Report and Home > Reports. 11. Verify the report in Windchill. Navigate to Home > Reports and Select the View Report action for the <MyReport> object. Creating a Report in a non-Site context In the primary procedure above, the Cognos Report was created in the Windchill public folder in Cognos. This folder correlates to the Site context in Windchill and the Windchill Report object is created in this context. A variation of the primary procedure is to create the Cognos Report and correlated proxy Windchill Report in a non-Site context such as an organization. You will need to create a folder structure in Cognos that corresponds to the non-Site contexts that you wish to use in Windchill. For example, assume you have an organization <MyOrg> that contains a product <MyProduct> and you want to create a report, <MyProductReport>, in the <MyProduct> context. Prior to following the above primary procedure steps, create the following folders in Cognos 1. Under the Public Folders > Windchill folder, create a folder with the name, wt.inf.container.OrgContainer=<MyOrg>. 2. Under the Public Folders > Windchill > wt.inf.container. OrgContainer=<MyOrg> folder, create a folder with the name, wt.pdmlink. PDMLinkProduct =<MyProduct>. 3. In step 6 of the above procedure, save the report to the Public Folders > Windchill > wt.inf.container.OrgContainer=<MyOrg> > wt.pdmlink. PDMLinkProduct =<MyProduct> folder as <MyProductReport>.

1182

Windchill Customization Guide

4. In step 6, save the report to the "Public Folders > Windchill > wt.inf.container. OrgContainer=<MyOrg> > wt.pdmlink.PDMLinkProduct =<MyProduct>" folder as <MyProductReport>. 5. After exposing the report in step 8, the Windchill Report will be displayed in "Product: <MyProduct> > Reports". Deleting a Report A report that is no longer needed can be removed from the system by deleting both the Cognos and Windchill Report objects. Assume you want to delete <MyReport>. 1. Use the Cognos UI to browse to <MyReport> in the Public Folders > Windchill folder (if it is a non-Site context report, then it will be in a sub-folder) and select the Delete action. 2. Then, use the WindchillUI to locate <MyReport> and select the Delete action.

Note The Reports table supports a multiple row delete action if the Reports table is within a context and you have delete access rights for Windchill Report objects in that context.

Limitations
The Cognos report authoring capabilities are designed for many different types of Data Sources. The WBR integration uses XML Data Sources. These may have some limitations when compared to other types of Cognos Data Sources. In most cases, Cognos is able to implement the similar functionality for XML Data Sources, but there may be implications. For example, it is possible to use aggregate functions to summarize data, but this processing takes place in the Cognos server after all data has been received so this may cause performance and scalability issues. Cognos Reports have a one-to-one association with the Windchill Report business object. This object implements the AccessControlled interface so that standard Windchill access control can be applied. Note that there is no access control concept of execution rights. If a user has read access, then that user is also able to execute the report. The out-of-the-box access control policy for Windchill Report objects is specified for the Site context which provides Read access for all. Other access control rules will apply to Report objects based on type inheritance. For example, the Report object extends WTObject so at the Site level, Full access is granted for Administrators.

Report Generation

1183

Cognos Reports are subject to the Cognos server s access control policies. When Cognos is deployed as part of WBR, the integration does not alter Cognos default access control permissions, users, or groups apart from configuring Cognos to share Windchill LDAP for authentication. Further alteration to the access control permissions, users, or groups in Cognos must be done via Cognos tools, i.e. via their UI or API which is described in the Cognos documentation. For a good overview, see the "Initial Security" chapter in the Cognos Administration and Security Guide.

Sample Code
Examples of Usage in Windchill Code
Windchill supports out-of-the-box reports for both the Windchill ProjectLink and Windchill PDMLink solutions. See the Windchill Basic Administration Guide for details. Directly modifying the associated objects is not supported.

Related Package/Class Package/Class Javadoc


CognosIntegration module com.ptc.windchill.cognos Reporting module com.ptc.windchill.enterprise.report Related Customization Documentation Cognos Help (http:// <WBRHost>/cognos8/documentation/help_docs. html) Related Windchill Documentation Windchill Basic Administration Guide Windchill Specialized Administration Guide

Related Websites
http://support.cognos.com/support

1184

Windchill Customization Guide

Reporting Info*Engine Task Data Source Customization


Objective
You want to create a new Windchill programmatic data retrieval task to use in a report.

Background
The Windchill Business Reporting (WBR) solution uses Data Source objects to retrieve data from Windchill. One type of Data Source is an Info*Engine task. An Info*Engine task is a text-based document that uses programmatic constructs to retrieve and manipulate Windchill data. The task must return its data in a tabular format (i.e. each element must have the same number of attributes) and task must be commented with special tags and syntax to define it as a WBR Data Source.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This documentation assumes that the Windchill Business Reporting (WBR) solution (i.e. Cognos) has been successfully installed and configured. The Windchill instance name is referred to as <WindchillInstanceName>. The Cognos root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is installed on <WBRHost>, then the <WBRHomeURL> would be http:// <WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to <WBRHomeURL> and you have sufficient Cognos privileges to view Windchill Data Source objects and create reports. Assume you have access to the Windchill server tasks directory, <WindchillHome>/tasks, to create an Info*Engine task <MyTask> in sub-directory <MyTaskPackage>. For WBR integration, you must also have access rights to update the reporting meta model. This document does not contain details on how to construct Info*Engine tasks. See the Info*Engine User's Guide for this information.

Intended Outcome
The end result of this solution is the creation of your Data Source that can be used to author Cognos reports.

Report Generation

1185

Solution
Construct an Info*Engine Task Data Source. Prerequisite knowledge To achieve this objective, you need to have an understanding of the following:

Info*Engine User's Guide


The Windchill APIs related to the Windchill business objects that will be used in the Info*Engine task JConsole User Interface Cognos User Interface

Solution Elements Element <MyTask>

Type Info*Engine Task

Description The Info*Engine task for retrieving and manipulating Windchill data.

Procedure Creating an Info*Engine Task Data Source


1. Create an Info*Engine task XML file in <WindchillHome>/tasks/ <MyTaskPackage>. 2. Write report task to return results in tabular format. This is an otherwise normal Info*Engine task that follows certain additional conventions. First, it returns a tabular Group where each column has objects of the same type. The following are the allowed column types: java.lang.Boolean java.lang.Long java.lang.String java.sql.Timestamp java.util.Date java.lang.Double com.ptc.core.meta.common.FloatingPoint com.ptc.core.meta.common.Hyperlink java.math.BigDecimal

1186

Windchill Customization Guide

3. Add WBR Data Source parameter information to the task comments. There can be zero or more parameter comments. Each specified parameter must exist on a single line. The syntax for the parameter comment is as follows:
@param <type> <name> <description>

where <type> is the parameter Java type, <name> is the parameter name, and <description> describes the parameter. The following are the allowed parameter types: java.lang.Boolean java.lang.Long java.lang.String java.sql.Timestamp java.util.Date java.lang.Double java.math.BigDecimal

4. Add WBR Data Source column information to the return task comment. The column information must be specified in the correct format for this task to be considered a Data Source. The syntax for the column comment is as follows:
@return <type> ${<variableName>} {columns: <columnList>}

where <type> is the Info*Engine task output type, <variableName> is a reference to the task variable that will be returned, and <columnList> describes the tabular format of the output. For more information on <type> and {<variableName>} consult section "SOAP Comments" in the Info*Engine User's Guide. The column is a comma separate list of one or more type and name pairs for each column in the tabular output. The type and name are separated by whitespace. The following are the allowed column types: java.lang.Boolean java.lang.Long java.lang.String java.sql.Timestamp java.util.Date java.lang.Double com.ptc.core.meta.common.FloatingPoint com.ptc.core.meta.common.Hyperlink java.math.BigDecimal

Report Generation

1187

5. Add task as a method to a ReportTask type. Create a file named .delegateInfo in the same directory as the task file. The file should contain the following two lines:
repositoryType=com.ptc.windchill typeId=com.ptc.windchill.enterprise.report.ReportTask

6. Create and Install a package for <MyTask>. See Advanced User Topics > Packages in the Info*Engine User's Guide. 7. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem. From the Operations tab, click updateModel. 8. Verify that the Data Source exists in Cognos. Login to Cognos using the <WBRHomeURL> and launch Report Studio. Find <MyTask> Data Source under Windchill > Report Tasks > com.ptc.windchill.enterprise.report. ReportTask in the Insertable Objects window under the Source tab. The following is an example of task comments for a Data Source.
<!--com.infoengine.soap.rpc.def Report Task Example. @param java.lang.String param1 A string parameter named param1. @param java.lang.Long param2 A numeric parameter named param2. @return INFOENGINE_GROUP ${out} {columns: java.lang.String name, com.ptc.core.meta.common.Hyperlink url, java.util.Date deadline, java.math.BigDecimal duration} -->

Customization Points
Procedure Creating an Info*Engine Task Data Source under another Type In the primary procedure above, the Info*Engine Task was created using the default reporting type, com.ptc.windchill.enterprise.report.ReportTask. The type correlates to the Windchill > Report Tasks > com.ptc.windchill.enterprise.report.

1188

Windchill Customization Guide

ReportTask level of the Source tab. The Report task type can be used to group Data Sources logically. A variation of the primary procedure is to create the Info*Engine Task under another type, myPackage.MyReportTask. 1. This type will need to be added to the comma separated list of reporting types specified in the property com.ptc.windchill.enterprise.report. reportTaskClassNames 2. This property must be changed before executing step 7 of the Creating an Info*Engine Task Data Source procedure above. 3. In step 5 of the Creating an Info*Engine Task Data Source procedure above, the .delegateInfo entry for typeId should specify myPackage.MyReportTask. 4. In step 8 of the Creating an Info*Engine Task Data Source procedure above, the Data Source will now be available under Windchill > Report Tasks > myPackage.MyReportTask. Procedure Deleting an Info*Engine Task Data Source An Info*Engine Task Data Source that is no longer needed can be removed from the system by deleting it from Windchill and updating the Cognos model. Alternatively, the task comments can be removed so that it is not recognized as a Data Source. 1. To remove a task, uninstall the package and remove the XML file from the tasks directory. 2. Then, update the Cognos model using step 3 of the Creating an Info*Engine Task Data Source procedure above.

Limitations
The typeId in the .delegateInfo file maps to the SOAP class and the task file name maps to the SOAP method within that class. Both of these names should only contain characters valid for Java identifiers. In addition, the methods must all be unique for a given class. For a given typeId, each task name must be unique.

Sample Code
Examples of Usage in Windchill Code There are several out-of-the-box reports that use Info*Engine Task Data Sources. These Data Sources are listed in the Windchill > Report Tasks > com.ptc. windchill.enterprise.report.ReportTask level of the Source tab. These Data Sources can be used for creating Cognos reports. However, directly modifying the associated Info*Engine Tasks is not supported.

Report Generation

1189

Packaged Samples A demo Info*Engine task Data Source, ContextItems, is available in the Windchill > Report Tasks > com.ptc.windchill.enterprise.report.ReportTask level of the Source tab. The task source is located in <WindchillHome>/tasks/com/ptc/ windchill/enterprise/reports/ContextItems.xml. It retrieves the union of all Parts and Documents in a specified context.

Additional Resources
Related Best Practices Reporting ReportTemplate Data Source Customization Reporting Cognos Presentation Customization

Related Package/Class Javadoc Reporting module com.ptc.windchill.enterprise.report Related Customization Documentation None

Other Related Windchill Documentation

Info*Engine User's Guide(Prerequisite Prerequisite) Info*Engine Implementation Guide Windchill Specialized Administration Guide

Related Websites http://support.cognow.com/support

1190

Windchill Customization Guide

Report Loading
Objective
You want to load reporting objects into a Windchill Business Reporting (WBR) system.

Background
The Windchill Business Reporting (WBR) solution uses Windchill and Cognos objects in the system. Often times these objects are developed in another system such as a development system and then moved to another system where they are used in production. This document describes how these Reporting objects are loaded into a system. For Windchill business objects, the standard Windchill Data Loading mechanism is used. These tools are based on describing objects and their attributes in XML files. The loading is accomplished by instantiating the business objects, populating the attributes specified in the XML files, and using standard Windchill create APIs. For Cognos report objects, standard Cognos SOAP APIs are used. Cognos report attributes are specified in a Java properties file and the reports definition is specified in an associated XML file. These files are processed and the data is passed to a Cognos SOAP API for creating reports.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This documentation assumes that the Windchill Business Reporting (WBR) solution (i.e. Cognos) has been successfully installed and configured. The Windchill instance name is referred to as <WindchillInstanceName>. The Cognos root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is installed on <WBRHost>, then the <WBRHomeURL> would be http:// <WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to <WBRHomeURL> and you have sufficient Cognos privileges to view Windchill Data Source objects and create reports. Assume you have access to the Windchill server tasks directory, <WindchillHome>/tasks, to create an Info*Engine task <MyTask> in its associated sub-directory <MyTaskPackage>. Assume that this task has already been developed and tested on another source system, <WindchillSourceHome>. Assume you have access to the Windchill UI and the ReportTemplate, <MyReportTemplate> in the Site context of another source system, <WindchillSourceHome>.

Report Generation

1191

Assume you will load a new Windchill Report object, <MyReport>, and it will use the <MyReportTemplate> to retrieve data from Windchill. It is also assumed that you will be able to create a Report object in Windchill in the Site context. For WBR integration, you must also have access rights to update the reporting meta model. Intended Outcome The end result of this solution is the creation of your reporting objects into your WBR system.

Solution
Construct and execute load files for Reporting objects. Prerequisite knowledge To achieve this objective, you need to have an understanding of the following:

Info*Engine User's Guide


JConsole User Interface Cognos User Interface Report Management User Interface Windchill Data Loading

Solution Elements Element <MyTask>

Type Info*Engine Task

<MyReportTemplate> Windchill ReportTemplate <MyReportTemplateQML> Windchill ReportTemplate Query Definition <MyReportTemplateLoad> Windchill Data Load Specification

Windchill Object

XML File

XML File

Description The Info*Engine task for retrieving and manipulating Windchill data. The Windchill object that specifies a query for retrieving Windchill data. The XML file that specifies a query associated with a Windchill ReportTemplate. The XML file that specifies data loading directives associated with a Windchill ReportTemplate.

1192

Windchill Customization Guide

Element <MyReport> Windchill Report

Type Windchill Object

<MyReportLoad> Windchill Data Load Specification

XML File

<MyCognosReport> Cog- Cognos Object nos Report

<MyCognosReportXML> XML File Cognos Report Query and Presentation Definition <MyCognosReportAttribu Properties File tes> Cognos Report Attributes

Description The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object. The XML file that specifies data loading directives associated with a Windchill Report. The Cognos object for a report that contains the definition of the query and specifies the presentation formatting. The XML file that specifies the query and presentation associated with a Cognos Report. The Properties file that specifies attributes associated with a Cognos Report.

Procedure Loading an Info*Engine Task Data Source 1. Copy the task XML file, <WindchillSourceHome>/tasks/<MyTaskPackage>/ <MyTask>.xml in <WindchillHome>/tasks/<MyTaskPackage>. This file could also be provided by PTC or another 3rd party developer. 2. Copy the associated .delegateInfo file in this same directory. 3. Create and Install a package for <MyTask>. See Advanced User Topics > Packages in the Info*Engine User's Guide. 4. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. 5. Make connection to Tomcat JVM instance. 6. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem. 7. From the Operations tab, click updateModel.

Report Generation

1193

8. Verify that the Data Source exists in Cognos. Login to Cognos using the <WBRHomeURL> and launch Report Studio. 9. Find <MyTask> Data Source under Windchill > Report Tasks > com.ptc. windchill.enterprise.report.ReportTask in the Insertable Objects window under the Source tab. Procedure Loading a ReportTemplate Data Source 1. Create the file, <WindchillHome>/loadFiles/reports/custom/ <MyReportTemplateQML>.xml using the Report Management Export action. This file could also be provided by PTC or another 3rd party developer. 2. Create a load file <WindchillHome>/loadFiles/custom/ <MyReportTemplateLoad>.xml.
<?xml version="1.0"?> <!DOCTYPE NmLoader SYSTEM "standardX10.dtd"> <NmLoader> <csvReportTemplate handler="wt.query.template.LoadReportTemplate.createReportTempl ate"> <csvfolder>/Default</csvfolder> <csvname><MyReportTemplate></csvname> <csvdescription></csvdescription> <csvxml>custom/<MyReportTemplateQML>.xml </csvxml> <csvxslType></csvxslType> <csvservice></csvservice> <csvcontainerPath></csvcontainerPath> <csvurl1></csvurl1> <csvurl2></csvurl2> </csvReportTemplate> </NmLoader>

3. Load <MyReportTemplate> using the following command.


windchill wt.load.LoadFromFile d <WindchillHome>/loadFiles/custom/<MyReportTemplateLoad>.xml CONT_PATH /

4. Verify the ReportTemplate exists in Windchill by launching Report Management in the Site context. 5. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. 6. Make connection to Tomcat JVM instance. 7. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem. 8. From the Operations tab, click updateModel. 9. Verify that the Data Source exists in Cognos. Login to Cognos using the <WBRHomeURL> and launch Report Studio. Find <MyReportTemplate>
1194

Windchill Customization Guide

Data Source under Windchill > Report Templates in the Insertable Objects window under the Source tab. Procedure Loading a Windchill Report Object 1. Create a load file <WindchillHome>/loadFiles/<MyReportLoad>.xml.
<?xml version="1.0"?> <!DOCTYPE NmLoader SYSTEM "standardX10.dtd"> <NmLoader> <csvCreateReport handler="com.ptc.windchill.enterprise.report.LoadReport.createR eport"> <csvname><MyReport></csvname> <csvcontainerPath/> <csvdescription></csvdescription> <csvinputPage/> <csvresourceBundle/> <csvuiContext></csvuiContext> <csvreadyForUse/> <csvsoapClass/> <csvsoapMethod/> <csvreportTemplateName><MyReportTemplate></csvreportTemplateNam e> <csvreportTemplateContainerPath/> </csvCreateReport> </NmLoader>

2. Load <MyReport> using the following command.


windchill wt.load.LoadFromFile d <WindchillHome>/loadFiles/custom/<MyReportLoad>.xml CONT_PATH /

3. Verify the Report exists in Windchill in the Reports table of the Site context. Procedure Loading a Cognos Report 1. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/ <MyCognosReportXML>.xml based on an existing Cognos Report. 2. Use Cognos Report Studio menu item Tools > Copy Report to Clipboard to copy the XML definition to the system clipboard. 3. Then, paste the clipboard contents into a text editor and save it to file. This file could also be provided by PTC or another 3rd party developer. 4. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/ <MyCognosReportAttributes> .properties. The base names from this and the previous step must match exactly (e.g. MyCognosReport.xml and MyCognosReport.properties.
type=report defaultName=<MyCognosReport> #defaultDescription=

Report Generation

1195

#resourceBundle=

5. Load <MyCognosReport> using the following command.


windchill com.ptc.windchill.cognos.CognosProxy loadreports <WindchillHome>/loadFiles/cognosReports/custom

6. Verify the report in Cognos. Refresh the Public Folders > Windchill folder and the <MyCognosReport> object should be listed. Use the Run with options action to run the report.

Customization Points
Procedure Loading Multiple Task Data Sources In the primary procedureProcedure Loading an Info*Engine Task Data Source on page 1193 above, a single Info*Engine Task is loaded. To load multiple tasks, repeat step 1 for each task. Each step in the remainder of the procedure only needs to be executed once. In the last step, verify that all Data Sources were loaded. Procedure Loading Multiple ReportTemplate Data Sources In the primary procedureProcedure Loading a ReportTemplate Data Source on page 1194 above, a single ReportTemplate is loaded. To load multiple ReportTemplates, in step 2, specify a separate csvReportTemplate element for each ReportTemplate. Each step in the remainder of the procedure only needs to be executed once. In the last step, verify that all Data Sources were loaded. Procedure Loading Multiple Windchill Report Objects In the primary procedureProcedure Loading a Windchill Report Object on page 1195 above, a single Windchill Report object is loaded. To load multiple Windchill Report objects, in step 2, specify a separate csvReport element for each object. Each step in the remainder of the procedure only needs to be executed once. In the last step, verify that all Windchill Report objects were loaded.

1196

Windchill Customization Guide

Procedure Specifying Windchill Report Object Attributes In the primary procedureProcedure Loading a Windchill Report Object on page 1195 above, only the basic Windchill Report Object attributes are specified. The following are the additional attributes that can be specified. For additional information see the Report javadoc. csvReport Element csvname Description

Required. This entry specifies the Reports name. csvcontainerPath Optional. This entry specifies a container where the report should be stored. If no value is specified, the site container is used by default. csvdescription Optional. This entry specifies a description of the Report. csvinputPage Optional. This entry specifies an input page for the Report. csvresourceBundle Optional. This entry specifies a resource bundle for the Report. csvuiContext Optional. This entry specifies the UI context mask to be used to control where the Report is displayed in the Windchill UI. csvreadyForUse Optional. This entry specifies whether the Report is ready for use for end users. If no value is specified, the default value is false. csvsoapClass Optional. This entry specifies the soap class if the Report uses a report task as its data source. This element is used along with the csvsoapMethod element to completely specify the report task. The Report must specify either a report task or ReportTemplate as its data source. csvsoapMethod Optional. This entry specifies the soap method if the Report uses a report task as its data source. This element is used along with the csvsoapClass element to completely specify the report task. The Report must specify either a report task or ReportTemplate as its data source. csvreportTemplateN Optional. This entry specifies the ReportTemplate name if ame the Report uses a ReportTemplate as its data source. This element is used along with the csvreportTemplateContainerPath element to completely specify the ReportTemplate. The Report must specify either a report task or ReportTemplate as its data source. csvreportTemplateC Optional. This entry specifies the ReportTemplate name if ontainerPath the Report uses a ReportTemplate as its data source. This element is used along with the csvreportTemplateName

Report Generation

1197

csvReport Element

Description element to completely specify the ReportTemplate. The Report must specify either a report task or ReportTemplate as its data source.

Procedure Loading Multiple Cognos Reports In the primary procedure above, Procedure Loading a Cognos Report on page 1195, a single Cognos Report is loaded. To load multiple Cognos Reports, repeat steps 3 and 4, for each Cognos Report. Each step in the remainder of the procedure only needs to be executed once. In the last step, verify that all Cognos Reports were loaded. Procedure Specifying Cognos Report Attributes In the primary procedureProcedure Loading a Cognos Report on page 1195 above, only the basic Cognos Report attributes are specified. The following are the additional attributes that can be specified. Property Name type Description Optional. This entry specifies the Reports type. The valid values are report, query, and reportTemplate. If not value is specified, then the default value is "report". Required. This entry specifies the Reports name. Optional. This entry specifies a description of the Report. Optional. This entry specifies the name of a Java resource bundle that is used to localize entries in the corresponding Cognos report specification XML file.

defaultName defaultDescription resourceBundle

Limitations
For Cognos Report loading, there are load file directories that are used for Windchill out-of-the-box reports. These directories should not be used for custom load files. The reserved directories are <WindchillHome>/loadFiles/cognosReports and <WindchillHome>/loadFiles/cognosReports/<assemblyId> where <assemblyId> is a standard Windchill assembly ID such as wnc, pdml, pjl, etc.

1198

Windchill Customization Guide

Sample Code
Examples of Usage in Windchill Code There are several out-of-the-box reports that use the load files described in this document. These are located in the <WindchillHome>/loadFiles, <WindchillHome>/loadFiles/reports, and <WindchillHome>/loadFiles/ cognosReports directories. Packaged Samples A demo load file for Windchill ReportTemplate and Report objects is available in <WindchillHome>/loadXMLFiles/DemoReports.xml.

Additional Resources
Reporting Info*Engine Task Data Source Customization on page 1185 ReportTemplate Data Source Customization on page 1200 Cognos Presentation Customization on page 1179

Related Package/Class Javadoc Foundation module wt.query.qml Reporting module Reporting module com.ptc.windchill.enterprise.report Other Related Windchill Documentation

Info*Engine User's Guide Windchill Data Loading Reference and Best Practices Guide Info*Engine Implementation Guide Windchill Specialized Administration Guide
Report Management online help

Related Websites http://support.cognos.com/support

Report Generation

1199

ReportTemplate Data Source Customization


Objective
You want to create a new Windchill data query to use in a Report.

Background
The Windchill Business Reporting (WBR) solution uses Data Source objects to retrieve data from Windchill . One type of Data Source is a ReportTemplate. A ReportTemplate is a standard, persistent Windchill business object that is maintained via the Report Management utility. This applet launches the Query Builder to create and edit a query that is stored as part of the ReportTemplate. When the ReportTemplate query is executed, standard Windchill APIs are used that apply all Windchill business logic (e.g. calling Windchill object methods, applying access control, etc.). Once a new ReportTemplate object is created it can be referenced from a Report object or exposed and used in the WBR solution as a custom Data Source.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This documentation assumes that the Windchill Business Reporting (WBR) solution (i.e. Cognos) has been successfully installed and configured. The Windchill instance name is referred to as <WindchillInstanceName>. The Cognos root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is installed on <WBRHost>, then the <WBRHomeURL> would be http:// <WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to <WBRHomeURL> and you have sufficient Cognos privileges to view Windchill Data Source objects and create reports. Assume you have access rights to create a ReportTemplate business object <MyReportTemplate> in the Site context. For WBR integration, you must also have access rights to update the reporting meta model. This document does not contain details on how to construct ReportTemplate queries. See the Query Builder online tutorial and help for this information.

Intended Outcome
The end result of this solution is the creation of your Data Source that can be used to author Cognos reports.

1200

Windchill Customization Guide

Solution
Use Report Management and Query Builder to construct a ReportTemplate Data Source.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Report Management User Interface Query Builder User Interface The Windchill data model for the area(s) related to the Windchill business objects that will be used in the ReportTemplate query JConsole User Interface Cognos User Interface

Solution Elements Element <MyReportTemplate> Windchill ReportTemplate

Type Windchill Object

Description The Windchill object that specifies a query for retrieving Windchill data.

Procedure Creating a ReportTemplate Data Source 1. Navigate to the Windchill Site > Utilities and launch the Report Management utility. 2. From the Report Management UI, click New to launch Query Builder. 3. Create a ReportTemplate query and save. This creates a ReportTemplate business object in Windchill that can be used as a WBR Data Source. 4. Update the Cognos model to recognize this new Data Source. Launch JConsole from installed Windchill shortcuts. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem. From the Operations tab, click updateModel. 5. Verify that the Data Source exists in Cognos. Login to Cognos using the <WBRHomeURL> and launch Report Studio. Find <MyReportTemplate> Data Source under Windchill > Report Templates in the Insertable Objects window under the Source tab.

Report Generation

1201

Customization Points
Procedure - Creating a ReportTemplate Data Source in a non-Site context In the primary procedure above, the ReportTemplate was created in the Site context. The Site context in Windchill correlates to the Windchill > Report Templates level of the Source tab. A variation of the primary procedure is to create the ReportTemplate in a non-Site context such as an organization. 1. Assume you have ReportTemplate create access in the organization < MyOrg>. 2. In step 1, navigate to the Utilities page under <MyOrg> instead of the Site Utilities page. 3. In step 5, the Data Source will now be available under Windchill > Report Templates > <MyOrg>. Procedure Deleting a ReportTemplate Data Source A ReportTemplate Data Source that is no longer needed can be removed from the system by deleting it from Windchill and updating the Cognos model. 1. Launch Report Management from the context associated with the ReportTemplate, select the object, and click Delete. 2. Then update the Cognos model using step 4 of the above Creating a ReportTemplate Data Source procedure. Limitations None.

Sample Code
Examples of Usage in Windchill Code There is no out-of-the-box functionality that depends directly on ReportTemplate Data Source objects. However, there are several out-of-the-box ReportTemplate objects and these are available in Cognos as ReportTemplate Data Source objects. These Data Sources can be used for creating Cognos reports. However, directly modifying these ReportTemplates is not supported. Packaged Samples A demo ReportTemplate Data Source object, PartList, is available. It can be loaded using the following command:
wt.load.LoadFromFile d <WindchillHome>/loadXMLFiles/DemoReports.xml CONT_PATH /

1202

Windchill Customization Guide

Note that if these objects were already loaded, exceptions may occur when running this command. The PartList ReportTemplate object is a simple query for Parts that returns two columns with part number information. It will be created at the Site context and will be available in Cognos after executing the update model operation. Related Customization Topics Reporting Info*Engine Task Data Source Customization on page 1185 Cognos Presentation Customization on page 1179

Related Package/Class Javadoc Foundation module wt.query.qml Reporting module Reporting module com.ptc.windchill.enterprise.report Other Related Windchill Documentation Report Management online help (Prerequisite) Query Builder online help (Prerequisite)

Windchill Specialized Administration Guide

Related Websites http://support.cognos.com/support

Report Generation

1203

Reporting Input Page Customization


Objective
You want to provide a parameter input page for the reports in your Windchill Business Reporting (WBR) system.

Background
The Windchill Business Reporting (WBR) solution supports reports with parameters. Both Windchill and Cognos viewers provide a basic input page that is presented to users to gather parameter values when the report is executed. Often times this input page requires customization for a better end user experience. There are two basic approaches for customizing input pages, use a standard Windchill Java Server Page (JSP) or use Cognos report functionality. The Windchill JSP approach can be used from the Windchill or Cognos viewers. The Cognos approach can only be used with the Cognos viewer.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This documentation assumes that the Windchill Business Reporting (WBR) solution (i.e. Cognos) has been successfully installed and configured. The Windchill instance name is referred to as <WindchillInstanceName>. The Cognos root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is installed on <WBRHost>, then the <WBRHomeURL> would be http:// <WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to <WBRHomeURL> and you have sufficient Cognos privileges to view Windchill Data Source objects and create reports. Assume you have access to the Windchill server JSP directory, <WindchillHome>/ codebase/wtcore/jsp, to create the JSP input page <MyInputPage> in its associated sub-directory <MyInputPagePackage>. Assume you have access rights to edit an existing Windchill Report object, <MyReport> in the Site context.

Intended Outcome
The end result of this solution is the use of your custom input when executing a report.

Solution
Construct and specify a custom input page for reports.
Windchill Customization Guide

1204

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following: Java Server Page (JSP) Cognos Report Studio

Solution Elements
Element Type <MyInputPage> JSP File Description The custom JSP page for specifying report input parameter values. <MyReport> Windchill Object The Windchill object that is displayed to Windchill Report end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object.

Procedure Specifying a Windchill JSP Input Page


1. Create a Windchill JSP page, <WindchillHome>/codebase/wtcore/jsp/ <MyInputPagePackage>/<MyInputPage>.jsp. The JSP specified an input field for param1 with default value default1 and a pre-specified value, value2 that is passed as a hidden input field for param2. This contrived example does not do any meaningful programmatic manipulation of the parameters, input fields, or values. It only demonstrates the basic mechanism for specifying parameters to a report. The details of JSP syntax and programming are beyond the scope of this document.
<%@page contentType="text/html" %><%@page pageEncoding="UTF-8" %><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %><fmt:requestEncoding value="UTF-8" /> <html> <head> <title>My Input Page</title> </head> <body> <h2>My Input Page</h2> <form> <% String paramName = param1; String defaultInputValue = default1; %> Name: <input type="text" name="<c:out value='<%=paramName%>'/>"

Report Generation

1205

value="<c:out value='<%=defaultInputValue%>'/>" size="60"/><br /> <blockquote><input type="submit" value='Execute Report'/></blockquote> <% String hiddenParamName = param2; String hiddenValue = value2; %> <input type="hidden" name="<c:out value='<%=hiddenParamName%>'/>" value="<c:out value='<%=hidenValue%>'/>"/> %> </form> </body> </html>

2. Update <MyReport> to specify the input page. Navigate to the Windchill Site > Reports page, select the edit action for <MyReport>. 3. Enter wtcore/jsp/<MyInputPagePackage>/<MyInputPage>.jsp into the Input Page text field and click OK. 4. Verify the report in Windchill. Navigate to the Home > Reports page and Select the View Report action for the <MyReport> object.

Procedure Specify a Cognos Input Page


As a third party reporting tool, Cognos is designed for authoring reports and input pages. Refer to the Cognos documentation for complete details.

Customization Points
Procedure Specifying Optional Parameters
Cognos reports that use Windchill Data Sources require every parameter value to be specified. However, a report can be more useful, if the user can optionally leave parameter values unspecified and the report ignores the related criteria or implicitly uses a suitable default. To achieve this behavior, it is possible to pass a parameter value consisting of a single space ( ) and by making a single space the default value for the parameter in you input page, the user will not be required to enter anything into the parameter input field. When using this technique, you must ensure that the underlying Data Source will be able to properly handle the empty space values that are passed.

1206

Windchill Customization Guide

Procedure Populating Cognos Components Using Data Sources


Cognos input pages can use Windchill Data Sources to populate components. For example, a list of Windchill Products could be displayed in a picker component. When this component is populated, it would dynamically retrieve Products from Windchill and show their display names. When the user selects the display name, the internal Windchill object ID can be passed as a parameter value input to the report.

Procedure Specifying Extra Parameters


By default, only the Data Source parameters are included in the Cognos request from Windchill. This means that any hidden form fields that might otherwise seem like request parameters are stripped off from the http request sent to Cognos (via a HTTP redirect). However, additional parameters can be explicitly added by including a parameter named extraReportParameters which specifies a list of parameter names that will be included in the Cognos request. Assume you want to pass a parameter with name, paramA with value valueA that is not in the list of parameters for the reports Data Source. The following is an example for specifying this.
type="hidden" name="paramA" value="valueA"/> type="hidden" name="extraReportParameters" value="paramA"/>

Data Source Also data source parameters can be excluded using the usual "parametersToOmit" request attribute. Note, this is a servlet request object attribute list not a parameter list. it was chosen for simplicity and ease of use.

Procedure Specifying Parameters To Omit


By default, only the Data Source parameters are included in the Cognos request from Windchill. However, parameters can be explicitly excluded using the "parametersToOmit" request attribute. Note, this is a servlet request object attribute list. Assume you want to omit the parameter with name, param1 that is in the list of parameters for the reports Data Source. The following is an example for specifying this.
<% request.setAttribute("parametersToOmit", Arrays.asList("param1")); %>

Report Generation

1207

Limitations
None.

Sample Code
Examples of Usage in Windchill Code
All of the out-of-the-box reports use Windchill JSP input pages.

Related Websites
http://support.cognos.com/support

1208

Windchill Customization Guide

Report Localization Customization


Objective
You want to provide localized versions of your custom reports in your Windchill Business Reporting (WBR) system.

Background
The Windchill Business Reporting (WBR) solution uses Windchill and Cognos objects. There are both Data Source and Report objects that contain text that can be localized. Localizing the text in these objects allows the text to be displayed in the client's locale.

Scope/Applicability/ Scope/Applicability/Assumptions Assumptions


This documentation assumes that the Windchill Business Reporting (WBR) solution (i.e. Cognos) has been successfully installed and configured. The Windchill instance name is referred to as <WindchillInstanceName>. The Cognos root URL is referred to as <WBRHomeURL>. Typically, if the WBR solution is installed on <WBRHost>, then the <WBRHomeURL> would be http:// <WBRHost>/cognos8/cgi-bin/cognos.cgi. It is assumed that you can login to <WBRHomeURL> and you have sufficient Cognos privileges to view Windchill Data Source objects and create reports. Assume you have access to create files in the source directory associated with <MyPackage> in <WindchillHome>. Assume you have created an Info*Engine task <MyTask> in its associated subdirectory <MyTaskPackage> in <WindchillHome>. Assume you have created the ReportTemplate, <MyReportTemplate> in the Site context of <WindchillHome>. Assume you have created a Windchill Report object, <MyReport> in the Site context. Assume you have created a Cognos Report, <MyCognosReport> in the Windchill folder.

For WBR integration, you must also have access rights to update the reporting meta model.

Report Generation

1209

This document describes procedures for using standard Java resource bundles to externalize text used in the WBR system. To support localized text, a language specific resource bundle must be created and the text translated to the appropriate language. It is assumed that you require support for more than one language and you have the ability to translate text to your supported languages. The text elements that are referred to in this document consist of report names, parameters, and columns. The actual data displayed in WBR reports is returned from Data Sources. Localizing this data is not covered in this document.

Intended Outcome
The end result of this solution is the use of your WBR reports in more the one language based on the client locale.

Solution
External localized text to Java resource bundles that can be translated to support a specific client locale.

Prerequisite knowledge
To achieve this objective, you need to have an understanding of the following:

Info*Engine User's Guide


JConsole User Interface Cognos User Interface Report Management User Interface

Solution Elements
Element <MyTask> Type Info*Engine Task Description The Info*Engine task for retrieving and manipulating Windchill data. The resource bundle info file used to localize Info*Engine task text items. The Windchill object that specifies a query for retrieving Windchill data. The resource bundle info file used to localize

<MyTaskResource>

Resource Bundle Info Properties File

<MyReportTemplate> Windchill Object Windchill ReportTemplate <MyReportTemplateReso Resource Bundle Info urce> Properties File

1210

Windchill Customization Guide

<MyReport> Windchill Report

Windchill Object

<MyReportResource>

Resource Bundle Info Properties File

<MyCognosReport> Cog- Cognos Object nos Report

<MyCognosReportResour Resource Bundle Info ce> Properties File

ReportTemplate text items. The Windchill object that is displayed to end users in the Windchill User Interface. It acts as a proxy to a corresponding Cognos Report object. The resource bundle info file used to localize Report text items. The Cognos object for a report that contains the definition of the query and specifies the presentation formatting. The resource bundle info file used to localize Cognos Report static text.

Procedure - Localizing an Info*Engine Task Data Source


1. Create the file, <WindchillHome>/src/<MyPackage>/<MyTaskResource>. rbInfo. Add entries, as necessary, for the task method name, parameter names, and column names. Create language specific versions of <MyTaskResource>. rbInfo and generate the associated java source and compiled class files. 2. Edit the task XML file, <WindchillHome>/tasks/<MyTaskPackage>/ <MyTask>.xml to specify the resource bundle. The following line should be added to the task comments.
{resouceBundle: <MyPackage>.<MyTaskResource> }

3. Update the Cognos model to incorporate the localized text. Launch JConsole from installed Windchill shortcuts. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, "Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem". From the Operations tab, click "updateModel".

Procedure - Localizing a ReportTemplate Data Source


1. Create the file, <WindchillHome>/src/<MyPackage>/ <MyReportTemplateResource>.rbInfo. Add entries, as necessary, for the task method name, parameter names, and column names. Create language specific

Report Generation

1211

versions of <MyReportTemplateResource>.rbInfo and generate the associated java source and compiled class files. 2. Update <MyReportTemplate> to specify the resource bundle. Navigate to the Windchill Site Utilities and launch the Report Management utility. From the Report Management UI, select <MyReportTemplate>, and click "Update" to launch Query Builder. Select the Report Properties menu item and enter <MyPackage>.<MyReportTemplateResource> into the "Resource Bundle" text field. Click "OK" and save the changes. 3. Update the Cognos model to incorporate the localized text. Launch JConsole from installed Windchill shortcuts. Make connection to Tomcat JVM instance. Select reporting management bean from the MBeans tab, "Tree > com.ptc > WebAppContexts > <WindchillInstanceName> > Monitors > ReportingSystem". From the Operations tab, click "updateModel".

Procedure - Localizing a Windchill Report Object's Name


1. Create the file, <WindchillHome>/src/<MyPackage>/<MyReport>.rbInfo. Add an entry for the Report Object's Name. Create language specific versions of <MyReportResource>.rbInfo and generate the associated java source and compiled class files. 2. Update <MyReport> to specify the resource bundle. Navigate to the Windchill "Site > Reports" page, select the edit action for <MyReport>. Enter "<MyPackage>.<MyReportResource>" into the "Resource Bundle" text field and click "OK". 3. Verify the Report attribute "localizedName" is the translated text based on the client locale.

Procedure - Localizing a Cognos Report


1. Once the Cognos meta model is localized (see Procedure - Localizing an Info*Engine Task Data Source on page 1211 and Procedure - Localizing a ReportTemplate Data Source on page 1211), there is only a single step required to localize the report's name, parameters, and columns. The Report Studio locale must be set to "en_ZW" before authoring a report. 2. Verify the report name, parameters, and columns is the translated text based on the client locale when the report is executed. Use the "Run with options" action to run the report.

1212

Windchill Customization Guide

Customization Points
Procedure - Localizing Cognos Report Static Text
When the above Procedure - Localizing a Cognos Report on page 1212 is followed all report parameter and column names are automatically localized based on the Data Source meta-model information. Any additional text added to a report such as banners or labels is not automatically localized. This can be accomplished using Windchill utilities. 1. Add the static text fields to <MyCognosReport>. 2. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/ <MyCognosReportXML>.xml based on an <MyCognosReport>t. Use Cognos Report Studio menu item "Tools > Copy Report to Clipboard" to copy the XML definition to the system clipboard. Then, paste the clipboard contents into a text editor and save it to file. 3. Generate the base resource bundle file, <WindchillHome>/src/<MyPackage>/ <MyCognosReportResource>.rbinfo using the CongosProxy utility.
windchill com.ptc.windchill.cognos.CognosProxy outputrbinfo <WindchillHome>/loadFiles/cognosReports/custom/<MyCognosReportX ML>.xml <WindchillHome>/src/<MyPackage>/<MyCognosReportResource>.rbinfo

4. Create language specific versions of <MyCognosReportResource>.rbInfo and generate the associated java source and compiled class files. 5. Create the file, <WindchillHome>/loadFiles/cognosReports/custom/ <MyCognosReportAttributes>.properties. The base names from this and step 2 must match exactly (e.g. MyCognosReport.xml and MyCognosReport. properties.
type=report defaultName=<MyCognosReport> resourceBundle=<MyPackage>/<MyCognosReportResource>.rbinfo

6. Load <MyCognosReport> using the following command.


windchill com.ptc.windchill.cognos.CognosProxy loadreports <WindchillHome>/loadFiles/cognosReports/custom/<MyCognosReportA ttributes>.properties

7. Verify the report in Cognos. Refresh the "Public Folders > Windchill" folder and the <MyCognosReport> object should be listed. Use the "Run with options" action to run the report. Try setting different client locales to ensure that the static text is translated properly.

Report Generation

1213

Limitations
To localize a Cognos report, the Report Studio locale must be set to "en_ZW" before authoring a report. Cognos reports reference localized data source and column names based on the Report Studio locale. Any change to these data source and column names for this locale will result in not being able to look up the translated text in another locale. The official workaround recommended by Cognos is to use non-volatile names in a special locale. This special locale is "en_ZW".

Sample Code
Examples of Usage in Windchill Code
All out-of-the-box reports are localized for all Windchill supported locales.

Related Packages/Class Packages/Class Javadoc


Foundation modulue wt.query.template Reporting module com.ptc.windchill

Related Customization Documentation


Internationalization and Localization on page 1395

Other Related Windchill Documentation


Info*Engine User's Guide Info*Engine Implementation Guide Windchill Specialized Administration Guide
Report Management online help

Related Websites
http://support.congos.com/support

1214

Windchill Customization Guide

Report Selection List Customization


Adding a custom action menu item under the ribbon toolbar is not currently supported. However, it is possible to add a menu item to the right-click context menus in the structure that can launch actions or other jsp pages (e.g., reports). There is an example action that can be used as a basis for creating custom actions or reports. Perform the following steps see the example action. 1. There is an example jsp file installed in the following location: <WT_HOME>/codebase/netmarkets/jsp/part/custom/ customAction.jsp. 2. In <WT_HOME>/codebase/config/actions/psb-actionmodels. xml, find the psbRelatedPartsTreeContextMenu model and uncomment the "customActionGWT" action by removing the <! and > delimiters.
<model name="psbRelatedPartsTreeContextMenu"> ...<snip>... <!-- <action name="customActionGWT" type="psb"/> --> </model>

The customActionGWT is defined in the <WT_HOME>/codebase/config/actions/psb-actions.xml file:


<action name="customActionGWT" ajax="component"> <command class="com.ptc.cat.ui.client.action.LaunchURLAction" method="execute" url="/ptc1/psb/customAction" windowType="popup"/> <supportedTypes> <type value="wt.part.WTPart" /> <type value="wt.part.WTPartUsageLink" /> <type value="wt.part.PartUsesOccurrence" /> <type value="wt.part.RTPartPathOccurrence" /> </supportedTypes> </action>

3. Restart the MethodServer and navigate to the Structure tab of a Part information page. 4. Right-click on any part in the structure and select Custom Action in the menu. This launches a window as defined by customAction.jsp. 5. To create custom actions or report, define the action in the appropriate *-actions.xml file (e.g., psb-actions.xml) using the customActionGWT as an example.

Report Generation

1215

Change the name of the action, the url parameter and supportedTypes as needed. Add the resourceBundle parameter to specify the file that contains the label of the action (see Resource Info (.rbInfo) Files section). Then update the model definition in the appropriate *-actionmodels.xml file to include the action defined.

1216

Windchill Customization Guide

27
Packages
Package Type-Based Properties............................................................................. 1218

1217

Package Type-Based Type-Based Properties


Package type-based properties are a new feature in the Windchill 10.0 release that allows customization properties to be assigned to Package objects by class type or soft type. These properties differ from those typically set in wt.properties, and from preferences set in the Preference Manager, in that different types of Package objects may have different settings for the same property. For example, the EnableContentControl property may be set to false for Package types while simultaneously being set to true for TechnicalDataPackage types. Package type-based properties are intended only for site-level and organizationlevel customization, and may only be changed by the Windchill site administrator.

Type-Based Type-Based Properties XML File


Type-based properties are configurable and customizable by loading an XML file that describes the property sets. The following is a sample customized type-based properties XML file:
<?xml version="1.0" encoding="utf-8"?> <WPTypeBasedProperties xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="WPTypeBasedProperties.xsd"> <WPTypePropertySet name="Default"> <WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage"> <EnableContentControl>false</EnableContentControl> <CollectorId>CreateWPBaseline</CollectorId> <IncludedManifestOptions> <ManifestOption default="true">Interactive</ManifestOption> </IncludedManifestOptions> <IncludedDeliveryOptions> <DeliveryOption>Full</DeliveryOption> <DeliveryOption>Incremental</DeliveryOption> </IncludedDeliveryOptions> </WPTypeProperties> <WPTypeProperties typeId="com.ptc.windchill.wp.tdp.TechnicalDataPackage"> . . </WPTypeProperties> </WPTypePropertySet> <WPTypePropertySet name="My Customized Set"> <WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage"> . . . </WPTypePropertySet> </WPTypeBasedProperties>

1218

Windchill Customization Guide

A type-based properties consists of a <WPTypeBasedProperties> root element that contains one or more <WPTypePropertySet> elements. In turn, each <WPTypePropertySet> element contains one or more <WPTypeProperties> elements. And finally, each <WPTypeProperties> element contains one or more elements to set specific properties. Note that within a single <WPTypeProperties> element a specific property, such as <IncludedDeliveryOptions>, may only be given once.

Reading and Loading Type-Based Type-Based Properties XML File


Type-based property sets are created and modified by loading an XML file that describes these sets (see sample in Type-Based Properties XML File on page 1218). This XML file can reside anywhere as long as the location is specified to the loader. The loader is invoked from a Windchill shell while the Method Server is running: java com.ptc.windchill.wp.WPTypeBasePropertiesLoader -load <XML file>

Note The loader will prompt for the site administrator user-id and password to perform this operation.
For convenience, the loader can be used to create an XML file that describes the current type-based property sets in the system or to recreate the default property set from the initial install. The newly created XML file can then be modified and loaded as described above. To retrieve the currently loaded sets, execute the loader from a Windchill shell while the Method Server is running as: java com.ptc.windchill.wp.WPTypeBasePropertiesLoader -read <XML file> To retrieve the OOTB default set from the initial installation, execute the loader from a Windchill shell while the Method Server is running as: java com.ptc.windchill.wp.WPTypeBasePropertiesLoader -read <XML file> -default

Packages

1219

Property Sets
A property set allows for a specific configuration of package types. For example, in one set, traditional Packages (WorkPackage type) can be configured to only allow for the creation of Interactive manifests (offline view) deliveries; while Technical Data Packages can be configured to only allow for Static manifests. Another set may define that Interactive and Static manifests are valid for both types of packages. Multiple sets can be defined in the system, but how the system behaves depends on the current active property set. The active set is selected from the Packages Property Set preference. Property sets are named by specifying a non-blank name attribute in the XML file. For example: <WPTypePropertySet name="My Customized Set"> This XML element defines a new property set named My Customized Set, which can be selected from a list when changing the Packages Property Set value in the Preference Manager. A property set named Default will always be available, even if it is not defined in the type-based properties XML file. In this case the Default properties set will simply specify OOTB system default values. An active set can be defined at the site level or at the organization level; hence, one set may be the active one at one organization while a different organization may have a different active set.

Type-Based Type-Based Property Descriptions


The following sections describe various property settings (see example in TypeBased Properties XML File on page 1218). Properties are given as XML elements that are located within <WPTypeProperties> elements for each package type. For example, the following defines property values that are used for packages of type com.ptc. windchill.wp.WorkPackage, and all of its sub-types and soft-types.
<WPTypeBasedProperties ...> <WPTypePropertySet name="My Customized Set"> <WPTypeProperties WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage"> : (Type-based properties for com.ptc.windchill.wp.WorkPackage) : </WPTypeProperties> </WPTypePropertySet> </WPTypeBasedProperties>

1220

Windchill Customization Guide

If different property values are required for a sub-type or soft-type then additional <WPTypeProperties> elements can be added. For example, the following defines one set of property values for packages of type com.ptc.windchill. wp.WorkPackage, and a different set of property values for the soft-type com. ptc.windchill.wp.WorkPackage|com.MyCompany.MyPackage.
<WPTypeBasedProperties ...> <WPTypePropertySet name="My Customized Set"> < WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage"> : (Type-based properties for com.ptc.windchill.wp.WorkPackage) : </WPTypeProperties> <WPTypeProperties WPTypeProperties typeId="com.ptc.windchill.wp.WorkPackage|com.MyCompany.MyPackage"> : (Properties for com.ptc.windchill.wp.WorkPackage|com.MyCompany.MyPackage) : </WPTypeProperties> </WPTypePropertySet> </WPTypeBasedProperties>

The actual property value used for any specific package type is taken from the most specific type defined in the XML file. If the exact package type cannot be found in the XML file, then the file is reexamined for a parent type. This process continues up the type hierarchy until either an exact type match is found, or the root package type com.ptc.windchill.wp.AbstractWorkPackage is reached. If the root type is reached then the system default property values are used (see Reading and Loading Type-Based Properties XML File on page 1219 for obtaining a XML file with system default values). Note that custom property values cannot be set for the root package type. The following sections describe each specific property that can be set. Singlevalued properties are specified by a single XML element, and multi-valued properties are specified by an outer XML element with one or more inner XML elements. All of the properties describe in the following sections are optional. If a property value is not specified for a specific type of package then the value from its parent type will be used. EnableContentControl The EnableContentControl property is used to enable or disable content control processing. For more information, see . See the File Table topic in the Windchill Help Center for more information. The following tag will enable content control processing for this package type:
<EnableContentControl>true</EnableContentControl>

Default value: false

Packages

1221

CollectorId The CollectorId property controls which collection component instance to use when the Configure link is selected from the Add to Package window. For example:
<CollectorId>MyCustomCollectorId</CollectorId>

Default value: CreateWPBaseline ExcludedSeedTypes The ExcludedSeedTypes property controls object types that cannot be added as seeds to a package. Object types specified in this property cannot be pasted into the Initially Selected Objects table in the Add to Package window. They will also not be returned in the Search Results table when searching for initially selected objects. For example, the following will exclude objects of type WTDocument and part soft-type com.MyCompany.MyCustomPart from being added to the Initially Selected Objects table.
<ExcludedSeedTypes> <SeedType>wt.part.WTPart|com.MyCompany.MyCustomPart</SeedType> <SeedType>wt.doc.WTDocument</SeedType> </ExcludedSeedTypes>

Default value: none no object types will be excluded and the full range of package seed types will be available IncludedContentRoles The IncludedContentRoles property controls which types of content files associated with a package object are added to an exported zip file (created using the Zip for Delivery action). Content files associated to a package by the WP_EXP_SECONDARY content role are always added, regardless of the values given for this property. For example, the following specifies that in addition to content files associated by role WP_EXP_SECONDARY, an export file will also contain content files associated with the package object by roles MyCustomContentRole and SECONDARY:
<IncludedContentRoles> <ContentRoleKey>MyCustomContentRole</ContentRoleKey> <ContentRoleKey>SECONDARY</ContentRoleKey> </IncludedContentRoles>

The value in the <ContentRoleKey> element must be a key defined in class wt.content.ContentRoleType. It can be a key for either a custom role or an OOTB role.
Windchill Customization Guide

1222

Default value: none only content files associated to a package object by the WP_EXP_SECONDARY role will be added to an export file IncludedDeliveryOptions The IncludedDeliveryOptions property controls which delivery options are presented in the Zip Package for Delivery window. The valid delivery options are: Full displays option Provide complete delivery. If selected, an exported zip file will contain all the package contents that are accessible to the recipient. Incremental displays option Provide incremental delivery from. If selected, an exported zip file will contain only the package contents that are accessible to the recipient, and were not included in the base delivery. Incremental manifest displays option Provide complete delivery with incremental information from. If selected, an exported zip file will contain all the package contents that are accessible to the recipient, similar to the Full option, but will also contain a manifest file describing incremental changes between the base delivery and the new delivery.

Regardless of the options specified, all exported zip files for the first version of a package will use the Full option, and the Zip Package for Delivery window will not display the delivery options. Also, regardless of the options specified, all exported zip files for any version of a package will use the Full option if this is the first version delivered to a recipient. For example, the following will cause all three delivery options to be displayed for recipients of earlier package versions:
<IncludeDeliveryOptions> <DeliveryOption>Full</DeliveryOption> <DeliveryOption>Incremental</DeliveryOption> <DeliveryOption>Incremental manifest</DeliveryOption> </IncludeDeliveryOptions>

If either of the incremental delivery options is selected in the Zip Package for Delivery window, then a base delivery must also be specified. Only earlier deliveries to the same recipient may be used as a base delivery. Default values: Full, Incremental IncludedManifestOptions The IncludedManifestOptions property controls which manifest options are presented in the Zip Package for Delivery window. The valid manifest options are:

Packages

1223

Interactive displays option Include offline viewer. If selected, an exported zip file will contain an offline view of the package and its contents, but will not contain a manifest file. Static displays option Include manifest file. If selected, an exported zip file will contain a manifest file and the content files associated with the package object and its members. It will not contain an offline view. The manifest will also be associated to the Delivery object as a primary content file. The name of the manifest file can be controlled using the ManifestFileName property (see the ManifestFileName section for more information). None displays option Do not include any manifest. If selected, an exported zip file will contain the content files associated with a package object and its members. It will not contain an offline view or a manifest file.

For example, the following will cause all three manifest options to be displayed, and the Static option will be pre-selected by default.
<IncludedManifestOptions> <ManifestOption>Interactive</ManifestOption> <ManifestOption default="true">Static</ManifestOption> <ManifestOption>None</ManifestOption> </IncludedManifestOptions>

The default=true attribute specifies which option will be pre-selected in the display. If this attribute is not specified then the first option given in the XML list will be pre-selected. Default value: Interactive ManifestFileName The ManifestFileName property defines the file name to be used when a static manifest is created during export (see the IncludedManifestOptions section ). For example, the following would set the manifest file name to MyManifest.txt: <ManifestFileName>MyManifest.txt</ManifestFileName> Default value: manifest.txt StaticManifestClassOverride The StaticManifestClassOverride property is used to override the OOTB Java class used to create a static manifest for an exported zip file (see the IncludeManifestOptions section for more information). The content and format of a static manifest file can be customized by creating a new Java class and setting this property to its fully qualified class name. A custom Java class for creating a static manifest file will have the form:
package com.MyCompany

1224

Windchill Customization Guide

import java.io.InputStream; import com.ptc.netmarkets.wp.ixb; import wt.util.WTException; class MyStaticManifest extends AbstractStaticManifest { protected InputStream createManifest(WPZipContent zipContent) throws WTException { : (Create custom static manifest file) : > }

For example, the following would specify that custom Java class com. MyCompany.MyStaticManifest be used to create a static manifest file:
<StaticManifestClassOverride> com.MyCompany.MyStaticManifest </StaticManifestClassOverride>

Default value: com.ptc.netmarkets.wp.ixb.StaticManifest ExcludedMemberContentRoles The ExcludedMemberContentRoles property controls which types of content files associated with package members are excluded from an export file. Also, when Content Control is enabled (see EnableContentControl section) content files for these roles are excluded from display in the Select Files window. For example, the following specifies that content files associated by roles THUMBNAIL and THUMBNAIL3D will not be added to an export file:
<ExcludedExportContentControlRoles> <ContentRoleKey>THUMBNAIL</ContentRoleKey> <ContentRoleKey>THUMBNAIL3D</ContentRoleKey> </ExcludedExportContentControlRoles>

The value in the <ContentRoleKey> element must be a key defined in class wt.content.ContentRoleType. It can be a key for either a custom role or an OOTB role.

Packages

1225

28
Desktop Integration
DTI Customization Framework................................................................................ 1228

1227

DTI Customization Framework


Windchill supports a Microsoft Office integration known as Windchill Desktop Integration (DTI). DTI supports Windchill actions, such as Create Document , Check In , Check Out , and Search , from within Microsoft Office applications under the Windchill tab. Windchill Desktop Integration supports customization to suit your site-specific action implementations. This customization involves the introduction of new actions (launch points) on the Microsoft Office ribbon UI and the implementation of those actions either on the remote Windchill server or on the local client system Windchill Desktop Integration provides a way to add custom actions to the Office ribbon menu, invoke the actions using command configurations and inject implementation using VBA macros, allowing you to perform a variety of tasks on the documents being managed using Windchill Desktop Integration. This chapter explains the customization framework concepts, rules and implementation. The chapter is divided into two major sections: Client Side Customization on page 1229 documents changes needed to support Microsoft Office applications on client systems Server Side Customization on page 1235 documents changes involved on the Windchill server side

1228

Windchill Customization Guide

Client Side Customization


Customizing the Ribbon U
For Microsoft Office 2007 and greater, Windchill Desktop Integration allows system administrators to introduce custom buttons on the Windchill tab in Microsoft Office applications. The only requirement is the presence of a valid XML file with the custom ribbon UI definition. This file must be located at: <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom/wtCustomMenu.xml The following section explains the structure of this XML file. Creating the custom menu Example code:
<group id="MyCustomActions" tag="MyCustomActions" getLabel="MsoiGetLabel" getScreentip="MsoiScreentip" getVisible= "MsoiServerVisible"> <button id="CustomAction01" tag="CustomAction01" enabled="true" label="Custom Action 01" screentip="Click this to launch the first custom action" getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="ca1"/> <button id="CustomAction02" tag="CustomAction02" getEnabled="MsoiIsEnabled" getLabel="MsoiGetLabel" getScreentip="MsoiScreentip" getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="ca2"/> </group>

Creating a Group All custom actions required to be implemented must be located inside a group. This serves as the root/document element for the custom ribbon UI in XML. Creating a Button Adding a button node as child to the group will make it display on the ribbon UI as a clickable item. Controlling Visibility of a Group If you want the group to be visible only when connected to an active Windchill server, the attribute getVisible for the group node must be set to MsoiServerVisible as above. If the group should be visible at all times, remove the getVisible attribute and set visible to true.

Desktop Integration

1229

Controlling State of a Button Unless server side changes are explicitly made to render the enabled/disabled state of a button, the button will remain disabled if the attribute getEnabled is set to MsoiIsEnabled. If the button should be enabled whenever the group is visible, remove the getEnabled attribute from the button node and set the enabled attribute to true. Creating an Application Specific Custom Menu Windchill Desktop Integration supports customization of the ribbon UI for a specific Microsoft Office application. The file name needs to be appended by the short application name. For example, having the following ribbon UI configuration in the <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom/wtCustomMenuExcel.xml file would make a new button display in Microsoft Excel.
<?xml version="1.0"?> <groups> <group id="ExcelActionsGroup" tag="ExcelActionsGroup" label="Excel actions group" screentip="Custom Excel actions group" visible="true"> <button id="MyExcelButton" tag="MyExcelButton" enabled="true" label="Invoke my own custom Excel action" screentip="Clicking here will launch my own Excel action." getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="ea"/> </group> </groups>

Static Text The attributes label and screentip control the label and the tooltip for the button respectively. In general, static text will marginally improve performance. Localizing Text Windchill Desktop Integration allows a way to localize the text displayed on the ribbon UI. This would enable end users to see translations in their native languages. PTC recommends that the id and the tag attributes be left as some unique text. Windchill Desktop Integration will use the tag attribute for further processing as mentioned below. Note that localization of ribbon button labels and screentips will work only when the label and screentip attributes are replaced with getLabel and getScreentip attributes respectively. The values for these attributes must be set to MsoiGetLabel and MsoiScreentip respectively.

1230

Windchill Customization Guide

Localizing the label Add a new node to the following file (or its locale specific equivalents) on the server: <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom/wtCustomLabels.xml The format of the node is given below:
<CustomAction02> <short>Custom Action 02</short> </CustomAction02>

The parent node name (CustomAction02 in this case) must match with the tag attribute of the group/button for which translated text is needed. Adding the relevant node text to the wtCustomLabels_ru.xml file will make the translation for Russian show up. Deploying the translations to all clients After the changes are saved on the server, a copy of this file will automatically get picked up by the Windchill Desktop Integration client. Localizing the tooltip This is similar to the label except that the child node should be named as tooltip. The modified translation node for the sample button looks:
<CustomAction02> <short>Custom Action 02</short> <tooltip>Click here to launch this custom action</tooltip> </CustomAction02>

Additional Resources See the Microsoft documentation on ribbons for further details on ribbon UI.

Custom commands
Windchill Desktop Integration allows the addition of new commands to the existing set. These commands are the implementations of sets of actions to be triggered, based on interaction with the new controls on the ribbon UI. These commands can be controlled from the server directly (rather than having to make changes on each client system). For the custom ribbon action introduced for Microsoft Office, the file in question on the server is: <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom/wtCustomActions.xml

Desktop Integration

1231

Creating Custom Commands Example


<command key="CustomAction01"> <action method="run_macro" type="CLIENT"> <defaultdata key="macro_name">DisplayHelloWorldAlert</defaultdata> </action> <action serverAction="customization.DTICustomizationDemo" type="WIZARD"/> </command>

Client Actions In this example, the SaveDoc method is invoked on the client, which saves the file opened in Microsoft Office. Server Actions Next, the create wizard is launched from the server in an embedded browser. Adding Action Specific Data The description for the document is pre-populated with the text Add your description below this:. If the intent is only to pass the data retrieved from the server from an earlier action to the next one, then an empty macro_args data node can be used as exemplified in the second run_macro action instance from the SearchParts example implementation scenario. Note that the method and serverAction mentioned is actually implemented on the client and the server respectively and would therefore work. Each attribute value should be accompanied with implementation else the Action not found error will be displayed by Windchill Desktop Integration. Deploying Custom Commands to All Clients After the changes to this file are saved, the Windchill Desktop Integration client will automatically pick up a copy of the changes from the server when it connects to the server the next time.

Implementing Custom Commands Using Macros


Running Macros Windchill Desktop Integration only expects the macro code to be available to the Office document in question. It can run both types of macros: those which were injected into the Office document via the import_module action or those which already existed in the document.

1232

Windchill Customization Guide

Action Configuration
<action method="run_macro" type="CLIENT"> <defaultdata key="macro_name">Macro1</defaultdata> <defaultdata key="macro_args">Albert Einstein</defaultdata> </action>

The macro_name key is a reserved and mandatory keyword. Providing Data to the Macro The macro_args is optional and can be used in case additional data needs to be provided to the macro. Handling Multiple Inputs In case the macro needs multiple inputs, PTC recommends that this be handled via VBA code within the macro itself. For example, assuming the macro needs more than one argument, an XML file could be generated with the relevant data and the relative filename provided as a value to macro_args. This XML file could again be placed on the server so that it is picked by all Windchill Desktop Integration clients on the subsequent connect action. Alternatively, multiple pieces of information could be provided using some delimiter (with proper XML escaping). The VBA macro code could again split the data on the delimiter and recreate the original information. Exception Handling PTC recommends that the macros be thoroughly tested using live Microsoft Office documents before being uploaded on the Windchill server for deployment. Windchill Desktop Integration is not responsible for any exceptions arising during macro execution. All errors will be displayed to the users. Injecting Macros Creating macro modules for injection The following example illustrates how to create a macro module for injection in Excel: 1. create a new folder named Excel under <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom 2. Create Module1.bas under it. and paste the following code into the file:
Sub Macro1(sUsername As String) MsgBox("Hello " & sUsername & "! This is a macro alert.") End Sub

Deploying macro modules to all clients

Desktop Integration

1233

The Windchill Desktop Integration client automatically picks up all modules on the subsequent connect action on the server. Importing macro modules into office 1. Importing macro modules into Microsoft Office requires changes to the wtCustomActions.xml file on the server as stated earlier. A sample of the import module action is given below for the syntax.
<action method="import_module" type="CLIENT"> <defaultdata key="module_path">custom\Excel\Module1.bas</defaultdata> </action>

If the value of module path parameter is not an absolute path, then it is expected to be the relative path from the custom folder. Where does the module get imported ? The module will get imported to different files and templates based on the Microsoft Office application in question. For example, Microsoft Word will normally import into the Normal.dot* template. On the other hand, Excel will directly import into the open workbook. The location can be confirmed by using the VBA editor (shortcut Alt + F11). Removing Macros To remove the macro in the Office document after it has been run, use the following action configuration:
<action method="remove_module" type="CLIENT"> <defaultdata key="module_name">Module1</defaultdata> </action>

The module_name key value should match with what is displayed as the module name in the VBA editor (Alt + F11).

1234

Windchill Customization Guide

Server Side Customization


When any set of actions require interaction with the Windchill server, either user interaction in the form of wizards or some data to be retrieved over the web, it is necessary to implement the action on the remote Windchill server. There are three steps to this server side customization: 1. Defining the custom action 2. Desiging the user interface 3. Implementing the form processor Defining the Custom Action To handle server side operations of DTI customization, create a new custom action. A custom action can be defined in any *-actions.xml file. Refer to the User Interface Customization section for more details. Example structure for the action definition The file <WT_HOME>/codebase/config/actions/custom-actions.xml could be modified to introduce the following XML fragment as a child node to the listofactions root node.
<objecttype name="test_object" class="wt.doc.WTDocument"> <action name="test_action"> <command class="com.ptc.customization.forms.TestFormProcessor" method="execute" windowType="popup" url="/netmarkets/jsp/customization/Test.jsp"/> </action> </objecttype>

This is the configuration for the test_action action defined for objects of type test_object. Invocation of this action would launch Test.jsp. On completion of interaction with the user interface rendered by this page, a response will be built in TestFormProcessor and can be passed on to the client, if desired. Designing the User Interface In case the server interaction involves any wizards, it is necessary to design the corresponding user interface. In its most simplistic form, the user interface can be a simple JSP file that resides on the server and performs some actions on a set of Windchill objects. For further details on implementing custom user interfaces, see User Interface Customization.

Desktop Integration

1235

Implementing the Form Processor When the data is to be submitted to the Windchill server, the form processor is responsible for generating the response to be returned to the client. The basic guideline of customizing Windchill UI remains the same, however. For details, refer to the Customizing the UI with Ajax.

1236

Windchill Customization Guide

Implementation Example
In the following example, the user needs to select a set of Windchill parts and query certain properties of these selected parts. We add these properties in a Micorsoft Excel sheet in the form of column headers. The properties to be selected and its sequence will be provided as an input to the Windchill server. The response from the server would be picked up by the client and will be populated in a tabular form in the Microsoft Excel sheet. A working example of this example is also available in the Windchill installation. To deploy the sample, using the Windchill shell, navigate to prog_examples/DTI_Customization. Under each of the folders src and src_web, find and invoke the ant script named build.xml. DTICustomizationReadMe.txt is included for quick reference. Once ant has been invoked on both the ant files, the Windchill server needs to be restarted. The rest of this section discusses the alternative manual steps needed to configure the example implementation.

Client Side Customization


Customizing the Ribbon UI Add the following text in the <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom/wtCustomMenu.xml file:
<?xml version="1.0"?> <groups> <group id="ExcelActionsGroup" tag="ExcelActionsGroup" label="Excel actions group" screentip="Custom Excel actions group" visible="true"> <button id="SearchParts" tag="SearchParts" enabled="true" label="Search parts" screentip="Sample custom action to search parts on the Windchill server." getImage="MsoiGetImage" onAction="MsoiOnAction" keytip="sp"/> </group> </groups>

The next time a Windchill Desktop Integration client running Microsoft Excel connects to this server, the updated ribbon UI definition will get downloaded to the client cache. We close Microsoft Excel and launch it again. This step is necessary because the Windchill add-in will load in the MS Office application (Excel) even before connecting to any Windchill server. When Microsoft Excel is launched a second time, you should be seeing a new group and an action under it as shown below.

Desktop Integration

1237

Custom Commands We now need to implement the custom action that we introduced. Configuring a command involves defining a set of actions that will get invoked once the ribbon control is clicked on. The tag attribute for the control SearchParts should match the command key. This is how Windchill Desktop Integration can establish an association with the custom controls on the ribbon UI with the command. Going by the problem description, we need to read the header values from the Microsoft Excel sheet, send the property names to be sent to the server, and feed the response into the sheet again. This calls for a command configuration as defined below. This text needs to be located in the <WT_HOME>/codebase/com/ptc/windchill/enterprise/ nativeapp/msoi/client/custom/wtCustomActions.xml file.
<?xml version="1.0"?> <commandset> <command key="SearchParts"> <action method="run_macro" type="CLIENT"> <defaultdata key="macro_name">GetHeaders</defaultdata> </action> <action serverAction="customization.DTICustomizationDemo" type="WIZARD"/> <action method="run_macro" type="CLIENT"> <defaultdata key="macro_name">PutValues</defaultdata> <defaultdata key="macro_args"/> </action> </command> </commandset>

Now we have two client side actions with a server action in between. Running Macros For the sake of simplicity, let us have the cells A1-D1 populated with the properties we need to query the parts. The Microsoft Excel sheet looks like this:

1238

Windchill Customization Guide

We introduce a macro that simply joins the text of these four cells with a separator.

The name of the macro GetHeaders must match with the action configuration data parameter macro_name. Similarly, we need another macro that will subsequently pick up response from the server and populate it in the sheet. According to the action configuration, this macro needs to be called PutValues. The VBA code for our Microsoft Excel workbook now looks like the following:

Note that the code within the PutValues macro above, will simply generate an alert message with the custom response received from the Windchill server. In practice, the code could do complex actions such as generating an inline validation dropdown for certain cells.
'A reference to msxml6.dll is needed Dim dom As New DOMDocument60 dom.LoadXML (strResponse) 'Using xpath, construct a csv list of choices for the number Dim strNumberChoices As String

Desktop Integration

1239

For Each elem In dom.SelectNodes("/Results/*/Number") strNumberChoices = strNumberChoices & "," & elem.Text Next 'Remove initial comma strNumberChoices = Strings.Right(strNumberChoices, Len(strNumberChoices) - 1) With Range("C1").Validation 'Remove previous validation (likely that user redoing a seed part search) .Delete .Add Type:=xlValidateList, _ AlertStyle:=xlValidAlertStop, _ Operator:=xlBetween, _ Formula1:=strNumberChoices End With

1240

Windchill Customization Guide

Server Side Customization


Defining the Custom Action The <WT_HOME>/codebase/config/actions/custom-actions.xml file is an empty file available Out of the box, which can be used for this sample customization. Add the following XML text as a child node for the listofactions document node.
<objecttype name="customization" class="wt.doc.WTDocument"> <action name="DTICustomizationDemo"> <command class="com.ptc.dti.customization.forms.DTICustomizationFormProcessor" method="execute" windowType="popup" url="/netmarkets/jsp/customization/partPicker.jsp"/> </action> </objecttype>

Here the DTICustomizationDemo action is defined which will be called from the DTI client side. On invocation of this action, a partPicker.jsp is launched. On completion of this wizard, a response is built in DTICustomizationFormProcessor. Designing the User Interface For this example, we need the WTPart search and multiple part picker capability, which is implemented in partPicker.jsp using itemPicker tag with WTPart as objectType.
<%@ taglib prefix="wctags" tagdir="/WEB-INF/tags" %> <%@ include file="/netmarkets/jsp/components/beginWizard.jspf"%> <%@ taglib uri="http://www.ptc.com/windchill/taglib/dti" prefix="dti"%> <wctags:externalFormData/> <input type="hidden" name="fieldsToDisplay" id="fieldsToDisplay" value="${dti:getCustomActionArg(param.externalFormData)}" /> <input type="hidden" name="selectedParts" id="selectedParts" value=" " /> <wctags:itemPicker id="dtiPartPicker" inline="true" pickerCallback="partPickerCallback" componentId="dtiPartPicker" pickerTitle="DTI Customization Part Picker Example" objectType="wt.part.WTPart" multiSelect="true" /> <SCRIPT> function partPickerCallback(objects) { var selectedPartsOid = ''; var myJSONObjects=objects.pickedObject; for(var i=0; i< myJSONObjects.length;i++) { if(i != 0){ selectedPartsOid += ';'; //partOID separator } selectedPartsOid += myJSONObjects[i]["oid"]; }

Desktop Integration

1241

$("selectedParts").value = selectedPartsOid; window.pickerCallback = "doNothing"; } </SCRIPT> <%@ include file="/netmarkets/jsp/util/end.jspf"%>

There are a few important points to note in this jsp: Use the wctags:externalFormData tag to pass DTI data in the form of hidden field. Use dti:getCustomActionArg(param.externalFormData) to capture the input argument that is send from DTI. It is passed to the form processor as hidden field.

In this example, the argument sent is a list of Windchill part properties to query with :: as separator(Name::Number::Version::State). A pickerCallback function is defined, which will capture OIDs of selected parts and put it in a string with ; separators, then pass that list of selected parts OIDs to form processor through selectedParts hidden field. The following screenshot is of the partPicker.jsp after searching and selecting a few records:

1242

Windchill Customization Guide

Implementing the Form Processor The form processor is implemented in the DTICustomizationFormProcessor.java file. The required data like fieldsToDisplay and selectedParts is obtained from beans data. Here, a user can format the response in any format like xml, txt, csv etc and put that in the session object in the form of a string. The same response is made available at DTI client side as response. The only requirement here is to pass DTI_CUSTOM_KEY=<dtiCustKey> as a part of wizardResponsehandler. Below is sample code of the setResultNextAction method:
String responseString = <RESULTS> <Result0 Name="01-51231.prt" Number="WCDS0000000104" State="INWORK" Version="A.1"/> <Result1 Name="01-51246_2.prt" Number="WCDS0000000150" State="INWORK" Version="A.5"/> <Result2 Name="01-52100.asm" Number="WCDS0000000473" State="INWORK" Version="A.2"/> <Result3 Name="01-512040.asm" Number="WCDS0000000654" State="INWORK" Version="A.1"/> <Result4 Name="01-51251a.prt" Number="WCDS0000000055" State="INWORK" Version="A.1"/> <Result5 Name="01-512106a.prt" Number="WCDS0000000363" State="INWORK" Version="A.1"/> </RESULTS>; String dtiCustkey = "DTI_CUST_DATA" + System.currentTimeMillis(); clientData.getRequest().getSession().setAttribute(dtiCustkey, responseString); wizardResponseHandler += "&DTI_CUSTOM_KEY="+ dtiCustkey;

Here responseString is built as an XML response based upon properties to query and parts selected. This same response string in the same format will be available at DTI client side. Refer to the DTICustomizationFormProcessor.java file available in your Windchill installation for more details on implementation.

Desktop Integration

1243

29
PLM Services Support in Windchill
Product Lifecycle Management Services, Version 2.0 ............................................... 1246 PLM Mapping Information ...................................................................................... 1247 PLM Message Format............................................................................................ 1279

1245

Product Lifecycle Management Services, Version 2.0


Overview The import and export functionality in Windchill is based on default Windchill format. This functionality also supports the PLM Services 2.0 format. The PLM Services import and export leverages the same infrastructure. In order to transform the data from and to Windchill format to and from PLM service format, a standard mapping file (%WT_HOME%\codebase\wt\ixb\impl\jaxb\plm \mapping.xml) is created. This mapping file defines the element and attribute mapping for all the elements. The out-of-the-box version of this mapping file is a sample mapping provided by PTC that must be customized by end users for their own business needs. Additional Resources For more information on Product Lifecycle Management Services Version 2.0, see the Object Management Groups website at: http://www.omg.org/spec/PLM/2.0/ http://schema.omg.org/specs/PLM/2.0/schema/InformationalModel.xsd For specific information on the InformationalModel.xsd schema, see:

1246

Windchill Customization Guide

PLM Mapping Information


This section contains details on the PLM Services support in Windchill 10.0. The details of the mapping includes the list of supported objects, the data models, sample mappings, and information on extending schemas.

Windchill Objects Supported for PLM Services 2.0


The import and export framework which is used to exchange data in Windchill schema supports the import and export in PLM Services 2.0 format. Current support is limited to the following Windchill objects: WTPart EPMDocument EPMMemberLink EPMDescribeLink EPMBuildHistory EPMBuildRule WTPartUsageLink

All required Windchill attributes are mapped for supported objects; if any other optional attributes are to be mapped, this can be achieved through customization. Customization to the out-of-the-box mapping is also possible and is discussed later in this documentation. If you want to use soft types of any of the objects listed above (wherever applicable), the soft types will be automatically supported for PLM Services 2.0 format.

Windchill Data Model Supported for PLM Services 2.0


Note: Only objects highlighted with a green rectangle ( ) are supported.

PLM Services Support in Windchill

1247

Part Structure (WTPart and WTPartUsageLink)

EPMMemberLink

1248

Windchill Customization Guide

EPMDescribeLink

mapping.xml mapping.xml file


A mapping file (mapping.xml) that defines the elements and attribute mapping is used to convert Windchill native format ( %WT_HOME%\loadXMLFiles\standardx20.dtd) to PLM Services format ( %WT_HOME%\codebase\wt\ixb\schema\plm \informationalModel.xsd). There are three types of mapping: alias_mapping value_reference_mapping element_mapping

Sample Mapping Name Patterns We have used following conventions to represent mapped element name and required attributes: Relative path, such as Template_instance/Name/value, get/set values by it. Absolute path for single element, such as /Digital_file, which means this element is stored in the same level as current element instead of sub element.

PLM Services Support in Windchill

1249

Alias path, such as alias_uid_for_item_version, which will be defined in alias_mapping section as following:
<alias name="alias_uid_for_item_version" path="Item_version" attribute="uid"/>

This will be same as Item_version/uid, we can use alias to reduce duplicated mapped name. Value reference path one, such as value_reference_classification_name, which will be defined in value_reference_mapping section as following:
<value_reference name="value_reference_classification_name" mapped_name="/Specific_item_classification" path="Classification_name" ref_attribute="Associated_item"/>

This means to create a Specific_item_classification element in the same level as current element and store value to Classification_name, also Specific_item_classification will hold a reference of current element by Associated_item, we can use value reference to reduce duplicated mapped name. Value reference path two, such as value_reference_File_format_path, which will be defined in value_reference_mapping section as following:
<value_reference name="value_reference_File_format_path" attribute_name="File_format" ref_type="/Document_format_property"> <sub_value_reference attribute_name="Data_format"/> </value_reference>

We will create a Document_format_property element, store the value to Data_format also set the element to current element by File_format, we can use value reference to reduce duplicated mapped name. Tips The following variables can be used in required_attributes: {ROOT} Use the root object of this element {UUID} Create a random UUID {KEY} Use the name of the current attribute {VALUE} Use the string representation of the current attributes value

1250

Windchill Customization Guide

Details of the Mapping between Windchill and PLM Services


Alias Mapping Defines alias for mapping path which can be used in mapped name and required attributes in element mapping section, we will use this to reduce duplicated mappings. This will be only relative path. Parent Name alias_mapping/alias Name exceptions Type element Data Type Required? DescripDescription no element Sub alias mapping, used with type attribute to provide different alias mapping by different attribute values. yes ID Unique name of alias element. no string Related path to store/retrieve value. no string Attribute name for store/retrieve value, used with path together. no string Windchill attribute name to be used to identify a different alias.

name

attribute

path

attribute

attribute

attribute

type

attribute

PLM Services Support in Windchill

1251

The following mapping will be mapping for exceptions: Parent Name exceptions Name value Type attribute Data Type Required? DescripDescription yes string The value of defined type attributes. no string Related path to store/retrieve value. no string Attribute name for store/retrieve value, used with path together.

path

attribute

attribute

attribute

Value Reference Mapping Defines alias for mapping path which can be used in mapped name and required attributes in element mapping section, we will use this to reduce duplicated mappings. This will contain two kinds of path: 1. Element which hold a reference of current element, as following:
<Specific_item_classification uid="uid"> <Associated_item>ref_uid</Associated_item> <Classification_name>assembly</Classification_name> </Specific_item_classification> <Item uid="ref_uid"> </Item>

2. Element which will be reference by current element, as following:


<Document_file uid="uid"> <File_format>ref_uid</File_format> </Document_file> <Document_format_property uid="ref_uid"> <Data_format>ApplicationData</Data_format> </Document_format_property>

Parent Name Name value_refer- exceptions ence_mapping/value_reference

Type element

Data Type Required? DescripDescription no element Used with type attribute in element mapping to define
Windchill Customization Guide

1252

Parent Name

Name

Type

sub_value_reference

element

name

attribute

path

attribute

condition

attribute

mapped_name

attribute

type

attribute

Data Type Required? DescripDescription different value reference mapping for different attribute value. no element Sub value reference mapping, used for path No. 2 only. yes ID Unique name of value reference element. no string Related path to store/retrieve value, used for path No.1 only. no string Condition to filter the element, used for path No.1 only, support following pattern only: <key>=<value> no string Parent element name for the path, used for path No.1 only. no string For path

PLM Services Support in Windchill

1253

Parent Name

Name

Type

ref_attribute attribute

connect_re- attribute ference reuse

attribute

Data Type Required? DescripDescription No.1:The relative path to check if current element is a supported windchill tag. for example, Item_shape will also be used to represent representation and EPMDescribeLink.For path No.2: The element name which will be create as reference, this should be sub element. no string The relative path which keeps the object reference, used for path No.1 only. no string The sub element which will be used as reference. no boolean Defines if this element is reusable, work with

1254

Windchill Customization Guide

Parent Name

Name

Type

locate_by

attribute

ref_type

attribute

required_at- attribute tributes

attribute_name

attribute

Data Type Required? DescripDescription locate_by attribute together to find previous created element instead of create new one all the time. no string Defines the attribute list of a reusable element, separated by a comma (,). no string The element name which will be create as reference, this should be root element, used for path No.2 only. no string Attributes which are required for current element, separated by a comma (,).It can be relative path and alias path. no string The relative path which

PLM Services Support in Windchill

1255

Parent Name

Name

Type

identifier

attribute

Data Type Required? DescripDescription will be used to hold reference or attribute value, used for path No.2 only. If identifier is configured, it will be used to store the name of attribute. no string The relative path which will be used to hold attribute value, works with attribute_name together to store attribute name and value.

The following mapping will be mapping for exceptions: Parent Name exceptions Name sub_value_reference Type element Data Type Required? DescripDescription no element Sub value reference mapping, used for path No. 2 only. no string The relative path which will be used to hold

attribute_name

attribute

1256

Windchill Customization Guide

Parent Name

Name

Type

value

attribute

ref_type

attribute

type

attribute

required_at- attribute tributes

Data Type Required? DescripDescription reference or attribute value, used for path No.2 only. no string The attribute value to choose current exception configuration. no string The element name which will be create as reference, this should be sub element, used for path No.2 only. no string The element name which will be create as reference, this should be root element, used for path No.2 only. no string Attributes which are required for current element, separated by a comma (,).It can be relative path

PLM Services Support in Windchill

1257

Parent Name

Name

Type

Data Type Required? DescripDescription and alias path.

The following mapping will be mapping for sub_value_reference_type Parent Name Type Name sub_vaadd_to_ele- element lue_referen- ment ce_type Data Type Required? DescripDescription no element Element mapping which current element will be added to. no element Element mapping which current element will reference it. no string The relative path which will be used to hold reference or attribute value, used for path No.2 only. If identifier is configured, it will be used to store the name of attribute. no string Attributes which are required for current element, separated by a

reference_to element

attribute_name

attribute

required_at- attribute tributes

1258

Windchill Customization Guide

Parent Name

Name

Type

connect_re- attribute ference

ref_type

attribute

unit_attribu- attribute te_name

reuse

attribute

Data Type Required? DescripDescription comma (,).It can be relative path and alias path. no string The sub element which will be used as reference. no string The element name which will be create as reference, this should be root element, used for path No.2 only. no string The relative path which will be used to hold unit attribute value. Used for path No.2 and iba only. no boolean Defines if this element is reusable, work with locate_by attribute together to find previous created element instead of create new

PLM Services Support in Windchill

1259

Parent Name

Name

Type

locate_by

attribute

identifier

attribute

Data Type Required? DescripDescription one all the time. no string Defines the attribute list of a reusable element, separated by a comma (,). no string The relative path which will be used to hold attribute value, works with attribute_name together to store attribute name and value.

The following mapping will be mapping for add_to_element and reference_to: Parent Name Name add_to_ele- name ment Type attribute Data Type Required? DescripDescription yes string Path which is used to add current element to another element. It can be relative path and alias path. yes string The value which will be used to find parent element. yes string Path which
Windchill Customization Guide

value

attribute

reference_to name

attribute

1260

Parent Name

Name

Type

value

attribute

connect_re- attribute ference

Data Type Required? DescripDescription is used to reference another element. It can be relative path and alias path. yes string The value which will be used to find another element. yes string The sub element which will be used as reference

Note Use following pattern to define value attribute: {ROOT}/usedBy/ObjectReference/ufid, this means to get value of attribute named usedBy/ObjectReference/ufid from current element.
Element Mapping Define the mapping from Windchill native element (or attribute) to other formats. There are two kinds of mappings: element and attribute. Element mapping can contain element_mapping or attribute mapping as sub elements. Parent Name element_mapping Name element Type element Data Type Required? DescripDescription yes element Root element mapping yes string Local name of the root element. no string Attribute name whose type is xsd: ID. no string Attribute

root_tag_name id_tag

attribute

attribute

ref_tag

attribute

PLM Services Support in Windchill

1261

Parent Name

Name

Type

required_at- attribute tributes

Data Type Required? DescripDescription name whose type is xsd: IDREF, which is used globally. no string Required attributes of the root element, separated by comma (,).

The following will be mapping for element: Parent Name element Name element attribute Type element element Data Type Required? DescripDescription no element Sub element mapping no element Attributes mapping under current element yes string Element name of windchill native format. yes string Mapped element name no boolean Defines whether the element should be retrieved from previous exported ones instead of creating new one,
Windchill Customization Guide

name

attribute

mapped_name reuse

attribute attribute

1262

Parent Name

Name

Type

default_attribute mapped_name_for_attributes

required_at- attribute tributes

Data Type Required? DescripDescription used with use_for_reuse in attribute mapping together to find exported element no string Mapped element name (with attribute element name and value element name) which is used to store the attributes which do not have explicit mappings. This should be the name of a value reference mapping. no string Attributes of the element which are required but cannot be set during export, separated by a comma (,). It can hold relative path, alias path and

PLM Services Support in Windchill

1263

Parent Name

Name

Type

type

attribute

mapped_tag_name

attribute

import_con- attribute text

add_curren- attribute

Data Type Required? DescripDescription value reference path. no string Windchill attribute name to be used to identify a different alias or value reference. no string Element name and value to identify current windchill element. It is used if one PLM element is used to represent multiple windchill elements. no string Decide windchill element name by value of parent element, mapping between element name and value of parent element should be one-one. no string The path used to add

1264

Windchill Customization Guide

Parent Name

Name t_element_to_parent_by

Type

connect_re- attribute ference

Data Type Required? DescripDescription current element to parent one. It can hold relative path, alias path and value reference path. This will be used for sub element only. no string The sub element which will be used to be added to parent element, used with add_current_element_to_parent_by together .

The fllowing will be mapping for attribute: Parent Name attribute Name exceptions Type element Data Type Required? DescripDescription no element Used to hold different attribute mapping by different attribute value. yes string Element name of windchill native format. yes string Mapped

name

attribute

attribute

PLM Services Support in Windchill

1265

Parent Name

Name mapped_name

Type

append

attribute

seperator

attribute

Data Type Required? DescripDescription element name. It can be relative path, alias path and value reference path. Separated by a comma (,). no boolean Defines whether to append to the existing value with defined separator, default value is false. For example, this can be used to append the iteration number to the version (A.5, where the value 5 is appended to A with a period [.] separator). no Separator string for append. For example, this can be used to concatenate the iteration number to
Windchill Customization Guide

1266

Parent Name

Name

Type

add_to_ele- attribute ment

use_for_reuse

attribute

connect_re- attribute ference

Data Type Required? DescripDescription version (A.5, where the value 5 is appended to A with a period [.] separator). no string Define the path which current element should be added after finding a previously exported element.It can be relative path, alias path and value reference path. Used for link element only. no boolean Defines whether the attribute should be used to find previously exported element, used with reuse in element mapping together. no string The sub element which will be used to be added

PLM Services Support in Windchill

1267

Parent Name

Name

Type

reference_to attribute

identifier

attribute

reuse

attribute

Data Type Required? DescripDescription to parent element, used with add_current_element_to_parent_by together. no string Defines the sub element used as reference. Used for link element only. Default value is false. no string Attribute name which is used to retrieve value from default_mapped_name_for_attributes configuration. If this is configured, mapped_name will not be used during import. no boolean Define whether the attribute value can be multiple. If set to false, multiple
Windchill Customization Guide

1268

Parent Name

Name

Type

value

attribute

required_at- attribute tributes

add_curren- attribute t_element_to_parent_by

Data Type Required? DescripDescription values can be retrieved during import. Must be used when mapped_name is not configured. Default value is false. no string This is used to represent a constant value, which will be set during export and can be fetched during import no string Attributes which are required for current element, separated by a comma (,).It can be relative path, alias path and value reference path. no string The path used to add current element to parent one. It can hold

PLM Services Support in Windchill

1269

Parent Name

Name

Type

Data Type Required? DescripDescription relative path, alias path and value reference path. This will be used for sub element only. string no Attributes which are required for parent element, separated by a comma (,).It can be relative path, alias path and value reference path. Worked with add_current_element_to_parent_by together to set attributes basing on different attribute value Define whether to use parent element as reference to find related element and

required_at- attribute tributes_for_parent

use_parent_object

attribute

boolean

no

1270

Windchill Customization Guide

Parent Name

Name

Type

index

attribute

Data Type Required? DescripDescription store/retrieve attribute value. Default value is false. no int Define the index to get value from a list value.

Following will be mapping for attribute exceptions: Parent Name exceptions Name value Type attribute Data Type Required? DescripDescription yes string Value of parent attribute. no string Mapped value for original value, it should be one-one mapping. no string Element name which is used to store the attribute value. It can be relative path, alias path and value reference path. Will not set attribute when mapped_element_name is configured

mapped_value

attribute

attribute_name

attribute

PLM Services Support in Windchill

1271

Parent Name

Name mapped_element_name

Type attribute

required_at- attribute tributes

add_curren- attribute t_element_to_parent_by

required_at- attribute

Data Type Required? DescripDescription no string Element name which is used to identify original value, it should be one to one mapping, used for import only. no string Attributes which are required for current element, separated by a comma (,).It can be relative path, alias path and value reference path. no string The path used to add current element to parent one. It can hold relative path, alias path and value reference path. This will be used for sub element only. no string Attributes which are
Windchill Customization Guide

1272

Parent Name

Name tributes_for_parent

Type

Data Type Required? DescripDescription required for parent element, separated by a comma (,).It can be relative path, alias path and value reference path. Worked with add_current_element_to_parent_by together to set attributes basing on different attribute value The sub element which will be used to be added to parent element, used with add_current_element_to_parent_by together Define whether to use parent element as reference to find related element and

connect_re- attribute ference

string

no

use_parent_object

attribute

boolean

no

PLM Services Support in Windchill

1273

Parent Name

Name

Type

Data Type Required? DescripDescription store/retrieve attribute value. Default value is false.

1274

Windchill Customization Guide

Windchill Elements and Attributes Mapping for Supported Windchill Objects


The tables below explains the mapping between elements and attributes for some of the key Windchill objects which are supported. WTPart Object Type = WTPart PLM Root Element = Item Windchill Attribute PLM Element Name number Id ObjectID/ufid Item_version/uid masterUfid name versionInfo/versionId versionInfo/iterationId iba uid Name Item_version/Id String_value or Numerical_value (depend on IbaType) Description original value will be stored as key-value pair original value will be stored as key-value pair concatenate as A.2 use Item_version/Design_discipline_item_definition/ Simple_property_association to build relationship with Item Use Document_assignment to build relationship with Item Use Item_version/Design_discipline_item_definition/ Simple_property_association/Specified_value to build relationship with item. The value is stored as a key-value pair, as following:
<Property_value xsi:type="String_value"> <Value_name> endItem</Value_name> <Value_specification>false </Value_specification> </Property_value>

contentItem

Digital_file

endItem defaultTraceCode genericType partType folderPath lifecycleInfo/ lifecycleTemplateName versionInfo/ versionLevel domainName

String_value

PLM Services Support in Windchill

1275

Windchill Attribute Name lifecycleInfo/ lifecycleState externalTypeId EPMDocument

PLM Element

Description

Object Type = EPMDocument PLM Root Element = Item Windchill Attribute PLM Element Name number Id ObjectID/ufid Item_version/uid name CADName Description orginal value will be stored as key-value pair

versionInfo/versionId versionInfo/iterationId iba

Name Item_version/Design_discipline_item_definition/ Item_instance/Id concat as A.2 Item_version/Id String_value or Numerical_value (depends on IbaType) Use Item_version/Design_discipline_item_definition/ Simple_property_association to build relationship with item. Use Item_version/Design_discipline_item_definition/ Document_assignment to build relationship with item for secondary content. Use Item_shape to build relationship with item for primary content. Use Item_version/Design_discipline_item_definition/ Simple_property_association/Specified_value to build relationship with item. The value is stored as a key-value

contentItem

Digital_file

masterUfid authoringApplication epmDocType derived domainName

String_ value

1276

Windchill Customization Guide

Windchill Attribute Name folderPath lifecycleInfo/ lifecycleTemplateName lifecycleInfo/ lifecycleState versionInfo/ versionLevel epmDocSubType externalTypeId EPMMemberLink

PLM Element

Description pair, as following:


<Property_value xsi:type="String_value"> <Value_name> derived </Value_name> <Value_specification> false </Value_specification> </Property_value>

Object Type = EPMMemberLink PLM Root Element = Next_higher_assembly Windchill Attribute Name iba PLM Element String_value or Numerical_value (depend on IbaType) uid Description Use Simple_property_association to build relationship with Next_higher_assembly. Original value will be stored as key-value pair Use Placement/Model_placement/Axis1 to build relationship with Next_higher_assembly. Use Placement/Model_placement/Axis2 to build relationship with Next_higher_assembly. Use Placement/Model_placement/Axis3 to build relationship with Next_higher_assembly. Use Placement/

ObjectID/localId

uses/ObjectReference/ufid Related transform/matrix4d/m0* Direction

transform/matrix4d/m0*

Direction

transform/matrix4d/m2*

Direction

transform/matrix4d/m3*

Cartesian_point

PLM Services Support in Windchill

1277

Windchill Attribute Name

PLM Element

Description Model_placement/Local_origin to build relationship with Next_higher_assembly. Use Simple_property_association/Specified_value to build relationship with item. The value is stored as a key-value pair, as following:
<Property_value xsi:type="String_value"> <Value_name> isAnnotated </Value_name> <Value_specification> false< /Value_specification> </Property_value>

occurences/attribute name isAnnotated asStoredChildName depType isPlaced isRequired externalTypeId

String_value

1278

Windchill Customization Guide

PLM Message Format


The PLM message format is contained in the assembly.jar file. It contains the following elements: CONTENTS (folder): Contains all the content files. These are not required because sometimes content is not provided. manifest : This file contains the properties used during export, including Windchill version and format. These are not required and you can set the format type during call import function. However, if you want to import the jar through the import/export manager UI, this is required. plm.xml : Contains all the business object information by PLM format, which is required. importList.txt: Contains the exported object id, which is not required. You can import without this file.

PLM Services Support in Windchill

1279

30
Deploying Arbortext Customizations
Annonymous Arbortext Access ............................................................................... 1282

Arbortext Editor (version 5.4 F000 and later) is capable of downloading a zipped custom directory structure using HTTP, extracting its contents to a temporary file system location, and using that as a custom directory. This allows administrators to store Arbortext doctypes and other customizations in Windchill. Windchill makes the zipped custom directories available by designating a special anonymous access folder whose contents will be made available over anonymous HTTP. The HTTP access is anonymous so the user is not presented with an unexpected credentials prompt during Arbortext Editor startup.

1281

Annonymous Arbortext Access


Process Overview To host an XML Application in Windchill and use it from Arbortext Editor: 1. Create a zip archive of the custom directory structure. 2. Log in to Windchill, locate a Product or Library (or create one if needed), and then select the Folders second-level navigation for the container.

Note Only Products and Libraries are supported. Other containers (Site, Org, Program, Project) are not supported by this feature.
3. Create a folder (if needed) to hold the Arbortext customizations. This folder can be at the top-level or it can be nested inside some other folder (at any depth). 4. Inside that same Product or Library, bring up the Preference Management utility, expand the Arbortext preference group, and locate the Customizations Folder preference. 5. Edit that preference and enter the name and path of the desired folder. Some example values are: Value Arbortext Customizations Arbortext/Applications Description Top level folder with a space in the folder name. Top level folder called Arbortext with a child folder called Applications.

Having set this preference, any WTDocument objects in the specified folder will now be available via anonymous HTTP. (specific details on constructing the URL will come later in this document). 6. Upload the zip file into the desired folder. When creating the document in Windchill, the Type and CAGE Code values do not matter. 7. Put the anonymous access URL for your archive into the browser and verify that you can successfully download the zipped archive. See Anonymous Access URL Format on page 1283 for information on the anonymous access URL. 8. Set the APTCUSTOM environment variable to the anonymous access URL for your zip archive and launch Arbortext Editor to use the customizations.

1282

Windchill Customization Guide

Note For more information on zipped Arbortext customizations, see the "Deploying zipped customizations" section of the Arbortext Help Center (Programming > Arbortext Customizer's Guide > Custom applications > Deploying zipped customizations).

Anonymous Access URL Format


Type Library URL Format http://server:port/Windchill/servlet/WindchillGW/com.ptc.arbortext.windchill.anonymous.AnonymousAccessDownloader/lib/orgName/ libraryName/name[?params] http://server:port/Windchill/servlet/WindchillGW/com.ptc.arbortext.windchill.anonymous.AnonymousAccessDownloader/product/ orgName/productName/name[?params]

Product

Note The folder name itself is not contained in the URL. The folder name is defined in the Customizations Folder preference. See Configuring the Folder Path for Anonymous Access on page 1286 for information on setting this preference. Note As is normal for HTTP URLs, some characters, like spaces, colons, and non-Latin characters will need to be escaped in the URL; for example, space characters will need to be replaced with %20.
The name portion of the URL can be one of three things: The object number in Windchill The object name in Windchill The filename of the underlying file. Generally, this is the originally uploaded file name.

Since folders in Windchill may contain multiple objects with the same name or underlying filename, the safest way to ensure you get the correct object is to use its number. Name clashes should be rare. As an example, suppose you uploaded a file called hello.txt into this folder. The object name may be hello, an example object number may be 0000007324, and the filename would be hello.txt. In this case, any of these could be used to specify this object in the URL.

Deploying Arbortext Customizations

1283

When looking for an object to match the given string, highest priority is given to matching the number. If no matching number is found then a match against the first object with same name is done. If no matching name is found the, lastly, a match against the first object with the same filename is done. In general, it is unlikely that there will be multiple objects with the same name or filename. But if that situation exists, the number can be used to safely access the desired object. The optional combination of query parameters are as follows: The order of these parameter does not matter. Parameter (no parameters) Description The latest iteration from the latest version will be selected; not counting working (checked-out) iterations. The most recent iteration from the most recent version that matches the given lifecycle state will be selected. The most recent iteration from the specified version will be selected. The iteration parameter is ignored. This is only used along with the version parameter. The iteration parameter will be ignored. See state above. The most recent iteration from the specified version that matches the given state will be selected. The specified iteration from the specified version will be selected. The iteration parameter will be ignored. See state, version above.

state

version iteration

state, iteration state, version

version, iteration state, version, iteration Examples of query parameter usage: Query Parameters .../custom.zip.xml? version=C&iteration=2 .../custom.zip? state=Approved .../custom.zip? state=Approved&version=B

Description Version C.2 of custom.zip The most-recent version marked as Approved. The most-recent version marked as Approved with a version of B.

1284

Windchill Customization Guide

Query Parameters .../custom.zip?version=B

Description The latest iteration in the B version.

If you specify the name of an object which does not exist in the folder, or no iteration of the object matches the given request parameters, the anonymous access URL will return a 404 response to the caller. This is normal HTTP behavior when the requested object is not found.

Note Selecting the Latest Version When dealing with versioned Windchill objects, the convention is that the latest object is selected by version and then by iteration. The latest iteration in version D will always be considered newer than the latest iteration in version C, even if that iteration was created more recently. For example, when browsing folder contents using the web UI, youll always see the latest iteration from the latest version, even if there are newer iterations in other versions. The version selection for anonymous access URLs works in this way. For example, if the state parameter is specified without a version, and A.4 and B.2 both have the requested state, B.2 will always be returned regardless of when A.4 was created.

Deploying Arbortext Customizations

1285

Objects Available for Anonymous Access


Although this functionality is primarily to allow Arbortext products to access Windchill-managed XML applications, other files types, such as word documents or text files can also be accessed. In order for the anonymous access URL to work, the target object must be a WTDocument object (or soft type thereof). You cannot access other Windchill object types, such as EPMDocument objects (CAD files or Arbortext Editor-created XML files) or WTPart structures.

Configuring the Folder Path for Anonymous Access


The Customization Folder preference specifies the path to a folder that contains Arbortext customizations in a zipped format. The content from all Windchill documents in the specified folder will be made available without authentication via a specially constructed URL. To set this preference navigate to Site Utilities Preference Management Arbortext Customizations Folder . Site/Organizations : To disable anonymous access, set an empty value for this preference and select the Lock checkbox. For Products/Libraries : Specify the path to a folder in this Product or Library that contains Arbortext customizations in a zipped format. An empty value for this preference means that no folders in the Product or Library are exposed anonymously

Note For more information on zipped Arbortext customizations, see the "Deploying zipped customizations" section of the Arbortext Help Center (Programming > Arbortext Customizer's Guide > Custom applications > Deploying zipped customizations).
By default, this preference value is empty. If a Product or Library has an empty value for this preference then anonymous access is not allowed for that container. One way for an administrator to forcibly disable this feature is to set and lock the preference at a Site or Org level to be an empty value. Due to the normal inheritance rules of Windchill, this will force all child Product and Library containers to also have an empty value for this preference and thus the feature will be entirely disabled.

1286

Windchill Customization Guide

Here are some example preference values: Arbortext Customizations : Creates a top level folder named Arbortext Customizations which includes a space in the folder name. Arbortext/Applications : Creates a parent folder named Arbortext with a child folder named Applications.

Suppose a non-empty value is set for this preference inside a Project or Program. That setting will have no effect because the feature does not work with those container types. To be more precise, there is no HTTP URL you can construct to access any such folder from these containers. Suppose a non-empty value is set for this preference inside a Site or Org. This is actually undesirable because, due to the inheritance rules, all child containers will inherit this value (unless they override a specific value of their own). This will imply that any child Product or Library that happens to have a folder path that matches the preference value, will have that folder s contents exposed anonymously. When setting the value of the preference, an alert will be displayed if a non-empty value is assigned to a site, organization, project, or program container context. A non-empty value assigned to a site or organization container would force the value to each child container and could inadvertently expose material. A non-empty value assigned to a project or program has no effect and without an alert, a user could be confused at the unexpected result. An example alert is shown below:

Deploying Arbortext Customizations

1287

Listing Objects Available for Anonymous Access


You can generate list of objects that are available through the anonymous access functionality. This can help you determine if any objects have been exposed by mistake and can assist you in providing the HTTP URL for each object. Generating the list of objects available through anonymous access is restricted to users with administrator access. To generate a list of objects being shared anonymously: 1. Open a Windchill Shell. See Windchill Shell for more information. 2. cd bin 3. ant -f anonymousAccess.xml listAvailableResources 4. Enter your administrator credentials. Sample Output for Available Items The output contains an entry for each document accessible via anonymous access and each entry lists the organization, container (product or library), and folder containing the document as well as the document name and a skeleton of a URL which can be used to access the document anonymously.
******************************************************************************** !+! STARTED @ Fri Oct 14 13:28:10 EDT 2011 ******************************************************************************** Log file is '<WT_HOME>\Windchill\buildlogs\0000-anonymousAccess.log' -------------------------------------------------------------------------------!+! ENTERING Anonymous Access -------------------------------------------------------------------------------listAvailableResources: [echo] -----------------------------------------------------------------[echo] The following is a list of documents in Windchill that are exposed [echo] to anonymous http access. Each entry lists the Organization, [echo] Product or Library, and Name of the document as well as the Url [echo] used to access it. [echo] -----------------------------------------------------------------[java] [java] Organization: Demo Organization [java] Library: New Library [java] Folder: /Shared Folder [java] Document: Lib Item 1 [java] URL: http://wcserver:1600/Windchill/servlet/WindchillGW/ com.ptc.arbortext.windchill.anonymous.AnonymousAccessDownloader/lib/ Demo%20Organization/New%20Library/Lib%20Item%201 [java] [java] [java] -------------------------------------------------------------------[java] [java] Organization: Demo Organization [java] Product: GOLF_CART

1288

Windchill Customization Guide

[java] Folder: /Apps [java] Document: Thing1 [java] URL: http://wcserver:1600/Windchill/servlet/WindchillGW/com.ptc.arbortext. windchill.anonymous.AnonymousAccessDownloader/product/Demo%20Organization/GOLF_CART/Thing1 [java] [java] -------------------------------------------------------------------[java] [java] Organization: Demo Organization [java] Product: GOLF_CART [java] Folder: /Apps [java] Document: Thing 2 [java] URL: http://wcserver:1600/Windchill/servlet/WindchillGW/com.ptc.arbortext. windchill.anonymous.AnonymousAccessDownloader/product/Demo%20Organization/GOLF_CART/Thing%20 [java] [echo] -----------------------------------------------------------------[echo] Example: [echo] http://MyServerName/Windchill/servlet/WindchillGW/com.ptc.arbortext. windchill.anonymous.AnonymousAccessDownloader/lib/ExampleOrganization/ ExampleLibraryName/ExampleDocName [echo] -----------------------------------------------------------------******************************************************************************** !+! FINISHED @Fri Oct 14 13:28:19 EDT 2011 !+! Log: <WT_HOME>\Windchill\buildlogs\0000-anonymousAccess.log ******************************************************************************** BUILD SUCCESSFUL Total time: 9 seconds

Note that the example URLs do not contain actual hostname and web-app values because these values are unavailable through the command line interface. The URLs displayed are quite long and break across lines in the command prompt. Viewing the log file referred to at the beginning of the listing is an easier way of viewing the output. This list includes all document objects being shared throughout your Windchill installation, including all products and libraries in all organizations. Sample Output for no Available Items There are three cases where no objects are exposed: 1. The Customizations Folder preference has been set to an empty value and locked at the site level. 2. No folders are exposed anonymously. 3. At least one folder is exposed anonymously, but it contains no WTDocument objects. If no documents are currently being shared using the anonymous access functionality, the following output is generated:
******************************************************************************** !+! STARTED @ Fri Oct 14 14:19:59 CDT 2011

Deploying Arbortext Customizations

1289

******************************************************************************** Created log dir <WT_HOME>\Windchill\buildlogs' -------------------------------------------------------------------------------!+! ENTERING Anonymous Access[<WT_HOME>\Windchill\bin\anonymousAccess.xml] -------------------------------------------------------------------------------listAvailableResources: [echo] -----------------------------------------------------------------[echo] The following is a list of documents in Windchill that are exposed [echo] to anonymous http access. Each entry lists the Organization, [echo] Product or Library, and Name of the document as well as the Url [echo] used to access it. [echo] -----------------------------------------------------------------[java] [java] No shared documents found. [java] [echo] -----------------------------------------------------------------[echo] Example: [echo] http://MyServerName/Windchill/servlet/WindchillGW/com.ptc.arbortext. windchill.anonymous.AnonymousAccessDownloader/lib/ExampleOrganization/ ExampleLibraryName/ExampleDocName [echo] -----------------------------------------------------------------******************************************************************************** !+! FINISHED @ Fri Oct 14 14:20:23 CDT 2011 !+! Log: <WT_HOME>\Windchill\buildlogs\0000-anonymousAccess.log ******************************************************************************** BUILD SUCCESSFUL Total time: 24 seconds

1290

Windchill Customization Guide

31
System Generation
Modeling Business Objects .................................................................................... 1292

This chapter describes the details of modeling business objects.

Note As of release 10.0 Windchill no longer uses Rational Rose for modeling

1291

Modeling Business Objects


Note Code examples in this chapter have been reformatted for presentation purposes and, therefore, may contain line number, hidden editing characters (such as tabs and end-of-line characters) and extraneous spaces. If you cut and paste code from this manual, check for these characters and remove them before attempting to use the example in your application.
Overview of Windchill Persistence The Windchill persistence architecture maps Java classes and fields to database rows and columns (schema). Modeling, the manner in which schema is described, consists of annotating the class declarations of Java source files with PTC GenAs annotations that include annotation members for describing properties, associations, and other meta-data. Java annotation processors are invoked during javac compilation and are responsible for generating fields, accessors, RMI and PDS externalization APIs, and other methods (such as equals() and hashCode()). SQL scripts representing the database schema (tables, columns, and indexes) are generated separately post-compilation. The Java compiler not only generates and compiles the necessary artifacts to implement the model as declared by the annotations, it also produces information required at runtime to introspect on the model. It registers classes (modelRegistry.properties), associations (associationRegistry. properties), and their hierarchy (descendentRegistry.properties) and produces ClassInfo files which are utilized by runtime introspection. Jython Jython is a Java implementation of the popular Python programming language. Jython is used in this chapter to provide working code that demonstrates the examples in real world scenarios. Jythons dynamic nature makes it particularly attractive (over Java programs) because its interpreter facilitates interaction and exploration that simply is not possible with compiled code and a debugger. Additionally, while Jython is a Python implementation (on top of Java), the syntax is readily familiar to Java programmers and instantly translatable. Jython can be obtained from http://jython.org.

Note The examples using Jython assume a Windchill CLASSPATH, which is readily available if run from inside a Windchill shell (which can be started by invoking <load point>/Windchill/bin shell).
Windchill Customization Guide

1292

Modeling Tables
Modeled class anatomy (GenAsPersistable) To begin with, here is a simple, functional example. Other sections within this chapter will refer back to this example. Listing 1: SimpleExample.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.acme.example; import import import import import wt.fc.InvalidAttributeException; wt.fc.WTObject; wt.inf.container.WTContained; wt.util.WTException; wt.util.WTPropertyVetoException;

import com.ptc.windchill.annotations.metadata.*; @GenAsPersistable(superClass=WTObject.class, interfaces={WTContained.class}, properties={ @GeneratedProperty(name="name", type=String.class, constraints=@PropertyConstraints(required=true)) }) public class SimpleExample extends _SimpleExample { static final long serialVersionUID = 1; public static SimpleExample newSimpleExample() throws WTException { final SimpleExample instance = new SimpleExample(); instance.initialize(); return instance; } @Override public void checkAttributes() throws InvalidAttributeException { super.checkAttributes(); try { nameValidate(name); } catch (WTPropertyVetoException wtpve) { throw new InvalidAttributeException(wtpve); } } }

A class, SimpleExample (line 16) is defined which extends _SimpleExample. The class is annotated by the GenAsPersistable annotation (lines 11-15), which indicates that this class is to be persisted as a table in the database. The class has a single property called name (lines 1314) which is a (required) String. Additionally, two methods have been implemented; a static factory method (lines 19-23) and an override of the checkAttributes() method (lines 25-33).

System Generation

1293

The source of the _SimpleExample is as follows: The annotation processor for the GenAsPersistable annotation generates the parent class (more precisely , it generates a source file which the compiler then compiles). The parent class provides an implementation (query constant, field, getter, setter, and setter validation) for the name property as well as externalization logic and other needed methods.

The _ class consists of the fields and methods shown in Listing 2. Listing 2: _SimpleExample javap results
01 public abstract class com.acme.example._SimpleExample extends wt.fc.WTObject implements wt.inf.container.WTContained,java.io.Externalizable{ 02 static final long serialVersionUID; 03 static final java.lang.String RESOURCE; 04 static final java.lang.String CLASSNAME; 05 public static final java.lang.String NAME; 06 static int NAME_UPPER_LIMIT; 07 java.lang.String name; 08 wt.inf.container.WTContainerRef containerReference; 09 public static final long EXTERNALIZATION_VERSION_UID; 10 public com.acme.example._SimpleExample(); 11 public java.lang.String getName(); 12 public void setName(java.lang.String) throws wt.util.WTPropertyVetoException; 13 void nameValidate(java.lang.String) throws wt.util.WTPropertyVetoException; 14 public java.lang.String getContainerName(); 15 public wt.inf.container.WTContainer getContainer(); 16 public wt.inf.container.WTContainerRef getContainerReference(); 17 public void setContainer(wt.inf.container.WTContainer) throws wt.util.WTPropertyVetoException, wt.util.WTException; 18 public void setContainerReference(wt.inf.container.WTContainerRef) throws wt.util.WTPropertyVetoException; 19 void containerReferenceValidate(wt.inf.container.WTContainerRef) throws wt.util.WTPropertyVetoException; 20 public java.lang.String getConceptualClassname(); 21 public wt.introspection.ClassInfo getClassInfo() throws wt.introspection.WTIntrospectionException; 22 public java.lang.String getType(); 23 public void writeExternal(java.io.ObjectOutput) throws java.io.IOException; 24 protected void super_writeExternal_SimpleExample(java.io.ObjectOutput) throws java.io.IOException; 25 public void readExternal(java.io.ObjectInput) throws java.io.IOException, java.lang.ClassNotFoundException; 26 protected void super_readExternal_SimpleExample(java.io.ObjectInput) throws java.io.IOException, java.lang.ClassNotFoundException; 27 public void writeExternal(wt.pds.PersistentStoreIfc) throws java.sql.SQLException, wt.pom.DatastoreException; 28 public void readExternal(wt.pds.PersistentRetrieveIfc) throws java.sql.SQLException, wt.pom.DatastoreException; 29 boolean readVersion6009937787959182077L(java.io.ObjectInput, long, boolean) boolean

1294

Windchill Customization Guide

30 31

32 33 34

throws java.io.IOException, java.lang.ClassNotFoundException; protected boolean readVersion(com.acme.example.SimpleExample, java.io.ObjectInput, long, boolean, boolean) boolean throws java.io.IOException, java.lang.ClassNotFoundExcepti protected boolean super_readVersion_SimpleExample(com.acme.example._SimpleExample, java.io.ObjectInput, long, boolean, boolean) boolean throws java.io.IOException, java.lang.ClassNotFoundException; boolean readOldVersion(java.io.ObjectInput, long, boolean, boolean) boolean throws java.io.IOException, java.lang.ClassNotFoundException; static {}; }

The annotation consists of a declaration that is then implemented by the compiler. Rather than implement all aspects of name manually, it is declared as a property within the annotation and the _ parent file implements all the necessary components. Listing 3 contains an example of the effect required=true has on the nameValidate() method. Listing 3: nameValidate() snippet
01 02 03 04 if (name == null || name.trim().length() == 0) throw new wt.util.WTPropertyVetoException("wt.fc.fcResource", wt.fc.fcResource.REQUIRED_ATTRIBUTE, new Object[] { new wt.introspection.PropertyDisplayName (CLASSNAME, "name") }, new java.beans.PropertyChangeEvent(this, "name", this.name, name));

The purpose of superClass and interfaces (line 11, listing 1) is as follows: The superClass annotation member is simple; extends was co-opted by the _ class so modeled elements could be generated into code and incorporated into the class. Consequently, superClass is needed to allow you to specify your true (logical) parent (in this case, WTObject), which the _ class (_SimpleExample) then extends for you (as seen above). The interfaces annotation member exists for a similar purpose: to make it possible to identify the interfaces you wish to implement. While implements was not similarly co-opted, various technical considerations made an annotation member the logical choice over utilizing implements directly. This example extends WTObject and implements WTContained. The compiler will enforce the public class <X> extends _<X> { ... } syntax and generates a compile error if this syntax is not used.

Note the use of the factory pattern (newSimpleExample() (line 19 of Listing 1). Windchill utilizes this pattern over constructors because externalization needs to construct an instance using the noarg constructor and calling it should be inexpensive. The factory pattern consists of a static method of the form public

System Generation

1295

static <X> new<X>(<args...>) throws WTException { ... } and should be used in place of constructors in annotated files. The body of the factory should follow the form demonstrated by the example. Specifically, it should: 1. Construct an instance of the class using its (default) no-arg constructor. 2. Call the (non-static) initialize method, passing the arguments provided to the static method. The static factory should never handle the arguments on its own because then no subclass could take advantage of the static methods work (this is the primary purpose of the initialize methods: to make it possible to inherit behavior). You may need to create your own initialize method (if one does not exist or you need to augment behavior), in which case it should be of the form protected void initialize(args...) throws WTException and should call super.initialize(...). 3. Return the instance. The following factory/initialize pair demonstrates the proper way one would add a factory method accepting name so as to assign the required property. Listing 4: Factory/initialize pair example
01 02 03 04 05 06 07 08 09 10 11 12 13 14 public static SimpleExample newSimpleExample(final String name) throws WTException { final SimpleExample instance = new SimpleExample(); instance.initialize(name); return instance; } protected void initialize(final String name) throws WTException { super.initialize(); try { setName(name); } catch (WTPropertyVetoException wtpve) { throw new WTException(wtpve); } }

Additionally, the serialVersionUID (line 17 of Listing 1) is necessary since Windchill manages externalization logic (including, as needed, old version deserialization) and system-assigned serial version UIDs would break this logic. As before, the compiler will generate a compile error if this is not provided. Finally, checkAttributes() is notable only in that it demonstrates the use of generated fields and methods (line 29, Listing 1). In particular, name and nameValidate() are generated with default access specifically to make them accessible to the annotated class.

1296

Windchill Customization Guide

Compilation Compilation is covered extensively in the JavaDoc for the com.ptc. windchill.annotations.metadata package. However, the SimpleExample customization can be compiled and incorporated by executing the following steps: 1. cd to your load point (for example, /opt/ptc/Windchill) 2. Start a Windchill shell by invoking bin/windchill shell 3. Create the src/com/acme/example directory via mkdir -p src/com/ acme/example 4. Create SimpleExample.java in this directory and give it the contents of the example above 5. Compile the example with ant -f bin/tools.xml class -Dclass. includes=com/acme/example/* (note that this command must be executed in the load point directory) 6. Generate SQL scripts with ant -f bin/tools.xml sql_script -Dgen.input=com.acme.example.* 7. Find the create_SimpleExample_Table.sql SQL script (it will be somewhere in db) and load it 8. Repeat for create_SimpleExample_Index.sql. 9. Start/restart the MethodServer Jython can be used to quickly validate the example, as shown in Listing 5. Listing 5: Persisting SimpleExample
01 02 03 04 05 06 from wt.fc import PersistenceHelper from com.acme.example import SimpleExample se = SimpleExample.newSimpleExample() se.setName('test') se = PersistenceHelper.manager.store(se)

When prompted, authenticate as the system administrator. The object will be created in the site container, which can be confirmed via sn.getContainer ().getName(). Note that, had we created the factory/initialize methods with name as an argument, we could have avoided calling setName(test) separately. Mapping classes to tables and columns The example persisted an instance of SimpleExample, resulting in the addition of a row in a table. Details of the table are shown in Listing 6. Listing 6: create_SimpleExample_Table.sql

System Generation

1297

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

exec WTPK.dropTable('SimpleExample') set echo on REM Creating table SimpleExample for com.acme.example.SimpleExample set echo off CREATE TABLE SimpleExample ( classnamekeycontainerReferen VARCHAR2(600), idA3containerReference NUMBER, name VARCHAR2(600) NOT NULL, createStampA2 DATE, markForDeleteA2 NUMBER NOT NULL, modifyStampA2 DATE, classnameA2A2 VARCHAR2(600), idA2A2 NUMBER NOT NULL, updateCountA2 NUMBER, updateStampA2 DATE, CONSTRAINT PK_SimpleExample PRIMARY KEY (idA2A2)) STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 ) ENABLE PRIMARY KEY USING INDEX TABLESPACE INDX STORAGE ( INITIAL 20k NEXT 20k PCTINCREASE 0 ) / COMMENT ON TABLE SimpleExample IS 'Table SimpleExample created for com.acme.example.SimpleExample' / REM @//com/acme/example/SimpleExample_UserAdditions

The tables name reflects the name of the class (this can be changed see the JavaDoc for the annotation member tableProperties and the associated member tableName for details). Of the columns, name is certainly recognizable, though the rest may not be. The classnamekeycontainerReferen and idA3containerReference columns are necessary to store the reference to the container, which we got by being WTContained. Everything else comes from being Persistable, which is the top-level interface for persisting Windchill classes as tables. Modeled associations (GenAsBinaryLink) GenAsPersistable is one of two annotations for mapping classes to tables. The other is GenAsBinaryLink, which represents an association, linking two persistent objects (rows in two tables) together. Each binary link consists of two roles, an A role and a B role. We can create a graph of SimpleExamples, in which a SimpleExample may have multiple parents and children. Listing 7: SimpleExampleLink.java
01 02 03 04 05 06 package com.acme.example; import wt.fc.ObjectToObjectLink; import wt.util.WTException; import com.ptc.windchill.annotations.metadata.*;

1298

Windchill Customization Guide

07 08 09 10 11 12 13 14 15 16 17 18 19

@GenAsBinaryLink(superClass=ObjectToObjectLink.class, roleA=@GeneratedRole(name="parent", type=SimpleExample.class), roleB=@GeneratedRole(name="child", type=SimpleExample.class)) public class SimpleExampleLink extends _SimpleExampleLink { static final long serialVersionUID = 1; public static SimpleExampleLink newSimpleExampleLink (final SimpleExample parent, final SimpleExample child) throws WTException { final SimpleExampleLink instance = new SimpleExampleLink(); instance.initialize(parent, child); return instance; } }

After similarly compiling it, it can be validated with Jython, as shown in Listing 8. Listing 8: Persisting SimpleExampleLink
01 02 03 04 05 06 07 08 09 10 11 12 from wt.fc import PersistenceHelper from com.acme.example import * parent = SimpleExample.newSimpleExample() parent.setName('parent') parent = PersistenceHelper.manager.store(parent) child = SimpleExample.newSimpleExample() child.setName('child') child = PersistenceHelper.manager.store(child) l = PersistenceHelper.manager.store(SimpleExampleLink.newSimpleExampleLink (parent, child))

As with SimpleExample, we have a factory method (lines 14-17). Links, however, always associate two objects, so the factory method (and associated initialize method) accepts the A/B roles as arguments.

System Generation

1299

Modeling Columns
Modeling Columns GenAsPersistable and GenAsBinaryLink provide three mechanisms for specifying database columns: 1. properties (an array of GeneratedPropertys) represent strings, numbers, booleans, etc. 2. foreignKeys (an array of GeneratedForeignKeys) reference other persistent objects (and are stored as a classname/key pair) 3. roleA/roleB (GenAsBinaryLink only) are a special form of a foreign key used in associations Additionally derivedProperties (an array of DerivedPropertys) provide convenience accessors to properties and foreign keys. It is sometimes useful to collect a set of properties together into its own class which can then be managed as an entity and aggregated into a persistent object. The GenAsObjectMappable annotation exists for this purpose and is widely utilized by Windchill cookies. When a GenAsObjectMappable-annotated class is specified as the type for a GeneratedProperty, all its properties become columns in the owning classs table. To prevent name-collisions, the names are mangled using a character/number pattern dictated by an arcane algorithm; it is this mangling that accounts for the idA3 in idA3containerReference and the mapping of Persistable. thePersistInfo.theObjectIdentifier.id to idA2A2. GeneratedProperty An example of GeneratedProperty in our SimpleExample (name, which is required and of type String) has already been shown. GeneratedProperty supports a number of annotation members for controlling generation and behavior. See the Windchill JavaDoc for more information. GeneratedForeignKey A foreign key was not modeled, it was inherited from WTContained. Listing 9: container definition snippet
01 02 @GeneratedForeignKey(name="ContainerLink", foreignKeyRole=@ForeignKeyRole(name="container", type=wt.inf.container.WTContainer.class, referenceType=wt.inf. container.WTContainerRef.class, supportedAPI=SupportedAPI.PRIVATE, constraints=@PropertyConstraints(required=true)), myRole=@MyRole(name="contents", supportedAPI=SupportedAPI.PRIVATE))

03 04

1300

Windchill Customization Guide

The impact of the container reference had on SimpleExamples schema is that it resulted in two columns (previously discussed). In fact, if we peel this back further, we can see that we got these fields from WTContainerRef a GenAsObjectMappable by way of ObjectReference. We can say that a foreign key is simply another property (and, in fact, you could model a property with a type of ObjectReference as the type and accomplish the same results (from the perspective of the columns that would be created)), however the Windchill persistence layer recognizes foreign keys as a type of association and can manage them for you. In particular: you can automatically retrieve the referenced object (when required=true) by setting autoNavigate=true, preventing an additional database hit when accessing the referenced object you can navigate the foreign key link just as you would any other binary link. you can prevent the foreignKeyRole object from being deleted (when it participates in your assocation) by setting owner=false you can cause the myRole object to be deleted when the foreignKeyRole object is deleted by setting cascade=true when cascade=false (the default value) and foreignKeyRole role is deleted, the reference held by myRole will automatically be cleared you get accessors for both the reference and the referenced object generated for you

The GeneratedForeignKey is used when a given persistable is associated to at most one other persistent object. It is preferable to utilize GeneratedForeignKey over a GeneratedProperty of some concrete subtype of WTReference because the former makes it possible for the Windchill persistence architecture to manage the reference as an association. However, there are exceptions to this. In particular, associations to WTPrincipals (users) should be modeled as GeneratedPropertys of type WTPrincipalReference rather than as GeneratedForeignKeys. This is because we dont need the association management (users cant be deleted) and because we only want accessors for the reference (which contains everything anyone should ever need to know about users).

Note Just as with GeneratedRoles, you can constrain an existing foreign key (modeled on a parent class/interface), as is commonly done to constrain an iterations master. When constraining a foreign key, you need only provide the values that are different from that of the foreign key youre inheriting from; you neednt faithfully re-specify all of the properties of your parent.

System Generation

1301

GeneratedRole The GeneratedRole annotation is used to describe the role A and B of a GenAsBinaryLink, which we saw earlier in SimpleExampleLink. Roles can be thought of as special foreign keys associating the link with two persistables (and have the same inheritance capabilities as foreign keys). Whereas foreign keys are applicable only when the cardinality of the associated role is 0-1 and where the association requires no additional data (properties), binary links are applicable when the association is many-to-many, when the association carries properties, or when the association would otherwise be persisted on a PTC business object (since you cannot alter existing PTC classes). DerivedProperties Derived properties arent themselves persisted, but they do provide convenience accessors (getters, setters, and query constants) to persisted properties that would otherwise be buried in cookies or across foreign key references. Lets say you have a field c which is buried inside a cookie b which is itself buried inside a cookie a which is a property of our current class. We could access it using this.getA().getB().getC(), being careful to handle possible NullPointerExceptions should the cookies not be initialized. Better yet, we could just add this derived property to our class and let everything (including the handling of NullPointerException) be handled for us. Listing 10: a.b.c derived property
@DerivedProperty(name="c", derivedFrom="a.b.c")

With this derived property, we can now simply call this.getC(). If you need to cross a foreign key to access a field in the associated object, use the > delimiter after the foreign keys name in place of .. To directly access the name of the associated master, WTPart relies on the following derived property: Listing 11: master>name derived property
@DerivedProperty (name="name " , derivedFrom="master>name " )

1302

Windchill Customization Guide

Specialized Persistence Constructs


GenAsUnPersistable tables All classes recognized as being mapped to database tables must extend wt.fc. Persistable. The GenAsPersistable-generated _ class automatically handles this for you; the GenAsBinaryLink-generated _ class achieves this by implementing wt.fc.BinaryLink, which extends Persistable. When modeling interfaces to be implemented by persistent classes, you will typically use these annotations to describe the columns (properties, foreign keys, and roles) youll ultimately want the implementing (concrete) classes to represent as columns. Windchills domain interfaces employ this strategy, allowing you to simply implement a bunch of interfaces to acquire important business logic like work-in-progress (Workable) lifecycle management (LifeCycleManaged), and so on. You must annotate an interface if you want implementing classes to (automatically) persist the interfaces properties. However, not every interface is always intended to be implemented only by persistent classes. In some (exceeding rare) cases, an interface may be implemented by persistent classes (necessitating that the interface be annotated so its data can be persisted) and by non-persistent classes (for which GenAsPersistable and GenAsBinaryLinks ensuring that the class ends up being Persistable is a problem). In these cases, you can use the GenAsUnPersistable annotation to bridge the gap: any persistent implementer will automatically treat the interface as though it were persistent, while non-persistent implementers wont get persistence foisted on them. It should be noted that youll likely want your non-persistent classes to be annotated with GenAsUnPersistable to get the same generation benefits as its persistent cousins do, but this is not necessary. Additionally, since externalization logic comes for free, you may wish to utilize this annotation in cases where the class is to be persisted as a BLOB , since RMI externalization is employed when blobbing instances. Here, persisted as a BLOB means that the entire class will be stored in a BLOB column inside a persisted classs table. BLOBing an object is almost never recommended because its easy to overlook the complexities of reading the BLOB back out, especially if the class has changed since the instance was put in. Note that if you wish to store as a BLOB any class implementing wt. fc.NetFactor, you must make that class wt.util.Evolvable. GenAsEnueratedType columns Windchill provides support for modeling a discrete, localizable set of strings. Lets say you want to store computer models in Windchill and wanted to categorize them as being either a desktop, laptop, or server. You could do this as follows:

System Generation

1303

Listing 12: ComputerType.java


01 02 03 04 05 06 07 08 09 10 package com.acme.example; import com.ptc.windchill.annotations.metadata.*; @GenAsEnumeratedType public class ComputerType extends _ComputerType { public static final ComputerType DESKTOP = toComputerType("desktop"); public static final ComputerType LAPTOP = toComputerType("laptop"); public static final ComputerType SERVER = toComputerType("server"); }

Listing 13: ComputerTypeRB.rbInfo


01 02 03 04 05 06 07 08 09 10 11 ResourceInfo.class=wt.tools.resource.EnumResourceInfo desktop.value=Desktop desktop.order=10 laptop.value=Laptop laptop.order=20 laptop.defaultValue=true server.value=Server server.order=30

You can incorporate this into your Computer class using a GeneratedProperty as follows: Listing 14: Computer type snippet
01 02 @GeneratedProperty(name="type", type=ComputerType.class, initialValue="ComputerType.getComputerTypeDefault()", constraints=@PropertyConstraints(upperLimit=20, required=true))

The class follows the general format established previously: an annotated class that extends its (generated) _ class. Classes annotated by GenAsEnumeratedType will ultimately extend wt.fc.EnumeratedType and, as can be seen, a number of methods are generated for you. Among them are to<X>(String) and get<X>Default(), where X is the name of our class (to see a complete listing, invoke javap com.acme.example. _ComputerType). Lines 7-9 (of Listing 12) consist of constant declarations which rely on the toComputerType(...) API to produce instances of the enumerated type. Note that these entries must be present in the corresponding rbInfo file, which is named <X>RB.rbInfo and resides in the same directory. This rbInfo file is of type ResourceInfo.class=wt.tools.resource. EnumResourceInfo and supports both localization and value ordering. We incorporate this enumerated type as a GeneratedProperty. Note the use of initialValue and the constraints: all computer models must be assigned to one of our three types, and the default type is laptop. Enumerated types are stored (and
1304

Windchill Customization Guide

serialized) as simple strings (in this case, the stored value will be one of desktop, laptop, or server). Since the default upperLimit for strings is fairly large at 200 characters (see JavaDoc for more information), a more reasonable limit is provided. To build the rbInfo file, run ant -f bin/tools.xml bundle -Dbundle. input=com.acme.example.*. The extension must be rbInfo, and is case sensitive. If you neglect the uppercase I, the bundle target will ignore your file. GenAsPrimitiveType columns If you look at the JavaDoc for wt.fc.EnumeratedType. you will see that EnumeratedType is annotated with GenAsPrimitiveType. Also, the single argument to the annotation is String.class. The GenAsPrimitiveType annotation is a simple annotation, requiring a single value: the primitive type the annotated class reduces to (for persistence and serialization). You will likely never use it, but it exists when you want to build a class (logic) around what is otherwise a pretty boring field. If you do use it, you not only need to specify the type to reduce this class to as part of the annotation, you also need to provide a constructor accepting the primitive type and a <typein-lower-case>Value() method to return the current value. For more information, refer to the annotations JavaDoc. GenAsDatastoreSequence database sequences Windchill, out-of-the-box, will automatically assign part number and document numbers. It does this by employing a database sequence. Listing 15: MySequence.java
01 02 03 04 05 06 package com.acme.example; import com.ptc.windchill.annotations.metadata.*; @GenAsDatastoreSequence public class MySequence extends _MySequence { }

As before, you need to generate and load the SQL (also, anytime you make a change to an annotated class, you will need to restart the MethodServer). Once completed, you can acquire values as demonstrated (the following example will print 1 and 2, assuming youve not already acquired sequence values): Listing 16: Acquiring sequence values
01 02 03 04 from com.acme.example import MySequence from wt.fc import PersistenceHelper print PersistenceHelper.manager.getNextSequence(MySequence )

System Generation

1305

05

print PersistenceHelper.manager.getNextSequence(MySequence )

Note The GenAsDatastoreSequence is one of four GenAsDatastore annotations.

1306

Windchill Customization Guide

Services
Windchill services provide APIs and logic to manage modeled business objects. They consist of: An (optional) helper consisting of static fields and methods, including a static field (generally named service or manager) referring to a service A service interface consisting of remotely-invocable method declarations A standard service which implements the service and is registered to run as a service in the Method Server.

Services are covered elsewhere in this document. However, this is the basic pattern. Listing 17: ExampleHelper.java
01 02 03 04 05 06 07 08 09 package com.acme.example; import wt.services.ServiceFactory; /** Helpers are not instantiated and should consist of only static fields/methods **/ public final class ExampleHelper { /** Use the ServiceFactory to acquire an instance of the service. **/ public static final ExampleService service = ServiceFactory. getService(ExampleService.class); }

Listing 18: ExampleService.java


01 02 03 04 05 06 07 08 09 10 11 package com.acme.example; import wt.method.RemoteInterface; import wt.util.WTException; /** RemoteInterface annotation is required for all service interfaces **/ @RemoteInterface public interface ExampleService { /** All interface methods are callable via RMI and must throw WTException **/ SimpleExample createSimpleExampleByName(final String name) throws WTException; }

Listing 19: StandardExampleService.java


01 02 03 04 05 06 07 08 09 10 package com.acme.example; import import import import wt.fc.PersistenceHelper; wt.services.StandardManager; wt.util.WTException; wt.util.WTPropertyVetoException;

/** service must extend StandardManager, implement service interface **/ public class StandardExampleService extends StandardManager implements ExampleService { /** MethodServer refectively calls this API during startup **/

System Generation

1307

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

public static StandardExampleService newStandardExampleService() throws WTException { final StandardExampleService instance = new StandardExampleService(); instance.initialize(); return instance; } @Override public SimpleExample createSimpleExampleByName(final String name) throws WTException { final SimpleExample example = SimpleExample.newSimpleExample(); try { example.setName(name); } catch (WTPropertyVetoException wtpve) { throw new WTException(wtpve); } return (SimpleExample) PersistenceHelper.manager.store(example); } }

The service must be registered in site.xconf; the number 99999 must be unique so as not to replace an existing service. Note that changes to site.xconf must be propagated using xconfmanager. Listing 20: site.xconf fragment
01 02 03 <Property name="wt.services.service.99999" targetFile="codebase/wt.properties" value="com.acme.training.MyService/com.acme. training.StandardMyService"/>

With this service, we could reduce our Jython example to persist a SimpleExample to the following: Listing 21: Persisting SimpleExample with service
01 02 03 from com. acme . example import se = ExampleHelper.service.createSimpleExampleByName(test)

1308

Windchill Customization Guide

Localized Text
We have already seen an example localized text; ComputerTypeRB.rbInfo contains the (default English) text for ComputerType. Beyond providing localized text for enumerated types, we will want to localize class and fields names as well as messages (like exception messages). Class and attribute names Introspection provides APIs to get the (localized) display name for classes and properties. Default display names are calculated when explicit values arent provided, as shown by the following example which produces Simple Example.Name: Listing 22: Display values for SimpleExample
01 02 03 04 05 from wt.introspection import WTIntrospector from com.acme.example import SimpleExample snci = WTIntrospector.getClassInfo(SimpleExample) print "%s.%s" % (snci.getDisplayName(), snci.getPropertyDisplayName (snci.getPropertyDescriptor('name'), None))

Lets say we want to display SimpleName as Simple and SimpleName. name as aka. You can do this by creating a MetadataResourceInfo in the same directory, as follows: Listing 23: exampleModelRB.rbInfo
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 ResourceInfo.class=wt.tools.resource.MetadataResourceInfo # # # # # # # # # # # # Entry Format (values equal to default value are not included) <key>.value= <key>.category= <key>.comment= <key>.argComment<n>= <key>.constant= <key>.customizable= <key>.deprecated= <key>.abbreviatedDisplay= <key>.fullDisplay= <key>.shortDescription= <key>.longDescription=

# Entry Contents SimpleExample.value=Simple SimpleExample.name.value=aka

These bundles are similar to the bundle style used for enumerated types and are compiled in the same manner. Once compiled, our Jython script will produce Simple.aka.

System Generation

1309

Messages Localizing class names and properties is not sufficient. Everything you wish to communicate to users should be localized (note: a developer is not, necessarily, a user). The rbInfo format is used for enumerated types as well as classes and their properties. For general messages (typically included in exception or status messages reported by services), Java source/class files ultimately extending java.util.ListResourceBundle are utilized. As the contract for ListResourceBundle is arcane, well utilize WTListResourceBundle, which is more declarative. An example: Listing 24: exampleResource.java
01 02 03 04 05 06 07 08 09 10 11 12 package com.acme.example; import wt.util.resource.*; /** This example blatantly plagiarized from the JavaDoc. **/ @RBUUID("com.acme.example.exampleResource") public class exampleResource extends WTListResourceBundle { @RBEntry("This is the localized text with a single substitution: \"{0}\".") @RBComment("An example entry.") @RBArgComment0("Any string...") public static final String EXAMPLE_STRING = "0"; }

With this, we produce a message or an exception: Listing 25: Messages utilizing exampleResource
01 02 03 04 05 06 from com.acme.example import exampleResource from wt.util import WTException, WTMessage print WTMessage(exampleResource.getName(), exampleResource.EXAMPLE_STRING, ['substitution']).getLocalizedMessage() raise WTException(exampleResource.getName(), exampleResource.EXAMPLE_STRING, ['substitution'])

The first call will produce This is the localized text with a single substitution: substitution. and the second will raise (throw) an exception with the message wt.util.WTException: (com.acme. example.exampleResource/0) wt.util.WTException: This is the localized text with a single substitution: substitution. For more information, refer to the JavaDoc for the wt.util.resource package, particularly wt.util.resource.WTListResourceBundle.

1310

Windchill Customization Guide

Documenting the Model


Every (supported) class is documented as part of JavaDoc, and every (supported) GenAs-annotated class includes the GenAs annotation in its JavaDoc. This means that Windchills schema is entirely documented in JavaDoc and is available for reference when modeling your own class. Furthermore, the annotations themselves are included in JavaDoc (and reside in the com.ptc.windchill. annotations.metadata package). Information about, and example usages of annotations are readily available in JavaDoc. JavaDoc is particularly useful for understanding how to model and for mining Windchills model for examples. However, it can be difficult to determine the associations a particular class participates in from the JavaDoc alone, as the role members typically dont include references to their associations in their own JavaDoc. Information about the associations a given object participates is available via Windchill introspection and can be accessed via two utilities. The first utility is InfoReport. When run against a specified class in a Windchill shell, InfoReport will generate everything that is known about the class, including properties, database info, descendants, and, especially, associations. The second utility is included as part of the Windchill user interface, but is not enabled by default. The client, when enabled, provides a navigable interface for browsing introspection information. To enable it: 1. Go to Site -> Utilities -> Preference Manager 2. Find in tree Client Customization 3. Right click, select Set Preference, and assign the value to yes. 4. Refresh the browser 5. Browse to the tool icon (next to Site) 6. Select Tools, then Modeled Objects

System Generation

1311

Developing with Eclipse


The examples in this chapter (and customizations similar to it) can be developed using nothing more than a text editor for authoring and Ant for building. They can also be developed using Eclipse (http://eclipse.org), which is an IDE (tools. xmls eclipse_project.help target will help you get started). In particular, you will need to to install Eclipse, install the FileSync plug-in, generate a workspace and project (via the eclipse_project target), and configure Eclipse to use both the workspace and project. All of this is covered in eclipse_project.help. The generated Eclipse project is configured to work with source in <load point>/src, just as is tools.xml. It builds into an Eclipse-managed output directory (<load point>/eclipse_codebase) and utilizes FileSync to propagate changes to the real codebase (load point/codebase), which ensures a final result equivalent to invoking the class target. The generated project doesnt compile directly to <load point>/codebase because Eclipse would otherwise obliterate it. Eclipse supports compilation and annotation processing: whenever a source file is saved, it is immediately compiled. Compilation includes, as necessary, invocation of annotation processors and generation of code. Eclipse support does not extend to building rbInfo files and generating SQL, however, requiring the continued use of tools.xml to build those artifacts. Eclipse users will want to utilize WTListResourceBundle and its annotations over the old rbInfo-formatted StringResourceInfo bundles. rbInfo files of type ResourceInfo.class=wt.tools.resource. StringResourceInfo are the only rbInfo format to compile to Java class files. Eclipse simply does not recognize class files produced in this way and wont provide completion for it (it flags usages of the constants in these bundles as errors). The WTListResourceBundle is, by contrast, fully compiled by Eclipse and Eclipse is fully aware of it. If you have existing StringResourceInfo files, consider converting them using the bundle_convert target. The generated Eclipse workspace includes a debug configuration for debugging the MethodServer (see the help for details). Even though Windchill does not ship source, but you will be able to debug your own code. The eclipse_target, notably, is fairly bereft of options. This is an intentional restriction to ensure a working workspace/project is created. A cursory glance at tools.xmls targets relating to eclipse_project and the output of

1312

Windchill Customization Guide

eclipse_project itself will give you a good sense of what is going on and will give you insight as to how you might tailor the results to make it more suitable to your needs.

System Generation

1313

Deploying Modeled Customizations


Modeled customizations, when built, will impact the installation in three primary ways: 1. Registering modeled (annotated) classes in <load point>/codebase (modelRegistry.properties, associationRegistry. properties, and descendentRegistry.properties) 2. Adding compiled Java Classes (*.class), introspection artifact files (*. ClassInfo.ser), and serialized bundle files (*.RB.ser) 3. Updating database scripts in load point/db to incorporate any additional schema (including indexes). Additionally, you may have added entries to site.xconf to, particularly, register services. Deploying your customization from your development environment to your production environment entails replaying your actions in the development enviroment on the production system. One strategy would be to simply copy over the source and rebuild it on the production system. This strategy, however, necessitates compiling on the production system and is generally rejected for this reason. Another strategy is to use a version control system, like Git or Subversion, putting your entire load point under it, allowing the version control system to tell you how your customization impacted the installation, and copying over the changes. In any case, you must 1. Copy over the changes introduced by your customization into the production system (these are the files enumerated above) 2. Install the schema by invoking the SQL scripts necessary to create tables and indexes 3. Augment the production systems site.xconf to incorporate the customizations changes (and run xconfmanager) 4. Restart the production system. Be careful to ensure that the production system and development system share the same fundamental state (installed the same solutions and are at the same release level) or your classes may be incompatible, your registries files may contain extraneous entries (or drop important ones), and your database schema may be incorrect.

1314

Windchill Customization Guide

32
Enumerated Types
The EnumeratedType Class ................................................................................... 1316 Creating an EnumeratedType Subclass................................................................... 1318 Editing the Resource Info for an Enumerated Type ................................................... 1319 Localizing an Enumerated Type .............................................................................. 1321 Extending an Enumerated Type .............................................................................. 1322 The Enumerated Type Customization Utility............................................................. 1323 GUI Usage of an Enumerated Type......................................................................... 1325

This chapter describes enumerated types.

1315

The EnumeratedType Class


EnumeratedType represents a type whose possible values are constrained to a set (as defined in a resource).

value The internal value, which is persisted. display The localizable display text. comment An optional comment describing the value. order Provides an explicit sort order for the value. defaultValue Specifies the value that is the default value for the type. selectable Specifies if the value should be allowed to be selected. The constructors for EnumeratedTypes are protected so that instances can only be constructed internally. The data needed for construction is obtained from a resource and used to construct the instances in the static initializer. getValueSet() returns the set of possible values for the class, where the possible values are instances of the class.

1316

Windchill Customization Guide

toString() returns the internal value, which will be persisted. This follows the pattern of primitive wrappers provided by Sun. This means toString() is not available for generic use by GUI components; they must use getDisplay().

Enumerated Types

1317

Creating an EnumeratedType Subclass


To create an EnumeratedType subclass, perform the following steps: 1. Create a java class annotated with @GenAsEnumeratedType. For example (src/example/MySize.java):
package example.MySize; import com.ptc.windchill.annotations.metadata.GenAsEnumeratedType; @GenAsEnumeratedType public class MySize extends _ MySize { static final long serialVersionUID = 1; }

2. Optionally, code any desired programmatic constants in MySize.java. For example:


public static final State SMALL = toMySize("sm");

3. . Create its companion resource info file. For MySize, it will be named MySizeRB.rbInfo. See details below.

1318

Windchill Customization Guide

Editing the Resource Info for an Enumerated Type


The name of the resource info file is RB.rbInfo , with the simple package name prepended, for example, MySizeRB.rbInfo. The following sections describe the resource info files.

Enumerated Type Resource Info Header


Each resource info file contains the following lines that define certain file level information:
ResourceInfo.class=wt.tools.resource.EnumResourceInfo ResourceInfo.customizable=true ResourceInfo.deprecated=false

The first line classifies the resource info and should never be changed. The values of the second two lines can be changed by the owner of the package, if the file should not be customized and if the file is deprecated.

Resource Entry Format


See Resource Entry Format on page 1404 in Internationalization and Localization on page 1395 . The <key>.value, the two Display values (abbreviatedDisplay and fullDisplay), and the two Description values (shortDescription and longDescription) are the only ones that are localizable.

Resource Entry Contents


The following are examples of the entries:
lrg.value=Large lrg.order=30 med.value=Medium med.order=20 sm.value=Small sm.order=10

If the order properties are not defined, the options will be displayed in alphabetical order, using the locale specific display value. One of the entries can have defaultValue set to true. For example, the attributes for the "sm" value could be as follows:
sm.value=Small sm.shortDescription=Small Comment

Enumerated Types

1319

sm.order=10 sm.defaultValue=true

Building Runtime Resources


Windchill provides a utility to build the runtime resource for the .rbInfo files. To build the runtime resources into the codebase for a particular RB file, use the following command: ResourceBuild <package.ClassName> For example:
ResourceBuild example.MySizeRB

To build the runtime resource into the codebase for all the resource info files for a particular directory, use the following command: ResourceBuild <directory_relative_to_src> For example:
ResourceBuild example

The above script is a convenience wrapper for the bundle target in the bin/tools. xml Ant script. To see all the options available for direct use of the bundle target, use the following command:
ant -f bin/tools.xml bundle.help

The resulting resource file is named <name>.RB.ser , which is a serialized instance of SerializedResourceBundle. For example, src/wt/example/MySizeRB.rbInfo will build to codebase/wt/example/MySizeRB.RB.ser. To verify the values stored in a resource bundle, a verification utility is provided by the EnumeratedType base class. A batch file, enumVerify.bat, can be used to invoke this verification, as follows:
enumVerify <fully_qualified_EnumClassname>[<language>][<country>]

[<variant>] The following are examples of usage:


enumVerify wt.lifecycle.State enumVerify wt.lifecycle.State fr enumVerify wt.lifecycle.State fr CA

For information on locales, and codes for languages and countries, see the java.util. Locale class entry in your installed Windchill Javadoc.

1320

Windchill Customization Guide

Localizing an Enumerated Type


To have a locale-specific set of display values for an enumerated type, a localespecific version of the enumerated types resource bundle can be created. To do so, perform the following steps: 1. Make a copy of the standard resource bundle for the enumerated type, giving it a file name with the appropriate locale suffix. For example, to create a French version of the resource bundle for MySize, copy the MySizeRB.rbInfo bundle and name it MySizeRB_fr.rbInfo. 2. Do not change the keys of entries being localized; they must match those in the standard bundle. 3. Edit the display and description fields with the appropriate translation. 4. Change the order and defaultValue fields if desired; it is not likely to be necessary. 5. Do not change the selectable field. After creating the resource info file for a specific locale and translating it, build the runtime resource from it. Then verify the results of your localization by using the verification utility mentioned earlier.

Enumerated Types

1321

Extending an Enumerated Type


An enumerated type can be extended, and using it in a constraining, or covariant, manner is supported. For example, MySize can be extended by MyDerivedSize, and it can be used as indicated by MyDerivedItem, as shown in the following figure.

The one caveat with using extended EnumeratedType instances is that, if concrete types are used in the model, they are the only types that can be read back from the database. Using the example in the preceding figure, this means that other subclasses of MySize can be assigned to the size attribute of MyItem, and they can be stored in the database, but they can be read out only as instances of the types that are modeled. This limitation would not apply if MySize were an abstract class. When an abstract class is modeled, the runtime type information is stored in the database along with the instance information. Therefore, the exact type and instance can be reconstructed when reading it back from the database.

1322

Windchill Customization Guide

The Enumerated Type Customization Utility


The Enumerated Type Customization Utility allows you to add or edit values of an enumerated type. When customizing enumerated types, use the Enumerated Type Customization Utility rather than directly creating customized resource info files. The utility will create, or update, files in a parallel directory structure defined by the wt.generation.custom.dir property, which defaults to $(wt.home)/wtCustom. The resource info files provided with Windchill should never be changed.

Note The Type and Attribute Management utility is now the one and only configuration point for "default values" shown in the UI
The remainder of this section describes how to start the utility. For specific instructions on its usage, see the online help available when you start the utility.

Starting the Utility


In the tools properties, the wt.resource and wt.clients.tools.enumtype properties (described in properties.html) are used to configure the utility for your environment. Most of these properties need not be set, since appropriate defaults are provided. To start the Enumerated Type Customization Utility , open a console prompt and enter the following script name:
enumCustomize

Enumerated Types

1323

To see the changes you have made after using the utility, perform the following steps: 1. Restart the method server. 2. Rebuild all of the client jar files (see Managing Client JAR Files in Managing Customizations) so clients can access the new values. 3. Restart any Java clients. (HTML clients access the new values as soon as their pages are refreshed from the server.)

1324

Windchill Customization Guide

GUI Usage of an Enumerated Type


The localizable display field for an enumerated type can be displayed by using getDisplay() or getDisplay(locale). To use enumerated types in GUI drop-down list selections, wt.clients.util. EnumeratedChoice is provided as a generic control for enumerated types. The following is a simple example of using the control:
// construct and initialize a ChoiceBox for an EnumeratedType EnumeratedChoice mySizeChoice = new EnumeratedChoice(); mySizeChoice.setEnumeratedTypeClassName( "wt.example.MySize" ); // set current choice selection to the current value mySizeChoice.setSelectedEnumeratedType( myItem.getSize() ); ... user makes selection // obtain the chosen selection MySize selection = (MySize)mySizeChoice.getSelectedEnumeratedType();

Enumerated Types

1325

33
Customizing LDAP Attributes
Customizing LDAP Mapped Attributes in a User Information Page ............................. 1328 Viewing LDAP Mapped Attributes in an Audit Report ................................................ 1331

This chapter contains details on customizing LDAP mapped attributes and viewing them on User Information Pages and on Audit Reports.

1327

Customizing LDAP Mapped Attributes in a User Information Page


1. Login as the Site Adminstrator and navigate to Site Utilities Info*Engine
Administrator

Edit the JNDI adapter which is configured for the LDAP that contains the additional attributes you want mapped to the user. In the Additional Properties section of the JNDI adapter properties page, add the property <service.name>.windchill.mapping.user. attributes and enter the attributes (comma separated) you want mapped as values for this property. The <service.name> is the name of the adapter whose properties you are modifying. If you chose to replace windchill with either the name you provided for the web application, or any other name, then you can add the property wt.org.webAppName to wt.properties and provide the name you intend to use. 2. Open the LogicalAttributes.xml file from the <WT_HOME>\codebase directory. Search for any definition of the WTUser class name and append definitions for the attributes you created in step 1 to this section. For example, for an attribute name citizenship the definition is shown below. Make sure the value in the LogicalForm tag is the same as the attribute you defined in step 1. The attributes are case-sensitive.
<Property> <LogicalForm>citizenship</LogicalForm> <ExternalForm>SCA|citizenship.key</ExternalForm> </Property>

3. Add additional information on each of these attributes and the corresponding Server Calculated Attribute Function (SCAF) that needs to be invoked to retrieve the values of these attributes, into a resource bundle that is supported for customization. For example, modify the orgModelRB.rbInfo file in the <WT_HOME>\src\wt\org directory and add entries similar to the following:
WCTYPE|wt.org.WTUser~SCA|citizenship.key.value=Citizenship WCTYPE|wt.org.WTUser~SCA|citizenship.key.abbreviatedDisplay=Citizenship WCTYPE|wt.org.WTUser~SCA|citizenship.key.dataType=java.lang.String WCTYPE|wt.org.WTUser~SCA|citizenship.key.serverFunction= com.ptc.core.foundation.org.server.impl.SACFLdapAttributeContainerFunction WCTYPE|wt.org.WTUser~SCA|citizenship.key.serverFunction.arg1=

1328

Windchill Customization Guide

String{citizenship}

Note The value of serverFunction should remain the same as the one provided above, unless you write your own SCAF function. In addition if the attribute was defined as a Boolean in step 1, then key.dataType should be java. lang.Boolean. Do not change the type in key.serverFunction. This must always be a String type.
4. Then run the following command in a Windchill shell to generate the corresponding .ser file in the runtime location (for example <WT_HOME>\codebase\wt\org).
tools bundle -Dbundle.input=<WT_HOME>\src\wt\org -Dbundle.recurse=true

5. Once the build is successful, check the runtime location at <WT_HOME>\codebase\wt\org to make sure the .ser files were created. 6. Run the following command in a Windchill shell and view the .lst file generated in the <WT_HOME>\temp directory to verify the entries generated correctly.
windchill wt.util.resource.ResourceBundleUtil wt.org.orgModelRB en_US

7. Run the following command from a Windchill shell to rebuild the client jars.
ant f codebase/MakeJar.xml

8. Delete the work directory from the <WT_HOME>\Tomcat directory. 9. Restart Windchill. 10. Navigate to the Site Utilities Type and Attribute Management . and create new alias attributes for the attributes defined in step 2 for the User type. Verify the value for Internal Name matches the name provided in the LogicalForm tag in step 2. Select the corresponding type in the next screen depending on whether the attribute in ldap that you are mapping to, is a String or a Boolean. On the following screen provide a display name. This can be anything. This controls what displays on the layout to which these attributes will be added. In the Mapping field, provide the value that matches the ExternalForm tag in step 2.

11. After the attributes are created, you can add them to the Information Page layout. By default these additional attributes will also appear on the Simplified User details page. To hide these additional attributes from the Simplified User details page, there needs to be a custom Java validator written. You will find an example validator under prog_examples\principal\user of your

Customizing LDAP Attributes

1329

install directory. The file is called UserAttributeCompanyNameValidator. The only thing that needs to change based on the attribute that you want hidden, is the name of the class and the return type. You will need to create a similar file in your customization directory and then execute the following command in a Windchill shell to build it.
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source= <custom directory structure where the file exists>

For example:
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source= <WT_HOME>\prog_examples\principal\user\validators

Note One validator must be written for each attribute that should be hidden.
12. The validator information should then be included in the <!-user attribute validators !> section of the PrincipalAdmin-service.properties.xconf file, which is located in the codebase\com\ptc\windchill\principal directory. Propogate the changes using the xconfManager Fp command. Example:
<OptionserviceClass="com.ptc.windchill.principal.user.validators. com.ptc.windchill.principal.user.validators. UserAttributeCompanyNameValidator" UserAttributeCompanyNameValidator cardinality="duplicate" requestor="null" selector="company company" />

13. Restart Windchill.

1330

Windchill Customization Guide

Viewing LDAP Mapped Attributes in an Audit Report


1. Create custom event recorder and custom event info files. The event info file creates a new table in the Windchill database that contains all the additional user information. It also references the AuditRecord table. Each property added to this file will map to a new column in the table. The event recorder will record all the additional user attributes information into this new table. Example event recorder and an event info files are located in: prog_examples\audit\configaudit and prog_examples\audit\eventinfo of your installation directory. The files are called UserInfoEventRecorder and UserInfo respectively.

2. Create similar files in your customization directory and then execute the following command in a Windchill shell to build it. First build the custom file in the eventinfo package since this is used by the event recorder.
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source= <<custom directory structure where the file exists>>

Example:
ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source= <WTHOME>\prog_examples\audit\eventinfo ant -f bin/tools.xml class -Dclass.includes=*.java -Dclass.source= <WTHOME>\prog_examples\audit\configaudit

3. Now generate .sql files for the event info using the following command from a Windchill shell:
tools sql_script -Dgen.input=<<custom event info path name>>

Example:
tools sql_script -Dgen.input=wt.audit.eventinfo.UserInfo

4. Verify the following eight files exist in <WT_HOME>\db\sql (or <WT_HOME>\db\sql3 for multi-byte database ) within the directory structure corresponding to your custom directory. In the example file structures above, the files should exist in <WT_HOME>\db\sql\wt\audit\eventinfo directory. Make_pkg_eventinfo_Table.sqL Make_pkg_eventinfo_Index.sql Drop_pkg_eventinfo_Table.sql Drop_pkg_eventinfo_Index.sql

Customizing LDAP Attributes

1331

create_UserInfo_Index.sql create_UserInfo_Table.sql drop_UserInfo_Index.sql drop_UserInfo_Table.sql

5. Login to the database and execute the first two .sql files and verify that the event info table (in the example, the UserInfo table) is created in the database. 6. Modify the configAudit.xml file located in <WT_HOME>\conf\auditing and add the below entry. Make sure to change the handler to match your custom handler.
<ConfigEntry class="wt.audit.AuditRecord" enabled="true"> enabled="true" <KeyedEventEntry eventKey="*/wt.org.OrganizationServicesEvent/ SET_ADDN_USER_ATTRIBUTES" enabled="true" handler="wt.audit.configaudit.UserInfoEventRecorder wt.audit.configaudit.UserInfoEventRecorder"/> </ConfigEntry>

7. Make a copy of the StandardAuditReport.XML file located in Windchill\loadFiles\reports\auditReports and rename it to StandardAuditReport.QML. This is necessary because the Report Management utility will work only with .QML extensions. The content of the file is the same. 8. Navigate to Site Utilities Report Management . 9. Import StandardAuditReport.qml from the above location. Verify there are no errors on the jconsole and that the StandardAuditReport entry shows up in the list of reports. 10. Select the newly added StandardAuditReport and click Edit .

1332

Windchill Customization Guide

11. On the From tab, enter the name of the new event info table you created in step 5. In the example above, the table name was UserInfo.

Customizing LDAP Attributes

1333

12. On the Join tab add a reference from the UserInfo table to the AuditRecord table

13. On the Select tab add the columns from the UserInfo table that you want to see in the audit report.

14. Save the report with a different file name (for example UserAuditReport) and Export (Report Management will export with a .QML extension) it back to

1334

Windchill Customization Guide

WT_HOME\loadFiles\reports\auditReports folder with a different file name UserAuditReport. 15. Make a copy of the new .QML file and rename it to an .xml extension. 16. Add the below property in wt.properties to specify the new file as template.
wt.audit.StandardAuditReportTemplate= UserAuditReport.xml

17. This new property will allow you to toggle the report template you want to use for audit reporting. So if you want to revert back to the OOTB template or use a different template, then change the value of this property accordingly. 18. Restart the servers so the new wt.property can take effect. 19. Login as Site Administrator and navigate to Site Utilities Security Audit Reporting and generate a preview of the report with the default settings. Verify the additional LDAP attribute that are mapped to the user object in Windchill show up as individual columns on the report.

Customizing LDAP Attributes

1335

34
System Configuration Collector Plugin
Creating a System Configuration Collector Plugin..................................................... 1338

1337

Creating a System Configuration Collector Plugin


You want to create a new plugin for use with the System Configuration Collector UI in Windchill that will perform some function that the available plugin lack. The plugin will likely assist you in debugging Windchill configuration, installation and runtime issues. Background The System Configuration Collector is a Windchill UI page, currently accessed via the UI navigation path of Site Utilities System Configuration Collector when logged into Windchill as a user from the system administrators LDAP group. The UI provides functionality that system administrators can use to collect, save and also send Windchill system and configuration information to both local system and remote systems, including PTC Technical Support. The directive of the System Configuration Collector is one that allows a user to gather as much appropriate information at one time regarding a Windchill system. The information collected is targeted to consumers who can then more readily use the information to diagnose any potential system and/or configuration issue with the Windchill instance. On the System Configuration Collector page the system administrator can select categories of problems, such as Performance and/or Runtime related issues. A number of corresponding plugins will then execute. The list of plugins that will execute can be seen by expanding each respective category root tree node on the UI. Each plugin collects a discrete set of about the current Windchill system and configuration. For example, some plugins collect information such as Windchill Method Server logs, xconf properties files, JMX Mbean configuration information and database information. The plugins are the discrete means to accomplish a task for the System Configuration Collector categories. These plugins can be designed to accomplish any task that can be done through Java, including executing SQL and QML scripts, java command utilities (those which include a main() method) and Windchill Windu tasks. The plugins comprise a set of software operations for one or more categories that adds specific capabilities to the System Configuration Collector. The System Configuration Collector was designed using plugin architecture such that the functionality provided could be customized by PTC R&D, PTC Global Services, PTC Technical Support and PTC customers. The plugin architecture is one that allows a developer to extend and add new functionality to the System Configuration Collector on a live Windchill system. Therefore, there is no need to

1338

Windchill Customization Guide

restart the Windchill servers for the new plugin to be recognized by the System Configuration Collector. The plugin architecture allows for immediate use of the developed plugin. Due to the plugin architecture and ability of a plugin to operate against other Java systems, databases, WinDu tasks, scripts, etc, a System Configuration Collector plugin is a very powerful piece of functionality. A Plugin is also a JMX Management Bean (MBean). This allows for the management of plugins via a JMX console such as those delivered with Windchill; JConsole and VisualVM. Using the MBean interface allows for a means to more easily manage and deploy plugins. For more information regarding the System Configuration Collector and its uses see the System Configuration Collector online help topic. For more information regarding JMX MBeans see the Windchill MBeans online help topic. Scope/Applicability/ Scope/Applicability/Assumptions Assumptions The scope is restricted to the System Configuration Collector UI page and creating plugins that operate on that page. Assume you have an issue with a Windchill system that you must diagnose and no current plugin provides the functionality you need to assist you in diagnosing the issue. Assume you want to extend the functionality of an existing plugin. Intended Outcome Once a plugin is properly designed, created and deployed in Windchill it can be immediately used with the System Configuration Collector page. The plugin will then execute whatever functionality it was designed to do to assist you in your diagnosis. After creating and deploying a plugin, refreshing the System Configuration Collector UI will allow a user to make use of the deployed plugin. In the screenshot below, the plugin has been added to the user defined Custom Plugins category. This category only contains the custom created plugin Tomcat Property Config File For more information see Sample Code on page 1374.

System Configuration Collector Plugin

1339

A user can now make use of this plugin in any category they create and execute the plugin accordingly. Another option is to make use of a custom plugin through a JMX console. After creating and deploying a plugin in a Windchill system a user can load that plugin through a JMX console and make use of its execution. This is accomplished due to each plugin also being a JMX MBean. A user must first run the reloadPlugins() MBean operation on the CustomerSupport MBean. See the below screenshot. This forces the plugin architecture to reload all MBeans and will find the custom plugin that was previously deployed.

1340

Windchill Customization Guide

After reloading the plugins, the custom created plugin can be seen in the Plugin MBean list.

In this case, the newly loaded plugin is the TomcatConfigProperties MBean. For more information see Sample Code on page 1374.
System Configuration Collector Plugin

1341

A user can now edit the attributes of this plugin through the JMX Console or run operations for this plugin (execute the plugin). Additionally, a user can add the custom plugin to existing custom categories. For a more information regarding using JMX MBeans consult the documentation. For more information regarding JMX MBeans see the Windchill MBeans online help topic. The created plugin will execute from either the System Configuration Collector UI or a JMX Console.

Solution
Design, develop, deploy and execute a custom plugin with the System Configuration Collector UI or a JMX Console. Prerequisite Knowledge To apply this solution, you need to have an understanding of the following: Basic development using Java For developing plugins Knowledge of Java Management Beans is helpful For developing complex plugins Knowledge of Java Jar Service Provider is helpful To understand plugin deployment

Solution Elements Element PluginMBean

Type Java Class - Interface

Description As noted earlier, each plugin is an MBean and must implement the PluginMBean interface. This interface specifies the contract required to implement a plugin while ensuring its use as an MBean. This class can be extended into new interface hierarchies to provide additional functionality.

1342

Windchill Customization Guide

Element

Type

Description Implementing this class allows a plugin to expose attributes and operations that can be executed from a JMX console. This class contains the primary APIs to implement MBean attributes and operations. An abstract class that wraps much of the complexity of implementing the PluginMBean interface for a plugin. This class provides concrete implementations of methods that can be used via inheritance from classes which extend it. This is the base parent class for all plugins and any custom plugin should extend this class either directly or hierarchically. Each plugin is a SelfAwareMBean, that is, each plugin is a standard MBean (as previously described) that knows its own MBean ObjectName allowing it to maintain a single register of itself in the MBean registry. All custom plugins should implement a call to super () in the plugin constructor (Sample Code on page 1374e) to ensure that each plugin is registered as a

AbstractPlugin

Java Class - Abstract

SelfAwareMBean

Java Class - Abstract

System Configuration Collector Plugin

1343

Element

Type

Description SelfAwareMBean. The AbstractPlugin base class implements a method call to register the plugin as a SelfAwareMBean. Anecdotally, all plugins should be SelfAwareMBeans as each plugin should eventually inherit from the base class AbstractPlugin which extends SelfAwareMBean. This Java package contains all the PTC provide plugin implementations. This package contains abstract source files for making the implementation of numerous plugins easier by providing default functionality for many required methods. Notably, the package includes the following abstract Java classes: AbstractMultipleFilePlugin AbstractQMLPlugin AbstractReportingPlugin AbstractSQLPlugin AbstactWinDUPlugin AbstractXconfPlugin GatherFilePlugin GatherFolderPlugin GatherLogsPlugin GatherEveryLogPlugin

com.ptc.customer support.plugins

Java Package

1344

Windchill Customization Guide

Element

Type

Description The functionality of these plugins can be used directly through Java inheritance to provide easier plugin implementations for common plugin functionality types. This class wraps common functionality needed for a plugin to gather a list of files. This class wraps common functionality needed for a plugin to execute a QML (Query Markup Language) files/scripts. These scripts usually contain a . qml file extension. This class wraps common functionality needed for a plugin to execute plugins against Windchill Business Reporting. This class wraps common functionality needed for a plugin to execute a SQL (Structured Query Language) files/scripts. This class wraps common functionality needed for a plugin to execute a WinDU (Windchill Diagnostic Utilitiy) task. This class wraps common functionality needed for a plugin to recursively identify referenced xconf files from a parent xconf file. This class wraps common functionality needed for a

AbstractMultiple FilePlugin

Java Class - Abstract

AbstractQMLPlugin

Java Class - Abstract

AbstractReportingPlugin

Java Class - Abstract

AbstractSQLPlugin

Java Class - Abstract

AbstractWinDUPlugin

Java Class Abstract

AbstractXconfPlugin

Java Class Abstract

GatherFilePlugin

Java Class - Abstract

System Configuration Collector Plugin

1345

Element

Type

GatherFolderPlugin

Java Class Abstract

GatherLogsPlugin

Java Class - Abstract

GatherEveryLogPlugin

Java Class - Abstract

CollectorMBean

Java Class - Interface

Collector

Java Class

Description plugin to gather a single file. This class wraps common functionality needed for a plugin to gather a parent and all child directories. This class wraps common functionality needed for a plugin to gather a directory of log files. This class differs slightly from the similar GatherFolderPlugin in that it operates over a specified date range for a file, in particular, the file modification time. This class wraps common functionality needed for a plugin to gather a directory of log files. This class differs slightly from the similar GatherLogsPlugin in that it ignores date range for a file, in particular, the file modification time. As such, it operates over every log file. A Java MBean interface that specifies the contract for how a plugin collects its targeted data. This MBean does not need to be implemented directly by a plugin as AbstractPlugin takes care of the implementation details. The concrete implementation class for the CollectorMBean interface. This is the class that all plugins essentially rely on to do
Windchill Customization Guide

1346

Element collect()

Type Java Method

Description their file collection. The two collect() methods are part of the PluginMBean interface and must be implemented by all plugins (as all plugins must implement the PluginMBean interface). These methods specify the APIs necessary to interact with the Collector class and ultimately carry out the work of the plugin. In general cases, the AbstractPlugin and other Abstract classes (see above) in the plugin hierarchy provide default implementations that can be relied upon for the collect() methods. Specifically, the collectData() method of AbstractPlugin.java can often simply be called by the collect() methods. However, more advanced plugins that handle very specific needs may require these methods to be overridden and implemented directly. Generally, these cases are rare and only occur when a plugin isnt simply collecting files but rather needs to run some Java process or invoke some separate operation that

System Configuration Collector Plugin

1347

Element

Type

Description does processing which results in a file that then needs to be collected. There are plugins in the com.ptc.customer support.plugin.* packages that do this which can be examined for examples, specifically, see MBeanDumpPlugin.java, WDSPlugin.java and AbstractWinduPlugin.java. Note that there are two collect() methods that must be implemented as there are essentially two ways the PluginMBean interfaces specifies a user can collect data. One API requires a callNumber parameter and the other requires a topicIdentifier. Each of these parameters is used to distinguish locations that information is collected to. This method requires a specific Map return value. For greater detail regarding the return value and this method see Abstracting the Plugin in Customization Points on page 1361 The collectData() method of AbstractPlugin.java wraps much of the complexity of implementing the collect() methods of

collectData()

Java Method

1348

Windchill Customization Guide

Element

Type

Description the PluginMBean interface. This method sets up the broadcast message to marshaled to each server as determined by the plugin. It also correctly builds up the return Map that is expected. Since this method hides the complexity of using the collection framework directly, it can often be relied upon by the collect () methods. One can simply call this method with the appropriate parameter values in most plugin cases. This method requires a specific Map return value. For greater detail regarding the return value and this method see Abstracting the Plugin in Customization Points on page 1361 This is a Java enumerated type class. Each plugin must specify one of the enumerated types of PluginType when initializing itself so that the Collector class knows what do with and where to place the collected information on the file system. This is a Java class that provides utility methods that may be useful for creating more advanced

PluginType

Java Class

PluginUtilities

Java Class

System Configuration Collector Plugin

1349

Element

Type

PluginPropertyUtils

Java Class

*Resource

Java Classes

Description plugins that do not rely on default behavior of the collect() methods. Of specific interest is the getReturnMap(boolean, String, String) method that will build up the Map return value that is expected by the collect() methods. This will assist in simplifying the implementation of advanced plugins which implement collect() methods with specific behavior. This is a Java class that provides utility methods for property information that may be useful for creating more advanced plugins. This class provides methods that allow a user to obtain xconf managed property value information as well as a means to resolve tokenized xconf paths into fully qualified canonical paths. Each plugins strings should be localized so that they can be viewed in various locales. The com.ptc. customer support.mbeans.plugin* packages contain resource classes. These resource Java classes maintain strings that can be localized and used in Java source code.

1350

Windchill Customization Guide

Element

Type

Description A plugin can make use of these or new resource files to provide localized strings. This is a standard Java .jar file and can be named anything. The .jar file is the standard way to deploy a custom plugin in the System Configuration Collector for use. The .jar should contain the compiled .class files for the plugin and any helper Java classes along with the PluginMBean services file (see below). The .jar file must maintain the directory structure of the package for the .class files and the service file. For more information on Java Jar files specification see Additional Resources on page 1381. This is a services file contained in a Java .jar file that allows the System Configuration Collectors Java class loader to know if a new plugin has been deployed. The file structure is rigid and must be maintained, otherwise, Java class loader issues will result and the plugin will not load nor be available for use. The .jar file must contain the file com.

<file_name>.jar

Java Jar File

com.ptc.customersupport .mbeans.PluginMBean

Java Jar Service File

System Configuration Collector Plugin

1351

Element

Type

Description ptc.customer support.mbeans.PluginMBean at location METAINF\services. The file contents must be of type: <java source package>. <plugin class name> (without the brackets). For more information on Java Service Provider Interface see Additional Resources on page 1381

As discussed above, the plugin packages contain a hierarchy of Java inheritance that a plugin developer can rely on to create plugins. Below is a UML diagram showing the hierarchical relationship between the abstract classes and MBean interface APIs.

1352

Windchill Customization Guide

As seen above, all plugins implement the PluginMBean interface and, eventually, extend the AbstractPlugin class. A custom plugin can make use of the plugin hierarchy and the functionality provided by any of the abstract classes.

Procedures Creating a Custom Plugin


Foremost, for the complete CustomPlugin.java class that is seen in the following sections as code snippets, refer to Sample Code on page 1374. Four distinct phases must be completed before a plugin can be used with the System Configuration Collector or a JMX Console. 1. Designing the plugin. 2. Implementing the plugin. 3. Compiling the plugin. 4. Deploying the plugin.

Designing the Plugin


There are numerous considerations to take into account when designing a plugin for the System Configuration Collector. 1. It is highly recommended, although not required, that a plugin class name include the word Plugin. Including the word Plugin as a suffix of the class name easily identifies its purpose. The plugin source file name should be of the form <ClassName>Plugin.java. For practicality, the <ClassName> should allude to the plugins purpose as well. For example, PTC provides a SiteXConfPlugin that collects the <wt_home>/site.xconf file. 2. It is highly recommend that a plugin developer maintain a reasonable Java package structure for their plugins. The PTC provided plugins generally maintain package structures relevant to their purpose and PluginType (see Solution on page 1342 for more information on the PluginType class). Many of the PTC plugins can be found in the package com.ptc.customersupport. mbeans.plugins. Placing custom plugins in this package may allow for easier debugging of custom plugins as well as identifying their locations after deployment. However, this is not a strict requirement and the package structure is left to the developer. 3. All plugins must implement the PluginMBean interface. Implementing the PluginMBean interface class allows a plugin to expose attributes and operations that be executed from a JMX console. In addition, the PluginMBean class enforces an API contract that all plugins must adhere to which is vitally important to the underlying collection framework (see the CollectorMBean and Collector class as noted in Solution on page 1342).

System Configuration Collector Plugin

1353

4. All plugins must extend the AbstractPlugin class. The AbstractPlugin wraps much of the complexity of implementing the PluginMBean interface. It provides default implementations for many methods that are common to creating a plugin. Certainly, the default method implementations can be overridden to provide varying functionality. For example:
public class CustomPlugin extends AbstractPlugin implements PluginMBean {}

This example shows a CustomPlugin class that implements the PluginMBean interface and extends the AbstractPlugin class. Note that in this example the required methods of the interface, namely the collect() methods, are not implemented and this simple class would not compile. See Sample Code on page 1374 for a complete sample plugin implementation for sample plugins packaged with Windchill. 5. All plugin object constructors must make a method call to its super class. This is to ensure that all plugins initialize as SelfAwareMBeans (see Solution on page 1342 details regarding SelfAwareMBean). Since all plugins must extend the AbstractPlugin class through the plugin hierarchy, the AbstractPlugin class will make the appropriate method calls to register a plugin as a SelfAwareMBean. Therefore, a plugin developer does not need to concern themselves with the actual plugin MBean registration other than ensuring their plugin calls the super() operator during construction and that the plugin inheritance eventually extends AbstractPlugin.java. For example:
public CustomPlugin() throws NotCompliantMBeanException { super(null); // TODO Other initialization of this particular plugin } public CustomPlugin(final String displayName, final String beanName, final String description, final String pluginVersion) throws NotCompliantMBeanException { super(null, displayName, beanName, description, pluginVersion); // TODO Other initialization of this particular plugin }

These constructors are implemented to match the constructors of AbstractPlugin and make calls to AbstractPlugin through the super operator. This causes the CustomPlugin to be registered as a SelfAwarePlugin. The constructors call to super takes a Class object. If the concrete class is known it can be specified, otherwise null can be used. Java will use Introspection to determine the Class name. For example, since the

1354

Windchill Customization Guide

CustomPlugin implements the PluginMBean the call to super could alternatively be: super(PluginMBean.class super class); See for options to rely on inheritance to design more succinct constructors. 6. Due to implementing the PluginMBean interface and extending AbstractPlugin, a plugin must implement the two collect() methods. These are methods that essentially organize and hand-off work to the Collector class and collection framework. For example:
@Override public Map<String, Object> collect(final long callNumber, final long maxAgeInDays,final long minAgeInDays, final String pathTimeStamp) { // TODO Do actual collection work and return correct Map return null; } @Override public Map<String, Object> collect(String topicIdentifier, final long maxAgeInDays, final long minAgeInDays, final String pathTimeStamp) { // TODO Do actual collection work and return correct Map return null; }

The collect() method implementations shown here do not do anything useful and are merely presented here for clarity. They should do whatever work the plugin collection needs to accomplish and return the correct Map<String, Object> value that is expected. There are numerous default implementations of the collect() methods that can be relied upon through the Abstract classes. Often, a plugin simply needs to call the collectData() method of AbstractPlugin.java passing through the parameters of the collect() method to the collectData() method. The collectData() method wraps the complexity of calling the collection framework directly in the collect() methods. The collect() methods are required by the PluginMBean interface API since the flexibility is necessary to allow a developer to implement the collect() methods as necessary since very advanced plugins might desire to avoid using the default behavior of collectData(). Additionally, the Abstract classes have additional methods that can be relied upon. Many of these methods are of the form collectXYZ() that can be called by the collect() method implementations of specific plugins. These collect () methods wrap the specific collect implementations for the Abstract type of work the plugin does. For example, the GatherFolderPlugin. java class has collect() methods that are implemented such that it passes

System Configuration Collector Plugin

1355

along the specific folder to be collected to the collection framework, provided that folder was correctly set in the plugin initialization. The collect() methods must return a Map<String, Object>. This return Map is what is used by the plugin framework to understand on what server a plugin was executed and the plugins status. This return value is actually a Map inside of a Map; Map<String, Map<String, String>>. The outer Map contains the server information while the inner Map contains the plugin execution status for that server. If a customizer does not rely on the default implementations of collect() methods either through using the parent collectData() or other collect() methods of Abstract classes one must take extreme care to ensure that the return Map is correctly built and contains valid values. See Customization Points on page 1361 for additional detail on using default collect() implementations as well as greater detail regarding the methods return Map<String, Object> value. 7. The last consideration is what your plugin must do for actual work, and the most appropriate means to accomplish this. This can be accomplished by making numerous classes to work in conjunction with each other or wrapping all execution in one class. Additionally, there are numerous utility methods and abstract classes, as discussed in Solution on page 1342which can simplify plugin implementation. However, plugins can be designed to be very complex or very simple depending on the task the plugin is supposed to accomplish. 8. In summary, a properly designed plugin is required to have at least these characteristics: Implement the PluginMBean interface. Extend the AbstractPlugin class, either directly or through inheritance. 2 constructors with super() operator calls which eventually lead to AbstractPlugin. 2 collect() methods (if not relying on parent collect() implementations).

Implementing the Plugin


Implementation of a plugin is code that will do the actual work for the plugin. The main steps are to ensure a plugin is correctly initialized (see the design step above) and adheres to the required interface. The final step is providing the necessary method implementations for the plugin to carry out its work. 1. Plugin initialization:
Windchill Customization Guide

1356

During plugin construction, the object should initialize its MBean attributes (again, all plugins are MBeans). Using the example from the design phase we can expand on the constructor method:
public CustomPlugin() throws NotCompliantMBeanException { super(null); // super(PluginMBean.class); initializeMBeanAttributes(); } private void initializeMBeanAttributes() { if (logger.isDebugEnabled()) { Plugin."); logger.debug("Initializing " + CUSTOM_PLUGIN_NAME + " } // set the plugin display name setDisplayName(CUSTOM_PLUGIN_NAME); // set the plugin description setDescription(CUSTOM_PLUGIN_DESCRIPTION); // set the plugin MBean name setMBeanName("TomcatConfigProperties"); // set the plugin enumerated type setPluginType(PluginType.MISC); // set the plugin version number setPluginVersion("1.0"); // set whether the plugin relies on database // administrator credentials setDbCredentialsNeeded(false); // set whether the plugin operates on each // cluster node setClusterAware(true); // set whether the plugin relies on file // date ranges for data collection setDateRangeUsed(false); // set whether the plugin should compress the // output of its data collection setCompressOutput(false); }

Here the constructor has been expanded to include a private method that initializes all the plugin attributes including the MBean values that are exposed. The value of the setMBeanName parameter should be a properly formed MBean Object Name. To avoid potential MBean loader issues, it is recommend to avoid using spaces in the string name. For complete details regarding MBean Object Name syntax refer toAdditional Resources on page 1381 Related Websites. 2. Plugin collect() methods: The bulk of the plugin work is contained in the collect() methods and the implementation details are left for the plugin developer to implement. See Sample Code on page 1374 for examples.

System Configuration Collector Plugin

1357

In advanced plugins the work is generally sufficiently large for the collect() methods such that it is reasonable to implement helper Java classes and private helper methods. This will allow the plugin to have more discrete methods for easier maintenance. The implementation of any helper method is solely based on the plugin and the developer s discretion, and therefore is also specific and left for the particular implementer of the plugin. Refer to Customization Points on page 1361 for greater detail regarding the collect() methods. 3. Plugin localization: As Windchill is a distributed application with the potential to have clients in different locales it is highly recommended that any Java Strings that are externalized in a plugin should be localized. The strings of note are the plugin name and plugin description. These values are presented to the user in the System Configuration Collector UI. The com.ptc.customersupport.plugins.* packages contain numerous *Resource.java files that are referenced throughout many of the plugins, and found in the same packages. These *Resource.java files contain public String reference values that are localized and read during MBean plugin initialization. However, it is not always possible or feasible to localize Java strings. If the values are not localized the values used are those entered and compiled into the class files; in the above cases, English. Using our example from CustomPlugin we add a new plugin member variable:
private static ResourceBundle RESOURCE = ResourceBundle.getBundle( CustomPluginResource.class.getName());

This will be our reference to where our localized Java strings reside. Our CustomPlugin can then make use of this reference to retrieve the localized values. The refactored setDisplayName(string) and setDescription(string) methods become:
// set the localized plugin display name setDisplayName(MBeanUtilities.formatMessage( RESOURCE.getString( CustomPluginResource.CUSTOM_PLUGIN_NAME))); // set the localized plugin description setDescription(MBeanUtilities.formatMessage( RESOURCE.getString( CustomPluginResource.CUSTOM_PLUGIN_DESC)));

The localized Strings CUSTOM_PLUGIN_NAME and CUSTOM_PLUGIN_DESC are retrieved from the correctly localized class file. NOTE: The localized plugin Strings are based on the server locale as the localized plugin strings are read from the server during plugin initialization.
Windchill Customization Guide

1358

The localized values will display according to server locale and not the client locale in the System Configuration Collector UI. For more information on how to properly localize Windchill strings see Internationalization and Localization on page 1395.

Compiling the Plugin


After all the plugin files have been implemented they must be compiled into .class files. Use the Java jdk version running Windchill to ensure proper class file compatibility. For information on how to compile Java source files using the javac command see Additional Resources on page 1381 Related Websites.

Deploying the Plugin


Finally, the plugin packaged files must be bundled and deployed into Windchill. As mentioned in Compiling the Plugin on page 1359, the System Configuration Collector makes use of a Java class loader to load all files that are custom plugins. For the class loader to recognize a plugin, a service file must be created and deployed with the plugin (see Solution Elements and Related Websites for information on this file). The steps to have a functionally deployed plugin are: 1. Package the files. 2. Jar the files. 3. Deploy the Jar. 1. At the root location of your packaged source directory create a directory named META-INF. Inside that directory, create a sub-directory named services. Inside the services directory, create a text file named com.ptc. customersupport.mbeans.PluginMBean. This is the service file which the class loader will examine for plugin class files. This file must contain each plugin to be loaded and must follow a strict syntax format. The format for each plugin entry in the service file is of the form: <java source package>.<plugin class name> (without the brackets). For example, returning to the CustomPlugin example the corresponding service file would appear as, and only contain this one line: com.ptc.customersupport.mbeans.plugins.CustomPlugin Here is an example of the package structure for the CustomPlugin source, class files and service file.

System Configuration Collector Plugin

1359

The items of note are: The package structure to the CustomPlugin source, com/ptc/ customersupport/mbeans/plugins is maintained. The .class files exist in the /plugins directory. Optionally, the .java source files can exist there as well. The META-INF/services directory exists. The /services directory contains the com.ptc.customersupport.mbeans. PluginMBean file with an entry for each plugin to be loaded.

2. After creating the package structure and the services file it is necessary to bundle the files into a Java .jar file. See Related Websites for complete details on using Javas jar command. Using a Windchill shell, navigate to your root package location and create the . jar file. Returning to our example above showing the package structure and using the command jar cvfM CustomPlugin.jar ./com ./META-INF yields CustomPlugin.jar that contains all the contents of the /com and /METAINF directories, including their subdirectories. 3. Lastly, this .jar file needs to be deployed into the System Configuration Collector class loader location. Copy this file and place it in <wt_home>/ utilities/SystemConfigurationCollector/plugins directory.

1360

Windchill Customization Guide

Now the plugin can be used in the System Configuration Collector page. To do so, simply refresh the browser and add the custom plugin to a custom category. See the help on using the System Configuration Collector for more information on creating custom categories. For more information regarding the System Configuration Collector and its uses see the System Configuration Collector online help topic. Alternatively, you can deploy the plugin for use in a JMX console since all plugins are MBeans. Using a JMX Console navigate to the CustomerSupport MBean and run the reloadPlugins() operation. This operation forces the plugin MBean loader to reload all the available plugins including those at the deployment location. The below screen shot shows a user invoking the reloadPlugins CustomerSupport MBean operation. After invoking the reloadPlugins CustomerSupport MBean operation, the custom plugin will be displayed under the com.ptc/plugins MBean node in the respective plugin type subdirectory for which the plugin was defined. See Intended Outcome for more details and images regarding reloading plugins from a JMX Console.

Customization Points
Extending the PluginMBean Interface A plugin does not necessaryily need to implement the PluginMBean interface directly. Instead a new interface that extends the PluginMBean interface could be defined and implemented by the concrete plugin implementation. However, the new plugin interface is still required to inherit the PluginMBean interface. For example: public interface XYZPluginMBean extends PluginMBean {} Here the XYZPluginMBean extends the PluginMBean. This interface can then further define any required methods or attributes that are to be exposed via MBean operations. The concrete implementation would then be: public class XYZPlugin extends AbstractPlugin implements XYZPluginMBean {}

System Configuration Collector Plugin

1361

Abstracting the Plugin Similar to Extending the PluginMBean Interface section, a developer can rely on the numerous abstract classes detailed in Solution Elements, or any abstract class the developer defines to initialize plugin MBean values to defaults. As previously stated, the abstract classes wrap much of the complexity of plugin creation. In addition to relying on the abstract classes for plugin initialization a developer can also rely on the abstract implementations of the collect() methods. AbstractPlugin.java API: public AbstractPlugin(final final Class mbeanInterface) throws NotCompliantMBeanException Parameter mbeanInterface Default Value None Possible Values Class Req? Yes Description A class name that is the concrete implementation for the plugin.

AbstractPlugin.java API: public AbstractPlugin(final final Class mbeanInterface, final String displayName, final String mBeanName, final String description, final String pluginVersion) throws NotCompliantMBeanException { Parameter mbeanInterface Default Value None Possible Values Class Req? Yes Description A class name that is the concrete implementation for the plugin. A String representation of the plugin name. A String representation of the plugins mbean name. This value should adhere to proper Java MBean ObjectNames. See Related

displayName

None

String

Yes

mBeanName

None

String

Yes

1362

Windchill Customization Guide

Parameter

Default Value

Possible Values

Req?

Description Websites for MBean Object Names. A String representation of the plugin description. A version number associated with this plugin.

description

None

String

Yes

pluginVersion

None

String

Yes

AbstractPlugin.java API: public abstract Map<String, Object> collect(long long callNumber, long maxAgeInDays, long minAgeInDays, String pathTimeStamp); A developer is required to implement this method as it is Abstract. It is called by UI layers as an entry point to do the plugin work.. Parameter callNumber Default Value None Possible Values long Req? Yes Description This is a long value that is associated with a PTC Technical Support call number. It is used as a location to collect plugin data to. This value should not need to be modified by the collect(...) method implementation. A long value that is a starting time value for if files are collected with respect to time.
1363

maxAgeInDays

None

long

Yes

System Configuration Collector Plugin

Parameter

Default Value

Possible Values

Req?

Description This value should not need to be modified by the collect(...) method implementation. A long value that is an ending time value for if files are collected with respect to time. This value should not need to be modified by the collect(...) method implementation. A String representation of a directory timestamp used as a name which plugins collect their data to. This value should not need to be modified by the collect(...) method implementation.

minAgeInDays None

long

Yes

pathTimeStamp

None

String

Yes

A developer can usually pass this methods parameters to the collectData() methods of AbstractPlugin.java. As previously discussed, the collectData() method handles the complexity of calling the collection framework.

1364

Windchill Customization Guide

A developer can implement the collect methods in a way that does not rely on collectData() or any of the Abstract classes parent collectXYZ() method implementations. In general, this is an exception however. Only advanced plugins that require specialized work, such as running a Java process that does some work to build a file to be collected, will probably avoid simply calling the parent collect () method implementations. Even in this situation, after the Java process has completed and generated its data, parent classes could still be relied on to do the actual collection. MBeanDumpPlugin.java and WDSPlugin.java are two plugins PTC provides that do additional work other than simply call the parent collection methods, these can be examined in greater detail for those wishing to build highly complex plugins. Return Value Map<String, Object> Possible Values Req? Yes A Map of type <String, Object> where Object is of type Map<String, String> Description The return type is a Map that contains an inner Map. Map<String, Map<String, String>>. The inner Map<String, String> is a Map that contains the plugin execution status. The outer Map<String, Object> is a Map that contains which server the plugin executed on. This allows the plugin framework to report information across the cluster for each plugin executed.

Care must be taken when providing the return type of the collect() method. The collectData() method of AbstractPlugin.java wraps all the complexity of creating a valid return type that the plugin framework will correctly interpret. This is also why it is recommended to use the collectData() method in the collect() method implementation. Not doing so increases the complexity of the implementation of the collect() method greatly. The Outer Map: Map <String, Object>
System Configuration Collector Plugin

1365

The String key must be the server process ID and hostname of the name the plugin executed on. For example, 5524@DSTUSYNSKI03D. While any String is valid, the plugin framework will report this to the user which will appear as meaningless data if it isnt properly built. The Object is actually an inner Map of type <String, String>. The Inner Map: Map <String, String> The inner Map should have four key entries, one for each String, success, path, message, location. Each of these keys values must be another String that corresponds to the appropriate value for the key. The success keys value should be true or false and is the value that states whether the collection framework was successful in collecting the plugin data or not. The path keys value is generated by the collection framework and it denotes the last directory in the canonical path for which the plugin data is collected to for the particular server the plugin executed on. The message keys value is a String message that might accompany the plugin generated by the collection framework. This is likely a status message of why a plugin failed. The value null should be used if no message is to be reported. The location keys value is a String representing a partial path to where the collection framework collects the plugin data. When not relying on the collectData() method of AbstractPlugin.java or other parent Abstract classes care must be taken to ensure the collect() methods return type adheres to this form such that it can be correctly processed by the plugin framework. If implementing a plugin and building the return Map<String, Object> directly examine the MBeanDump.java and WDSPlugin.java implementations for greater detail. Both of these classes do not rely on the Abstract classes or the collection framework directly and therefore build the correct return type in their collect() method implementations. For the advanced plugin that requires the return Map to be built a developer can rely on the PluginUtilites.getReturnMap() method which is discussed further in this section. AbstractPlugin.java API: public abstract Map<String, Object> collect(String topicIdentifier, long maxAgeInDays, long minAgeInDays, String pathTimeStamp); A developer is required to implement this method as it is Abstract. It is called by UI layers as an entry point to do the plugin work. Parameter Default Value topicIdentifier None Possible Values String Req? Yes Description This is a String representation
Windchill Customization Guide

1366

Parameter

Default Value

Possible Values

Req?

Description of a directory used as a location to collect plugin data to. This value should not need to be modified by the collect(...) method implementation. A long value that is a starting time value for if files are collected with respect to time. This value should not need to be modified by the collect(...) method implementation. A long value that is an ending time value for if files are collected with respect to time. This value should not need to be modified by the collect(...) method implementation. A String representation of a directory

maxAgeInDays

None

long

Yes

minAgeInDays None

long

Yes

pathTimeStamp

None

String

Yes

System Configuration Collector Plugin

1367

Parameter

Default Value

Possible Values

Req?

Description timestamp used as a name which plugins collect their data to. This value should not need to be modified by the collect(...) method implementation.

See the previous collect() method for detail on this methods usage. AbstractPlugin.java API: public Map<String, Object> collectData(String srcPath, final long callNumber, final long maxAgeInDays, final long minAgeInDays, String pathTimeStamp) { Parameter srcPath Default Value None Possible Values String Req? Yes Description This is a String representation of a location that a plugins source data is collected from. This is usually a tokenized Windchill property string. For example, the WindchillLogs Plugin.java would pass $(wt.logs.dir) as the parameter. This value can also be a canonical file path to the data to be collected.
Windchill Customization Guide

1368

Parameter

Default Value

Possible Values

Req?

Description However, care must be ensured as this file path will likely not exist on each server the plugin is executed on. If a canonical file path is used the plugin should only execute on one cluster node by setting the plugin attribute isClusterAware to false during plugin initialization. This is a long value that is associated with a PTC Technical Support call number. It is used as a location to collect plugin data to. A long value that is a starting time value for if files are collected with respect to time. A long value that is an ending time value for if files are

callNumber

None

long

Yes

maxAgeInDays

None

long

Yes

minAgeInDays None

long

Yes

System Configuration Collector Plugin

1369

Parameter

Default Value

Possible Values

Req?

Description collected with respect to time. A String representation of a directory timestamp used as a name which plugins collect their data to.

pathTimeStamp

None

String

Yes

This is the method wraps the complexity of using the collection framework directly for collecting plugin data. Although not strictly required, it is recommended, that it be called by the collect() method implementations for a plugin. Often, calling this method in the collect() method and returning its value is all that is required of a collect() method implementation. The return value of this method is the same return value as the collect() methods described above. AbstractPlugin.java API: public Map<String, Object> collectData(String srcPath, final String topicIdentifier, final long maxAgeInDays, final long minAgeInDays, String pathTimeStamp) { Parameter srcPath Default Value None Possible Values String Req? Yes Description This is a String representation of a location that a plugins source data is collected from. This is usually a tokenized Windchill property string. For example, the WindchillLogs Plugin.java would pass $(wt.logs.dir) as the
Windchill Customization Guide

1370

Parameter

Default Value

Possible Values

Req?

Description parameter. This value can also be a canonical file path to the data to be collected. However, care must be ensured as this file path will likely not exist on each server the plugin is executed on. If a canonical file path is used the plugin should only execute on one cluster node by setting the plugin attribute isClusterAware to false during plugin initialization. This is a String representation of a directory used as a location to collect plugin data to. A long value that is a starting time value for if files are collected with respect to time. A long value that is an

topicIdentifier None

String

Yes

maxAgeInDays

None

long

Yes

minAgeInDays None

long

Yes

System Configuration Collector Plugin

1371

Parameter

Default Value

Possible Values

Req?

Description ending time value for if files are collected with respect to time. A String representation of a directory timestamp used as a name which plugins collect their data to.

pathTimeStamp

None

String

Yes

See the previous collect() method for detail on this methods usage. PluginUtilities.java API: public static Map<String, Object> getReturnMap(final final boolean success, final String path, final String message, final String location) { Parameter success Default Value None Possible Values boolean Req? Yes Description The success value for the plugin execution to be placed in the inner Map for the plugin framework status. The path directory value which is the parent directory for where the file is collected to be placed in the inner Map for the plugin framework
Windchill Customization Guide

path

None

String

Yes

1372

Parameter message

Default Value None

Possible Values String

Req? Yes

Description status. The message to be placed in the inner Map for the plugin framework status. The location partial file path to the PluginType directory be placed in the inner Map for the plugin framework status.

location

None

String

Yes

This method will build up a return value for use with the collect() method implementations provided correct values are passed into this method via its parameters. This method is a utility method that makes the creation of the collect () methods return value easier. Essentially, it wraps the creation of the return value freeing the implementor of the collect() method the need to create the outer and inner Maps. As each parameters description details, the parameters are used to generate the inner Map and the method implementation will handle generating the outer Map<String, Object>. The resulting return value is a Map<String, Object> where the Object is of type Map<String, String> that can then be used as the return type of a collect() method. While each of these parameters arent strictly required, they should be considered as such, otherwise the methods return value Map<String, Object> will simply be incomplete. The inner Map will not contain the correct data required by the plugin framework for reporting on the plugin execution status. Note that this method will only be useful as a utility for use when a developer does not rely on the collectData() implementation of AbstractPlugin.java or other Abstract collectXYZ() method implementations.

System Configuration Collector Plugin

1373

Limitations
Plugins used on the System Configuration Collector or used as MBeans can be quite powerful. They can be used to collect files, directories, properties as well as execute java classes, windu tasks, scripts, and gather database information. Currently, the plugin execution is limited to SQL and QML scripts, Windu tasks and Java code.

Sample Code
CustomPlugin.java CustomPlugin.java
package com.ptc.customersupport.mbeans.plugins; import java.util.Map; import java.util.ResourceBundle; import javax.management.NotCompliantMBeanException; import org.apache.log4j.Logger; import wt.jmx.core.MBeanUtilities; import wt.log4j.LogR; import import import public com.ptc.customersupport.mbeans.AbstractPlugin; com.ptc.customersupport.mbeans.PluginMBean; com.ptc.customersupport.mbeans.PluginType; class CustomPlugin extends AbstractPlugin implements PluginMBean {

private static ResourceBundle RESOURCE = ResourceBundle.getBundle(CustomPluginResource.class.getName()); LogR.getLogger(CustomPlugin.class.getName()); private static final Logger logger = public CustomPlugin() throws NotCompliantMBeanException { super(null); // super(PluginMBean.class); initializeMBeanAttributes(); } public CustomPlugin(final String displayName, final String beanName, final String description, final String pluginVersion) throws NotCompliantMBeanException { // super(PluginMBean.class, displayName, beanName, // description, pluginVersion); super(null, displayName, beanName, description, pluginVersion); } @Override public Map<String, Object> collect(final long callNumber, final long maxAgeInDays,final long minAgeInDays, final String pathTimeStamp) {

1374

Windchill Customization Guide

// TODO Do actual collection work and return correct Map return null; } @Override public Map<String, Object> collect(String topicIdentifier, final long maxAgeInDays, final long minAgeInDays, final String pathTimeStamp) { // TODO Do actual collection work and return correct Map return null; } private void initializeMBeanAttributes() { if (logger.isDebugEnabled()) { logger.debug("Initializing " + MBeanUtilities.formatMessage( RESOURCE.getString( CustomPluginResource. CUSTOM_PLUGIN_NAME)) + " Plugin."); } // set the localized plugin display name setDisplayName(MBeanUtilities.formatMessage( RESOURCE.getString( CustomPluginResource.CUSTOM_PLUGIN_NAME))); // set the localized plugin description setDescription(MBeanUtilities.formatMessage( RESOURCE.getString( CustomPluginResource.CUSTOM_PLUGIN_DESC))); // set the plugin MBean name setMBeanName("TomcatConfigProperties"); // set the plugin enumerated type setPluginType(PluginType.MISC); // set the plugin version number setPluginVersion("1.0"); // set whether the plugin relies on database // administrator credentials setDbCredentialsNeeded(false); // set whether the plugin operates on each // cluster node setClusterAware(true); // set whether the plugin relies on file // date ranges for collection setDateRangeUsed(false); // set whether the plugin should compress the // output of its collected data setCompressOutput(false); } }

CustomPluginResource.java CustomPluginResource.java
package com.ptc.customersupport.mbeans.plugins; import wt.util.resource.RBEntry;

System Configuration Collector Plugin

1375

import wt.util.resource.RBUUID; import wt.util.resource.WTListResourceBundle; @RBUUID("com.ptc.customersupport.mbeans.plugins.CustomPluginResource") public class CustomPluginResource extends WTListResourceBundle{ @RBEntry("My Custom Plugin") public static final String CUSTOM_PLUGIN_NAME = "0"; @RBEntry("A plugin that does xyz.") public static final String CUSTOM_PLUGIN_DESC = "1"; }

TomcatConfigPropertiesPlugin.java TomcatConfigPropertiesPlugin.java This is sample code that will collect the config.properties file at location installedProduct.location.Tomcat which is a wt.property value. The plugin is not localized for simplicity.
package demo; import java.util.Map; import javax.management.NotCompliantMBeanException; import org.apache.log4j.Logger; import wt.log4j.LogR; import com.ptc.customersupport.mbeans.PluginType; import com.ptc.customersupport.mbeans.plugins.GatherFilePlugin;

/** * A sample Plugin that gathers the Tomcat config.properties file. * The location of this file is controlled by the location of * Tomcat on an installed system. Generally, this location is * <wt_home>/tomcat/config.properties. However, there exists a * wt.property which points to where the tomcat instance is * installed. This property is installed.Product.location.Tomcat, * and it is used to build a tokenized path to the location of the * config.properties file. * <BR><BR> * This class extends the * {@link com.ptc.customersupport.mbeans.files.GatherFilePlugin * GatherFilePlugin} which is used to provide functionality that is * already implemented that this Plugin can rely upon for default * behavior. Most plugins will be able to make use of existing * Abstract plugin classes for much of their behavior and method * implementations. See the * {@link com.ptc.customersupport.mbeans.files.GatherFilePlugin * GatherFilePlugin} for more infomration on the parent class of * this Plugin and it's methods. * <BR><BR> */ public class TomcatConfigPropertiesPlugin extends GatherFilePlugin {

1376

Windchill Customization Guide

/* * Optionally provide some form of localization for plugin strings. * * In order to localize the values like name, description, * and version, follow these steps: * * 1. Create a tomcatConfigPropertiesPluginResource.rbInfo * file with the correct values. * * 2. Get an instance of a ResouceBundle like this: private static * ResourceBundle RESOURCE = * ResourceBundle.getBundle( * tomcatConfigPropertiesPluginResource.class.getName()); * * 3. Set the name (or other value) like this: * setDisplayName(MBeanUtilities.formatMessage( * RESOURCE.getString( * tomcatConfigPropertiesPluginResource. * PLUGIN_DISPLAY_NAME))); */ // Set member variables for ease of use. private static final String TCP_PLUGIN_NAME = "Tomcat Property Config File"; private static final String TCP_PLUGIN_DESCRIPTION = "<tomcat_home>/config.properties file."; /* * Optionally, provide some logging capabilities. Doing so * can facilitate easier Plugin debugging or provide * status/information messages to the running servers. */ private static final Logger logger = LogR.getLogger( TomcatConfigPropertiesPlugin.class.getName()); /** * Default constructor that sets all the required values. */ public TomcatConfigPropertiesPlugin() throws NotCompliantMBeanException { /* * The operator call to super() allows the * TomcatConfigPropertiesPlugin to rely on the parent class for * much of the Plugin initialization. This call will set * default values which are later overridden as necessary. This * also sets up and initializes this Plugin as a SelfAwareMBean * as the inheritance hierarchy eventually reaches * AbstractPlugin. */ super(); /* * This method call is simply for convenience of setting * all the Plugin values in one place that we are * overriding the default values for which were set when * super() was called. */ initializeMBeanAttributes();

System Configuration Collector Plugin

1377

} /** * Initializes all the Plugin values for this specific Plugin. * Those values which were initially set by parent classes are * overidden. */ private void initializeMBeanAttributes() { // Log a debug message that the Plugin is being initialized. if (logger.isDebugEnabled()) { logger.debug("Initializing " + TCP_PLUGIN_NAME + "" + " Plugin."); } /* * Set the attribute values that are common to all Plugins, * regardless of the PluginType. */ // The name that will be used for this Plugin. setDisplayName(TCP_PLUGIN_NAME); // The description that will be displayed for this Plugin. setDescription(TCP_PLUGIN_DESCRIPTION); // Set the MBean ObjectName. setMBeanName("TomcatConfigProperties"); /* * Set the PluginType value. This will control where the * data is collected to in terms of directory structure. */ setPluginType(PluginType.PROPERTY); // Set the Plugin version information. setPluginVersion("1.0"); /* * Set the file name that we want to collect. This value * overrides the default value set by the parent. The * GatherFilePluginMBean Interface of the parent class * specifies this method must be implemented. Since we * are extending the parent class and want to collect a * specific file (not the default file the parent specifies) * we override the value and set it to the location: * $(installedProduct.location.Tomcat)$(dir.sep) * config.properties * * This is a tokenized wt.property value. When the * collection framework operates on this Plugin, these * tokenized values are replaced by their canonicalized * paths and a file path results. This is how the collection * framework knows where to find files to collect. Ideally * tokenized or property values should be used to create * a path to the file. If hard-coded file paths are used * the Plugin will not operate across a cluster correctly. */ setFileName("$(installedProduct.location.Tomcat)" + "$(dir.sep)config.properties"); }

1378

Windchill Customization Guide

/** * Override the collect methods as needed. Incidentally, this * Plugin does not dictate the collect(...) methods be * overridden. The implementation of this method is actually * the same as the parent implementation. However, for clarity * of the example the collect(...) methods are shown. */ @Override public Map<String, Object> collect(final long callNumber, final long maxAgeInDays, final long minAgeInDays, final String pathTimeStamp) { /* * Here we call the collectData(...) method of AbstractPlugin * which will handle the actual collecting of the file * specified as the first parameter. Here the first parameter * is returned by the getFileName() method of the parent * class. * * The collectData method sets up and hides all the complexity * of using the collection framework and allows a developer to * avoid implementing a specific collect(...) implementation. * * However, there are instances when certain Plugins require * specific collect(...) method behavior, these instances * are usually reserved for very advanced Plugins. */ return collectData(getFileName(), callNumber, maxAgeInDays, minAgeInDays, pathTimeStamp); } @Override public Map<String, Object> collect(final String topicIdentifier, final long maxAgeInDays, final long minAgeInDays, final String pathTimeStamp) { return collectData(getFileName(), topicIdentifier, maxAgeInDays, minAgeInDays, pathTimeStamp); } }

Examples of Usage in Windchill Code


com.ptc. com.ptc.customersupport. customersupport.mbeans mbeans package This Java package contains the AbstractPlugin and PluginMBean interface. It also contains additional utility classes that can be utilized in creating plugins such as the PluginType.java and PluginUtilities.java. com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin plugin package This Java package contains many of the abstract classes seen in the UML diagram and discussed in Solution Elements. This package includes

System Configuration Collector Plugin

1379

com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin. plugin.logs logs package This Java package contains concrete plugin implementations that are of PluginType logs. These plugins are generally responsible for collecting log files. Log4jFilesPlugin, WindchillLogsPlugin and WDSLogsPlugin are examples that vary in complexity. com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin. plugin.misc misc package This Java package contains concrete plugin implementations that are of PluginType misc. These plugins are generally responsible for collecting miscellaneous information. UpgradeFolderPlugin, MigrationReportsFolderPlugin and WtSafeAreaFolderPlugin are examples that vary in complexity. com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin. plugin.properties properties package This Java package contains concrete plugin implementations that are of PluginType properties. These plugins are generally responsible for collecting properties files. DbPropertiesPlugin, DeclarationsXconfPlugin and IePropertiesPlugin are examples that vary in complexity. com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin. plugin.third third package This Java package contains concrete plugin implementations that are of PluginType third. These plugins are generally responsible for collecting third party product information. ApacheConfFolderPlugin, ApacheLogsPlugin and CogStartupXmlPlugin are examples that vary in complexity. com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin. plugin.util util package This Java package contains concrete plugin implementations that are of PluginType util. These plugins are generally responsible for collecting utility information. GatherInfoScriptPlugin, MBeanDumpPlugin and WDSMBeanDumpPlugin are examples that vary in complexity. MBeanDumpPlugin.java is a complex plugin that does not rely on the collect() method implementations of the Abstract classes. This plugin can be examined to provide greater insight into creating complex plugins that implement the collect () methods in a manner that doesnt make use of the Abstract classes implementations of collect() methods or the collection framework directly.

1380

Windchill Customization Guide

com.ptc. com.ptc.customersupport. customersupport.mbeans. mbeans.plugin. plugin.windu windu package This Java package contains concrete plugin implementations that are of PluginType windu. These plugins are generally responsible for executing and collecting Windu task information. ContainerStructurePlugin, DatabaseIndexUtilityPlugin and InvalidLdapEntriesPlugin are examples that vary in complexity. Packaged Samples PTC provides packaged plugin sample code at <wt_home>/utilities/ SystemConfigurationCollector/plugins/examples. This directory contains packaged samples that maintain the com.ptc.customersupport.* packaging in a sample subdirectory. These can be examined to see how one can make use of SQL, QML, Java commands, etc inside a plugin.

Additional Resources
Related Package/Class Package/Class Javadoc com.ptc.customersupport.mbeans* package(s) contain the Java plugin interfaces, numerous abstract plugins that provide common functionality, and concrete plugin implementations. Related Windchill Documentation For more information regarding the System Configuration Collector and its uses see the System Configuration Collector online help topic. Related Websites Java Jar Service Provider Specification : http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/ guides/jpda/jpda_spis.html http://java.sun.com/developer/technicalArticles/javase/extensible/ http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes /guides/jar/jar.html#Service%20Provider Java Jar File Specification : http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes /guides/jar/jar.html Java MBean Object Names : http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/ best-practices.jsp#mozTocId509360
System Configuration Collector Plugin

1381

Java Compiling : http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/tooldocs/ solaris/javac.html

Java Jar Command : http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/deployment/ jar/build.html

1382

Windchill Customization Guide

35
Customizing Modeled Elements
Customizing Column Lengths ................................................................................. 1384

This chapter describes how to customize modeled elements.

1383

Customizing Column Lengths


A column length for a modeled attribute can be customized. These column lengths are obtained through the wt.introspection package. The value of this property can be overridden by placing entries in the customizations property file for modeled packages. To change the column length for a modeled attribute, perform the following steps: 1. Determine which customization property entry must be added. 2. Add the customization entry to the appropriate customizations property file. 3. Generate the class info objects and SQL scripts. 4. Verify the customization. 5. Create the database tables. 6. Restart the method servers if they were running during the procedure. The following example sets the column length for the name attribute of the wt.doc. WTDocumentMaster class to 350. The following steps describe how to determine which customizations property file entry will contain the new column length, and how to set the value. The customization will be made in a location parallel with the originally modeled attribute. The default location for these customizations is $(wt.home)\wtCustom, as defined by the wt.generation.custom.dir entry in the tools properties. Create this directory if it does not already exist.

Note See the tools.properties file and user.properties file descriptions in The Windchill Development Environment.
1. Determine which customization property entry must be added: a. Obtain an info report for the class by executing the following command: infoReport wt.doc.WTDocumentMaster b. Inspect the value of the WTIntrospector.UPPER_LIMIT property (the value being customized) of the name PropertyDescriptor:
getValue( WTIntrospector.UPPER_LIMIT ) : 60

c. Inspect the value of the WTIntrospector.DEFINED_AS property of the name PropertyDescriptor:


getValue( WTIntrospector.DEFINED_AS ) : wt.doc.WTDocumentMaster.name

1384

Windchill Customization Guide

d. Based on this information, use the following values: The customization property file is <Windchill>\wtCustom\wt\doc\docModel.properties. The customization property entry is "WTDocumentMaster.name. UpperLimit".

2. Add the customization property entry to the appropriate customizations property file. In this example, add the following entry to <Windchill>\wtCustom\wt\doc\docModel.properties (create this file if it does not exist):
WTDocumentMaster.name.UpperLimit=350 # ignore multi-byte database character sets when setting value

3. Generate the class info objects and the SQL scripts. Update the serialized info object and the SQL script for the customized class by entering the following command (on one line):
ant -f <Windchill>\bin\tools.xml custom_column -Dgen.input=wt.doc

4. Verify the customization: a. Obtain an info report for the class and inspect the UPPER_LIMIT value as described in the preceding steps. The value should reflect the customization. b. If the info report value is unchanged, verify that the generate step actually updated the following serialized info file:
<Windchill>\codebase\wt\doc\WTDocumentMaster.ClassInfo.ser

5. Create the database tables, if they dont already exist, by executing the relevant SQL scripts generated above. If the tables already exist, adjust the length of the customized column by taking the following steps: a. For further information about the Upgrade Manager command options see the Windchill Upgrade Guide. b. c. Inspect the generated output to find the SQL script(s) related to this customization.

Caution Review the output carefully to ensure the results are what you expect. You should never execute any SQL that you do not understand, or that does not seem related to your intended customizations
d. Execute the relevant SQL scripts.

Customizing Modeled Elements

1385

In this example, WTDocumentMaster.name is also the source for the derived attribute WTDocument.name. This derived attribute, WTDocument.name, gets its UpperLimit from the source attribute, WTDocumentMaster.name. A derived attribute cannot set the UpperLimit property in the annotation. Therefore, the derived attribute cannot be customized in this manner.

1386

Windchill Customization Guide

36
Windchill Design Patterns
The Object Reference Design Pattern ..................................................................... 1388 The Business Service Design Pattern...................................................................... 1390 The Master-iteration Design Pattern ........................................................................ 1393

This section describes design patterns that represent Windchills current best practices regarding development of server logic, most notably the design pattern on how to develop business services. These patterns have emerged during the development of the Windchill services and should be used as standards and guidelines when developing new server logic.

1387

The Object Reference Design Pattern


One of the most basic design patterns is the object reference design pattern.

Object Reference Pattern This pattern essentially encapsulates details concerning persistable objects and their unique database query key. The pattern asserts that an object is a derived attribute aggregated by reference and is not persisted. The objects unique database query key is aggregated by value, is persisted, and is write-protected against the attempt of any other package class to set its value. In cases where database performance and storage are issues, object references persist only their object identifiers, and can be used in place of actual objects and acted upon via their identifiers. However, when the actual object is required, it can

1388

Windchill Customization Guide

be gotten from the object reference which may or may not be currently holding the object. If the object reference does not hold the object and the object is asked for, the object is refreshed via its query key from the database.

Windchill Design Patterns

1389

The Business Service Design Pattern

This pattern has the following major kinds of abstractions: Type Cookie Helper Service ServiceEvent ServiceException ServiceFactory

1390

Windchill Customization Guide

Type The Type abstraction provides an interface for means to type an object as being of a particular kind. This interface is what the service expects to deal with in terms of input and output, other than additional information. An object that does not specify it is of a certain type cannot statically be used by the service and thus is rejected at compile-time. In general, a Type is a kind of persistable object. Cookie The Cookie abstraction provides a class that is used to specify the information to be associated with and stored as a part of the typed object. When an object asserts itself as being a Type, the Cookie and its attributes, including all nested attributes, are code generated into the object along with applicable accessors. If a Cookies cardinality is 0..1, the Cookie and all its nested attributes can be stored as null if none of the Cookies attributes are required. If any of the simple, or structured, attributes of the Cookie are constrained to be non-null in the database, the Cookie is forced to be non-null. Helper The Helper abstraction provides a class representing the services external interface from which all visible functionality can be invoked. The helper is intended to specify only static methods and attributes which any other class can access without having to create any instances. The static methods are typically Cookie accessors. Service The Service abstraction provides an interface that specifies the main functionality of the service itself, which may or may not be invoked remotely if the interface is annotated with the @RemoteInterface. Otherwise, the services interface will be available only locally in the server. This interface must be adhered to and implemented for the service to function properly. Additionally, a standard implementation of the services methods exists. This standard implementation is a singleton executing on the server and is the default for all Windchill services. ServiceEvent The ServiceEvent abstraction provides a common definition of an event that can be emitted from the service and cause another service to be notified of the event. This event specifies one or more kinds of occurrences that are used to generate keys for listeners. Because these specific kinds of occurrences are extremely simple in nature, only one event per service that defines all occurrences is specified.

Windchill Design Patterns

1391

ServiceException The ServiceException abstraction provides a common definition of an exceptional condition that may occur as a result of abnormal behavior in the service. This exception, along with the services resource bundle, can be used exclusively to throw any and all kinds of errors. However, it may be appropriate, but not necessary, to specialize this exception for more explicit and applicable errors. ServiceFactory The ServiceFactory is a utility to look up implementations of Windchill service interfaces. The ServiceFactory is primarily intended for remotely invokable services, but can also be used for server-side services (such as PersistenceManagerSvr).

1392

Windchill Customization Guide

The Master-iteration Master-iteration Design Pattern


The design pattern that you must adhere to for all versioned data is the masteriteration design pattern.

Master-Iteration Pattern This pattern typically establishes two objects that work in concert with one another. Without one, the other should not exist and is certainly invalid. At the root are the basic abstractions: Mastered Iterated

The Mastered interface provides an abstraction of a plug-and-play component in conjunction with the Iterated interface. The intent is that, in a business model, an object would assert that it is a master by inheriting the Mastered interface. With this assertion, the business object can then be mastered through the version control services API. The business object must assert itself as being a kind of mastered object in order for its instance to be iterated.

Windchill Design Patterns

1393

The Iterated interface provides an abstraction of a plug-and-play component in conjunction with the Mastered interface. The intent is that, in a business model, an object would assert that it is an iteration (instance) by inheriting the Iterated interface. With this assertion, the business object can then be incrementally superseded, rolled back, and rolled up through the version control services API, provided it has a master. The business object must assert itself as being a kind of Iterated object in order for it to be incrementally changed. The next level of master-iteration pairs defines abstract entities that start pulling together (that is, assert) all applicable capabilities from a general [virtual] enterprise perspective. The level below starts becoming more concrete where the EnterpriseItemMaster is concrete but the EnterpriseItem is not. It is at this level where the association between master and iteration is overridden with the exact named roles. However, it should be noted that cardinality of the iterations within a master can be specialized to be further constrained. Also, this association again specifies itself as a foreign key and the master can be auto-navigated from the iteration. Thus, when an iteration is fetched from the database, its master is fetched as well in one SQL statement via a database view. Note that the iteration at this level need not be concrete for an association of this kind with the foreign key, and auto-navigation on the concrete class can have the other side as an abstract class. At the very bottom, all of the concrete specializations of the EnterpriseItem exist. All of these specializations inherit the foreign key, auto-navigate association from EnterpriseItem. And thus, each is generated with a specific database view such that three database views are generated for EnterpriseItem1, EnterpriseItem2, and EnterpriseItem3.

1394

Windchill Customization Guide

37
Internationalization and Localization
Background .......................................................................................................... 1396 The Windchill Approach ......................................................................................... 1397 Localizing Text Visible to the User ........................................................................... 1399 Resource Info (.rbInfo) Files ................................................................................... 1403

Internationalization is the process of designing and developing an application that can be easily adapted to the cultural and language differences of locales other than the one in which the application was developed. Localization is the process of adapting an application to fit the culture and language of a specific locale. All Windchill applications are fully internationalized and ready to be localized. Windchill applications are delivered with a default locale of US English (en_US). This chapter describes how to localize text visible to the user by using resource bundles.

1395

Background
Changing an application for use in another country or culture is often thought of as merely translating the language that appears in the user interface. There are many other aspects, however, that you should consider when developing a global application. How will you identify the preferred language and geographic location of the userYou may want to design into the application (or underlying product architecture) the ability to determine the locale and present the appropriate version from a collection of different localized versions. What data used within your application is sensitive to localeConsider the use of decimals within numbers, currency symbols, date formats, address styles, and system of measurement. How should data be formattedConsider the order in which text and numbers are read by different audiences. Languages that display numbers from left to right and text from right to left affect the layout of menu bars and text entry fields. The grammar of a language may dictate different placement of variables in error messages. Collation of sortable lists Consider how different alphabets affect the collation sequence and how collation of typical list elements is done in the locales of potential users of your application. Non-Roman alphabets Your application must be able to accommodate different fonts and different sizes of fonts. This again can affect the layout of menu bars and text entry fields. What are the cultural sensitivities toward graphics and use of colorWhen designing icons or other graphics, and deciding on background and other colors, consider whether they may be objectionable in another culture Both client and server developers need to be aware of these factors. You must be able to localize not only the GUI, but also feedback messages and exceptions that might be displayed to the user.

1396

Windchill Customization Guide

The Windchill Approach


Rather than try to keep all these preceding factors in mind and accommodate them individually as you develop an application, the best approach is to isolate any language- or locale-dependent code from the language-independent code (that is, the applications executable code). Windchill is designed to allow you to do this. Windchill takes advantage of many Java features that support international applications: Locale class Each locale-sensitive object maintains its own locale-specific information. The initial default for locale is specified in the system but users can specify a preference in the Web browser. Resource bundles In a resource bundle, you define pairs of keys and values, where the values are strings and other language-dependent objects for a specific locale. Within code, you use the key to indicate where the corresponding string or object should be inserted. For example, Windchill uses resource bundles in its online help and to identify button names, field names, and other elements of graphic user interfaces. The default or preferred locale specifies which resource bundle to use and, therefore, determines which strings and objects to display. (An example is shown later in this chapter.) Windchill uses a structured properties file format to manage much of the localizable text. Unlike the java.util.PropertyResourceBundle properties files, these resource info files are not used at runtime. They are more like java.util. ListResourceBundle java files, where they are used to manage the information, and runtime resource bundles are built from them. These resource info files have a .rbInfo file extension. This format is required for managing the localizable information for EnumeratedTypes and display names for metadata, since these localizable resources are updated by generation tools. The resource info format can be used for storing other localizable text, but it is not mandatory. Unicode This is a 16-bit international character-encoding standard. A character encoding is a numeric representation of alphanumeric and special text characters. A multi-byte encoding is necessary to represent characters such as those used in Asian countries. The intent of Unicode is to be able to represent all written languages in the world today. Localized text manipulation

Internationalization and Localization

1397

The Java classes java.io.inputStreamReader and java.io.OutputStreamWriter provide the mechanism to convert standard character encodings to Unicode and back, thus enabling the translation of characters to and from platform and locale-dependent encoding. Handling local customs The java.text package provides classes that convert dates and numbers to a format that conforms to the local conventions. This package also handles sorting of strings. java.text.NumberFormat. formats numbers, monetary amounts, and percentages. java.text.DateFormat contains the names of the months in the language of the locale and formats the data according to the local convention. This class is used with the TimeZone and Calendar classes of the java.util package. TimeZone tells DateFormat the time zone in which the date should be interpreted and Calendar separates the date into days, weeks, months, and years. All Windchill dates are stored by the server in the database based on a conversion to Greenwich Mean Time. To display Timestamps in the correct Timezone, the application programmer should use wt.util.WTContext to set the Timezone in the DateFormat as follows:
DateFormat df = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT,WTContext.getContext().getLocale() ); df.setTimeZone(WTContext.getContext().getTimeZone()); System.out.println("The current time is: " + df.format(new Timestamp(current_time_millis)));

java.text.Collator can compare, sort, and search strings in a localedependent way.

1398

Windchill Customization Guide

Localizing Text Visible to the User


Windchill provides internationalized applications with US English (en_US) as the default locale. We recommend that you provide a localized resource bundle for every other locale that you support. Resource bundles are used to hold information, generally text, that you may want to modify based on your locale. A resource bundle is a hash table of key/value pairs, where the values are specific to the locale. Every package should have a resource bundle. The Windchill naming convention is as follows: <your package name>.<pkg>Resource.class Implementation classes have a generated constant, RESOURCE, to identify their fully qualified resource bundle class. Resource bundles are loaded at runtime based on the system setting or userspecified preference for locale. To load the resource bundle, a Java program calls java.util.ResourceBundle.getBundle, specifying the base name of the desired ResourceBundle. For example, the algorithm to find a ResourceBundle named fc. fcResource is as follows: 1. Search for a class with the name fc.fcResource_language_country_variant. 2. Search for a class with the name fc.fcResource_language_country. 3. Search for a class with the name fc.fcResource_language. 4. Search for a class with the name fc.fcResource. All Windchill resource bundles are provided for the default locale en_US. Because these resource bundles are specified by the base name, they have no extension. Because IDEs may generate code to handle graphical components and interactions, do not put references to resource bundles in sections that have been generated. If you make any changes and regenerate the code, those references will be lost. Instead, create a localize method that overrides the hard-coded label with the appropriate label from a resource bundle and put it outside the generated code area. The following example shows how to make visible text locale dependent. For example, within the localize method, the line:
lblUser.setText(RB.getString("lblUser") + ":");

associates the label defined internally as lblUser with the string found in the resource bundle that corresponds to the lblUser key; that is,
{"lblUser","User"},

The string "User" is then displayed in this label.


static ResourceBundle RB; public void addNotify() {

Internationalization and Localization

1399

//Localize localize(); } //{{DECLARE_CONTROLS //}}

//{{DECLARE_MENUS //}} } private void localize() { RB=ResourceBundle.getBundle("wt.clients.administrator.LabelsRB" ,getLocale()); lblUser.setText(RB.getString("lblUser") + ":"); btnSearch.setLabel(RB.getString("btnSearch")); btnCreate.setLabel(RB.getString("btnCreate")); btnUpdate.setLabel(RB.getString("btnUpdate")); btnAddUsertoGroup.setLabel(RB.getString "btnAddUsertoGroup")); btnView.setLabel(RB.getString("btnView")); btnDelete.setLabel(RB.getString("btnDelete")); btnClose.setLabel(RB.getString("btnClose")); try { //MultiList column headings java.lang.String[] tempString = new java.lang. String[4]; tempString[0] = RB.getString("Full Name"); tempString[1] = RB.getString("UserID"); tempString[2] = RB.getString("Web Server ID"); tempString[3] = RB.getString("E-Mail"); lstUsers.setHeadings(tempString); } catch (PropertyVetoException e) {} }

(If using rbInfo files, See Resource Info section below.)


package wt.clients.administrator; import java.util.ListResourceBundle; public class LabelsRB extends java.util.ListResourceBundle {

1400

Windchill Customization Guide

public Object getContents()[][] { return contents; } static final Object[][]contents = { //Labels {"lblAdministrative","Administrative"}, {"lblAllGroups","All Groups"}, {"lblAttach","Attach"}, {"lblAuthorization","*Web Server ID"}, {"lblBelongs","Groups User Belongs to"}, {"lblCity","City"}, {"lblCountry","Country"}, {"lblCreate","Create"}, {"lblCreated","Created"}, {"lblDelete","Delete"}, {"lblDescription","Description"}, {"lblEmail","E-Mail"}, {"lblFullName","Full Name"}, {"lblGroup","Group"}, {"lblGroupName","Group Name"}, {"lblID","*ID"}, {"lblLocale","Locale"}, {"lblModify","Modify"}, {"lblName","Name"}, {"lblRead","Read"}, {"lblState","State"}, {"lblStreet1","Street1"}, {"lblStreet2","Street2"}, {"lblTitle","Title"}, {"lblUse","Use"}, {"lblUser","User"}, {"lblUserName","User Name"}, {"lblZip","Zip"}, //Button Labels {"btnAdd","Add>>"}, {"btnAddAll","Add All>>"}, {"btnAddRemove","Add/Remove Members"}, {"btnAddUsertoGroup","Add User to Group"}, {"btnApply","Apply"}, {"btnCancel","Cancel"}, {"btnClear","Clear"}, {"btnClose","Close"}, {"btnCreate","Create"}, {"btnDelete","Delete"}, {"btnGenerate","Generate Now"}, {"btnNewGroup","New Group..."}, {"btnNewUser","New User..."}, {"btnOK","OK"}, {"btnRefresh","Refresh"}, {"btnRegenerate","Regenerate"}, {"btnRemove","< {"btnRemove","<

Internationalization and Localization

1401

To create a different localization for this resource bundle, for example, French, you would create a new class in the wt.clients.administrator package called LabelsRB_fr. This class would contain the same label keys, such as "lblAdministrative" but its value would be "administratif" rather than "Administrative". All the other values would likewise be changed to their French counterparts. You would compile the new class; then the Java runtime would be able to find a French resource bundle for the Administrator client.

1402

Windchill Customization Guide

Resource Info (.rbInfo) (.rbInfo) Files


wt.L10N. wt.L10N.complete complete
Resource Info files are an alternative to storing localizable text in ListResourceBundle source code files. They are structured properties files that facilitate easy manipulation by automated tools. Resource info (or rbInfo for short) files are resource files used to store localizable strings of Java programs. The primary purpose of the rbInfo files is to provide an easier and more manageable way to handle localizable strings than resource bundles. RbInfo files offer a number of advantages over resource bundles: Resource bundle files are Java source files, so that a single misplaced curly bracket, missing double quote or extra comma will cause a syntax error and break the compile and integration process. RbInfo files have much simpler format, it is easier to localize and more difficult to introduce syntax errors. Because of the simpler format of the rbInfo files, it is easier to handle them with localization tools; perform change tracking, change propagation and so on. It is more difficult to abuse the rbInfo file format and introduce tricky resource types. Java resource bundles can hold any type of objects, but rbInfo files can handle strings only. (This may appear to be a limitation, but it is not. It makes localization easier.)

RbInfo files are converted to compiled Java class files in the integration process, so that the same naming convention rules apply to rbInfos as resource bundles. (Localized versions are kept in separate files; there is one resource file per language, the name of the locale is appended to the name of the localized files.) The format of the rbInfo files is PTC-specific. It was designed primarily for Windchill, but can be used in other Java-based products as well. The migration from resource bundles to rbInfo files is seamless; there is no need to change the source code. Old resource bundles can be converted to rbInfo format using a relatively straightforward process. To find out more about the migration, refer to the Windchill Upgrade and Migration Guide.

Resource Info Categories


Localizable text is considered to be in one three categories for the purpose of resource info file usage. Resource Type Message Text Source File Run-Time Run-Time File *RB.rbInfo*Resource.rbInfo *RB.class*Resource.class

Internationalization and Localization

1403

Resource Type Source File Modeled Metadata <package>ModelRB.rbInfo (Display Names) EnumeratedType Op- <EnumType>RB.rbInfo tions Definition

Run-Time Run-Time File <package>ModelRB.RB.ser <EnumType>RB.RB.ser

General Resource Info File Usage Rules


A line beginning with # is considered a freeform comment. Each file must contain a header line that categorizes the file. Only String values are supported. Since values are assumed to be Strings, they should not be in quotes. Each entry must exist on a single line, and the following escaped characters are supported: \\, \n, \r, \t, \f, \". Key cannot contain =, since it is the key/value separator. Key cannot contain "#", since it is a comment character, but the character is allowed in the value.

Resource Entry Format


The following keys define the structure of resource entries. Key <key>.value <key>.constant Description The localizable text that will be displayed. A string that will be used to generate a constant field into the runtime resource bundle, which can be used by code that does resource lookups. A comment describing the entry. A comment for each substitution argument of the value string. Indicates whether the resource entry is customizable. Indicates (to the Usage Required Message text: Optional Metadata: Unused EnumeratedType: Unused

<key>.comment <key>.argComment<n>

Optional Optional

<key>.customizable

Optional

<key>.deprecated

Optional

1404

Windchill Customization Guide

Description developer) whether the resource entry is deprecated. <key>.abbreviatedDisplay Reserved for future use. <key>.fullDisplay Reserved for future use. <key>.shortDescription Reserved for future use. <key>.longDescription Reserved for future use. <key>.order Explicit sort order for the value, unused for alpha ordering.

Key

Usage

Unused Unused Unused Unused Message text: Unused Metadata: Unused EnumeratedType: Optional Message text: Unused Metadata: Unused EnumeratedType: Optional Message text: Unused Metadata: Unused EnumeratedType: Optional

<key>.defaultValue

Specifies the value is the default value for the Enumerated Type.

<key>.selectable

Specifies if the value should be allowed to be selected.

Resource Info File Descriptions by Category


Message Text
The Message Text category most commonly contains error messages and labels for user interface actions, but is the general category for any localizable text that does not fall into one of the other categories. The Message Text files are completely user-maintained, while the maintenance of the entries in the other two categories is automated via various generation tools. Since this category is not maintained by automated tools, and since the resulting run-time bundle is the same ListResourceBundle subclass that it would be if the information were stored in a ListResourceBundle source code file, the use of .rbInfo file format is optional for Message Text. The following sections describe the resource info files for Message Text.

Internationalization and Localization

1405

Message Text Resource Info Header Each resource info file must contain the following lines that define certain file level information.
ResourceInfo.class=wt.tools.resource.StringResourceInfo ResourceInfo.customizable=false ResourceInfo.deprecated=false

The first line classifies the resource info and should never be changed. The values of the second and third lines can be changed by the owner of the package, if the file can be customized, and/or the file is deprecated. Message Text Resource Entry Examples
//Labels lblAdministrative.value=Administrative lblAdministrative.constant=LBL_ADMIN lblAdministrative.comment=administrative ui label lblAllGroups.value=All Groups lblAllGroups.constant=LBL_ALL_GROUPS //Button Labels btnAdd.value=Add>> btnAdd.constant=BTN_ADD btnAddAll.value=Add All>> btnAddAll.constant=BTN_ADD_ALL //MultiList column headings Class.value=Class Created On.value=Created On

Modeled Metadata (Display Names)


Resource Info files for modeled metadata are generated by the Windchill System Generation Tool.

EnumeratedType Options Definition


Resource Info files for enumerated types are described in Enumerated Types on page 1315 .

Building Runtime Resource Bundles for Resource Info Files


Since the information is not stored in Java source code files, a tool other than the Java compiler is needed to build the runtime resource bundles. This tool can be executed by using the ResourceBuild script.

1406

Windchill Customization Guide

38
The Enterprise Layer
Enterprise Abstractions .......................................................................................... 1408 Document Abstractions .......................................................................................... 1415 Part Abstractions ................................................................................................... 1418 Change Abstractions ............................................................................................. 1426

This chapter describes the classes and interfaces available in four packages: wt.enterprise wt.doc wt.part wt.change2

The classes provided in these packages were designed and intended for you to extend as you customize Windchill for your own use.

1407

Enterprise Abstractions
The wt.enterprise package provides the basic business objects used in the Windchill system. Most business classes you construct will be extended from the enterprise classes or their subclasses.

The enterprise Package Business classes should be extended from one of the abstract classes included in the wt.enterprise package to take advantage of the capabilities and services they offer. This diagram shows convenience classes designed to consolidate a basic set of features that various business classes might require. Most of the business classes in your model are expected to extend one of these classes and simplify your implementations.

1408

Windchill Customization Guide

Simple Business Class


A simple business class is a first class information object that is subject to business rules, such as access control. These objects have no managed life cycle and are not organized into folders. Because these objects are not visible via folders, they tend to be more administrative in nature (that is, created by administrators but referenced by end users).

Simple Business Class

Folder Resident Business Class


A folder resident business class is a business object that resides in a folder. Because these objects are accessible in folders, they are visible to users in the Windchill Explorer. These objects are subject to access control rules.

The Enterprise Layer

1409

FolderResident business objects are not subject to life cycle management. Therefore, they are more administrative in nature. All FolderResident objects automatically record the principal (user) who created them.

Folder Resident Business Class

1410

Windchill Customization Guide

Managed Business Class


Managed business class objects are subject to a controlled life cycle. They reside in folders for organizational purposes. They are non-revisable objects that the system manages and controls via access control. These objects record the principal (user) who created them. The creator can be used as a role in certain processing for life cycle and workflow operations.

Managed Business Class

Revision Controlled Business Class


RevisionControlled business objects are identified by a revision identifier. They are managed and changed via a checkin/checkout mechanism. They are subject to life cycle management and other forms of management by the enterprise. They have a
The Enterprise Layer

1411

creator by virtue of being a Workable object (which is an Iterated object). Because the class is also Versioned, there can be multiple business versions of the Master object, such as revision A and revision B of a single document.

Revision Controlled Business Class Revision controlled business objects are managed as two separate classes:
Master

Represents the version independent idea of a business concept. It contains the information that identifies the business objects. Typically this is information such as a name and number that remains constant for all versions (or, more accurately, is the same for all versions).
Revision controlled

Represents the successive changes to the business objects as it is developed over time. A RevisionControlled object represents an official version (for example, revision A or B) but also provides access to previous iterations of that version. The previous iterations are considered a history of work-in-progress activity (checkouts and checkins) for the object.

1412

Windchill Customization Guide

Iterated Folder Resident Business Class


IteratedFolderResident business class objects reside in folders where they are visible to users of the Windchill Explorer. Users create new iterations of these objects using checkout/checkin operations. They are also subject to access control and automatically record the principal (user) who created them. IteratedFolderResident objects are similar to RevisionControlled objects. However, they are lighter weight objects in that they are neither versioned nor life cyclemanaged, as is the case with RevisionControlled objects.

Iterated Folder Resident Business Class

The Enterprise Layer

1413

Cabinet Managed Business Class


Cabinet managed business class objects are non-iterated, life cycle-managed objects. Because cabinet managed business objects are not Foldered, they do not reside in folders and are not visible to users of the Windchill Explorer. They are, however, associated with cabinets for reasons of access control and local search.

Cabinet managed business class

1414

Windchill Customization Guide

Document Abstractions
The wt.doc package provides a standard implementation of managed documents. A simplification of the document model is shown below. This simplification shows some of the core interfaces that make up WTDocument and WTDocumentMaster. These objects actually implement a number of interfaces to acquire their behavior. To see the full scope of interfaces that are implemented by these two objects go to the Javadoc for wt.doc.WTDocument and wt.doc.WTDocumentMaster.

Doc Package The document classes are implemented based on the pattern established for revision controlled objects in the wt.enterprise package. These classes, WTDocumentMaster and WTDocument, provide concrete classes exhibiting the management characteristics established in wt.enterprise and add specifics for documents. The properties of a document are specified on the WTDocument class. Then, for normalization purposes, the sum of the properties are stored on the WTDocumentMaster. More specifically, WTDocument implements Format ContentHolder to give it a primary content item and multiple secondary content

The Enterprise Layer

1415

items. WTDocument can create two types of relationships to other documents. The first, WTDocumentUsageLink, is similar to the WTPartUsageLink in that it also subclasses IteratedUsageLink. It does not have a quantity. WTDocumentUsageLink is used to create uses relationships between documents or document structure. Documents should use this if a document is made up of subdocuments and the sub-documents can be reused by other documents, or need to be controlled separately. Similar to the part implementation, the WTDocumentService has convenience methods for navigating this relationship and there is a WTDocument ConfigSpec to filter results. The second, WTDocumentDependencyLink implements IteratedDescribeLink which is also implemented by WTPartDescribeLink. This is a version-specific relationship between two documents. This relationship is shown in the client as references. A reference between two documents can be created to show a dependency on another document. A document may reference some information in another document, so during a create or update, a reference to that document is added. The references relationship has a comment attribute that can be used to explain why the reference exists or what the dependency is. WTDocument Service also has convenience methods for navigating the WTDocumentDependencyLink. The doc package is an example of implementing a Revision Controlled Business subclass. The concrete document business classes inherit from the Revision Controlled Business model (Master and RevisionControlled) template in the enterprise model. Document inherits most of its functionality from the enterprise object RevisionControlled. RevisionControlled pulls together many plug and play functionality interfaces. To see the full list of interfaces go to wt.enterprise. Revisioncontrolled in the javadoc. In particular, it includes interfaces from the content package. This means that a WTDocument is a content holder; that is, it can have files or URLs included in it. Attributes are on either WTDocumentMaster or WTDocument. Attributes on WTDocumentMaster have the same value for all versions and iterations. If an attribute on the master changes after several versions and iterations have been created, the change is reflected in all the versions and iterations. Attributes on WTDocument can generally have different values for each iteration, so changes impact only one iteration. This is why content holder is implemented on DocumentIteration.

Attributes Specific to Windchill Foundation & PDM


The docType attribute of a document is held in common for all iterations and versions. It is stored in the WTDocument merely to allow for database partitioning based on the document type attribute. Customers wishing to create new document types will add values to the DocumentType resource bundle.

1416

Windchill Customization Guide

The DocumentType resource bundle defines all the types of documents. When users construct documents, they may pick a document type from the enumerated list. Customers may add new document types to the list by putting additional values in the resource bundle. A "$$" prefix on a document type means it is a Windchill-provided document type. The "$$" prefix should not be used for customer types. Using the DocumentType resource bundle, it is possible to construct new types of documents that users can pick from. This has the following impacts from an administrative perspective: Administrative rules do not recognize the new document types. Therefore, all document types are the same from an administrative perspective; they receive the same access control and indexing rules. From a workflow point of view, the docType property can be used as an activity variable for workflow branching logic.

To add new document types that can have different administrative controls, the WTDocument class must be extended. Subclassing of WTDocument also is preferable if there are specific associations in which only some documents can participate. These kinds of rules are difficult to specify without subclassing WTDocument. Use the following rules when extending WTDocument: For every new child of WTDocument, you must make a corresponding entry in the DocumentType resource bundle. This ensures that the WTDocumentMaster object for each WTDocument child knows the type for its document version. When adding new classes of documents, it is not necessary to extend the WTDocumentMaster class, only the WTDocument class. All children classes of WTDocument can share the same WTDocumentMaster class. Follow the constructor pattern established in WTDocument. Override the appropriate initialize methods from WTDocument, invoking super.initialize() and then performing your class specific logic. Specifically, invoke the method initialize(number, name, type) where type is substituted for a value that has been added to DocumentTypeRB.java.

Department is implemented as an enumerated type attribute or a valid value list. The valid values are defined in the wt.doc.DepartmentListRB.java file. The values in DepartmentListRB.java can be changed, the file compiled, and replaced in the codebase. For further information, seeEnumerated Types on page 1315.

The Enterprise Layer

1417

Part Abstractions
The wt.part package provides a standard implementation of parts. A part is an item that can be produced or consumed, such as, an engine, a bolt, or paint. Parts can be assembled to produce other parts; for example, the drive train of an automobile can be thought of as a part composed of an engine, transmission, shaft, differential, and so on.

Design Overview
The following figure illustrates the basic concepts encapsulated by the Windchill part reference implementation.

Part Reference Implementation The part classes are implemented based on the pattern established for revision controlled objects in the wt.enterprise package. These classes, WTPartMaster and WTPart, provide concrete classes exhibiting the management characteristics established in wt.enterprise and add specifics for parts. The properties of a part are specified on the WTpart class. Then, for normalization purposes, the sum of the properties are stored on the WTPartMaster. The part package is an example of implementing a Revision Controlled Business subclass. The concrete part business classes inherit from the Revision Controlled Business model (Master and RevisionControlled) template in the enterprise model. Part inherits most of its functionality from the enterprise object RevisionControlled. RevisionControlled pulls together the following plug and play functionality: Foldered, Indexable, Notifiable, DomainAdministered, AccessControlled, BusinessInformation, LifeCycleManaged, Version, Workable, and Changeable.

1418

Windchill Customization Guide

Attributes are on either WTPartMaster or WTPart. The WTPartMaster, as a Mastered object, represents the parts identity. As such, "number" and "name" have been placed on it. The parts number is the stamp the enterprise recognizes and uses for tracking purposes. The name is the human-readable component. These properties of the part are assigned carefully and rarely changed. Attributes on WTPartMaster have the same value for all versions and iterations. If an attribute on the master changes after several versions and iterations have been created, the change is reflected in all the versions and iterations. The WTPart, as a Versioned and Workable object, undergoes change that is recorded in its versions and iterations as a result of a check-out and check-in process. Attributes on WTPart can generally have different values for each iteration, so changes impact only one iteration. An iteration occurs every time a part is checked out and in. It can be viewed as a working copy of the part. Iterations are assumed to happen many times between versions. Versions, however, represent a business increment; that is, an approved, major change to a part. A typical scenario is that version A of a part is approved and put into production. Then a change is determined to be necessary. The part goes through many iterations while the change is being investigated and tested. Finally, version B is approved. Also, being ViewManageable, WTPart can be assigned to views, allowing it to progress through stages of development, such as engineering and manufacturing stages. It resides in folders, is subject to access control, progresses through life cycles, and is part of the change process as a consequence of being RevisionControlled. It can also be assigned to baselines to preserve a specific implementation and its versions can be made effective to indicate to a manufacturing process what to build. Although shown in the preceding figure, WTPart is no longer a ContentHolder by default. The capability to hold files and URLs still exists, but it is no longer exposed to the user.

The Enterprise Layer

1419

The WTPart also contains as aggregated properties a source and a type (as shown in the following figure).

WTPart Properties The source can be used to indicate how the part is procured, for example by being made or bought. The type specifies how it can be decomposed, for example by being separable (is assembled from components that can be taken apart to be serviced), inseparable (is assembled, but can not be disassembled), or component (is not assembled). The values of these properties can be altered by editing their resource bundles. Also, note that number and name are modeled as derived and are implemented to set and get the real values from its WTPartMaster. The DerivedFrom property in the Windchill tab of the attribute specification has been used to indicate that it has been derived from the master s attributes by specifying the database derivation; also, the getters and setters have been overridden in a manner similar to the following:
((WTPartMaster) getMaster()).get/set...(...)

WTParts can use other parts to build assemblies using the WTPartUsageLink as shown in the following figure.

Building Assemblies with the WTPartUsageLink

1420

Windchill Customization Guide

The WTPartUsageLink is a type of IteratedUsageLink, an association defined to be used to build structures. The WTPartUsageLinks aggregated Quantity can be used to indicate the amount of the component that is being consumed. The QuantityUnits values can be altered by editing its resource bundle. The WTPartUsageLink can be navigated using the PersistenceManager s navigate APIs, or even the StructServices navigateUses and navigateUsedBy APIs. Be aware that navigating the usedBy role results in the returning of all part iterations; StructServices navigateUsedBy API returns only versions. However, the StructServices APIs navigate using the IteratedUsageLink as its target; the WTPartUsageLink might not be the only IteratedUsageLink in a customization. We recommend using the APIs in the following figure.

Navigating the WTPartUsageLink getUsesWTParts navigates to the WTPartMaster and resolves WTParts from the masters using a WTPartConfigSpec, returning a QueryResult of Persistable[]s in which the WTPartUsageLink is in the 0th position and the WTPart/WTPartMaster in the 1st. getUsesWTPartMasters simply navigates the WTPartUsageLink and returns a QueryResult of WTPartUsageLinks. Finally, getUsedByWTParts returns a QueryResult of WTParts (the versions, not simply all iterations) representing the implementations that call out the part. WTParts can also reference documents (see the following figure).

WTPartReferenceLink and Navigate API

The Enterprise Layer

1421

Parts generally reference documents for one of two reasons: The part is not the logical owner of a document. An example of such a document is a standards document. A standards document is independent of a part, but may be used to verify conformance to the document. A document (file) is conceptually owned by the part, but must be separately life cycle managed, checked in and out independently of the file, and so on. Note that the WTPartReferenceLink may not be appropriate if the documents versions are not necessarily interchangeable from the perspective of the WTPart. If a specific version of a document should be linked to a specific version of a part, use the DescribedBy link (as described later in this section) instead.

The WTPartReferenceLink can be navigated using the WTPartServices getReferencesWTDocumentMasters API. A WTPart can also be linked to a document that describes it on a version-specific level using WTPartDescribedByLink. An example of such a document is a CAD drawing that shows exactly how a specific version of a part is designed and should be built. If a change is made to the part and a new version created, the revised version of the CAD drawing, that reflects that change, should be linked to the new part using the DescribedBy functionality. To summarize, a reference should be considered supplemental information that is useful but not required. It is likely to have its own life cycle and change independently of the part referencing it. A document linked to a part by a DescribedBy link contains information you may need specifically for that version of the part. A specific version of the document is linked to a specific version of the part. The WTPartConfigSpec was alluded to by the getUsesWTParts API. It is used by the Product Structure Explorer during its navigations. It consists of three ConfigSpecs: the WTPartStandardConfigSpec, the WTPartEffectivityConfigSpec, and the WTPartBaselineConfigSpec (as shown in the following figure).

1422

Windchill Customization Guide

WTPartConfigSpec A concept of zones has been added to the WTPartConfigSpec to determine which ConfigSpec is active at any given time. The WTPartConfigSpec is stored, one per principal, using the WTPartServices APIs listed in the following figure.

Finding and Saving the WTPartConfigSpec The ConfigSpecs aggregated by the WTPartConfigSpec have the following behavior: WTPartStandardConfigSpec When active, WTParts are filtered based on their state and their view membership. workingIncluded can be used to allow users to toggle between their working copies and their checked-out versions. WTPartEffectivityConfigSpec When active, allows the user to see structures based on effectivity and view. Only WTParts designated as effective are shown (see the wt.effectivity package for additional information). WTPartBaselineConfigSpec When active, displays only those WTParts assigned to the specified baseline (see the wt.vc.baseline package for additional information). Parts can often be replaced by other parts, either globally or in the context of an assembly. This interchangeability is used to indicate that one part is equivalent to another in a given situation. The WTPartAlternateLink (shown in the following

The Enterprise Layer

1423

figure) is used to indicate global interchangeably, while the WTPartSubstituteLink indicates interchangeability within the context of an assembly. Note that the WTPartSubstituteLink is copied whenever the WTPartUsageLink is copied.

Alternate and Substitute Links Both of these links can be navigated using the Persistence Manager s navigate APIs. In addition, the WTPartService offers getAlternatesWTPartMasters and getAlternateForWTPartMasters methods for navigation of WTPartAlternateLinks and getSubstitutesWTPartMasters and getSubstituteForWTPartUsageLinks methods for navigation of WTPartSubstituteLinks. Both WTPartAlternateLinks and WTPartSubstituteLinks are access controlled, so permission to perform operations such as creation and deletion of links is defined using the access control service.

1424

Windchill Customization Guide

The Part, PartMaster, and PartIteration classes modeled in the wt.part package (see the following figure) are placeholders for future functionality.

Placeholders

The Enterprise Layer

1425

Change Abstractions
The change2 package includes the basic service methods and change item classes necessary to support change management. The change management module provides the means by which users can identify, plan, and track changes to the product information managed by the Windchill product data management system.

Note The change2 package replaces the change package available in releases prior to Release 4.0.
The following figure shows the five conceptual steps in the change management process.

Change management process To understand the Windchill change management object model, it is important to understand these conceptual steps, as described below. Although the order of these steps is not fixed, they are presented here in a logical sequence. Describe symptoms The symptoms of a perceived problem are recorded. The person experiencing the symptoms could be an internal employee, a customer, or any other end user or person. This person records the symptoms. Pursue formal change At some point, the group of symptoms is evaluated. A formal decision is made to investigate the symptoms.

1426

Windchill Customization Guide

Identify problem pause By investigating the symptoms and performing analysis, the root cause of the problem is determined. As part of this work, the person investigating the problem may identify relevant parts or documents. Propose solution A course of action to fix the problem is proposed. As part of this work, the person preparing a solution may identify relevant parts or documents. Implement solution A solution is chosen and implemented. As part of the implementation work, the users of the change process identify part or document revisions, both old revisions (that is, those that require a change) and new revisions (that is, those that have been changed). This step includes the incorporation of the solution into production, if appropriate.

Change Item Classes


The following figure shows the model for the change classes provided by Windchills change management module.

Change Management Class Model

The Enterprise Layer

1427

The following figure shows the relationship between the change item classes and the change management process shown earlier.

Change Management Process and Related Classes Following are descriptions of the available change objects: Change issue A change issue holds information about the problems symptoms. A change issue can be thought of as a suggestion box. Change request A change request is the object that organizes the other change objects. It represents a formal, traceable change. This object can be associated with product data versions (for example: parts, products, product instances, documents, or CAD documents). Change investigation A change investigation organizes the information pertaining to the root cause of the problem. It is used when the root cause is not trivial or obvious. If the research to determine the root cause is very detailed or complicated, analysis activities are used to organize the effort into logical work breakdowns. Change proposal A change proposal organizes the information pertaining to a solution for the problem. It is used when the problem solution is not trivial or obvious. If the research to determine the solution is very detailed or complicated, analysis activities are used to organize the effort into logical work breakdowns.

1428

Windchill Customization Guide

Analysis activity An analysis activity is used in conjunction with either a change investigation or a change proposal. When the cause of the problem is complex, an analysis activity helps to further organize a change investigation. When the solution to a problem is complex, an analysis activity helps to further organize a change proposal. This object can be associated with product data versions that are relevant to the analysis work. Change order A change order is created if a change proposal is chosen for implementation. Change activity A change activity serves as the work breakdown for a change order. This object can be associated with product data versions for two distinct reasons: the product data is defective or otherwise must be changed, or the product data version is a result of a change. This allows users of the system to track the reason for change to product data.

Associations with Product Information


A changeable is a PDM object whose changes can be tracked by the change management system. These are referred to as product data versions to the end user. The term product data version appears on the Change Management user interface rather than the term "changeable." At this release, Windchill parts, products, product instances, documents, and EPM documents are the only changeables, as shown in the following figure.

Changeable Objects

The Enterprise Layer

1429

The change management model defines four distinct relationships between change objects and changeables. Any number of changeables can be associated with each of the relationships. In the following figure, one part and one document is associated to the change object in each case. Also shown is a relationship between a change request and a product master, which is not changeable.

Relationships to Product Information The following are the four relationships between change objects and changeables and the relationship between a change request and a product master. Relevant request data The relevant request data association identifies changeables that are relevant the change request for any reason.

1430

Windchill Customization Guide

Relevant analysis data The relevant analysis data association identifies changeables that are relevant to the analysis for a change investigation or change proposal. Affected activity data The affected activity data association identifies changeables that must be changed to satisfy a change activity. Change record The change record association identifies changeables that have been changed as a result of a change activity. Subject product The subject product association identifies product masters that are the subject of the change request. Product masters are not changeables and may not be directly affected by the change request. To summarize, relevant request data and relevant analysis activity data identify versions that might change, affected activity data identifies old (or defective) revisions which have been superseded, and change record identifies new (or improved) revisions. Also, subject product identifies product masters that are the subject of a change request, but are not necessarily affected themselves. The following figure shows a UML class diagram representing these associations:

Associations Class Diagram

The Enterprise Layer

1431

Change Item Modeling Approach


Each change management object is modeled using a three-tiered approach: interface, abstract class, and concrete class, as shown in the following figure:

Change Item Modeling Approach Interface layer The interface classes simply implement the Persistable interface to indicate that the change management classes are objects stored by Windchill. Abstract classes The abstract classes implement various Windchill plug and play interfaces and enterprise package classes to obtain standard Windchill functionality. Each abstract class implements ContentHolder, which provides the ability to attach files. In addition, each abstract class extends either Managed or CabinetManaged (see the enterprise package, earlier in this chapter for an explanation of these classes). The abstract classes also contain modeled associations among change objects, and between change objects and product information objects. Concrete classes The concrete classes contain modeled business attributes.

Change Items Classes


The following sections show the models for the change item classes. Because many attributes are common, descriptions of all the attributes defined on these items are shown at the end of this section under Change Item Attribute Descriptions on page 1438.

1432

Windchill Customization Guide

Change issue
The following figure shows the model for change issues:

Change Issue Model

The Enterprise Layer

1433

Change Request
The following figure shows the model for change requests:

Change Request Model

1434

Windchill Customization Guide

Change Investigation
The following shows the model for change investigations:

Change Investigation Model

The Enterprise Layer

1435

Change Proposal
The following figure shows the model for change proposals:

Change Proposal Model

Analysis Activity
The following figure shows the model for analysis activities:

1436

Windchill Customization Guide

Analysis Activity Model

Change Order
The following figure shows the model for change orders:

Change Order Model

The Enterprise Layer

1437

Change Activity
The following figure shows the model for change activities:

Change Activity Model

Change Item Attribute Descriptions


The following is a list of the attributes on change manager items: category The category to which the change object belongs. The category identifies the general reason for the suggested change (for example, a cost reduction, quality improvement, or safety issue). complexity The complexity of the change object. description A description of the change object. issuePriority or requestPriority The priority of the change object. name The summary of the change object. This attribute is displayed on the user interface as summary.

1438

Windchill Customization Guide

needDate The target date by which the change object should be resolved and closed. number The automatically generated number of the change object. requester The user who created the change object. results The results of the change investigation or change proposal.

The Enterprise Layer

1439

1441

39
Evolvable Classes
Background Information ......................................................................................... 1443 General Externalization Guidelines ......................................................................... 1443 Hand-coded Externalization Guidelines ................................................................... 1445 Migration Guidelines for Classes with Hand-coded Externalization............................. 1446 Examples of Generated Externalization Code for Evolvable Classes.......................... 1447

This chapter describes evolvable classes. Externalizable classes that implement the Evolvable interface are the Windchill classes that can be serialized into BLOB columns in the database. As the persistent structure of these classes changes, action may be required to maintain compatibility with previous versions that have been serialized into the database. Any modeled class that is intended to support being serialized into a BLOB database column must implement the Evolvable interface. Once Evolvable is implemented, the owner of the class must manage its compatibility from version to version. The Persistent Data Service (PDS) will report any classes being serialized into the database that implement the NetFactor interface and not the Evolvable interface. This allows third party classes, such as Vectors, Hashtables, and so on, to be serialized into the database. This also allows modeled classes that do not implement NetFactor to be serialized into the database; however, we do not recommend this practice because it leaves the class exposed to serious data migration problems. The best way to specify that a modeled class will implement the Evolvable interface is to set the Serializable property for the class to Evolvable.
Windchill Customization Guide

1442

Background Information
The generated externalization code reads and writes a data stream according to the following order, with field values for each class ordered alphabetically: 1. BottomClass.ID 2. MiddleClass.ID 3. TopClass.ID 4. TopClass field value1 5. TopClass field value2 6. TopClass field value...N 7. MiddleClass field value1 8. MiddleClass field value2 9. MiddleClass field value...N 10. BottomClass field value1 11. BottomClass field value2 12. BottomClass field value...N To maintain externalization compatibility of a class from version to version, it is most important to understand the resulting stream layout for each version of a class. When the persistent signature of a class is being changed significantly, it may be helpful to map out the stream format for each version, in order to understand clearly what is necessary to read a previous version of the stream. Beyond the fundamental understanding of the stream format, points in the following sections provide guidance concerning when and what kind of manual intervention is necessary to maintain compatibility.

General Externalization Guidelines


The following are general externalization guidelines: Inserting a parent into the hierarchy is handled automatically. Removing a parent from the hierarchy requires implementation of readOldVersion for pre-Release 9.0 versions. The old ID and fields must be read (removed) from the stream. Changing the persistent signature of a class requires implementation of readOldVersion pre-Release 9.0 versions. Adding or removing fields. Changing the name or type of a field.

Evolvable Classes

1443

For Windchill Release 9.0 and beyond, the virtually all changes are handled automatically. See explanations in examples sections below for details on how the automated readVersion<EXTERNALIZATION_VERSION_UID> methods are generated.

1444

Windchill Customization Guide

Hand-coded Hand-coded Externalization Guidelines


The following are guidelines for hand-coded externalization: Use the version ID that is generated as the EXTERNALIZATION_VERSION_UID constant. This allows subclasses to use it for their own comparisons. If you want to control the EXTERNALIZATION_VERSION_UID, you must model it and specify its initial value in the model. A modeled attribute supersedes the one provided by the code generator. To calculate this version UID, the code generator uses the name of the parent class, and the names and types of all the non-transient, persistent fields. It is prudent to manually control this value if the hand-coded externalization is not related to the signature, or footprint, of the nontransient, persistent fields of the class. (This occurrence should be rare.) Do not model a serialVersionUIDattribute with a value other than 1 as this disallows the ability to read old versions of the class.

Evolvable Classes

1445

Migration Guidelines for Classes with Hand-coded Hand-coded Externalization


The following are guidelines for the migration of classes with hand-coded externalization: First, check whether the code generated into the readVersion method looks the same as the code that is preserved in readExternal. If so, you should turn off preservation and just let it all be generated. If the class had modeled a serialVersionUID attribute, remove it from the model. Set the Serializable property to Evolvable. If the class already implemented readOldVersion, multiple old versions will now need to be supported. If the class is not final, the following guidelines apply: If the class was using something other than the generated version ID number, you must change the read/write to use the EXTERNALIZATION_VERSION_UID constant. In addition, OLD_FORMAT_VERSION_UID should be ignored because it is incorrect for your class. To read in instances externalized in the old format, reference the version UID that was actually used. You must also add support for the old ID to readOldVersion(). You must move code from readExternal() to readVersion(), and set preserve=no for readExternal().

1446

Windchill Customization Guide

Examples of Generated Externalization Code for Evolvable Classes


This section contains examples of generated externalization code for evolvable classes.

Example of Version/UID Version/UID Mapping Table


The generator manages the release specific externalization by storing a table that maps each release to its externalization uid. This is stored in a comment block following the imports section of each source file. In the following example, the version column is the internal id for the release and the uid column is the externalization uid for the release version. As the UID changes, the table will be updated. A line will be added for each release version with its unique id.
//##begin version.uid preserve=yes /* version X-10 */ //##end version.uid uid = 6676079877272797361L

Example of Generated Constants


static final long serialVersionUID = 1; public static final long EXTERNALIZATION_VERSION_UID = 6676079877272797361L; protected static final long OLD_FORMAT_VERSION_UID = -6779867937001963664L; // OLD_FORMAT_VERSION_UID is only valid for R4 instances of the class

Example of a writeExternal Method


public void writeExternal( ObjectOutput output ) throws IOException { //##begin writeExternal%writeExternal.body preserve=no output.writeLong( EXTERNALIZATION_VERSION_UID ); super.writeExternal( output ); output.writeObject( a1 ); output.writeObject( a2 ); output.writeObject( a3 ); output.writeObject( list ); output.writeObject( (size == null ? null : size.getStringValue()) ); output.writeObject( theOneMoreReference ); output.writeObject( timeline ); output.writeObject( work );

Evolvable Classes

1447

//##end writeExternal%writeExternal.body }

Example of a readVersion Method


The generator generates a readVersion method that include a conditional block for each version/uid line in the mapping table, unless a developer has taken over maintenance of the method by setting preserve=yes. The final "else" block calls the old readOldVersion() method, to support externalization code that might already have been implemented in this method. For negative uids, the minus sign is converted to an underscore in the method name, since a dash is not a valid character in Java method names.
protected boolean readVersion( MyItem thisObject, ObjectInput input, long readSerialVersionUID, boolean passThrough, boolean superDone ) throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException { //##begin readVersion%readVersion.body preserve=no boolean success = true; if ( readSerialVersionUID == 6676079877272797361L ) return readVersion6676079877272797361L( input, readSerialVersionUID, superDone ); else success = readOldVersion( input, readSerialVersionUID, passThrough, superDone ); if (input instanceof wt.pds.PDSObjectInput) wt.fc.EvolvableHelper.requestRewriteOfEvolvedBlobbedObject(); return success; //##end readVersion%readVersion.body }

1448

Windchill Customization Guide

Example of a readVersion<EXTERNALIZATION_VERSION_UID> Method


A method is generated for each line in the version/uid mapping table, but the body is only generated for the uid that matches the current release version. In this example, the current release version is Windchill R9.0, so its method body will be generated. The current release version is stored in release.properties, which is stored in SystemGeneration.jar. The property cannot be overridden by configuring it in user.properties. The preserve=maybe tag has been introduced with this automated evolvability generation to support the generator making the decision regarding whether to preserve the method body. As with other methods, a particular method can be permanently taken over by the developer by changing it to preserve=yes. With these externalization methods generated to be release specific, support for class evolution is automated but there are still issues that developers will need to manage. The first is when an attribute (field) is removed from a release. This case is easy, since the old externalization methods will no longer compile, since they reference non-existent fields. The developer will need to modify the code to not set field, but the old field must still be read off the stream, or it will throw a runtime exception. For example, if the title field is removed from the class, the previous readVersion<EXTERNALIZATION_VERSION_UID> methods will need to change the line that reads the title, as follows.
/*title = (String)*/input.readObject(); // field to assign no longer exists

The second scenario is when attributes (fields) are added. In this case, there will be no compile error and the code will deserialize without problem, but the object could possibly be left in an invalid state. The developer should be aware of this possibility and ensure that the object will be initialized to a valid state.
private boolean readVersion6676079877272797361L( ObjectInput input, long readSerialVersionUID, boolean superDone ) throws IOException, ClassNotFoundException { //##begin readVersion6676079877272797361L%readVersion6676079877272797361L. body preserve=maybe if ( !superDone ) compatibility super.readExternal( input ); a1 = (String)input.readObject(); a2 = (Date)input.readObject(); // if not doing backward

// handle super class

Evolvable Classes

1449

a3 = (Xyz)input.readObject(); list = (Vector)input.readObject(); String size_string_value = (String)input.readObject(); try { size = (MySize)wt.fc.EnumeratedTypeUtil.toEnumeratedType( size_string_value ); } catch( wt.util.WTInvalidParameterException e ) { // old format size = MySize.toMySize( size_string_value ); } theOneMoreReference = (ObjectReference)input.readObject(); timeline = (Timeline)input.readObject(); work = (MyAddress)input.readObject(); return true; //##end readVersion6676079877272797361L%readVersion6676079877272797361L.body }

Example of a readOldVersion Method


This method is generated virtually the same as readVersion <EXTERBALIZATION_VERSION_UID> to support backward compatibility. To support backward compatibility for multiple releases, the method should include a conditional block for each old version that is being supported. Each condition should check for the version UID that was used in that version of the class, and the block that reads the fields should be the same set of read calls that the were used for that version. The generated OLD_FORMAT_VERSION_UID constant is only valid for R4 instances of the class. Fields that no longer exist can be read and discarded (not assigned). Fields that didn't exist for the version can be initialized in the manner necessary to put the object into a valid state.
private boolean readOldVersion( ObjectInput input, long readSerialVersionUID, boolean passThrough, boolean superDone ) throws IOException, ClassNotFoundException { //##begin readOldVersion%readOldVersion.body preserve=no boolean success = true; // handle previous version if ( readSerialVersionUID == OLD_FORMAT_VERSION_UID ) { a1 = (String)input.readObject();

1450

Windchill Customization Guide

a2 = (Date)input.readObject(); a3 = (Xyz)input.readObject(); list = (Vector)input.readObject(); String size_string_value = (String)input.readObject(); try { size = (MySize)wt.fc.EnumeratedType.toEnumeratedType( size_string_value ); } // in case it was old format catch( wt.util.WTInvalidParameterException e ) { size = MySize.toMySize( size_string_value ); } theOneMoreReference = (ObjectReference)input.readObject(); timeline = (Timeline)input.readObject(); work = (MyAddress)input.readObject(); } else if ( !superDone ) { success = super.readVersion( this, input, readSerialVersionUID, false, false ); // reformatted streamif ( success &amp;&amp; !passThrough &amp;&amp; // forced pass through to skip me // I have been inserted into hierarchy readSerialVersionUID != super.EXTERNALIZATION_VERSION_UID ) // try mine again readVersion( this, input, input.readLong(), false, true ); } else throw new java.io.InvalidClassException( CLASSNAME, "Local class not compatible:" + " stream classdesc externalizationVersionUID= " + readSerialVersionUID + " local class externalizationVersionUID= " + EXTERNALIZATION_VERSION_UID ); return success; //##end readOldVersion%readOldVersion.body }

Evolvable Classes

1451

You might also like